2 Implement image verification services for secure boot service in UEFI2.3.1.
4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "DxeImageVerificationLib.h"
17 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
19 UINT32 mPeCoffHeaderOffset
;
20 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
21 UINTN mImageDigestSize
;
22 EFI_IMAGE_DATA_DIRECTORY
*mSecDataDir
= NULL
;
23 UINT8
*mImageBase
= NULL
;
27 // Notify string for authorization UI.
29 CHAR16 mNotifyString1
[MAX_NOTIFY_STRING_LEN
] = L
"Image verification pass but not found in authorized database!";
30 CHAR16 mNotifyString2
[MAX_NOTIFY_STRING_LEN
] = L
"Launch this image anyway? (Yes/Defer/No)";
32 // Public Exponent of RSA Key.
34 CONST UINT8 mRsaE
[] = { 0x01, 0x00, 0x01 };
38 // OID ASN.1 Value for Hash Algorithms
40 UINT8 mHashOidValue
[] = {
41 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
42 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
43 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
44 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
45 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
46 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
49 HASH_TABLE mHash
[] = {
50 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
51 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
52 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
53 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
54 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
58 Reads contents of a PE/COFF image in memory buffer.
60 @param FileHandle Pointer to the file handle to read the PE/COFF image.
61 @param FileOffset Offset into the PE/COFF image to begin the read operation.
62 @param ReadSize On input, the size in bytes of the requested read operation.
63 On output, the number of bytes actually read.
64 @param Buffer Output buffer that contains the data read from the PE/COFF image.
66 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
70 DxeImageVerificationLibImageRead (
73 IN OUT UINTN
*ReadSize
,
79 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
80 return EFI_INVALID_PARAMETER
;
83 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
84 return EFI_INVALID_PARAMETER
;
87 EndPosition
= FileOffset
+ *ReadSize
;
88 if (EndPosition
> mImageSize
) {
89 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
92 if (FileOffset
>= mImageSize
) {
96 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
105 @param[in] File This is a pointer to the device path of the file that is
108 @return UINT32 Image Type
113 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
117 EFI_HANDLE DeviceHandle
;
118 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
119 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
122 // First check to see if File is from a Firmware Volume
125 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
126 Status
= gBS
->LocateDevicePath (
127 &gEfiFirmwareVolume2ProtocolGuid
,
131 if (!EFI_ERROR (Status
)) {
132 Status
= gBS
->OpenProtocol (
134 &gEfiFirmwareVolume2ProtocolGuid
,
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
140 if (!EFI_ERROR (Status
)) {
141 return IMAGE_FROM_FV
;
146 // Next check to see if File is from a Block I/O device
149 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
150 Status
= gBS
->LocateDevicePath (
151 &gEfiBlockIoProtocolGuid
,
155 if (!EFI_ERROR (Status
)) {
157 Status
= gBS
->OpenProtocol (
159 &gEfiBlockIoProtocolGuid
,
163 EFI_OPEN_PROTOCOL_GET_PROTOCOL
165 if (!EFI_ERROR (Status
) && BlockIo
!= NULL
) {
166 if (BlockIo
->Media
!= NULL
) {
167 if (BlockIo
->Media
->RemovableMedia
) {
169 // Block I/O is present and specifies the media is removable
171 return IMAGE_FROM_REMOVABLE_MEDIA
;
174 // Block I/O is present and specifies the media is not removable
176 return IMAGE_FROM_FIXED_MEDIA
;
183 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
184 // the device path supports the Simple File System Protocol.
187 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
188 Status
= gBS
->LocateDevicePath (
189 &gEfiSimpleFileSystemProtocolGuid
,
193 if (!EFI_ERROR (Status
)) {
195 // Simple File System is present without Block I/O, so assume media is fixed.
197 return IMAGE_FROM_FIXED_MEDIA
;
201 // File is not from an FV, Block I/O or Simple File System, so the only options
202 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
204 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
205 while (!IsDevicePathEndType (TempDevicePath
)) {
206 switch (DevicePathType (TempDevicePath
)) {
208 case MEDIA_DEVICE_PATH
:
209 if (DevicePathSubType (TempDevicePath
) == MEDIA_RELATIVE_OFFSET_RANGE_DP
) {
210 return IMAGE_FROM_OPTION_ROM
;
214 case MESSAGING_DEVICE_PATH
:
215 if (DevicePathSubType(TempDevicePath
) == MSG_MAC_ADDR_DP
) {
216 return IMAGE_FROM_REMOVABLE_MEDIA
;
223 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
225 return IMAGE_UNKNOWN
;
229 Caculate hash of Pe/Coff image based on the authenticode image hashing in
230 PE/COFF Specification 8.0 Appendix A
232 @param[in] HashAlg Hash algorithm type.
234 @retval TRUE Successfully hash image.
235 @retval FALSE Fail in hash image.
245 EFI_IMAGE_SECTION_HEADER
*Section
;
250 UINTN SumOfBytesHashed
;
251 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
255 UINT32 NumberOfRvaAndSizes
;
258 SectionHeader
= NULL
;
261 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
266 // Initialize context of hash.
268 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
270 if (HashAlg
== HASHALG_SHA1
) {
271 mImageDigestSize
= SHA1_DIGEST_SIZE
;
272 mCertType
= gEfiCertSha1Guid
;
273 } else if (HashAlg
== HASHALG_SHA256
) {
274 mImageDigestSize
= SHA256_DIGEST_SIZE
;
275 mCertType
= gEfiCertSha256Guid
;
280 CtxSize
= mHash
[HashAlg
].GetContextSize();
282 HashCtx
= AllocatePool (CtxSize
);
283 if (HashCtx
== NULL
) {
287 // 1. Load the image header into memory.
289 // 2. Initialize a SHA hash context.
290 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
297 // Measuring PE/COFF Image Header;
298 // But CheckSum field and SECURITY data directory (certificate) are excluded
300 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
302 // 3. Calculate the distance from the base of the image header to the image checksum address.
303 // 4. Hash the image header from its base to beginning of the image checksum.
305 HashBase
= mImageBase
;
306 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
310 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
311 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
312 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
316 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
317 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
320 // Invalid header magic number.
326 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
332 // 5. Skip over the image checksum (it occupies a single ULONG).
334 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
336 // 6. Since there is no Cert Directory in optional header, hash everything
337 // from the end of the checksum to the end of image header.
339 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
343 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
344 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
349 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
350 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
354 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
361 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
363 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
367 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
368 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
373 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
374 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
378 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
385 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
386 // 9. Hash everything from the end of the Cert Directory to the end of image header.
388 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
392 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
393 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
398 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
399 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
403 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
411 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
413 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
417 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
422 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
426 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
428 mPeCoffHeaderOffset
+
430 sizeof (EFI_IMAGE_FILE_HEADER
) +
431 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
435 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
436 // structures in the image. The 'NumberOfSections' field of the image
437 // header indicates how big the table should be. Do not include any
438 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
440 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
441 if (SectionHeader
== NULL
) {
446 // 12. Using the 'PointerToRawData' in the referenced section headers as
447 // a key, arrange the elements in the table in ascending order. In other
448 // words, sort the section headers according to the disk-file offset of
451 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
453 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
454 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
457 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
462 // 13. Walk through the sorted table, bring the corresponding section
463 // into memory, and hash the entire section (using the 'SizeOfRawData'
464 // field in the section header to determine the amount of data to hash).
465 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
466 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
468 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
469 Section
= &SectionHeader
[Index
];
470 if (Section
->SizeOfRawData
== 0) {
473 HashBase
= mImageBase
+ Section
->PointerToRawData
;
474 HashSize
= (UINTN
) Section
->SizeOfRawData
;
476 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
481 SumOfBytesHashed
+= HashSize
;
485 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
486 // data in the file that needs to be added to the hash. This data begins
487 // at file offset SUM_OF_BYTES_HASHED and its length is:
488 // FileSize - (CertDirectory->Size)
490 if (mImageSize
> SumOfBytesHashed
) {
491 HashBase
= mImageBase
+ SumOfBytesHashed
;
493 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
496 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
500 CertSize
= mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
505 CertSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
509 if (mImageSize
> CertSize
+ SumOfBytesHashed
) {
510 HashSize
= (UINTN
) (mImageSize
- CertSize
- SumOfBytesHashed
);
512 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
516 } else if (mImageSize
< CertSize
+ SumOfBytesHashed
) {
522 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
525 if (HashCtx
!= NULL
) {
528 if (SectionHeader
!= NULL
) {
529 FreePool (SectionHeader
);
535 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
536 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
539 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
540 @retval EFI_SUCCESS Hash successfully.
549 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
551 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
553 if (PkcsCertData
->Hdr
.dwLength
< sizeof (WIN_CERTIFICATE_EFI_PKCS
) + 32) {
554 return EFI_UNSUPPORTED
;
557 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
559 // Check the Hash algorithm in PE/COFF Authenticode.
560 // According to PKCS#7 Definition:
561 // SignedData ::= SEQUENCE {
563 // digestAlgorithms DigestAlgorithmIdentifiers,
564 // contentInfo ContentInfo,
566 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
567 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
568 // Fixed offset (+32) is calculated based on two bytes of length encoding.
570 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
572 // Only support two bytes of Long Form of Length Encoding.
577 if (PkcsCertData
->Hdr
.dwLength
< sizeof (WIN_CERTIFICATE_EFI_PKCS
) + 32 + mHash
[Index
].OidLength
) {
578 return EFI_UNSUPPORTED
;
581 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
586 if (Index
== HASHALG_MAX
) {
587 return EFI_UNSUPPORTED
;
591 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
593 if (!HashPeImage(Index
)) {
594 return EFI_UNSUPPORTED
;
602 Returns the size of a given image execution info table in bytes.
604 This function returns the size, in bytes, of the image execution info table specified by
605 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
607 @param ImageExeInfoTable A pointer to a image execution info table structure.
609 @retval 0 If ImageExeInfoTable is NULL.
610 @retval Others The size of a image execution info table in bytes.
614 GetImageExeInfoTableSize (
615 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
619 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoItem
;
622 if (ImageExeInfoTable
== NULL
) {
626 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoTable
+ sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
));
627 TotalSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
628 for (Index
= 0; Index
< ImageExeInfoTable
->NumberOfImages
; Index
++) {
629 TotalSize
+= ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
);
630 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoItem
+ ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
));
637 Create an Image Execution Information Table entry and add it to system configuration table.
639 @param[in] Action Describes the action taken by the firmware regarding this image.
640 @param[in] Name Input a null-terminated, user-friendly name.
641 @param[in] DevicePath Input device path pointer.
642 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
643 @param[in] SignatureSize Size of signature.
648 IN EFI_IMAGE_EXECUTION_ACTION Action
,
649 IN CHAR16
*Name OPTIONAL
,
650 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
651 IN EFI_SIGNATURE_LIST
*Signature OPTIONAL
,
652 IN UINTN SignatureSize
655 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
;
656 EFI_IMAGE_EXECUTION_INFO_TABLE
*NewImageExeInfoTable
;
657 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoEntry
;
658 UINTN ImageExeInfoTableSize
;
659 UINTN NewImageExeInfoEntrySize
;
661 UINTN DevicePathSize
;
663 ImageExeInfoTable
= NULL
;
664 NewImageExeInfoTable
= NULL
;
665 ImageExeInfoEntry
= NULL
;
668 if (DevicePath
== NULL
) {
673 NameStringLen
= StrSize (Name
);
676 ImageExeInfoTable
= NULL
;
677 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
**) &ImageExeInfoTable
);
678 if (ImageExeInfoTable
!= NULL
) {
680 // The table has been found!
681 // We must enlarge the table to accmodate the new exe info entry.
683 ImageExeInfoTableSize
= GetImageExeInfoTableSize (ImageExeInfoTable
);
687 // We should create a new table to append to the configuration table.
689 ImageExeInfoTableSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
692 DevicePathSize
= GetDevicePathSize (DevicePath
);
693 NewImageExeInfoEntrySize
= sizeof (EFI_IMAGE_EXECUTION_INFO
) + NameStringLen
+ DevicePathSize
+ SignatureSize
;
694 NewImageExeInfoTable
= (EFI_IMAGE_EXECUTION_INFO_TABLE
*) AllocateRuntimePool (ImageExeInfoTableSize
+ NewImageExeInfoEntrySize
);
695 if (NewImageExeInfoTable
== NULL
) {
699 if (ImageExeInfoTable
!= NULL
) {
700 CopyMem (NewImageExeInfoTable
, ImageExeInfoTable
, ImageExeInfoTableSize
);
702 NewImageExeInfoTable
->NumberOfImages
= 0;
704 NewImageExeInfoTable
->NumberOfImages
++;
705 ImageExeInfoEntry
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) NewImageExeInfoTable
+ ImageExeInfoTableSize
);
707 // Update new item's infomation.
709 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->Action
, Action
);
710 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->InfoSize
, (UINT32
) NewImageExeInfoEntrySize
);
713 CopyMem ((UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
), Name
, NameStringLen
);
716 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
,
720 if (Signature
!= NULL
) {
722 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
+ DevicePathSize
,
728 // Update/replace the image execution table.
730 gBS
->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
*) NewImageExeInfoTable
);
733 // Free Old table data!
735 if (ImageExeInfoTable
!= NULL
) {
736 FreePool (ImageExeInfoTable
);
741 Discover if the UEFI image is authorized by user's policy setting.
743 @param[in] Policy Specify platform's policy setting.
745 @retval EFI_ACCESS_DENIED Image is not allowed to run.
746 @retval EFI_SECURITY_VIOLATION Image is deferred.
747 @retval EFI_SUCCESS Image is authorized to run.
758 Status
= EFI_ACCESS_DENIED
;
762 case QUERY_USER_ON_SECURITY_VIOLATION
:
764 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, mNotifyString1
, mNotifyString2
, NULL
);
765 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
766 Status
= EFI_SUCCESS
;
768 } else if (Key
.UnicodeChar
== L
'N' || Key
.UnicodeChar
== L
'n') {
769 Status
= EFI_ACCESS_DENIED
;
771 } else if (Key
.UnicodeChar
== L
'D' || Key
.UnicodeChar
== L
'd') {
772 Status
= EFI_SECURITY_VIOLATION
;
778 case ALLOW_EXECUTE_ON_SECURITY_VIOLATION
:
779 Status
= EFI_SUCCESS
;
782 case DEFER_EXECUTE_ON_SECURITY_VIOLATION
:
783 Status
= EFI_SECURITY_VIOLATION
;
786 case DENY_EXECUTE_ON_SECURITY_VIOLATION
:
787 Status
= EFI_ACCESS_DENIED
;
795 Check whether signature is in specified database.
797 @param[in] VariableName Name of database variable that is searched in.
798 @param[in] Signature Pointer to signature that is searched for.
799 @param[in] CertType Pointer to hash algrithom.
800 @param[in] SignatureSize Size of Signature.
802 @return TRUE Found the signature in the variable database.
803 @return FALSE Not found the signature in the variable database.
807 IsSignatureFoundInDatabase (
808 IN CHAR16
*VariableName
,
810 IN EFI_GUID
*CertType
,
811 IN UINTN SignatureSize
815 EFI_SIGNATURE_LIST
*CertList
;
816 EFI_SIGNATURE_DATA
*Cert
;
823 // Read signature database variable.
828 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
829 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
833 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
838 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
839 if (EFI_ERROR (Status
)) {
843 // Enumerate all signature data in SigDB to check if executable's signature exists.
845 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
846 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
847 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
848 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
849 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
850 for (Index
= 0; Index
< CertCount
; Index
++) {
851 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
853 // Find the signature in database.
859 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
867 DataSize
-= CertList
->SignatureListSize
;
868 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
880 Verify PKCS#7 SignedData using certificate found in Variable which formatted
881 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
883 @param VariableName Name of Variable to search for Certificate.
884 @param VendorGuid Variable vendor GUID.
886 @retval TRUE Image pass verification.
887 @retval FALSE Image fail verification.
891 IsPkcsSignedDataVerifiedBySignatureList (
892 IN CHAR16
*VariableName
,
893 IN EFI_GUID
*VendorGuid
897 BOOLEAN VerifyStatus
;
898 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
899 EFI_SIGNATURE_LIST
*CertList
;
900 EFI_SIGNATURE_DATA
*Cert
;
913 VerifyStatus
= FALSE
;
914 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
917 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
918 if (Status
== EFI_BUFFER_TOO_SMALL
) {
919 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
924 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
925 if (EFI_ERROR (Status
)) {
930 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
932 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
933 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
934 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
935 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
936 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
937 for (Index
= 0; Index
< CertCount
; Index
++) {
939 // Iterate each Signature Data Node within this CertList for verify.
941 RootCert
= Cert
->SignatureData
;
942 RootCertSize
= CertList
->SignatureSize
;
945 // Call AuthenticodeVerify library to Verify Authenticode struct.
947 VerifyStatus
= AuthenticodeVerify (
948 PkcsCertData
->CertData
,
949 PkcsCertData
->Hdr
.dwLength
- sizeof(PkcsCertData
->Hdr
),
958 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
961 DataSize
-= CertList
->SignatureListSize
;
962 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
975 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
977 @retval EFI_SUCCESS Image pass verification.
978 @retval EFI_SECURITY_VIOLATION Image fail verification.
982 VerifyCertPkcsSignedData (
987 // 1: Find certificate from DBX forbidden database for revoked certificate.
989 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
991 // DBX is forbidden database, if Authenticode verification pass with
992 // one of the certificate in DBX, this image should be rejected.
994 return EFI_SECURITY_VIOLATION
;
998 // 2: Find certificate from KEK database and try to verify authenticode struct.
1000 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
)) {
1005 // 3: Find certificate from DB database and try to verify authenticode struct.
1007 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
1010 return EFI_SECURITY_VIOLATION
;
1015 Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
1017 @retval EFI_SUCCESS Image pass verification.
1018 @retval EFI_SECURITY_VIOLATION Image fail verification.
1019 @retval other error value
1023 VerifyCertUefiGuid (
1028 WIN_CERTIFICATE_UEFI_GUID
*EfiCert
;
1029 EFI_SIGNATURE_LIST
*KekList
;
1030 EFI_SIGNATURE_DATA
*KekItem
;
1031 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1048 EfiCert
= (WIN_CERTIFICATE_UEFI_GUID
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1049 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) EfiCert
->CertData
;
1050 if (!CompareGuid (&EfiCert
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
)) {
1052 // Invalid Certificate Data Type.
1054 return EFI_SECURITY_VIOLATION
;
1058 // Get KEK database variable data size
1060 Result
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &KekDataSize
, NULL
);
1061 if (Result
!= EFI_BUFFER_TOO_SMALL
) {
1062 return EFI_SECURITY_VIOLATION
;
1066 // Get KEK database variable.
1068 GetEfiGlobalVariable2 (EFI_KEY_EXCHANGE_KEY_NAME
, &KekList
, NULL
);
1069 if (KekList
== NULL
) {
1070 return EFI_SECURITY_VIOLATION
;
1074 // Enumerate all Kek items in this list to verify the variable certificate data.
1075 // If anyone is authenticated successfully, it means the variable is correct!
1077 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
1078 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1079 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
1080 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
1081 for (Index
= 0; Index
< KekCount
; Index
++) {
1082 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1086 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1089 KekDataSize
-= KekList
->SignatureListSize
;
1090 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1095 // Signed key is not a trust one.
1101 // Now, we found the corresponding security policy.
1102 // Verify the data payload.
1111 // Set RSA Key Components.
1112 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
1114 Status
= RsaSetKey (Rsa
, RsaKeyN
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
1118 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
1123 // Verify the signature.
1125 Status
= RsaPkcs1Verify (
1129 CertBlock
->Signature
,
1130 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
1134 if (KekList
!= NULL
) {
1143 return EFI_SECURITY_VIOLATION
;
1148 Provide verification service for signed images, which include both signature validation
1149 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1150 MSFT Authenticode type signatures are supported.
1152 In this implementation, only verify external executables when in USER MODE.
1153 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1155 The image verification process is:
1156 Is the Image signed?
1158 Does the image verify against a certificate (root or intermediate) in the allowed db?
1160 Image verification fail
1161 Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
1164 Is the Image's Hash in the forbidden database (DBX)?
1167 Is the Image's Hash in the allowed database (DB)?
1173 @param[in] AuthenticationStatus
1174 This is the authentication status returned from the security
1175 measurement services for the input file.
1176 @param[in] File This is a pointer to the device path of the file that is
1177 being dispatched. This will optionally be used for logging.
1178 @param[in] FileBuffer File buffer matches the input file device path.
1179 @param[in] FileSize Size of File buffer matches the input file device path.
1181 @retval EFI_SUCCESS The file specified by File did authenticate, and the
1182 platform policy dictates that the DXE Core may use File.
1183 @retval EFI_INVALID_PARAMETER Input argument is incorrect.
1184 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1185 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1186 the platform policy dictates that File should be placed
1187 in the untrusted state. A file may be promoted from
1188 the untrusted to the trusted state at a future time
1189 with a call to the Trust() DXE Service.
1190 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
1191 the platform policy dictates that File should not be
1192 used for any purpose.
1197 DxeImageVerificationHandler (
1198 IN UINT32 AuthenticationStatus
,
1199 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1200 IN VOID
*FileBuffer
,
1206 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1207 EFI_STATUS VerifyStatus
;
1209 EFI_SIGNATURE_LIST
*SignatureList
;
1210 UINTN SignatureListSize
;
1211 EFI_SIGNATURE_DATA
*Signature
;
1212 EFI_IMAGE_EXECUTION_ACTION Action
;
1213 WIN_CERTIFICATE
*WinCertificate
;
1215 UINT8
*SecureBootEnable
;
1216 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1217 UINT32 NumberOfRvaAndSizes
;
1221 return EFI_INVALID_PARAMETER
;
1224 SignatureList
= NULL
;
1225 SignatureListSize
= 0;
1226 WinCertificate
= NULL
;
1227 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1228 Status
= EFI_ACCESS_DENIED
;
1230 // Check the image type and get policy setting.
1232 switch (GetImageType (File
)) {
1235 Policy
= ALWAYS_EXECUTE
;
1238 case IMAGE_FROM_OPTION_ROM
:
1239 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1242 case IMAGE_FROM_REMOVABLE_MEDIA
:
1243 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1246 case IMAGE_FROM_FIXED_MEDIA
:
1247 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1251 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1255 // If policy is always/never execute, return directly.
1257 if (Policy
== ALWAYS_EXECUTE
) {
1259 } else if (Policy
== NEVER_EXECUTE
) {
1260 return EFI_ACCESS_DENIED
;
1263 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, &SecureBootEnable
, NULL
);
1265 // Skip verification if SecureBootEnable variable doesn't exist.
1267 if (SecureBootEnable
== NULL
) {
1272 // Skip verification if SecureBootEnable is disabled.
1274 if (*SecureBootEnable
== SECURE_BOOT_DISABLE
) {
1275 FreePool (SecureBootEnable
);
1279 FreePool (SecureBootEnable
);
1281 GetEfiGlobalVariable2 (EFI_SETUP_MODE_NAME
, &SetupMode
, NULL
);
1284 // SetupMode doesn't exist means no AuthVar driver is dispatched,
1285 // skip verification.
1287 if (SetupMode
== NULL
) {
1292 // If platform is in SETUP MODE, skip verification.
1294 if (*SetupMode
== SETUP_MODE
) {
1295 FreePool (SetupMode
);
1299 FreePool (SetupMode
);
1302 // Read the Dos header.
1304 if (FileBuffer
== NULL
) {
1305 return EFI_INVALID_PARAMETER
;
1308 mImageBase
= (UINT8
*) FileBuffer
;
1309 mImageSize
= FileSize
;
1311 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1312 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1313 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeImageVerificationLibImageRead
;
1316 // Get information about the image being loaded
1318 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1319 if (EFI_ERROR (Status
)) {
1321 // The information can't be got from the invalid PeImage
1326 Status
= EFI_ACCESS_DENIED
;
1328 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1329 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1331 // DOS image header is present,
1332 // so read the PE header after the DOS image header.
1334 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1336 mPeCoffHeaderOffset
= 0;
1339 // Check PE/COFF image.
1341 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1342 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1344 // It is not a valid Pe/Coff file.
1349 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1350 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1354 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1355 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1356 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1360 // Use PE32+ offset.
1362 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1363 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1364 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1368 if ((mSecDataDir
== NULL
) || ((mSecDataDir
!= NULL
) && (mSecDataDir
->Size
== 0))) {
1370 // This image is not signed.
1372 if (!HashPeImage (HASHALG_SHA256
)) {
1376 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1378 // Image Hash is in forbidden database (DBX).
1383 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1385 // Image Hash is in allowed database (DB).
1391 // Image Hash is not found in both forbidden and allowed database.
1397 // Verify signature of executables.
1399 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1401 CertSize
= sizeof (WIN_CERTIFICATE
);
1403 if ((mSecDataDir
->Size
<= CertSize
) || (mSecDataDir
->Size
< WinCertificate
->dwLength
)) {
1407 switch (WinCertificate
->wCertificateType
) {
1409 case WIN_CERT_TYPE_EFI_GUID
:
1410 CertSize
= sizeof (WIN_CERTIFICATE_UEFI_GUID
) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256
) - sizeof (UINT8
);
1411 if (WinCertificate
->dwLength
< CertSize
) {
1416 // Verify UEFI GUID type.
1418 if (!HashPeImage (HASHALG_SHA256
)) {
1422 VerifyStatus
= VerifyCertUefiGuid ();
1425 case WIN_CERT_TYPE_PKCS_SIGNED_DATA
:
1427 // Verify Pkcs signed data type.
1429 Status
= HashPeImageByType();
1430 if (EFI_ERROR (Status
)) {
1434 VerifyStatus
= VerifyCertPkcsSignedData ();
1437 // For image verification against enrolled certificate(root or intermediate),
1438 // no need to check image's hash in the allowed database.
1440 if (!EFI_ERROR (VerifyStatus
)) {
1441 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1451 // Get image hash value as executable's signature.
1453 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1454 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1455 if (SignatureList
== NULL
) {
1456 Status
= EFI_OUT_OF_RESOURCES
;
1459 SignatureList
->SignatureHeaderSize
= 0;
1460 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1461 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1462 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1463 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1464 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1466 // Signature database check after verification.
1468 if (EFI_ERROR (VerifyStatus
)) {
1470 // Verification failure.
1472 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1473 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1475 // Verification fail, Image Hash is not in forbidden database (DBX),
1476 // and Image Hash is in allowed database (DB).
1478 Status
= EFI_SUCCESS
;
1480 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1481 Status
= EFI_ACCESS_DENIED
;
1483 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1485 // Executable signature verification passes, but is found in forbidden signature database.
1487 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1488 Status
= EFI_ACCESS_DENIED
;
1489 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1491 // Executable signature is found in authorized signature database.
1493 Status
= EFI_SUCCESS
;
1496 // Executable signature verification passes, but cannot be found in authorized signature database.
1497 // Get platform policy to determine the action.
1499 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED
;
1500 Status
= ImageAuthorization (Policy
);
1504 if (Status
!= EFI_SUCCESS
) {
1506 // Policy decides to defer or reject the image; add its information in image executable information table.
1508 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1511 if (SignatureList
!= NULL
) {
1512 FreePool (SignatureList
);
1519 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1521 @param[in] Event Event whose notification function is being invoked.
1522 @param[in] Context Pointer to the notification function's context.
1527 VariableWriteCallBack (
1532 UINT8 SecureBootMode
;
1533 UINT8
*SecureBootModePtr
;
1535 VOID
*ProtocolPointer
;
1537 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1538 if (EFI_ERROR (Status
)) {
1543 // Check whether "SecureBoot" variable exists.
1544 // If this library is built-in, it means firmware has capability to perform
1545 // driver signing verification.
1547 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &SecureBootModePtr
, NULL
);
1548 if (SecureBootModePtr
== NULL
) {
1549 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1551 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1554 EFI_SECURE_BOOT_MODE_NAME
,
1555 &gEfiGlobalVariableGuid
,
1556 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1561 FreePool (SecureBootModePtr
);
1566 Register security measurement handler.
1568 @param ImageHandle ImageHandle of the loaded driver.
1569 @param SystemTable Pointer to the EFI System Table.
1571 @retval EFI_SUCCESS The handlers were registered successfully.
1575 DxeImageVerificationLibConstructor (
1576 IN EFI_HANDLE ImageHandle
,
1577 IN EFI_SYSTEM_TABLE
*SystemTable
1583 // Register callback function upon VariableWriteArchProtocol.
1585 EfiCreateProtocolNotifyEvent (
1586 &gEfiVariableWriteArchProtocolGuid
,
1588 VariableWriteCallBack
,
1593 return RegisterSecurityHandler (
1594 DxeImageVerificationHandler
,
1595 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED