]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
2458ee2ae1c586f6f919c6ccc1dac89e7be308a8
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
1 /** @file
2 Implement image verification services for secure boot service in UEFI2.3.1.
3
4 Caution: This file requires additional review when modified.
5 This library will have external input - PE/COFF image.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
8
9 DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content
10 read is within the image buffer.
11
12 DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
13 untrusted PE/COFF image and validate its data structure within this image buffer before use.
14
15 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
16 This program and the accompanying materials
17 are licensed and made available under the terms and conditions of the BSD License
18 which accompanies this distribution. The full text of the license may be found at
19 http://opensource.org/licenses/bsd-license.php
20
21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23
24 **/
25
26 #include "DxeImageVerificationLib.h"
27
28 //
29 // Caution: This is used by a function which may receive untrusted input.
30 // These global variables hold PE/COFF image data, and they should be validated before use.
31 //
32 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
33 UINT32 mPeCoffHeaderOffset;
34 EFI_GUID mCertType;
35
36 //
37 // Information on current PE/COFF image
38 //
39 UINTN mImageSize;
40 UINT8 *mImageBase = NULL;
41 UINT8 mImageDigest[MAX_DIGEST_SIZE];
42 UINTN mImageDigestSize;
43
44 //
45 // Notify string for authorization UI.
46 //
47 CHAR16 mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"Image verification pass but not found in authorized database!";
48 CHAR16 mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"Launch this image anyway? (Yes/Defer/No)";
49 //
50 // Public Exponent of RSA Key.
51 //
52 CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
53
54
55 //
56 // OID ASN.1 Value for Hash Algorithms
57 //
58 UINT8 mHashOidValue[] = {
59 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
64 };
65
66 HASH_TABLE mHash[] = {
67 { L"SHA1", 20, &mHashOidValue[0], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
68 { L"SHA224", 28, &mHashOidValue[5], 9, NULL, NULL, NULL, NULL },
69 { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},
70 { L"SHA384", 48, &mHashOidValue[23], 9, NULL, NULL, NULL, NULL },
71 { L"SHA512", 64, &mHashOidValue[32], 9, NULL, NULL, NULL, NULL }
72 };
73
74 /**
75 Reads contents of a PE/COFF image in memory buffer.
76
77 Caution: This function may receive untrusted input.
78 PE/COFF image is external input, so this function will make sure the PE/COFF image content
79 read is within the image buffer.
80
81 @param FileHandle Pointer to the file handle to read the PE/COFF image.
82 @param FileOffset Offset into the PE/COFF image to begin the read operation.
83 @param ReadSize On input, the size in bytes of the requested read operation.
84 On output, the number of bytes actually read.
85 @param Buffer Output buffer that contains the data read from the PE/COFF image.
86
87 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
88 **/
89 EFI_STATUS
90 EFIAPI
91 DxeImageVerificationLibImageRead (
92 IN VOID *FileHandle,
93 IN UINTN FileOffset,
94 IN OUT UINTN *ReadSize,
95 OUT VOID *Buffer
96 )
97 {
98 UINTN EndPosition;
99
100 if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
101 return EFI_INVALID_PARAMETER;
102 }
103
104 if (MAX_ADDRESS - FileOffset < *ReadSize) {
105 return EFI_INVALID_PARAMETER;
106 }
107
108 EndPosition = FileOffset + *ReadSize;
109 if (EndPosition > mImageSize) {
110 *ReadSize = (UINT32)(mImageSize - FileOffset);
111 }
112
113 if (FileOffset >= mImageSize) {
114 *ReadSize = 0;
115 }
116
117 CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
118
119 return EFI_SUCCESS;
120 }
121
122
123 /**
124 Get the image type.
125
126 @param[in] File This is a pointer to the device path of the file that is
127 being dispatched.
128
129 @return UINT32 Image Type
130
131 **/
132 UINT32
133 GetImageType (
134 IN CONST EFI_DEVICE_PATH_PROTOCOL *File
135 )
136 {
137 EFI_STATUS Status;
138 EFI_HANDLE DeviceHandle;
139 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
140 EFI_BLOCK_IO_PROTOCOL *BlockIo;
141
142 if (File == NULL) {
143 return IMAGE_UNKNOWN;
144 }
145
146 //
147 // First check to see if File is from a Firmware Volume
148 //
149 DeviceHandle = NULL;
150 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
151 Status = gBS->LocateDevicePath (
152 &gEfiFirmwareVolume2ProtocolGuid,
153 &TempDevicePath,
154 &DeviceHandle
155 );
156 if (!EFI_ERROR (Status)) {
157 Status = gBS->OpenProtocol (
158 DeviceHandle,
159 &gEfiFirmwareVolume2ProtocolGuid,
160 NULL,
161 NULL,
162 NULL,
163 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
164 );
165 if (!EFI_ERROR (Status)) {
166 return IMAGE_FROM_FV;
167 }
168 }
169
170 //
171 // Next check to see if File is from a Block I/O device
172 //
173 DeviceHandle = NULL;
174 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
175 Status = gBS->LocateDevicePath (
176 &gEfiBlockIoProtocolGuid,
177 &TempDevicePath,
178 &DeviceHandle
179 );
180 if (!EFI_ERROR (Status)) {
181 BlockIo = NULL;
182 Status = gBS->OpenProtocol (
183 DeviceHandle,
184 &gEfiBlockIoProtocolGuid,
185 (VOID **) &BlockIo,
186 NULL,
187 NULL,
188 EFI_OPEN_PROTOCOL_GET_PROTOCOL
189 );
190 if (!EFI_ERROR (Status) && BlockIo != NULL) {
191 if (BlockIo->Media != NULL) {
192 if (BlockIo->Media->RemovableMedia) {
193 //
194 // Block I/O is present and specifies the media is removable
195 //
196 return IMAGE_FROM_REMOVABLE_MEDIA;
197 } else {
198 //
199 // Block I/O is present and specifies the media is not removable
200 //
201 return IMAGE_FROM_FIXED_MEDIA;
202 }
203 }
204 }
205 }
206
207 //
208 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
209 // the device path supports the Simple File System Protocol.
210 //
211 DeviceHandle = NULL;
212 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
213 Status = gBS->LocateDevicePath (
214 &gEfiSimpleFileSystemProtocolGuid,
215 &TempDevicePath,
216 &DeviceHandle
217 );
218 if (!EFI_ERROR (Status)) {
219 //
220 // Simple File System is present without Block I/O, so assume media is fixed.
221 //
222 return IMAGE_FROM_FIXED_MEDIA;
223 }
224
225 //
226 // File is not from an FV, Block I/O or Simple File System, so the only options
227 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
228 //
229 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
230 while (!IsDevicePathEndType (TempDevicePath)) {
231 switch (DevicePathType (TempDevicePath)) {
232
233 case MEDIA_DEVICE_PATH:
234 if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
235 return IMAGE_FROM_OPTION_ROM;
236 }
237 break;
238
239 case MESSAGING_DEVICE_PATH:
240 if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
241 return IMAGE_FROM_REMOVABLE_MEDIA;
242 }
243 break;
244
245 default:
246 break;
247 }
248 TempDevicePath = NextDevicePathNode (TempDevicePath);
249 }
250 return IMAGE_UNKNOWN;
251 }
252
253 /**
254 Caculate hash of Pe/Coff image based on the authenticode image hashing in
255 PE/COFF Specification 8.0 Appendix A
256
257 Caution: This function may receive untrusted input.
258 PE/COFF image is external input, so this function will validate its data structure
259 within this image buffer before use.
260
261 @param[in] HashAlg Hash algorithm type.
262
263 @retval TRUE Successfully hash image.
264 @retval FALSE Fail in hash image.
265
266 **/
267 BOOLEAN
268 HashPeImage (
269 IN UINT32 HashAlg
270 )
271 {
272 BOOLEAN Status;
273 UINT16 Magic;
274 EFI_IMAGE_SECTION_HEADER *Section;
275 VOID *HashCtx;
276 UINTN CtxSize;
277 UINT8 *HashBase;
278 UINTN HashSize;
279 UINTN SumOfBytesHashed;
280 EFI_IMAGE_SECTION_HEADER *SectionHeader;
281 UINTN Index;
282 UINTN Pos;
283 UINT32 CertSize;
284 UINT32 NumberOfRvaAndSizes;
285
286 HashCtx = NULL;
287 SectionHeader = NULL;
288 Status = FALSE;
289
290 if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
291 return FALSE;
292 }
293
294 //
295 // Initialize context of hash.
296 //
297 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
298
299 if (HashAlg == HASHALG_SHA1) {
300 mImageDigestSize = SHA1_DIGEST_SIZE;
301 mCertType = gEfiCertSha1Guid;
302 } else if (HashAlg == HASHALG_SHA256) {
303 mImageDigestSize = SHA256_DIGEST_SIZE;
304 mCertType = gEfiCertSha256Guid;
305 } else {
306 return FALSE;
307 }
308
309 CtxSize = mHash[HashAlg].GetContextSize();
310
311 HashCtx = AllocatePool (CtxSize);
312 if (HashCtx == NULL) {
313 return FALSE;
314 }
315
316 // 1. Load the image header into memory.
317
318 // 2. Initialize a SHA hash context.
319 Status = mHash[HashAlg].HashInit(HashCtx);
320
321 if (!Status) {
322 goto Done;
323 }
324
325 //
326 // Measuring PE/COFF Image Header;
327 // But CheckSum field and SECURITY data directory (certificate) are excluded
328 //
329 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
330 //
331 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
332 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
333 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
334 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
335 //
336 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
337 } else {
338 //
339 // Get the magic value from the PE/COFF Optional Header
340 //
341 Magic = mNtHeader.Pe32->OptionalHeader.Magic;
342 }
343
344 //
345 // 3. Calculate the distance from the base of the image header to the image checksum address.
346 // 4. Hash the image header from its base to beginning of the image checksum.
347 //
348 HashBase = mImageBase;
349 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
350 //
351 // Use PE32 offset.
352 //
353 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
354 NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
355 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
356 //
357 // Use PE32+ offset.
358 //
359 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
360 NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
361 } else {
362 //
363 // Invalid header magic number.
364 //
365 Status = FALSE;
366 goto Done;
367 }
368
369 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
370 if (!Status) {
371 goto Done;
372 }
373
374 //
375 // 5. Skip over the image checksum (it occupies a single ULONG).
376 //
377 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
378 //
379 // 6. Since there is no Cert Directory in optional header, hash everything
380 // from the end of the checksum to the end of image header.
381 //
382 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
383 //
384 // Use PE32 offset.
385 //
386 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
387 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
388 } else {
389 //
390 // Use PE32+ offset.
391 //
392 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
393 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
394 }
395
396 if (HashSize != 0) {
397 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
398 if (!Status) {
399 goto Done;
400 }
401 }
402 } else {
403 //
404 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
405 //
406 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
407 //
408 // Use PE32 offset.
409 //
410 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
411 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
412 } else {
413 //
414 // Use PE32+ offset.
415 //
416 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
417 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
418 }
419
420 if (HashSize != 0) {
421 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
422 if (!Status) {
423 goto Done;
424 }
425 }
426
427 //
428 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
429 // 9. Hash everything from the end of the Cert Directory to the end of image header.
430 //
431 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
432 //
433 // Use PE32 offset
434 //
435 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
436 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
437 } else {
438 //
439 // Use PE32+ offset.
440 //
441 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
442 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
443 }
444
445 if (HashSize != 0) {
446 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
447 if (!Status) {
448 goto Done;
449 }
450 }
451 }
452
453 //
454 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
455 //
456 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
457 //
458 // Use PE32 offset.
459 //
460 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
461 } else {
462 //
463 // Use PE32+ offset
464 //
465 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
466 }
467
468
469 Section = (EFI_IMAGE_SECTION_HEADER *) (
470 mImageBase +
471 mPeCoffHeaderOffset +
472 sizeof (UINT32) +
473 sizeof (EFI_IMAGE_FILE_HEADER) +
474 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
475 );
476
477 //
478 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
479 // structures in the image. The 'NumberOfSections' field of the image
480 // header indicates how big the table should be. Do not include any
481 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
482 //
483 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
484 if (SectionHeader == NULL) {
485 Status = FALSE;
486 goto Done;
487 }
488 //
489 // 12. Using the 'PointerToRawData' in the referenced section headers as
490 // a key, arrange the elements in the table in ascending order. In other
491 // words, sort the section headers according to the disk-file offset of
492 // the section.
493 //
494 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
495 Pos = Index;
496 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
497 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
498 Pos--;
499 }
500 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
501 Section += 1;
502 }
503
504 //
505 // 13. Walk through the sorted table, bring the corresponding section
506 // into memory, and hash the entire section (using the 'SizeOfRawData'
507 // field in the section header to determine the amount of data to hash).
508 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
509 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
510 //
511 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
512 Section = &SectionHeader[Index];
513 if (Section->SizeOfRawData == 0) {
514 continue;
515 }
516 HashBase = mImageBase + Section->PointerToRawData;
517 HashSize = (UINTN) Section->SizeOfRawData;
518
519 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
520 if (!Status) {
521 goto Done;
522 }
523
524 SumOfBytesHashed += HashSize;
525 }
526
527 //
528 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
529 // data in the file that needs to be added to the hash. This data begins
530 // at file offset SUM_OF_BYTES_HASHED and its length is:
531 // FileSize - (CertDirectory->Size)
532 //
533 if (mImageSize > SumOfBytesHashed) {
534 HashBase = mImageBase + SumOfBytesHashed;
535
536 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
537 CertSize = 0;
538 } else {
539 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
540 //
541 // Use PE32 offset.
542 //
543 CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
544 } else {
545 //
546 // Use PE32+ offset.
547 //
548 CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
549 }
550 }
551
552 if (mImageSize > CertSize + SumOfBytesHashed) {
553 HashSize = (UINTN) (mImageSize - CertSize - SumOfBytesHashed);
554
555 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
556 if (!Status) {
557 goto Done;
558 }
559 } else if (mImageSize < CertSize + SumOfBytesHashed) {
560 Status = FALSE;
561 goto Done;
562 }
563 }
564
565 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);
566
567 Done:
568 if (HashCtx != NULL) {
569 FreePool (HashCtx);
570 }
571 if (SectionHeader != NULL) {
572 FreePool (SectionHeader);
573 }
574 return Status;
575 }
576
577 /**
578 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
579 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
580 8.0 Appendix A
581
582 Caution: This function may receive untrusted input.
583 PE/COFF image is external input, so this function will validate its data structure
584 within this image buffer before use.
585
586 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
587 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
588
589 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
590 @retval EFI_SUCCESS Hash successfully.
591
592 **/
593 EFI_STATUS
594 HashPeImageByType (
595 IN UINT8 *AuthData,
596 IN UINTN AuthDataSize
597 )
598 {
599 UINT8 Index;
600
601 for (Index = 0; Index < HASHALG_MAX; Index++) {
602 //
603 // Check the Hash algorithm in PE/COFF Authenticode.
604 // According to PKCS#7 Definition:
605 // SignedData ::= SEQUENCE {
606 // version Version,
607 // digestAlgorithms DigestAlgorithmIdentifiers,
608 // contentInfo ContentInfo,
609 // .... }
610 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
611 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
612 // Fixed offset (+32) is calculated based on two bytes of length encoding.
613 //
614 if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
615 //
616 // Only support two bytes of Long Form of Length Encoding.
617 //
618 continue;
619 }
620
621 if (AuthDataSize < 32 + mHash[Index].OidLength) {
622 return EFI_UNSUPPORTED;
623 }
624
625 if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
626 break;
627 }
628 }
629
630 if (Index == HASHALG_MAX) {
631 return EFI_UNSUPPORTED;
632 }
633
634 //
635 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
636 //
637 if (!HashPeImage(Index)) {
638 return EFI_UNSUPPORTED;
639 }
640
641 return EFI_SUCCESS;
642 }
643
644
645 /**
646 Returns the size of a given image execution info table in bytes.
647
648 This function returns the size, in bytes, of the image execution info table specified by
649 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
650
651 @param ImageExeInfoTable A pointer to a image execution info table structure.
652
653 @retval 0 If ImageExeInfoTable is NULL.
654 @retval Others The size of a image execution info table in bytes.
655
656 **/
657 UINTN
658 GetImageExeInfoTableSize (
659 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable
660 )
661 {
662 UINTN Index;
663 EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem;
664 UINTN TotalSize;
665
666 if (ImageExeInfoTable == NULL) {
667 return 0;
668 }
669
670 ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));
671 TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
672 for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {
673 TotalSize += ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize);
674 ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize));
675 }
676
677 return TotalSize;
678 }
679
680 /**
681 Create an Image Execution Information Table entry and add it to system configuration table.
682
683 @param[in] Action Describes the action taken by the firmware regarding this image.
684 @param[in] Name Input a null-terminated, user-friendly name.
685 @param[in] DevicePath Input device path pointer.
686 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
687 @param[in] SignatureSize Size of signature.
688
689 **/
690 VOID
691 AddImageExeInfo (
692 IN EFI_IMAGE_EXECUTION_ACTION Action,
693 IN CHAR16 *Name OPTIONAL,
694 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
695 IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
696 IN UINTN SignatureSize
697 )
698 {
699 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;
700 EFI_IMAGE_EXECUTION_INFO_TABLE *NewImageExeInfoTable;
701 EFI_IMAGE_EXECUTION_INFO *ImageExeInfoEntry;
702 UINTN ImageExeInfoTableSize;
703 UINTN NewImageExeInfoEntrySize;
704 UINTN NameStringLen;
705 UINTN DevicePathSize;
706
707 ImageExeInfoTable = NULL;
708 NewImageExeInfoTable = NULL;
709 ImageExeInfoEntry = NULL;
710 NameStringLen = 0;
711
712 if (DevicePath == NULL) {
713 return ;
714 }
715
716 if (Name != NULL) {
717 NameStringLen = StrSize (Name);
718 } else {
719 NameStringLen = sizeof (CHAR16);
720 }
721
722 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **) &ImageExeInfoTable);
723 if (ImageExeInfoTable != NULL) {
724 //
725 // The table has been found!
726 // We must enlarge the table to accomodate the new exe info entry.
727 //
728 ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);
729 } else {
730 //
731 // Not Found!
732 // We should create a new table to append to the configuration table.
733 //
734 ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
735 }
736
737 DevicePathSize = GetDevicePathSize (DevicePath);
738 NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;
739 NewImageExeInfoTable = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);
740 if (NewImageExeInfoTable == NULL) {
741 return ;
742 }
743
744 if (ImageExeInfoTable != NULL) {
745 CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);
746 } else {
747 NewImageExeInfoTable->NumberOfImages = 0;
748 }
749 NewImageExeInfoTable->NumberOfImages++;
750 ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) NewImageExeInfoTable + ImageExeInfoTableSize);
751 //
752 // Update new item's infomation.
753 //
754 WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->Action, Action);
755 WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->InfoSize, (UINT32) NewImageExeInfoEntrySize);
756
757 if (Name != NULL) {
758 CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);
759 } else {
760 ZeroMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), sizeof (CHAR16));
761 }
762 CopyMem (
763 (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,
764 DevicePath,
765 DevicePathSize
766 );
767 if (Signature != NULL) {
768 CopyMem (
769 (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,
770 Signature,
771 SignatureSize
772 );
773 }
774 //
775 // Update/replace the image execution table.
776 //
777 gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
778
779 //
780 // Free Old table data!
781 //
782 if (ImageExeInfoTable != NULL) {
783 FreePool (ImageExeInfoTable);
784 }
785 }
786
787 /**
788 Check whether signature is in specified database.
789
790 @param[in] VariableName Name of database variable that is searched in.
791 @param[in] Signature Pointer to signature that is searched for.
792 @param[in] CertType Pointer to hash algrithom.
793 @param[in] SignatureSize Size of Signature.
794
795 @return TRUE Found the signature in the variable database.
796 @return FALSE Not found the signature in the variable database.
797
798 **/
799 BOOLEAN
800 IsSignatureFoundInDatabase (
801 IN CHAR16 *VariableName,
802 IN UINT8 *Signature,
803 IN EFI_GUID *CertType,
804 IN UINTN SignatureSize
805 )
806 {
807 EFI_STATUS Status;
808 EFI_SIGNATURE_LIST *CertList;
809 EFI_SIGNATURE_DATA *Cert;
810 UINTN DataSize;
811 UINT8 *Data;
812 UINTN Index;
813 UINTN CertCount;
814 BOOLEAN IsFound;
815 //
816 // Read signature database variable.
817 //
818 IsFound = FALSE;
819 Data = NULL;
820 DataSize = 0;
821 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
822 if (Status != EFI_BUFFER_TOO_SMALL) {
823 return FALSE;
824 }
825
826 Data = (UINT8 *) AllocateZeroPool (DataSize);
827 if (Data == NULL) {
828 return FALSE;
829 }
830
831 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
832 if (EFI_ERROR (Status)) {
833 goto Done;
834 }
835 //
836 // Enumerate all signature data in SigDB to check if executable's signature exists.
837 //
838 CertList = (EFI_SIGNATURE_LIST *) Data;
839 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
840 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
841 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
842 if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, CertType))) {
843 for (Index = 0; Index < CertCount; Index++) {
844 if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
845 //
846 // Find the signature in database.
847 //
848 IsFound = TRUE;
849 break;
850 }
851
852 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
853 }
854
855 if (IsFound) {
856 break;
857 }
858 }
859
860 DataSize -= CertList->SignatureListSize;
861 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
862 }
863
864 Done:
865 if (Data != NULL) {
866 FreePool (Data);
867 }
868
869 return IsFound;
870 }
871
872 /**
873 Verify PKCS#7 SignedData using certificate found in Variable which formatted
874 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
875
876 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
877 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
878 @param[in] VariableName Name of Variable to search for Certificate.
879 @param[in] VendorGuid Variable vendor GUID.
880
881 @retval TRUE Image pass verification.
882 @retval FALSE Image fail verification.
883
884 **/
885 BOOLEAN
886 IsPkcsSignedDataVerifiedBySignatureList (
887 IN UINT8 *AuthData,
888 IN UINTN AuthDataSize,
889 IN CHAR16 *VariableName,
890 IN EFI_GUID *VendorGuid
891 )
892 {
893 EFI_STATUS Status;
894 BOOLEAN VerifyStatus;
895 EFI_SIGNATURE_LIST *CertList;
896 EFI_SIGNATURE_DATA *Cert;
897 UINTN DataSize;
898 UINT8 *Data;
899 UINT8 *RootCert;
900 UINTN RootCertSize;
901 UINTN Index;
902 UINTN CertCount;
903
904 Data = NULL;
905 CertList = NULL;
906 Cert = NULL;
907 RootCert = NULL;
908 RootCertSize = 0;
909 VerifyStatus = FALSE;
910
911 DataSize = 0;
912 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
913 if (Status == EFI_BUFFER_TOO_SMALL) {
914 Data = (UINT8 *) AllocateZeroPool (DataSize);
915 if (Data == NULL) {
916 return VerifyStatus;
917 }
918
919 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);
920 if (EFI_ERROR (Status)) {
921 goto Done;
922 }
923
924 //
925 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
926 //
927 CertList = (EFI_SIGNATURE_LIST *) Data;
928 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
929 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
930 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
931 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
932 for (Index = 0; Index < CertCount; Index++) {
933 //
934 // Iterate each Signature Data Node within this CertList for verify.
935 //
936 RootCert = Cert->SignatureData;
937 RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
938
939 //
940 // Call AuthenticodeVerify library to Verify Authenticode struct.
941 //
942 VerifyStatus = AuthenticodeVerify (
943 AuthData,
944 AuthDataSize,
945 RootCert,
946 RootCertSize,
947 mImageDigest,
948 mImageDigestSize
949 );
950 if (VerifyStatus) {
951 goto Done;
952 }
953 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
954 }
955 }
956 DataSize -= CertList->SignatureListSize;
957 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
958 }
959 }
960
961 Done:
962 if (Data != NULL) {
963 FreePool (Data);
964 }
965
966 return VerifyStatus;
967 }
968
969 /**
970 Provide verification service for signed images, which include both signature validation
971 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
972 MSFT Authenticode type signatures are supported.
973
974 In this implementation, only verify external executables when in USER MODE.
975 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
976
977 The image verification policy is:
978 If the image is signed,
979 At least one valid signature or at least one hash value of the image must match a record
980 in the security database "db", and no valid signature nor any hash value of the image may
981 be reflected in the security database "dbx".
982 Otherwise, the image is not signed,
983 The SHA256 hash value of the image must match a record in the security database "db", and
984 not be reflected in the security data base "dbx".
985
986 Caution: This function may receive untrusted input.
987 PE/COFF image is external input, so this function will validate its data structure
988 within this image buffer before use.
989
990 @param[in] AuthenticationStatus
991 This is the authentication status returned from the security
992 measurement services for the input file.
993 @param[in] File This is a pointer to the device path of the file that is
994 being dispatched. This will optionally be used for logging.
995 @param[in] FileBuffer File buffer matches the input file device path.
996 @param[in] FileSize Size of File buffer matches the input file device path.
997 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
998
999 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
1000 FileBuffer did authenticate, and the platform policy dictates
1001 that the DXE Foundation may use the file.
1002 @retval EFI_SUCCESS The device path specified by NULL device path DevicePath
1003 and non-NULL FileBuffer did authenticate, and the platform
1004 policy dictates that the DXE Foundation may execute the image in
1005 FileBuffer.
1006 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1007 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1008 the platform policy dictates that File should be placed
1009 in the untrusted state. The image has been added to the file
1010 execution table.
1011 @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not
1012 authenticate, and the platform policy dictates that the DXE
1013 Foundation many not use File.
1014
1015 **/
1016 EFI_STATUS
1017 EFIAPI
1018 DxeImageVerificationHandler (
1019 IN UINT32 AuthenticationStatus,
1020 IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
1021 IN VOID *FileBuffer,
1022 IN UINTN FileSize,
1023 IN BOOLEAN BootPolicy
1024 )
1025 {
1026 EFI_STATUS Status;
1027 UINT16 Magic;
1028 EFI_IMAGE_DOS_HEADER *DosHdr;
1029 EFI_STATUS VerifyStatus;
1030 EFI_SIGNATURE_LIST *SignatureList;
1031 UINTN SignatureListSize;
1032 EFI_SIGNATURE_DATA *Signature;
1033 EFI_IMAGE_EXECUTION_ACTION Action;
1034 WIN_CERTIFICATE *WinCertificate;
1035 UINT32 Policy;
1036 UINT8 *SecureBoot;
1037 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1038 UINT32 NumberOfRvaAndSizes;
1039 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
1040 WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
1041 UINT8 *AuthData;
1042 UINTN AuthDataSize;
1043 EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
1044 UINT32 OffSet;
1045
1046 SignatureList = NULL;
1047 SignatureListSize = 0;
1048 WinCertificate = NULL;
1049 SecDataDir = NULL;
1050 PkcsCertData = NULL;
1051 Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
1052 Status = EFI_ACCESS_DENIED;
1053 VerifyStatus = EFI_ACCESS_DENIED;
1054
1055 //
1056 // Check the image type and get policy setting.
1057 //
1058 switch (GetImageType (File)) {
1059
1060 case IMAGE_FROM_FV:
1061 Policy = ALWAYS_EXECUTE;
1062 break;
1063
1064 case IMAGE_FROM_OPTION_ROM:
1065 Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);
1066 break;
1067
1068 case IMAGE_FROM_REMOVABLE_MEDIA:
1069 Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);
1070 break;
1071
1072 case IMAGE_FROM_FIXED_MEDIA:
1073 Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);
1074 break;
1075
1076 default:
1077 Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
1078 break;
1079 }
1080 //
1081 // If policy is always/never execute, return directly.
1082 //
1083 if (Policy == ALWAYS_EXECUTE) {
1084 return EFI_SUCCESS;
1085 } else if (Policy == NEVER_EXECUTE) {
1086 return EFI_ACCESS_DENIED;
1087 }
1088
1089 //
1090 // The policy QUERY_USER_ON_SECURITY_VIOLATION violates the UEFI spec and has been removed.
1091 //
1092 ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION);
1093 if (Policy == QUERY_USER_ON_SECURITY_VIOLATION) {
1094 CpuDeadLoop ();
1095 }
1096
1097 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);
1098 //
1099 // Skip verification if SecureBoot variable doesn't exist.
1100 //
1101 if (SecureBoot == NULL) {
1102 return EFI_SUCCESS;
1103 }
1104
1105 //
1106 // Skip verification if SecureBoot is disabled.
1107 //
1108 if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {
1109 FreePool (SecureBoot);
1110 return EFI_SUCCESS;
1111 }
1112 FreePool (SecureBoot);
1113
1114 //
1115 // Read the Dos header.
1116 //
1117 if (FileBuffer == NULL) {
1118 return EFI_INVALID_PARAMETER;
1119 }
1120
1121 mImageBase = (UINT8 *) FileBuffer;
1122 mImageSize = FileSize;
1123
1124 ZeroMem (&ImageContext, sizeof (ImageContext));
1125 ImageContext.Handle = (VOID *) FileBuffer;
1126 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;
1127
1128 //
1129 // Get information about the image being loaded
1130 //
1131 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1132 if (EFI_ERROR (Status)) {
1133 //
1134 // The information can't be got from the invalid PeImage
1135 //
1136 goto Done;
1137 }
1138
1139 Status = EFI_ACCESS_DENIED;
1140
1141 DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
1142 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1143 //
1144 // DOS image header is present,
1145 // so read the PE header after the DOS image header.
1146 //
1147 mPeCoffHeaderOffset = DosHdr->e_lfanew;
1148 } else {
1149 mPeCoffHeaderOffset = 0;
1150 }
1151 //
1152 // Check PE/COFF image.
1153 //
1154 mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);
1155 if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1156 //
1157 // It is not a valid Pe/Coff file.
1158 //
1159 goto Done;
1160 }
1161
1162 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1163 //
1164 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1165 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1166 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1167 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1168 //
1169 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1170 } else {
1171 //
1172 // Get the magic value from the PE/COFF Optional Header
1173 //
1174 Magic = mNtHeader.Pe32->OptionalHeader.Magic;
1175 }
1176
1177 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1178 //
1179 // Use PE32 offset.
1180 //
1181 NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1182 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1183 SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1184 }
1185 } else {
1186 //
1187 // Use PE32+ offset.
1188 //
1189 NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1190 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1191 SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1192 }
1193 }
1194
1195 //
1196 // Start Image Validation.
1197 //
1198 if (SecDataDir == NULL || SecDataDir->Size == 0) {
1199 //
1200 // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",
1201 // and not be reflected in the security data base "dbx".
1202 //
1203 if (!HashPeImage (HASHALG_SHA256)) {
1204 goto Done;
1205 }
1206
1207 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
1208 //
1209 // Image Hash is in forbidden database (DBX).
1210 //
1211 goto Done;
1212 }
1213
1214 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
1215 //
1216 // Image Hash is in allowed database (DB).
1217 //
1218 return EFI_SUCCESS;
1219 }
1220
1221 //
1222 // Image Hash is not found in both forbidden and allowed database.
1223 //
1224 goto Done;
1225 }
1226
1227 //
1228 // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
1229 // "Attribute Certificate Table".
1230 // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
1231 //
1232 for (OffSet = SecDataDir->VirtualAddress;
1233 OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
1234 OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {
1235 WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
1236 if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
1237 (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
1238 break;
1239 }
1240
1241 //
1242 // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
1243 //
1244 if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
1245 //
1246 // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
1247 // Authenticode specification.
1248 //
1249 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
1250 if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
1251 break;
1252 }
1253 AuthData = PkcsCertData->CertData;
1254 AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
1255 } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
1256 //
1257 // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
1258 //
1259 WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
1260 if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
1261 break;
1262 }
1263 if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
1264 continue;
1265 }
1266 AuthData = WinCertUefiGuid->CertData;
1267 AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
1268 } else {
1269 if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
1270 break;
1271 }
1272 continue;
1273 }
1274
1275 Status = HashPeImageByType (AuthData, AuthDataSize);
1276 if (EFI_ERROR (Status)) {
1277 continue;
1278 }
1279
1280 //
1281 // Check the digital signature against the revoked certificate in forbidden database (dbx).
1282 //
1283 if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
1284 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
1285 VerifyStatus = EFI_ACCESS_DENIED;
1286 break;
1287 }
1288
1289 //
1290 // Check the digital signature against the valid certificate in allowed database (db).
1291 //
1292 if (EFI_ERROR (VerifyStatus)) {
1293 if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
1294 VerifyStatus = EFI_SUCCESS;
1295 }
1296 }
1297
1298 //
1299 // Check the image's hash value.
1300 //
1301 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
1302 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
1303 VerifyStatus = EFI_ACCESS_DENIED;
1304 break;
1305 } else if (EFI_ERROR (VerifyStatus)) {
1306 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
1307 VerifyStatus = EFI_SUCCESS;
1308 }
1309 }
1310 }
1311
1312 if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
1313 //
1314 // The Size in Certificate Table or the attribute certicate table is corrupted.
1315 //
1316 VerifyStatus = EFI_ACCESS_DENIED;
1317 }
1318
1319 if (!EFI_ERROR (VerifyStatus)) {
1320 return EFI_SUCCESS;
1321 } else {
1322 Status = EFI_ACCESS_DENIED;
1323 if (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED || Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
1324 //
1325 // Get image hash value as executable's signature.
1326 //
1327 SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
1328 SignatureList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);
1329 if (SignatureList == NULL) {
1330 Status = EFI_OUT_OF_RESOURCES;
1331 goto Done;
1332 }
1333 SignatureList->SignatureHeaderSize = 0;
1334 SignatureList->SignatureListSize = (UINT32) SignatureListSize;
1335 SignatureList->SignatureSize = (UINT32) mImageDigestSize;
1336 CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));
1337 Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
1338 CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
1339 }
1340 }
1341
1342 Done:
1343 if (Status != EFI_SUCCESS) {
1344 //
1345 // Policy decides to defer or reject the image; add its information in image executable information table.
1346 //
1347 AddImageExeInfo (Action, NULL, File, SignatureList, SignatureListSize);
1348 Status = EFI_SECURITY_VIOLATION;
1349 }
1350
1351 if (SignatureList != NULL) {
1352 FreePool (SignatureList);
1353 }
1354
1355 return Status;
1356 }
1357
1358 /**
1359 Register security measurement handler.
1360
1361 @param ImageHandle ImageHandle of the loaded driver.
1362 @param SystemTable Pointer to the EFI System Table.
1363
1364 @retval EFI_SUCCESS The handlers were registered successfully.
1365 **/
1366 EFI_STATUS
1367 EFIAPI
1368 DxeImageVerificationLibConstructor (
1369 IN EFI_HANDLE ImageHandle,
1370 IN EFI_SYSTEM_TABLE *SystemTable
1371 )
1372 {
1373 return RegisterSecurity2Handler (
1374 DxeImageVerificationHandler,
1375 EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
1376 );
1377 }