TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeImageVerificationLib.c
Go to the documentation of this file.
1
22
23//
24// Caution: This is used by a function which may receive untrusted input.
25// These global variables hold PE/COFF image data, and they should be validated before use.
26//
28UINT32 mPeCoffHeaderOffset;
29EFI_GUID mCertType;
30
31//
32// Information on current PE/COFF image
33//
34UINTN mImageSize;
35UINT8 *mImageBase = NULL;
36UINT8 mImageDigest[MAX_DIGEST_SIZE];
37UINTN mImageDigestSize;
38
39//
40// Notify string for authorization UI.
41//
42CHAR16 mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"Image verification pass but not found in authorized database!";
43CHAR16 mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"Launch this image anyway? (Yes/Defer/No)";
44//
45// Public Exponent of RSA Key.
46//
47CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
48
49//
50// OID ASN.1 Value for Hash Algorithms
51//
52UINT8 mHashOidValue[] = {
53 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
54 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
55 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
56 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
58};
59
60HASH_TABLE mHash[] = {
61 #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
62 { L"SHA1", 20, &mHashOidValue[0], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
63 #else
64 { L"SHA1", 20, &mHashOidValue[0], 5, NULL, NULL, NULL, NULL },
65 #endif
66 { L"SHA224", 28, &mHashOidValue[5], 9, NULL, NULL, NULL, NULL },
67 { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
68 { L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
69 { L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final }
70};
71
72EFI_STRING mHashTypeStr;
73
84VOID
85EFIAPI
87 IN CHAR16 *VariableName,
88 IN EFI_GUID *VendorGuid,
89 IN UINTN DataSize,
90 IN VOID *Data
91 );
92
109EFIAPI
111 IN VOID *FileHandle,
112 IN UINTN FileOffset,
113 IN OUT UINTN *ReadSize,
114 OUT VOID *Buffer
115 )
116{
117 UINTN EndPosition;
118
119 if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
120 return EFI_INVALID_PARAMETER;
121 }
122
123 if (MAX_ADDRESS - FileOffset < *ReadSize) {
124 return EFI_INVALID_PARAMETER;
125 }
126
127 EndPosition = FileOffset + *ReadSize;
128 if (EndPosition > mImageSize) {
129 *ReadSize = (UINT32)(mImageSize - FileOffset);
130 }
131
132 if (FileOffset >= mImageSize) {
133 *ReadSize = 0;
134 }
135
136 CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
137
138 return EFI_SUCCESS;
139}
140
150UINT32
153 )
154{
155 EFI_STATUS Status;
156 EFI_HANDLE DeviceHandle;
157 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
158 EFI_BLOCK_IO_PROTOCOL *BlockIo;
159
160 if (File == NULL) {
161 return IMAGE_UNKNOWN;
162 }
163
164 //
165 // First check to see if File is from a Firmware Volume
166 //
167 DeviceHandle = NULL;
168 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
169 Status = gBS->LocateDevicePath (
170 &gEfiFirmwareVolume2ProtocolGuid,
171 &TempDevicePath,
172 &DeviceHandle
173 );
174 if (!EFI_ERROR (Status)) {
175 Status = gBS->OpenProtocol (
176 DeviceHandle,
177 &gEfiFirmwareVolume2ProtocolGuid,
178 NULL,
179 NULL,
180 NULL,
181 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
182 );
183 if (!EFI_ERROR (Status)) {
184 return IMAGE_FROM_FV;
185 }
186 }
187
188 //
189 // Next check to see if File is from a Block I/O device
190 //
191 DeviceHandle = NULL;
192 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
193 Status = gBS->LocateDevicePath (
194 &gEfiBlockIoProtocolGuid,
195 &TempDevicePath,
196 &DeviceHandle
197 );
198 if (!EFI_ERROR (Status)) {
199 BlockIo = NULL;
200 Status = gBS->OpenProtocol (
201 DeviceHandle,
202 &gEfiBlockIoProtocolGuid,
203 (VOID **)&BlockIo,
204 NULL,
205 NULL,
206 EFI_OPEN_PROTOCOL_GET_PROTOCOL
207 );
208 if (!EFI_ERROR (Status) && (BlockIo != NULL)) {
209 if (BlockIo->Media != NULL) {
210 if (BlockIo->Media->RemovableMedia) {
211 //
212 // Block I/O is present and specifies the media is removable
213 //
214 return IMAGE_FROM_REMOVABLE_MEDIA;
215 } else {
216 //
217 // Block I/O is present and specifies the media is not removable
218 //
219 return IMAGE_FROM_FIXED_MEDIA;
220 }
221 }
222 }
223 }
224
225 //
226 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
227 // the device path supports the Simple File System Protocol.
228 //
229 DeviceHandle = NULL;
230 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
231 Status = gBS->LocateDevicePath (
232 &gEfiSimpleFileSystemProtocolGuid,
233 &TempDevicePath,
234 &DeviceHandle
235 );
236 if (!EFI_ERROR (Status)) {
237 //
238 // Simple File System is present without Block I/O, so assume media is fixed.
239 //
240 return IMAGE_FROM_FIXED_MEDIA;
241 }
242
243 //
244 // File is not from an FV, Block I/O or Simple File System, so the only options
245 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
246 //
247 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
248 while (!IsDevicePathEndType (TempDevicePath)) {
249 switch (DevicePathType (TempDevicePath)) {
250 case MEDIA_DEVICE_PATH:
251 if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
252 return IMAGE_FROM_OPTION_ROM;
253 }
254
255 break;
256
258 if (DevicePathSubType (TempDevicePath) == MSG_MAC_ADDR_DP) {
259 return IMAGE_FROM_REMOVABLE_MEDIA;
260 }
261
262 break;
263
264 default:
265 break;
266 }
267
268 TempDevicePath = NextDevicePathNode (TempDevicePath);
269 }
270
271 return IMAGE_UNKNOWN;
272}
273
291BOOLEAN
293 IN UINT32 HashAlg
294 )
295{
296 BOOLEAN Status;
298 VOID *HashCtx;
299 UINTN CtxSize;
300 UINT8 *HashBase;
301 UINTN HashSize;
302 UINTN SumOfBytesHashed;
303 EFI_IMAGE_SECTION_HEADER *SectionHeader;
304 UINTN Index;
305 UINTN Pos;
306 UINT32 CertSize;
307 UINT32 NumberOfRvaAndSizes;
308
309 HashCtx = NULL;
310 SectionHeader = NULL;
311 Status = FALSE;
312
313 if ((HashAlg >= HASHALG_MAX)) {
314 return FALSE;
315 }
316
317 //
318 // Initialize context of hash.
319 //
320 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
321
322 switch (HashAlg) {
323 #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
324 case HASHALG_SHA1:
325 mImageDigestSize = SHA1_DIGEST_SIZE;
326 mCertType = gEfiCertSha1Guid;
327 break;
328 #endif
329
330 case HASHALG_SHA256:
331 mImageDigestSize = SHA256_DIGEST_SIZE;
332 mCertType = gEfiCertSha256Guid;
333 break;
334
335 case HASHALG_SHA384:
336 mImageDigestSize = SHA384_DIGEST_SIZE;
337 mCertType = gEfiCertSha384Guid;
338 break;
339
340 case HASHALG_SHA512:
341 mImageDigestSize = SHA512_DIGEST_SIZE;
342 mCertType = gEfiCertSha512Guid;
343 break;
344
345 default:
346 return FALSE;
347 }
348
349 mHashTypeStr = mHash[HashAlg].Name;
350 CtxSize = mHash[HashAlg].GetContextSize ();
351
352 HashCtx = AllocatePool (CtxSize);
353 if (HashCtx == NULL) {
354 return FALSE;
355 }
356
357 // 1. Load the image header into memory.
358
359 // 2. Initialize a SHA hash context.
360 Status = mHash[HashAlg].HashInit (HashCtx);
361
362 if (!Status) {
363 goto Done;
364 }
365
366 //
367 // Measuring PE/COFF Image Header;
368 // But CheckSum field and SECURITY data directory (certificate) are excluded
369 //
370
371 //
372 // 3. Calculate the distance from the base of the image header to the image checksum address.
373 // 4. Hash the image header from its base to beginning of the image checksum.
374 //
375 HashBase = mImageBase;
376 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
377 //
378 // Use PE32 offset.
379 //
380 HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
381 NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
382 } else if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
383 //
384 // Use PE32+ offset.
385 //
386 HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
387 NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
388 } else {
389 //
390 // Invalid header magic number.
391 //
392 Status = FALSE;
393 goto Done;
394 }
395
396 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
397 if (!Status) {
398 goto Done;
399 }
400
401 //
402 // 5. Skip over the image checksum (it occupies a single ULONG).
403 //
404 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
405 //
406 // 6. Since there is no Cert Directory in optional header, hash everything
407 // from the end of the checksum to the end of image header.
408 //
409 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
410 //
411 // Use PE32 offset.
412 //
413 HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
414 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
415 } else {
416 //
417 // Use PE32+ offset.
418 //
419 HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
420 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
421 }
422
423 if (HashSize != 0) {
424 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
425 if (!Status) {
426 goto Done;
427 }
428 }
429 } else {
430 //
431 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
432 //
433 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
434 //
435 // Use PE32 offset.
436 //
437 HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
438 HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
439 } else {
440 //
441 // Use PE32+ offset.
442 //
443 HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
444 HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
445 }
446
447 if (HashSize != 0) {
448 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
449 if (!Status) {
450 goto Done;
451 }
452 }
453
454 //
455 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
456 // 9. Hash everything from the end of the Cert Directory to the end of image header.
457 //
458 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
459 //
460 // Use PE32 offset
461 //
462 HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
463 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
464 } else {
465 //
466 // Use PE32+ offset.
467 //
468 HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
469 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
470 }
471
472 if (HashSize != 0) {
473 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
474 if (!Status) {
475 goto Done;
476 }
477 }
478 }
479
480 //
481 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
482 //
483 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
484 //
485 // Use PE32 offset.
486 //
487 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
488 } else {
489 //
490 // Use PE32+ offset
491 //
492 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
493 }
494
495 Section = (EFI_IMAGE_SECTION_HEADER *)(
496 mImageBase +
497 mPeCoffHeaderOffset +
498 sizeof (UINT32) +
499 sizeof (EFI_IMAGE_FILE_HEADER) +
500 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
501 );
502
503 //
504 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
505 // structures in the image. The 'NumberOfSections' field of the image
506 // header indicates how big the table should be. Do not include any
507 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
508 //
509 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
510 if (SectionHeader == NULL) {
511 Status = FALSE;
512 goto Done;
513 }
514
515 //
516 // 12. Using the 'PointerToRawData' in the referenced section headers as
517 // a key, arrange the elements in the table in ascending order. In other
518 // words, sort the section headers according to the disk-file offset of
519 // the section.
520 //
521 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
522 Pos = Index;
523 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
524 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
525 Pos--;
526 }
527
528 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
529 Section += 1;
530 }
531
532 //
533 // 13. Walk through the sorted table, bring the corresponding section
534 // into memory, and hash the entire section (using the 'SizeOfRawData'
535 // field in the section header to determine the amount of data to hash).
536 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
537 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
538 //
539 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
540 Section = &SectionHeader[Index];
541 if (Section->SizeOfRawData == 0) {
542 continue;
543 }
544
545 HashBase = mImageBase + Section->PointerToRawData;
546 HashSize = (UINTN)Section->SizeOfRawData;
547
548 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
549 if (!Status) {
550 goto Done;
551 }
552
553 SumOfBytesHashed += HashSize;
554 }
555
556 //
557 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
558 // data in the file that needs to be added to the hash. This data begins
559 // at file offset SUM_OF_BYTES_HASHED and its length is:
560 // FileSize - (CertDirectory->Size)
561 //
562 if (mImageSize > SumOfBytesHashed) {
563 HashBase = mImageBase + SumOfBytesHashed;
564
565 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
566 CertSize = 0;
567 } else {
568 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
569 //
570 // Use PE32 offset.
571 //
572 CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
573 } else {
574 //
575 // Use PE32+ offset.
576 //
577 CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
578 }
579 }
580
581 if (mImageSize > CertSize + SumOfBytesHashed) {
582 HashSize = (UINTN)(mImageSize - CertSize - SumOfBytesHashed);
583
584 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
585 if (!Status) {
586 goto Done;
587 }
588 } else if (mImageSize < CertSize + SumOfBytesHashed) {
589 Status = FALSE;
590 goto Done;
591 }
592 }
593
594 Status = mHash[HashAlg].HashFinal (HashCtx, mImageDigest);
595
596Done:
597 if (HashCtx != NULL) {
598 FreePool (HashCtx);
599 }
600
601 if (SectionHeader != NULL) {
602 FreePool (SectionHeader);
603 }
604
605 return Status;
606}
607
626 IN UINT8 *AuthData,
627 IN UINTN AuthDataSize
628 )
629{
630 UINT8 Index;
631
632 for (Index = 0; Index < HASHALG_MAX; Index++) {
633 //
634 // Check the Hash algorithm in PE/COFF Authenticode.
635 // According to PKCS#7 Definition:
636 // SignedData ::= SEQUENCE {
637 // version Version,
638 // digestAlgorithms DigestAlgorithmIdentifiers,
639 // contentInfo ContentInfo,
640 // .... }
641 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
642 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
643 // Fixed offset (+32) is calculated based on two bytes of length encoding.
644 //
645 if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
646 //
647 // Only support two bytes of Long Form of Length Encoding.
648 //
649 continue;
650 }
651
652 if (AuthDataSize < 32 + mHash[Index].OidLength) {
653 return EFI_UNSUPPORTED;
654 }
655
656 if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
657 break;
658 }
659 }
660
661 if (Index == HASHALG_MAX) {
662 return EFI_UNSUPPORTED;
663 }
664
665 //
666 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
667 //
668 if (!HashPeImage (Index)) {
669 return EFI_UNSUPPORTED;
670 }
671
672 return EFI_SUCCESS;
673}
674
687UINTN
689 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable
690 )
691{
692 UINTN Index;
693 EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem;
694 UINTN TotalSize;
695
696 if (ImageExeInfoTable == NULL) {
697 return 0;
698 }
699
700 ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));
701 TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
702 for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {
703 TotalSize += ReadUnaligned32 ((UINT32 *)&ImageExeInfoItem->InfoSize);
704 ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)ImageExeInfoItem + ReadUnaligned32 ((UINT32 *)&ImageExeInfoItem->InfoSize));
705 }
706
707 return TotalSize;
708}
709
720VOID
722 IN EFI_IMAGE_EXECUTION_ACTION Action,
723 IN CHAR16 *Name OPTIONAL,
725 IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
726 IN UINTN SignatureSize
727 )
728{
729 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;
730 EFI_IMAGE_EXECUTION_INFO_TABLE *NewImageExeInfoTable;
731 EFI_IMAGE_EXECUTION_INFO *ImageExeInfoEntry;
732 UINTN ImageExeInfoTableSize;
733 UINTN NewImageExeInfoEntrySize;
734 UINTN NameStringLen;
735 UINTN DevicePathSize;
736 CHAR16 *NameStr;
737
738 ImageExeInfoTable = NULL;
739 NewImageExeInfoTable = NULL;
740 ImageExeInfoEntry = NULL;
741 NameStringLen = 0;
742 NameStr = NULL;
743
744 if (DevicePath == NULL) {
745 return;
746 }
747
748 if (Name != NULL) {
749 NameStringLen = StrSize (Name);
750 } else {
751 NameStringLen = sizeof (CHAR16);
752 }
753
754 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **)&ImageExeInfoTable);
755 if (ImageExeInfoTable != NULL) {
756 //
757 // The table has been found!
758 // We must enlarge the table to accommodate the new exe info entry.
759 //
760 ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);
761 } else {
762 //
763 // Not Found!
764 // We should create a new table to append to the configuration table.
765 //
766 ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
767 }
768
769 DevicePathSize = GetDevicePathSize (DevicePath);
770
771 //
772 // Signature size can be odd. Pad after signature to ensure next EXECUTION_INFO entry align
773 //
774 ASSERT (Signature != NULL || SignatureSize == 0);
775 NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;
776
777 NewImageExeInfoTable = (EFI_IMAGE_EXECUTION_INFO_TABLE *)AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);
778 if (NewImageExeInfoTable == NULL) {
779 return;
780 }
781
782 if (ImageExeInfoTable != NULL) {
783 CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);
784 } else {
785 NewImageExeInfoTable->NumberOfImages = 0;
786 }
787
788 NewImageExeInfoTable->NumberOfImages++;
789 ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)NewImageExeInfoTable + ImageExeInfoTableSize);
790 //
791 // Update new item's information.
792 //
793 WriteUnaligned32 ((UINT32 *)ImageExeInfoEntry, Action);
794 WriteUnaligned32 ((UINT32 *)((UINT8 *)ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32)NewImageExeInfoEntrySize);
795
796 NameStr = (CHAR16 *)(ImageExeInfoEntry + 1);
797 if (Name != NULL) {
798 CopyMem ((UINT8 *)NameStr, Name, NameStringLen);
799 } else {
800 ZeroMem ((UINT8 *)NameStr, sizeof (CHAR16));
801 }
802
803 CopyMem (
804 (UINT8 *)NameStr + NameStringLen,
805 DevicePath,
806 DevicePathSize
807 );
808 if (Signature != NULL) {
809 CopyMem (
810 (UINT8 *)NameStr + NameStringLen + DevicePathSize,
811 Signature,
812 SignatureSize
813 );
814 }
815
816 //
817 // Update/replace the image execution table.
818 //
819 gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *)NewImageExeInfoTable);
820
821 //
822 // Free Old table data!
823 //
824 if (ImageExeInfoTable != NULL) {
825 FreePool (ImageExeInfoTable);
826 }
827}
828
845 IN UINT8 *Certificate,
846 IN UINTN CertSize,
847 IN EFI_SIGNATURE_LIST *SignatureList,
848 IN UINTN SignatureListSize,
849 OUT EFI_TIME *RevocationTime,
850 OUT BOOLEAN *IsFound
851 )
852{
853 EFI_STATUS Status;
854 EFI_SIGNATURE_LIST *DbxList;
855 UINTN DbxSize;
856 EFI_SIGNATURE_DATA *CertHash;
857 UINTN CertHashCount;
858 UINTN Index;
859 UINT32 HashAlg;
860 VOID *HashCtx;
861 UINT8 CertDigest[MAX_DIGEST_SIZE];
862 UINT8 *DbxCertHash;
863 UINTN SiglistHeaderSize;
864 UINT8 *TBSCert;
865 UINTN TBSCertSize;
866
867 Status = EFI_ABORTED;
868 *IsFound = FALSE;
869 DbxList = SignatureList;
870 DbxSize = SignatureListSize;
871 HashCtx = NULL;
872 HashAlg = HASHALG_MAX;
873
874 if ((RevocationTime == NULL) || (DbxList == NULL)) {
875 return EFI_INVALID_PARAMETER;
876 }
877
878 //
879 // Retrieve the TBSCertificate from the X.509 Certificate.
880 //
881 if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {
882 return Status;
883 }
884
885 while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {
886 //
887 // Determine Hash Algorithm of Certificate in the forbidden database.
888 //
889 if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
890 HashAlg = HASHALG_SHA256;
891 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
892 HashAlg = HASHALG_SHA384;
893 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
894 HashAlg = HASHALG_SHA512;
895 } else {
896 DbxSize -= DbxList->SignatureListSize;
897 DbxList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxList + DbxList->SignatureListSize);
898 continue;
899 }
900
901 //
902 // Calculate the hash value of current TBSCertificate for comparision.
903 //
904 if (mHash[HashAlg].GetContextSize == NULL) {
905 goto Done;
906 }
907
908 ZeroMem (CertDigest, MAX_DIGEST_SIZE);
909 HashCtx = AllocatePool (mHash[HashAlg].GetContextSize ());
910 if (HashCtx == NULL) {
911 goto Done;
912 }
913
914 if (!mHash[HashAlg].HashInit (HashCtx)) {
915 goto Done;
916 }
917
918 if (!mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize)) {
919 goto Done;
920 }
921
922 if (!mHash[HashAlg].HashFinal (HashCtx, CertDigest)) {
923 goto Done;
924 }
925
926 FreePool (HashCtx);
927 HashCtx = NULL;
928
929 SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
930 CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)DbxList + SiglistHeaderSize);
931 CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
932 for (Index = 0; Index < CertHashCount; Index++) {
933 //
934 // Iterate each Signature Data Node within this CertList for verify.
935 //
936 DbxCertHash = CertHash->SignatureData;
937 if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
938 //
939 // Hash of Certificate is found in forbidden database.
940 //
941 Status = EFI_SUCCESS;
942 *IsFound = TRUE;
943
944 //
945 // Return the revocation time.
946 //
947 CopyMem (RevocationTime, (EFI_TIME *)(DbxCertHash + mHash[HashAlg].DigestLength), sizeof (EFI_TIME));
948 goto Done;
949 }
950
951 CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)CertHash + DbxList->SignatureSize);
952 }
953
954 DbxSize -= DbxList->SignatureListSize;
955 DbxList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxList + DbxList->SignatureListSize);
956 }
957
958 Status = EFI_SUCCESS;
959
960Done:
961 if (HashCtx != NULL) {
962 FreePool (HashCtx);
963 }
964
965 return Status;
966}
967
983 IN CHAR16 *VariableName,
984 IN UINT8 *Signature,
985 IN EFI_GUID *CertType,
986 IN UINTN SignatureSize,
987 OUT BOOLEAN *IsFound
988 )
989{
990 EFI_STATUS Status;
991 EFI_SIGNATURE_LIST *CertList;
992 EFI_SIGNATURE_DATA *Cert;
993 UINTN DataSize;
994 UINT8 *Data;
995 UINTN Index;
996 UINTN CertCount;
997
998 //
999 // Read signature database variable.
1000 //
1001 *IsFound = FALSE;
1002 Data = NULL;
1003 DataSize = 0;
1004 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1005 if (Status != EFI_BUFFER_TOO_SMALL) {
1006 if (Status == EFI_NOT_FOUND) {
1007 //
1008 // No database, no need to search.
1009 //
1010 Status = EFI_SUCCESS;
1011 }
1012
1013 return Status;
1014 }
1015
1016 Data = (UINT8 *)AllocateZeroPool (DataSize);
1017 if (Data == NULL) {
1018 return EFI_OUT_OF_RESOURCES;
1019 }
1020
1021 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
1022 if (EFI_ERROR (Status)) {
1023 goto Done;
1024 }
1025
1026 //
1027 // Enumerate all signature data in SigDB to check if signature exists for executable.
1028 //
1029 CertList = (EFI_SIGNATURE_LIST *)Data;
1030 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
1031 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1032 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1033 if ((CertList->SignatureSize == sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid (&CertList->SignatureType, CertType))) {
1034 for (Index = 0; Index < CertCount; Index++) {
1035 if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
1036 //
1037 // Find the signature in database.
1038 //
1039 *IsFound = TRUE;
1040 //
1041 // Entries in UEFI_IMAGE_SECURITY_DATABASE that are used to validate image should be measured
1042 //
1043 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) {
1044 SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);
1045 }
1046
1047 break;
1048 }
1049
1050 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);
1051 }
1052
1053 if (*IsFound) {
1054 break;
1055 }
1056 }
1057
1058 DataSize -= CertList->SignatureListSize;
1059 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
1060 }
1061
1062Done:
1063 if (Data != NULL) {
1064 FreePool (Data);
1065 }
1066
1067 return Status;
1068}
1069
1080BOOLEAN
1082 IN EFI_TIME *SigningTime,
1083 IN EFI_TIME *RevocationTime
1084 )
1085{
1086 if (SigningTime->Year != RevocationTime->Year) {
1087 return (BOOLEAN)(SigningTime->Year < RevocationTime->Year);
1088 } else if (SigningTime->Month != RevocationTime->Month) {
1089 return (BOOLEAN)(SigningTime->Month < RevocationTime->Month);
1090 } else if (SigningTime->Day != RevocationTime->Day) {
1091 return (BOOLEAN)(SigningTime->Day < RevocationTime->Day);
1092 } else if (SigningTime->Hour != RevocationTime->Hour) {
1093 return (BOOLEAN)(SigningTime->Hour < RevocationTime->Hour);
1094 } else if (SigningTime->Minute != RevocationTime->Minute) {
1095 return (BOOLEAN)(SigningTime->Minute < RevocationTime->Minute);
1096 }
1097
1098 return (BOOLEAN)(SigningTime->Second <= RevocationTime->Second);
1099}
1100
1110BOOLEAN
1112 IN EFI_TIME *Time
1113 )
1114{
1115 if ((Time->Year == 0) && (Time->Month == 0) && (Time->Day == 0) &&
1116 (Time->Hour == 0) && (Time->Minute == 0) && (Time->Second == 0))
1117 {
1118 return TRUE;
1119 }
1120
1121 return FALSE;
1122}
1123
1138BOOLEAN
1140 IN UINT8 *AuthData,
1141 IN UINTN AuthDataSize,
1142 IN EFI_TIME *RevocationTime
1143 )
1144{
1145 EFI_STATUS Status;
1146 BOOLEAN VerifyStatus;
1147 EFI_SIGNATURE_LIST *CertList;
1148 EFI_SIGNATURE_DATA *Cert;
1149 UINT8 *DbtData;
1150 UINTN DbtDataSize;
1151 UINT8 *RootCert;
1152 UINTN RootCertSize;
1153 UINTN Index;
1154 UINTN CertCount;
1155 EFI_TIME SigningTime;
1156
1157 //
1158 // Variable Initialization
1159 //
1160 VerifyStatus = FALSE;
1161 DbtData = NULL;
1162 CertList = NULL;
1163 Cert = NULL;
1164 RootCert = NULL;
1165 RootCertSize = 0;
1166
1167 //
1168 // If RevocationTime is zero, the certificate shall be considered to always be revoked.
1169 //
1170 if (IsTimeZero (RevocationTime)) {
1171 return FALSE;
1172 }
1173
1174 //
1175 // RevocationTime is non-zero, the certificate should be considered to be revoked from that time and onwards.
1176 // Using the dbt to get the trusted TSA certificates.
1177 //
1178 DbtDataSize = 0;
1179 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, NULL);
1180 if (Status != EFI_BUFFER_TOO_SMALL) {
1181 goto Done;
1182 }
1183
1184 DbtData = (UINT8 *)AllocateZeroPool (DbtDataSize);
1185 if (DbtData == NULL) {
1186 goto Done;
1187 }
1188
1189 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *)DbtData);
1190 if (EFI_ERROR (Status)) {
1191 goto Done;
1192 }
1193
1194 CertList = (EFI_SIGNATURE_LIST *)DbtData;
1195 while ((DbtDataSize > 0) && (DbtDataSize >= CertList->SignatureListSize)) {
1196 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1197 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1198 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1199 for (Index = 0; Index < CertCount; Index++) {
1200 //
1201 // Iterate each Signature Data Node within this CertList for verify.
1202 //
1203 RootCert = Cert->SignatureData;
1204 RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
1205 //
1206 // Get the signing time if the timestamp signature is valid.
1207 //
1208 if (ImageTimestampVerify (AuthData, AuthDataSize, RootCert, RootCertSize, &SigningTime)) {
1209 //
1210 // The signer signature is valid only when the signing time is earlier than revocation time.
1211 //
1212 if (IsValidSignatureByTimestamp (&SigningTime, RevocationTime)) {
1213 VerifyStatus = TRUE;
1214 goto Done;
1215 }
1216 }
1217
1218 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);
1219 }
1220 }
1221
1222 DbtDataSize -= CertList->SignatureListSize;
1223 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
1224 }
1225
1226Done:
1227 if (DbtData != NULL) {
1228 FreePool (DbtData);
1229 }
1230
1231 return VerifyStatus;
1232}
1233
1245BOOLEAN
1247 IN UINT8 *AuthData,
1248 IN UINTN AuthDataSize
1249 )
1250{
1251 EFI_STATUS Status;
1252 BOOLEAN IsForbidden;
1253 BOOLEAN IsFound;
1254 UINT8 *Data;
1255 UINTN DataSize;
1256 EFI_SIGNATURE_LIST *CertList;
1257 UINTN CertListSize;
1258 EFI_SIGNATURE_DATA *CertData;
1259 UINT8 *RootCert;
1260 UINTN RootCertSize;
1261 UINTN CertCount;
1262 UINTN Index;
1263 UINT8 *CertBuffer;
1264 UINTN BufferLength;
1265 UINT8 *TrustedCert;
1266 UINTN TrustedCertLength;
1267 UINT8 CertNumber;
1268 UINT8 *CertPtr;
1269 UINT8 *Cert;
1270 UINTN CertSize;
1271 EFI_TIME RevocationTime;
1272
1273 //
1274 // Variable Initialization
1275 //
1276 IsForbidden = TRUE;
1277 Data = NULL;
1278 CertList = NULL;
1279 CertData = NULL;
1280 RootCert = NULL;
1281 RootCertSize = 0;
1282 Cert = NULL;
1283 CertBuffer = NULL;
1284 BufferLength = 0;
1285 TrustedCert = NULL;
1286 TrustedCertLength = 0;
1287
1288 //
1289 // The image will not be forbidden if dbx can't be got.
1290 //
1291 DataSize = 0;
1292 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1293 ASSERT (EFI_ERROR (Status));
1294 if (Status != EFI_BUFFER_TOO_SMALL) {
1295 if (Status == EFI_NOT_FOUND) {
1296 //
1297 // Evidently not in dbx if the database doesn't exist.
1298 //
1299 IsForbidden = FALSE;
1300 }
1301
1302 return IsForbidden;
1303 }
1304
1305 Data = (UINT8 *)AllocateZeroPool (DataSize);
1306 if (Data == NULL) {
1307 return IsForbidden;
1308 }
1309
1310 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)Data);
1311 if (EFI_ERROR (Status)) {
1312 goto Done;
1313 }
1314
1315 //
1316 // Verify image signature with RAW X509 certificates in DBX database.
1317 // If passed, the image will be forbidden.
1318 //
1319 CertList = (EFI_SIGNATURE_LIST *)Data;
1320 CertListSize = DataSize;
1321 while ((CertListSize > 0) && (CertListSize >= CertList->SignatureListSize)) {
1322 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1323 CertData = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1324 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1325
1326 for (Index = 0; Index < CertCount; Index++) {
1327 //
1328 // Iterate each Signature Data Node within this CertList for verify.
1329 //
1330 RootCert = CertData->SignatureData;
1331 RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
1332
1333 //
1334 // Call AuthenticodeVerify library to Verify Authenticode struct.
1335 //
1336 IsForbidden = AuthenticodeVerify (
1337 AuthData,
1338 AuthDataSize,
1339 RootCert,
1340 RootCertSize,
1341 mImageDigest,
1342 mImageDigestSize
1343 );
1344 if (IsForbidden) {
1345 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is forbidden by DBX.\n"));
1346 goto Done;
1347 }
1348
1349 CertData = (EFI_SIGNATURE_DATA *)((UINT8 *)CertData + CertList->SignatureSize);
1350 }
1351 }
1352
1353 CertListSize -= CertList->SignatureListSize;
1354 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
1355 }
1356
1357 //
1358 // Check X.509 Certificate Hash & Possible Timestamp.
1359 //
1360
1361 //
1362 // Retrieve the certificate stack from AuthData
1363 // The output CertStack format will be:
1364 // UINT8 CertNumber;
1365 // UINT32 Cert1Length;
1366 // UINT8 Cert1[];
1367 // UINT32 Cert2Length;
1368 // UINT8 Cert2[];
1369 // ...
1370 // UINT32 CertnLength;
1371 // UINT8 Certn[];
1372 //
1373 Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);
1374 if ((BufferLength == 0) || (CertBuffer == NULL) || ((*CertBuffer) == 0)) {
1375 IsForbidden = TRUE;
1376 goto Done;
1377 }
1378
1379 //
1380 // Check if any hash of certificates embedded in AuthData is in the forbidden database.
1381 //
1382 CertNumber = (UINT8)(*CertBuffer);
1383 CertPtr = CertBuffer + 1;
1384 for (Index = 0; Index < CertNumber; Index++) {
1385 CertSize = (UINTN)ReadUnaligned32 ((UINT32 *)CertPtr);
1386 Cert = (UINT8 *)CertPtr + sizeof (UINT32);
1387 //
1388 // Advance CertPtr to the next cert in image signer's cert list
1389 //
1390 CertPtr = CertPtr + sizeof (UINT32) + CertSize;
1391
1392 Status = IsCertHashFoundInDbx (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime, &IsFound);
1393 if (EFI_ERROR (Status)) {
1394 //
1395 // Error in searching dbx. Consider it as 'found'. RevocationTime might
1396 // not be valid in such situation.
1397 //
1398 IsForbidden = TRUE;
1399 } else if (IsFound) {
1400 //
1401 // Found Cert in dbx successfully. Check the timestamp signature and
1402 // signing time to determine if the image can be trusted.
1403 //
1404 if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {
1405 IsForbidden = FALSE;
1406 //
1407 // Pass DBT check. Continue to check other certs in image signer's cert list against DBX, DBT
1408 //
1409 continue;
1410 } else {
1411 IsForbidden = TRUE;
1412 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));
1413 goto Done;
1414 }
1415 }
1416 }
1417
1418 IsForbidden = FALSE;
1419
1420Done:
1421 if (Data != NULL) {
1422 FreePool (Data);
1423 }
1424
1425 Pkcs7FreeSigners (CertBuffer);
1426 Pkcs7FreeSigners (TrustedCert);
1427
1428 return IsForbidden;
1429}
1430
1441BOOLEAN
1443 IN UINT8 *AuthData,
1444 IN UINTN AuthDataSize
1445 )
1446{
1447 EFI_STATUS Status;
1448 BOOLEAN VerifyStatus;
1449 BOOLEAN IsFound;
1450 EFI_SIGNATURE_LIST *CertList;
1451 EFI_SIGNATURE_DATA *CertData;
1452 UINTN DataSize;
1453 UINT8 *Data;
1454 UINT8 *RootCert;
1455 UINTN RootCertSize;
1456 UINTN Index;
1457 UINTN CertCount;
1458 UINTN DbxDataSize;
1459 UINT8 *DbxData;
1460 EFI_TIME RevocationTime;
1461
1462 Data = NULL;
1463 CertList = NULL;
1464 CertData = NULL;
1465 RootCert = NULL;
1466 DbxData = NULL;
1467 RootCertSize = 0;
1468 VerifyStatus = FALSE;
1469
1470 //
1471 // Fetch 'db' content. If 'db' doesn't exist or encounters problem to get the
1472 // data, return not-allowed-by-db (FALSE).
1473 //
1474 DataSize = 0;
1475 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1476 ASSERT (EFI_ERROR (Status));
1477 if (Status != EFI_BUFFER_TOO_SMALL) {
1478 return VerifyStatus;
1479 }
1480
1481 Data = (UINT8 *)AllocateZeroPool (DataSize);
1482 if (Data == NULL) {
1483 return VerifyStatus;
1484 }
1485
1486 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)Data);
1487 if (EFI_ERROR (Status)) {
1488 goto Done;
1489 }
1490
1491 //
1492 // Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'.
1493 // If any other errors occurred, no need to check 'db' but just return
1494 // not-allowed-by-db (FALSE) to avoid bypass.
1495 //
1496 DbxDataSize = 0;
1497 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);
1498 ASSERT (EFI_ERROR (Status));
1499 if (Status != EFI_BUFFER_TOO_SMALL) {
1500 if (Status != EFI_NOT_FOUND) {
1501 goto Done;
1502 }
1503
1504 //
1505 // 'dbx' does not exist. Continue to check 'db'.
1506 //
1507 } else {
1508 //
1509 // 'dbx' exists. Get its content.
1510 //
1511 DbxData = (UINT8 *)AllocateZeroPool (DbxDataSize);
1512 if (DbxData == NULL) {
1513 goto Done;
1514 }
1515
1516 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *)DbxData);
1517 if (EFI_ERROR (Status)) {
1518 goto Done;
1519 }
1520 }
1521
1522 //
1523 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
1524 //
1525 CertList = (EFI_SIGNATURE_LIST *)Data;
1526 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
1527 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1528 CertData = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1529 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1530
1531 for (Index = 0; Index < CertCount; Index++) {
1532 //
1533 // Iterate each Signature Data Node within this CertList for verify.
1534 //
1535 RootCert = CertData->SignatureData;
1536 RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
1537
1538 //
1539 // Call AuthenticodeVerify library to Verify Authenticode struct.
1540 //
1541 VerifyStatus = AuthenticodeVerify (
1542 AuthData,
1543 AuthDataSize,
1544 RootCert,
1545 RootCertSize,
1546 mImageDigest,
1547 mImageDigestSize
1548 );
1549 if (VerifyStatus) {
1550 //
1551 // The image is signed and its signature is found in 'db'.
1552 //
1553 if (DbxData != NULL) {
1554 //
1555 // Here We still need to check if this RootCert's Hash is revoked
1556 //
1557 Status = IsCertHashFoundInDbx (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime, &IsFound);
1558 if (EFI_ERROR (Status)) {
1559 //
1560 // Error in searching dbx. Consider it as 'found'. RevocationTime might
1561 // not be valid in such situation.
1562 //
1563 VerifyStatus = FALSE;
1564 } else if (IsFound) {
1565 //
1566 // Check the timestamp signature and signing time to determine if the RootCert can be trusted.
1567 //
1568 VerifyStatus = PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime);
1569 if (!VerifyStatus) {
1570 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed and signature is accepted by DB, but its root cert failed the timestamp check.\n"));
1571 }
1572 }
1573 }
1574
1575 //
1576 // There's no 'dbx' to check revocation time against (must-be pass),
1577 // or, there's revocation time found in 'dbx' and checked againt 'dbt'
1578 // (maybe pass or fail, depending on timestamp compare result). Either
1579 // way the verification job has been completed at this point.
1580 //
1581 goto Done;
1582 }
1583
1584 CertData = (EFI_SIGNATURE_DATA *)((UINT8 *)CertData + CertList->SignatureSize);
1585 }
1586 }
1587
1588 DataSize -= CertList->SignatureListSize;
1589 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
1590 }
1591
1592Done:
1593
1594 if (VerifyStatus) {
1595 SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);
1596 }
1597
1598 if (Data != NULL) {
1599 FreePool (Data);
1600 }
1601
1602 if (DbxData != NULL) {
1603 FreePool (DbxData);
1604 }
1605
1606 return VerifyStatus;
1607}
1608
1657EFIAPI
1659 IN UINT32 AuthenticationStatus,
1660 IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
1661 IN VOID *FileBuffer,
1662 IN UINTN FileSize,
1663 IN BOOLEAN BootPolicy
1664 )
1665{
1666 EFI_IMAGE_DOS_HEADER *DosHdr;
1667 BOOLEAN IsVerified;
1668 EFI_SIGNATURE_LIST *SignatureList;
1669 UINTN SignatureListSize;
1670 EFI_SIGNATURE_DATA *Signature;
1671 EFI_IMAGE_EXECUTION_ACTION Action;
1672 WIN_CERTIFICATE *WinCertificate;
1673 UINT32 Policy;
1674 UINT8 SecureBoot;
1675 UINTN SecureBootSize;
1676 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1677 UINT32 NumberOfRvaAndSizes;
1678 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
1679 WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
1680 UINT8 *AuthData;
1681 UINTN AuthDataSize;
1682 EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
1683 UINT32 SecDataDirEnd;
1684 UINT32 SecDataDirLeft;
1685 UINT32 OffSet;
1686 CHAR16 *NameStr;
1687 RETURN_STATUS PeCoffStatus;
1688 EFI_STATUS HashStatus;
1689 EFI_STATUS DbStatus;
1690 EFI_STATUS VarStatus;
1691 UINT32 VarAttr;
1692 BOOLEAN IsFound;
1693 UINT8 HashAlg;
1694 BOOLEAN IsFoundInDatabase;
1695
1696 SignatureList = NULL;
1697 SignatureListSize = 0;
1698 WinCertificate = NULL;
1699 SecDataDir = NULL;
1700 PkcsCertData = NULL;
1701 Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
1702 IsVerified = FALSE;
1703 IsFound = FALSE;
1704 IsFoundInDatabase = FALSE;
1705
1706 //
1707 // Check the image type and get policy setting.
1708 //
1709 switch (GetImageType (File)) {
1710 case IMAGE_FROM_FV:
1711 Policy = ALWAYS_EXECUTE;
1712 break;
1713
1714 case IMAGE_FROM_OPTION_ROM:
1715 Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);
1716 break;
1717
1718 case IMAGE_FROM_REMOVABLE_MEDIA:
1719 Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);
1720 break;
1721
1722 case IMAGE_FROM_FIXED_MEDIA:
1723 Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);
1724 break;
1725
1726 default:
1727 Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
1728 break;
1729 }
1730
1731 //
1732 // If policy is always/never execute, return directly.
1733 //
1734 if (Policy == ALWAYS_EXECUTE) {
1735 return EFI_SUCCESS;
1736 }
1737
1738 if (Policy == NEVER_EXECUTE) {
1739 return EFI_ACCESS_DENIED;
1740 }
1741
1742 //
1743 // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION
1744 // violates the UEFI spec and has been removed.
1745 //
1746 ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);
1747 if ((Policy == QUERY_USER_ON_SECURITY_VIOLATION) || (Policy == ALLOW_EXECUTE_ON_SECURITY_VIOLATION)) {
1748 CpuDeadLoop ();
1749 }
1750
1751 SecureBootSize = sizeof (SecureBoot);
1752 VarStatus = gRT->GetVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &VarAttr, &SecureBootSize, &SecureBoot);
1753 //
1754 // Skip verification if SecureBoot variable doesn't exist.
1755 //
1756 if (VarStatus == EFI_NOT_FOUND) {
1757 return EFI_SUCCESS;
1758 }
1759
1760 //
1761 // Skip verification if SecureBoot is disabled but not AuditMode
1762 //
1763 if ((VarStatus == EFI_SUCCESS) &&
1764 (VarAttr == (EFI_VARIABLE_BOOTSERVICE_ACCESS |
1765 EFI_VARIABLE_RUNTIME_ACCESS)) &&
1766 (SecureBoot == SECURE_BOOT_MODE_DISABLE))
1767 {
1768 return EFI_SUCCESS;
1769 }
1770
1771 //
1772 // Read the Dos header.
1773 //
1774 if (FileBuffer == NULL) {
1775 return EFI_ACCESS_DENIED;
1776 }
1777
1778 mImageBase = (UINT8 *)FileBuffer;
1779 mImageSize = FileSize;
1780
1781 ZeroMem (&ImageContext, sizeof (ImageContext));
1782 ImageContext.Handle = (VOID *)FileBuffer;
1784
1785 //
1786 // Get information about the image being loaded
1787 //
1788 PeCoffStatus = PeCoffLoaderGetImageInfo (&ImageContext);
1789 if (RETURN_ERROR (PeCoffStatus)) {
1790 //
1791 // The information can't be got from the invalid PeImage
1792 //
1793 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: PeImage invalid. Cannot retrieve image information.\n"));
1794 goto Failed;
1795 }
1796
1797 DosHdr = (EFI_IMAGE_DOS_HEADER *)mImageBase;
1798 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1799 //
1800 // DOS image header is present,
1801 // so read the PE header after the DOS image header.
1802 //
1803 mPeCoffHeaderOffset = DosHdr->e_lfanew;
1804 } else {
1805 mPeCoffHeaderOffset = 0;
1806 }
1807
1808 //
1809 // Check PE/COFF image.
1810 //
1811 mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(mImageBase + mPeCoffHeaderOffset);
1812 if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1813 //
1814 // It is not a valid Pe/Coff file.
1815 //
1816 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Not a valid PE/COFF image.\n"));
1817 goto Failed;
1818 }
1819
1820 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1821 //
1822 // Use PE32 offset.
1823 //
1824 NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1825 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1826 SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1827 }
1828 } else {
1829 //
1830 // Use PE32+ offset.
1831 //
1832 NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1833 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1834 SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1835 }
1836 }
1837
1838 //
1839 // Start Image Validation.
1840 //
1841 if ((SecDataDir == NULL) || (SecDataDir->Size == 0)) {
1842 //
1843 // This image is not signed. The hash value of the image must match a record in the security database "db",
1844 // and not be reflected in the security data base "dbx".
1845 //
1846 HashAlg = sizeof (mHash) / sizeof (HASH_TABLE);
1847 while (HashAlg > 0) {
1848 HashAlg--;
1849 if ((mHash[HashAlg].GetContextSize == NULL) || (mHash[HashAlg].HashInit == NULL) || (mHash[HashAlg].HashUpdate == NULL) || (mHash[HashAlg].HashFinal == NULL)) {
1850 continue;
1851 }
1852
1853 if (!HashPeImage (HashAlg)) {
1854 continue;
1855 }
1856
1857 DbStatus = IsSignatureFoundInDatabase (
1859 mImageDigest,
1860 &mCertType,
1861 mImageDigestSize,
1862 &IsFound
1863 );
1864 if (EFI_ERROR (DbStatus) || IsFound) {
1865 //
1866 // Image Hash is in forbidden database (DBX).
1867 //
1868 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));
1869 goto Failed;
1870 }
1871
1872 DbStatus = IsSignatureFoundInDatabase (
1874 mImageDigest,
1875 &mCertType,
1876 mImageDigestSize,
1877 &IsFound
1878 );
1879 if (!EFI_ERROR (DbStatus) && IsFound) {
1880 //
1881 // Image Hash is in allowed database (DB).
1882 //
1883 IsFoundInDatabase = TRUE;
1884 }
1885 }
1886
1887 if (IsFoundInDatabase) {
1888 return EFI_SUCCESS;
1889 }
1890
1891 //
1892 // Image Hash is not found in both forbidden and allowed database.
1893 //
1894 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));
1895 goto Failed;
1896 }
1897
1898 //
1899 // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
1900 // "Attribute Certificate Table".
1901 // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
1902 //
1903 SecDataDirEnd = SecDataDir->VirtualAddress + SecDataDir->Size;
1904 for (OffSet = SecDataDir->VirtualAddress;
1905 OffSet < SecDataDirEnd;
1906 OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength)))
1907 {
1908 SecDataDirLeft = SecDataDirEnd - OffSet;
1909 if (SecDataDirLeft <= sizeof (WIN_CERTIFICATE)) {
1910 break;
1911 }
1912
1913 WinCertificate = (WIN_CERTIFICATE *)(mImageBase + OffSet);
1914 if ((SecDataDirLeft < WinCertificate->dwLength) ||
1915 (SecDataDirLeft - WinCertificate->dwLength <
1916 ALIGN_SIZE (WinCertificate->dwLength)))
1917 {
1918 break;
1919 }
1920
1921 //
1922 // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
1923 //
1924 if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
1925 //
1926 // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
1927 // Authenticode specification.
1928 //
1929 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *)WinCertificate;
1930 if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
1931 break;
1932 }
1933
1934 AuthData = PkcsCertData->CertData;
1935 AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof (PkcsCertData->Hdr);
1936 } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
1937 //
1938 // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
1939 //
1940 WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *)WinCertificate;
1941 if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {
1942 break;
1943 }
1944
1945 if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
1946 continue;
1947 }
1948
1949 AuthData = WinCertUefiGuid->CertData;
1950 AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
1951 } else {
1952 if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
1953 break;
1954 }
1955
1956 continue;
1957 }
1958
1959 HashStatus = HashPeImageByType (AuthData, AuthDataSize);
1960 if (EFI_ERROR (HashStatus)) {
1961 continue;
1962 }
1963
1964 //
1965 // Check the digital signature against the revoked certificate in forbidden database (dbx).
1966 //
1967 if (IsForbiddenByDbx (AuthData, AuthDataSize)) {
1968 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
1969 IsVerified = FALSE;
1970 break;
1971 }
1972
1973 //
1974 // Check the digital signature against the valid certificate in allowed database (db).
1975 //
1976 if (!IsVerified) {
1977 if (IsAllowedByDb (AuthData, AuthDataSize)) {
1978 IsVerified = TRUE;
1979 }
1980 }
1981
1982 //
1983 // Check the image's hash value.
1984 //
1985 DbStatus = IsSignatureFoundInDatabase (
1987 mImageDigest,
1988 &mCertType,
1989 mImageDigestSize,
1990 &IsFound
1991 );
1992 if (EFI_ERROR (DbStatus) || IsFound) {
1993 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
1994 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s hash of image is found in DBX.\n", mHashTypeStr));
1995 IsVerified = FALSE;
1996 break;
1997 }
1998
1999 if (!IsVerified) {
2000 DbStatus = IsSignatureFoundInDatabase (
2002 mImageDigest,
2003 &mCertType,
2004 mImageDigestSize,
2005 &IsFound
2006 );
2007 if (!EFI_ERROR (DbStatus) && IsFound) {
2008 IsVerified = TRUE;
2009 } else {
2010 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND;
2011 DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is not allowed by DB and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));
2012 }
2013 }
2014 }
2015
2016 if (OffSet != SecDataDirEnd) {
2017 //
2018 // The Size in Certificate Table or the attribute certificate table is corrupted.
2019 //
2020 IsVerified = FALSE;
2021 }
2022
2023 if (IsVerified) {
2024 return EFI_SUCCESS;
2025 }
2026
2027 if ((Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED) || (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND)) {
2028 //
2029 // Get image hash value as signature of executable.
2030 //
2031 SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
2032 SignatureList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (SignatureListSize);
2033 if (SignatureList == NULL) {
2034 SignatureListSize = 0;
2035 goto Failed;
2036 }
2037
2038 SignatureList->SignatureHeaderSize = 0;
2039 SignatureList->SignatureListSize = (UINT32)SignatureListSize;
2040 SignatureList->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize);
2041 CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));
2042 Signature = (EFI_SIGNATURE_DATA *)((UINT8 *)SignatureList + sizeof (EFI_SIGNATURE_LIST));
2043 CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
2044 }
2045
2046Failed:
2047 //
2048 // Policy decides to defer or reject the image; add its information in image
2049 // executable information table in either case.
2050 //
2051 NameStr = ConvertDevicePathToText (File, FALSE, TRUE);
2052 AddImageExeInfo (Action, NameStr, File, SignatureList, SignatureListSize);
2053 if (NameStr != NULL) {
2054 DEBUG ((DEBUG_INFO, "The image doesn't pass verification: %s\n", NameStr));
2055 FreePool (NameStr);
2056 }
2057
2058 if (SignatureList != NULL) {
2059 FreePool (SignatureList);
2060 }
2061
2062 if (Policy == DEFER_EXECUTE_ON_SECURITY_VIOLATION) {
2063 return EFI_SECURITY_VIOLATION;
2064 }
2065
2066 return EFI_ACCESS_DENIED;
2067}
2068
2078VOID
2079EFIAPI
2081 IN EFI_EVENT Event,
2082 IN VOID *Context
2083 )
2084{
2085 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;
2086 UINTN ImageExeInfoTableSize;
2087
2088 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **)&ImageExeInfoTable);
2089 if (ImageExeInfoTable != NULL) {
2090 return;
2091 }
2092
2093 ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
2094 ImageExeInfoTable = (EFI_IMAGE_EXECUTION_INFO_TABLE *)AllocateRuntimePool (ImageExeInfoTableSize);
2095 if (ImageExeInfoTable == NULL) {
2096 return;
2097 }
2098
2099 ImageExeInfoTable->NumberOfImages = 0;
2100 gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *)ImageExeInfoTable);
2101}
2102
2112EFIAPI
2114 IN EFI_HANDLE ImageHandle,
2115 IN EFI_SYSTEM_TABLE *SystemTable
2116 )
2117{
2118 EFI_EVENT Event;
2119
2120 //
2121 // Register the event to publish the image execution table.
2122 //
2124 TPL_CALLBACK,
2126 NULL,
2127 &Event
2128 );
2129
2132 EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
2133 );
2134}
UINT64 UINTN
#define MAX_ADDRESS
UINTN EFIAPI Sha256GetContextSize(VOID)
Definition: CryptSha256.c:20
UINTN EFIAPI Sha384GetContextSize(VOID)
Definition: CryptSha512.c:20
BOOLEAN EFIAPI Sha512Final(IN OUT VOID *Sha512Context, OUT UINT8 *HashValue)
Definition: CryptSha512.c:389
#define SHA1_DIGEST_SIZE
Definition: BaseCryptLib.h:39
UINTN EFIAPI Sha512GetContextSize(VOID)
Definition: CryptSha512.c:246
BOOLEAN EFIAPI Sha1Final(IN OUT VOID *Sha1Context, OUT UINT8 *HashValue)
Definition: CryptSha1.c:163
BOOLEAN EFIAPI Sha512Init(OUT VOID *Sha512Context)
Definition: CryptSha512.c:270
#define SHA512_DIGEST_SIZE
Definition: BaseCryptLib.h:54
BOOLEAN EFIAPI Sha256Init(OUT VOID *Sha256Context)
Definition: CryptSha256.c:44
BOOLEAN EFIAPI Pkcs7GetSigners(IN CONST UINT8 *P7Data, IN UINTN P7Length, OUT UINT8 **CertStack, OUT UINTN *StackLength, OUT UINT8 **TrustedCert, OUT UINTN *CertLength)
BOOLEAN EFIAPI AuthenticodeVerify(IN CONST UINT8 *AuthData, IN UINTN DataSize, IN CONST UINT8 *TrustedCert, IN UINTN CertSize, IN CONST UINT8 *ImageHash, IN UINTN HashSize)
BOOLEAN EFIAPI Sha256Final(IN OUT VOID *Sha256Context, OUT UINT8 *HashValue)
Definition: CryptSha256.c:161
#define SHA256_DIGEST_SIZE
Definition: BaseCryptLib.h:44
BOOLEAN EFIAPI Sha384Update(IN OUT VOID *Sha384Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha512.c:115
BOOLEAN EFIAPI Sha1Init(OUT VOID *Sha1Context)
Definition: CryptSha1.c:46
BOOLEAN EFIAPI Sha256Update(IN OUT VOID *Sha256Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha256.c:113
VOID EFIAPI Pkcs7FreeSigners(IN UINT8 *Certs)
BOOLEAN EFIAPI ImageTimestampVerify(IN CONST UINT8 *AuthData, IN UINTN DataSize, IN CONST UINT8 *TsaCert, IN UINTN CertSize, OUT EFI_TIME *SigningTime)
Definition: CryptTs.c:555
UINTN EFIAPI Sha1GetContextSize(VOID)
Definition: CryptSha1.c:22
BOOLEAN EFIAPI Sha384Final(IN OUT VOID *Sha384Context, OUT UINT8 *HashValue)
Definition: CryptSha512.c:163
BOOLEAN EFIAPI Sha384Init(OUT VOID *Sha384Context)
Definition: CryptSha512.c:44
BOOLEAN EFIAPI X509GetTBSCert(IN CONST UINT8 *Cert, IN UINTN CertSize, OUT UINT8 **TBSCert, OUT UINTN *TBSCertSize)
Definition: CryptX509.c:798
BOOLEAN EFIAPI Sha512Update(IN OUT VOID *Sha512Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha512.c:341
BOOLEAN EFIAPI Sha1Update(IN OUT VOID *Sha1Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha1.c:115
#define SHA384_DIGEST_SIZE
Definition: BaseCryptLib.h:49
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
Definition: Unaligned.c:177
UINT32 EFIAPI ReadUnaligned32(IN CONST UINT32 *Buffer)
Definition: Unaligned.c:145
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define MSG_MAC_ADDR_DP
Definition: DevicePath.h:550
#define MEDIA_RELATIVE_OFFSET_RANGE_DP
Definition: DevicePath.h:1162
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
BOOLEAN EFIAPI IsDevicePathEndType(IN CONST VOID *Node)
BOOLEAN HashPeImage(IN UINT32 HashAlg)
BOOLEAN IsForbiddenByDbx(IN UINT8 *AuthData, IN UINTN AuthDataSize)
EFI_STATUS IsSignatureFoundInDatabase(IN CHAR16 *VariableName, IN UINT8 *Signature, IN EFI_GUID *CertType, IN UINTN SignatureSize, OUT BOOLEAN *IsFound)
EFI_STATUS IsCertHashFoundInDbx(IN UINT8 *Certificate, IN UINTN CertSize, IN EFI_SIGNATURE_LIST *SignatureList, IN UINTN SignatureListSize, OUT EFI_TIME *RevocationTime, OUT BOOLEAN *IsFound)
EFI_STATUS EFIAPI DxeImageVerificationHandler(IN UINT32 AuthenticationStatus, IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL, IN VOID *FileBuffer, IN UINTN FileSize, IN BOOLEAN BootPolicy)
EFI_STATUS HashPeImageByType(IN UINT8 *AuthData, IN UINTN AuthDataSize)
VOID AddImageExeInfo(IN EFI_IMAGE_EXECUTION_ACTION Action, IN CHAR16 *Name OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN EFI_SIGNATURE_LIST *Signature OPTIONAL, IN UINTN SignatureSize)
UINT32 GetImageType(IN CONST EFI_DEVICE_PATH_PROTOCOL *File)
EFI_STATUS EFIAPI DxeImageVerificationLibImageRead(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
BOOLEAN IsTimeZero(IN EFI_TIME *Time)
VOID EFIAPI OnReadyToBoot(IN EFI_EVENT Event, IN VOID *Context)
BOOLEAN IsValidSignatureByTimestamp(IN EFI_TIME *SigningTime, IN EFI_TIME *RevocationTime)
EFI_STATUS EFIAPI DxeImageVerificationLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID EFIAPI SecureBootHook(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINTN DataSize, IN VOID *Data)
Definition: Measurement.c:290
BOOLEAN PassTimestampCheck(IN UINT8 *AuthData, IN UINTN AuthDataSize, IN EFI_TIME *RevocationTime)
BOOLEAN IsAllowedByDb(IN UINT8 *AuthData, IN UINTN AuthDataSize)
UINTN GetImageExeInfoTableSize(EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimePool(IN UINTN AllocationSize)
#define EFI_SECURE_BOOT_MODE_NAME
EFI_STATUS EFIAPI HashUpdate(IN HASH_HANDLE HashHandle, IN VOID *DataToHash, IN UINTN DataToHashLen)
Definition: HashLibTdx.c:69
#define EFI_IMAGE_SECURITY_DATABASE2
#define EFI_IMAGE_SECURITY_DATABASE1
#define EFI_IMAGE_SECURITY_DATABASE
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
RETURN_STATUS(EFIAPI * PE_COFF_LOADER_READ_FILE)(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
Definition: PeCoffLib.h:65
RETURN_STATUS EFIAPI PeCoffLoaderGetImageInfo(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:577
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: PeImage.h:143
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: PeImage.h:194
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define EFI_AUTH_OPERATION_IMAGE_REQUIRED
EFI_STATUS EFIAPI RegisterSecurity2Handler(IN SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler, IN UINT32 AuthenticationOperation)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
GUID EFI_GUID
Definition: UefiBaseType.h:25
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
EFI_STATUS EFIAPI EfiCreateEventReadyToBootEx(IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *ReadyToBootEvent)
Definition: UefiNotTiano.c:164
EFI_BLOCK_IO_MEDIA * Media
Definition: BlockIo.h:224
BOOLEAN RemovableMedia
Definition: BlockIo.h:137
UINT32 e_lfanew
File address of new exe header.
Definition: PeImage.h:76
UINT16 e_magic
Magic number.
Definition: PeImage.h:58
Definition: Base.h:213
HASH_FINAL HashFinal
Pointer to Hash Final function.
CHAR16 * Name
Name for Hash Algorithm.
HASH_UPDATE HashUpdate
Pointer to Hash Update function.
HASH_GET_CONTEXT_SIZE GetContextSize
Pointer to Hash GetContentSize function.
HASH_INIT HashInit
Pointer to Hash Init function.
PE_COFF_LOADER_READ_FILE ImageRead
Definition: PeCoffLib.h:100
UINT16 wCertificateType