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
;
254 UINTN SumOfSectionBytes
;
255 EFI_IMAGE_SECTION_HEADER
*SectionCache
;
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
);
296 // Measuring PE/COFF Image Header;
297 // But CheckSum field and SECURITY data directory (certificate) are excluded
299 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
301 // 3. Calculate the distance from the base of the image header to the image checksum address.
302 // 4. Hash the image header from its base to beginning of the image checksum.
304 HashBase
= mImageBase
;
305 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
309 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
310 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
314 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
317 // Invalid header magic number.
323 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
328 // 5. Skip over the image checksum (it occupies a single ULONG).
329 // 6. Get the address of the beginning of the Cert Directory.
330 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
332 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
336 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
337 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
342 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
343 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
346 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
351 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
352 // 9. Hash everything from the end of the Cert Directory to the end of image header.
354 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
358 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
359 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
364 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
365 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
368 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
373 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
375 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
379 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
384 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
388 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
390 mPeCoffHeaderOffset
+
392 sizeof (EFI_IMAGE_FILE_HEADER
) +
393 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
396 SectionCache
= Section
;
397 for (Index
= 0, SumOfSectionBytes
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++, SectionCache
++) {
398 SumOfSectionBytes
+= SectionCache
->SizeOfRawData
;
402 // Sanity check for file corruption. Sections raw data size should be smaller
405 if (SumOfSectionBytes
>= mImageSize
) {
411 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
412 // structures in the image. The 'NumberOfSections' field of the image
413 // header indicates how big the table should be. Do not include any
414 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
416 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
417 if (SectionHeader
== NULL
) {
422 // 12. Using the 'PointerToRawData' in the referenced section headers as
423 // a key, arrange the elements in the table in ascending order. In other
424 // words, sort the section headers according to the disk-file offset of
427 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
429 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
430 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
433 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
438 // 13. Walk through the sorted table, bring the corresponding section
439 // into memory, and hash the entire section (using the 'SizeOfRawData'
440 // field in the section header to determine the amount of data to hash).
441 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
442 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
444 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
445 Section
= &SectionHeader
[Index
];
446 if (Section
->SizeOfRawData
== 0) {
449 HashBase
= mImageBase
+ Section
->PointerToRawData
;
450 HashSize
= (UINTN
) Section
->SizeOfRawData
;
452 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
457 SumOfBytesHashed
+= HashSize
;
461 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
462 // data in the file that needs to be added to the hash. This data begins
463 // at file offset SUM_OF_BYTES_HASHED and its length is:
464 // FileSize - (CertDirectory->Size)
466 if (mImageSize
> SumOfBytesHashed
) {
467 HashBase
= mImageBase
+ SumOfBytesHashed
;
468 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
469 if (mImageSize
- SumOfBytesHashed
< mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
) {
478 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
481 if (mImageSize
- SumOfBytesHashed
< mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
) {
490 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
494 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
499 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
502 if (HashCtx
!= NULL
) {
505 if (SectionHeader
!= NULL
) {
506 FreePool (SectionHeader
);
512 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
513 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
516 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
517 @retval EFI_SUCCESS Hash successfully.
526 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
528 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
530 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
532 // Check the Hash algorithm in PE/COFF Authenticode.
533 // According to PKCS#7 Definition:
534 // SignedData ::= SEQUENCE {
536 // digestAlgorithms DigestAlgorithmIdentifiers,
537 // contentInfo ContentInfo,
539 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
540 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
541 // Fixed offset (+32) is calculated based on two bytes of length encoding.
543 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
545 // Only support two bytes of Long Form of Length Encoding.
550 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
555 if (Index
== HASHALG_MAX
) {
556 return EFI_UNSUPPORTED
;
560 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
562 if (!HashPeImage(Index
)) {
563 return EFI_UNSUPPORTED
;
571 Returns the size of a given image execution info table in bytes.
573 This function returns the size, in bytes, of the image execution info table specified by
574 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
576 @param ImageExeInfoTable A pointer to a image execution info table structure.
578 @retval 0 If ImageExeInfoTable is NULL.
579 @retval Others The size of a image execution info table in bytes.
583 GetImageExeInfoTableSize (
584 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
588 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoItem
;
591 if (ImageExeInfoTable
== NULL
) {
595 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoTable
+ sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
));
596 TotalSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
597 for (Index
= 0; Index
< ImageExeInfoTable
->NumberOfImages
; Index
++) {
598 TotalSize
+= ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
);
599 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoItem
+ ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
));
606 Create an Image Execution Information Table entry and add it to system configuration table.
608 @param[in] Action Describes the action taken by the firmware regarding this image.
609 @param[in] Name Input a null-terminated, user-friendly name.
610 @param[in] DevicePath Input device path pointer.
611 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
612 @param[in] SignatureSize Size of signature.
617 IN EFI_IMAGE_EXECUTION_ACTION Action
,
618 IN CHAR16
*Name OPTIONAL
,
619 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
620 IN EFI_SIGNATURE_LIST
*Signature OPTIONAL
,
621 IN UINTN SignatureSize
624 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
;
625 EFI_IMAGE_EXECUTION_INFO_TABLE
*NewImageExeInfoTable
;
626 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoEntry
;
627 UINTN ImageExeInfoTableSize
;
628 UINTN NewImageExeInfoEntrySize
;
630 UINTN DevicePathSize
;
632 ImageExeInfoTable
= NULL
;
633 NewImageExeInfoTable
= NULL
;
634 ImageExeInfoEntry
= NULL
;
637 if (DevicePath
== NULL
) {
642 NameStringLen
= StrSize (Name
);
645 ImageExeInfoTable
= NULL
;
646 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
**) &ImageExeInfoTable
);
647 if (ImageExeInfoTable
!= NULL
) {
649 // The table has been found!
650 // We must enlarge the table to accmodate the new exe info entry.
652 ImageExeInfoTableSize
= GetImageExeInfoTableSize (ImageExeInfoTable
);
656 // We should create a new table to append to the configuration table.
658 ImageExeInfoTableSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
661 DevicePathSize
= GetDevicePathSize (DevicePath
);
662 NewImageExeInfoEntrySize
= sizeof (EFI_IMAGE_EXECUTION_INFO
) + NameStringLen
+ DevicePathSize
+ SignatureSize
;
663 NewImageExeInfoTable
= (EFI_IMAGE_EXECUTION_INFO_TABLE
*) AllocateRuntimePool (ImageExeInfoTableSize
+ NewImageExeInfoEntrySize
);
664 if (NewImageExeInfoTable
== NULL
) {
668 if (ImageExeInfoTable
!= NULL
) {
669 CopyMem (NewImageExeInfoTable
, ImageExeInfoTable
, ImageExeInfoTableSize
);
671 NewImageExeInfoTable
->NumberOfImages
= 0;
673 NewImageExeInfoTable
->NumberOfImages
++;
674 ImageExeInfoEntry
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) NewImageExeInfoTable
+ ImageExeInfoTableSize
);
676 // Update new item's infomation.
678 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->Action
, Action
);
679 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->InfoSize
, (UINT32
) NewImageExeInfoEntrySize
);
682 CopyMem ((UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
), Name
, NameStringLen
);
685 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
,
689 if (Signature
!= NULL
) {
691 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
+ DevicePathSize
,
697 // Update/replace the image execution table.
699 gBS
->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
*) NewImageExeInfoTable
);
702 // Free Old table data!
704 if (ImageExeInfoTable
!= NULL
) {
705 FreePool (ImageExeInfoTable
);
710 Discover if the UEFI image is authorized by user's policy setting.
712 @param[in] Policy Specify platform's policy setting.
714 @retval EFI_ACCESS_DENIED Image is not allowed to run.
715 @retval EFI_SECURITY_VIOLATION Image is deferred.
716 @retval EFI_SUCCESS Image is authorized to run.
727 Status
= EFI_ACCESS_DENIED
;
731 case QUERY_USER_ON_SECURITY_VIOLATION
:
733 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, mNotifyString1
, mNotifyString2
, NULL
);
734 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
735 Status
= EFI_SUCCESS
;
737 } else if (Key
.UnicodeChar
== L
'N' || Key
.UnicodeChar
== L
'n') {
738 Status
= EFI_ACCESS_DENIED
;
740 } else if (Key
.UnicodeChar
== L
'D' || Key
.UnicodeChar
== L
'd') {
741 Status
= EFI_SECURITY_VIOLATION
;
747 case ALLOW_EXECUTE_ON_SECURITY_VIOLATION
:
748 Status
= EFI_SUCCESS
;
751 case DEFER_EXECUTE_ON_SECURITY_VIOLATION
:
752 Status
= EFI_SECURITY_VIOLATION
;
755 case DENY_EXECUTE_ON_SECURITY_VIOLATION
:
756 Status
= EFI_ACCESS_DENIED
;
764 Check whether signature is in specified database.
766 @param[in] VariableName Name of database variable that is searched in.
767 @param[in] Signature Pointer to signature that is searched for.
768 @param[in] CertType Pointer to hash algrithom.
769 @param[in] SignatureSize Size of Signature.
771 @return TRUE Found the signature in the variable database.
772 @return FALSE Not found the signature in the variable database.
776 IsSignatureFoundInDatabase (
777 IN CHAR16
*VariableName
,
779 IN EFI_GUID
*CertType
,
780 IN UINTN SignatureSize
784 EFI_SIGNATURE_LIST
*CertList
;
785 EFI_SIGNATURE_DATA
*Cert
;
792 // Read signature database variable.
797 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
798 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
802 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
807 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
808 if (EFI_ERROR (Status
)) {
812 // Enumerate all signature data in SigDB to check if executable's signature exists.
814 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
815 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
816 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
817 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
818 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
819 for (Index
= 0; Index
< CertCount
; Index
++) {
820 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
822 // Find the signature in database.
828 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
836 DataSize
-= CertList
->SignatureListSize
;
837 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
849 Verify PKCS#7 SignedData using certificate found in Variable which formatted
850 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
852 @param VariableName Name of Variable to search for Certificate.
853 @param VendorGuid Variable vendor GUID.
855 @retval TRUE Image pass verification.
856 @retval FALSE Image fail verification.
860 IsPkcsSignedDataVerifiedBySignatureList (
861 IN CHAR16
*VariableName
,
862 IN EFI_GUID
*VendorGuid
866 BOOLEAN VerifyStatus
;
867 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
868 EFI_SIGNATURE_LIST
*CertList
;
869 EFI_SIGNATURE_DATA
*Cert
;
882 VerifyStatus
= FALSE
;
883 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
886 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
887 if (Status
== EFI_BUFFER_TOO_SMALL
) {
888 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
893 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
894 if (EFI_ERROR (Status
)) {
899 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
901 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
902 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
903 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
904 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
905 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
906 for (Index
= 0; Index
< CertCount
; Index
++) {
908 // Iterate each Signature Data Node within this CertList for verify.
910 RootCert
= Cert
->SignatureData
;
911 RootCertSize
= CertList
->SignatureSize
;
914 // Call AuthenticodeVerify library to Verify Authenticode struct.
916 VerifyStatus
= AuthenticodeVerify (
917 PkcsCertData
->CertData
,
918 mSecDataDir
->Size
- sizeof(PkcsCertData
->Hdr
),
927 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
930 DataSize
-= CertList
->SignatureListSize
;
931 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
944 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
946 @retval EFI_SUCCESS Image pass verification.
947 @retval EFI_SECURITY_VIOLATION Image fail verification.
951 VerifyCertPkcsSignedData (
956 // 1: Find certificate from DBX forbidden database for revoked certificate.
958 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
960 // DBX is forbidden database, if Authenticode verification pass with
961 // one of the certificate in DBX, this image should be rejected.
963 return EFI_SECURITY_VIOLATION
;
967 // 2: Find certificate from KEK database and try to verify authenticode struct.
969 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
)) {
974 // 3: Find certificate from DB database and try to verify authenticode struct.
976 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
979 return EFI_SECURITY_VIOLATION
;
984 Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
986 @retval EFI_SUCCESS Image pass verification.
987 @retval EFI_SECURITY_VIOLATION Image fail verification.
988 @retval other error value
997 WIN_CERTIFICATE_UEFI_GUID
*EfiCert
;
998 EFI_SIGNATURE_LIST
*KekList
;
999 EFI_SIGNATURE_DATA
*KekItem
;
1000 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1017 EfiCert
= (WIN_CERTIFICATE_UEFI_GUID
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1018 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) EfiCert
->CertData
;
1019 if (!CompareGuid (&EfiCert
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
)) {
1021 // Invalid Certificate Data Type.
1023 return EFI_SECURITY_VIOLATION
;
1027 // Get KEK database variable data size
1029 Result
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &KekDataSize
, NULL
);
1030 if (Result
!= EFI_BUFFER_TOO_SMALL
) {
1031 return EFI_SECURITY_VIOLATION
;
1035 // Get KEK database variable.
1037 KekList
= GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME
);
1038 if (KekList
== NULL
) {
1039 return EFI_SECURITY_VIOLATION
;
1043 // Enumerate all Kek items in this list to verify the variable certificate data.
1044 // If anyone is authenticated successfully, it means the variable is correct!
1046 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
1047 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1048 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
1049 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
1050 for (Index
= 0; Index
< KekCount
; Index
++) {
1051 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1055 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1058 KekDataSize
-= KekList
->SignatureListSize
;
1059 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1064 // Signed key is not a trust one.
1070 // Now, we found the corresponding security policy.
1071 // Verify the data payload.
1080 // Set RSA Key Components.
1081 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
1083 Status
= RsaSetKey (Rsa
, RsaKeyN
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
1087 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
1092 // Verify the signature.
1094 Status
= RsaPkcs1Verify (
1098 CertBlock
->Signature
,
1099 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
1103 if (KekList
!= NULL
) {
1112 return EFI_SECURITY_VIOLATION
;
1117 Provide verification service for signed images, which include both signature validation
1118 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1119 MSFT Authenticode type signatures are supported.
1121 In this implementation, only verify external executables when in USER MODE.
1122 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1124 The image verification process is:
1125 Is the Image signed?
1127 Does the image verify against a certificate (root or intermediate) in the allowed db?
1129 Image verification fail
1130 Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
1133 Is the Image's Hash in the forbidden database (DBX)?
1136 Is the Image's Hash in the allowed database (DB)?
1142 @param[in] AuthenticationStatus
1143 This is the authentication status returned from the security
1144 measurement services for the input file.
1145 @param[in] File This is a pointer to the device path of the file that is
1146 being dispatched. This will optionally be used for logging.
1147 @param[in] FileBuffer File buffer matches the input file device path.
1148 @param[in] FileSize Size of File buffer matches the input file device path.
1150 @retval EFI_SUCCESS The file specified by File did authenticate, and the
1151 platform policy dictates that the DXE Core may use File.
1152 @retval EFI_INVALID_PARAMETER Input argument is incorrect.
1153 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1154 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1155 the platform policy dictates that File should be placed
1156 in the untrusted state. A file may be promoted from
1157 the untrusted to the trusted state at a future time
1158 with a call to the Trust() DXE Service.
1159 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
1160 the platform policy dictates that File should not be
1161 used for any purpose.
1166 DxeImageVerificationHandler (
1167 IN UINT32 AuthenticationStatus
,
1168 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1169 IN VOID
*FileBuffer
,
1175 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1176 EFI_STATUS VerifyStatus
;
1178 EFI_SIGNATURE_LIST
*SignatureList
;
1179 UINTN SignatureListSize
;
1180 EFI_SIGNATURE_DATA
*Signature
;
1181 EFI_IMAGE_EXECUTION_ACTION Action
;
1182 WIN_CERTIFICATE
*WinCertificate
;
1184 UINT8
*SecureBootEnable
;
1185 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1188 return EFI_INVALID_PARAMETER
;
1191 SignatureList
= NULL
;
1192 SignatureListSize
= 0;
1193 WinCertificate
= NULL
;
1194 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1195 Status
= EFI_ACCESS_DENIED
;
1197 // Check the image type and get policy setting.
1199 switch (GetImageType (File
)) {
1202 Policy
= ALWAYS_EXECUTE
;
1205 case IMAGE_FROM_OPTION_ROM
:
1206 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1209 case IMAGE_FROM_REMOVABLE_MEDIA
:
1210 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1213 case IMAGE_FROM_FIXED_MEDIA
:
1214 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1218 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1222 // If policy is always/never execute, return directly.
1224 if (Policy
== ALWAYS_EXECUTE
) {
1226 } else if (Policy
== NEVER_EXECUTE
) {
1227 return EFI_ACCESS_DENIED
;
1230 SecureBootEnable
= GetVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
);
1232 // Skip verification if SecureBootEnable variable doesn't exist.
1234 if (SecureBootEnable
== NULL
) {
1239 // Skip verification if SecureBootEnable is disabled.
1241 if (*SecureBootEnable
== SECURE_BOOT_DISABLE
) {
1242 FreePool (SecureBootEnable
);
1246 SetupMode
= GetEfiGlobalVariable (EFI_SETUP_MODE_NAME
);
1249 // SetupMode doesn't exist means no AuthVar driver is dispatched,
1250 // skip verification.
1252 if (SetupMode
== NULL
) {
1257 // If platform is in SETUP MODE, skip verification.
1259 if (*SetupMode
== SETUP_MODE
) {
1260 FreePool (SetupMode
);
1264 // Read the Dos header.
1266 if (FileBuffer
== NULL
) {
1267 FreePool (SetupMode
);
1268 return EFI_INVALID_PARAMETER
;
1270 mImageBase
= (UINT8
*) FileBuffer
;
1271 mImageSize
= FileSize
;
1273 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1274 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1275 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeImageVerificationLibImageRead
;
1278 // Get information about the image being loaded
1280 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1281 if (EFI_ERROR (Status
)) {
1283 // The information can't be got from the invalid PeImage
1288 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1289 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1291 // DOS image header is present,
1292 // so read the PE header after the DOS image header.
1294 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1296 mPeCoffHeaderOffset
= 0;
1299 // Check PE/COFF image.
1301 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1302 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1304 // It is not a valid Pe/Coff file.
1306 return EFI_ACCESS_DENIED
;
1309 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1310 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1314 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1315 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1317 // Use PE32+ offset.
1319 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1322 // Invalid header magic number.
1324 Status
= EFI_INVALID_PARAMETER
;
1328 if (mSecDataDir
->VirtualAddress
>= mImageSize
) {
1330 // Sanity check to see if this file is corrupted.
1332 Status
= EFI_INVALID_PARAMETER
;
1336 if (mSecDataDir
->Size
== 0) {
1338 // This image is not signed.
1340 if (!HashPeImage (HASHALG_SHA256
)) {
1344 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1346 // Image Hash is in forbidden database (DBX).
1348 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1349 Status
= EFI_ACCESS_DENIED
;
1353 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1355 // Image Hash is in allowed database (DB).
1361 // Image Hash is not found in both forbidden and allowed database.
1363 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1364 Status
= EFI_ACCESS_DENIED
;
1369 // Verify signature of executables.
1371 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1373 switch (WinCertificate
->wCertificateType
) {
1375 case WIN_CERT_TYPE_EFI_GUID
:
1377 // Verify UEFI GUID type.
1379 if (!HashPeImage (HASHALG_SHA256
)) {
1383 VerifyStatus
= VerifyCertUefiGuid ();
1386 case WIN_CERT_TYPE_PKCS_SIGNED_DATA
:
1388 // Verify Pkcs signed data type.
1390 Status
= HashPeImageByType();
1391 if (EFI_ERROR (Status
)) {
1395 VerifyStatus
= VerifyCertPkcsSignedData ();
1398 // For image verification against enrolled certificate(root or intermediate),
1399 // no need to check image's hash in the allowed database.
1401 if (!EFI_ERROR (VerifyStatus
)) {
1402 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1409 Status
= EFI_ACCESS_DENIED
;
1413 // Get image hash value as executable's signature.
1415 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1416 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1417 if (SignatureList
== NULL
) {
1418 Status
= EFI_OUT_OF_RESOURCES
;
1421 SignatureList
->SignatureHeaderSize
= 0;
1422 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1423 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1424 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1425 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1426 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1428 // Signature database check after verification.
1430 if (EFI_ERROR (VerifyStatus
)) {
1432 // Verification failure.
1434 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1435 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1437 // Verification fail, Image Hash is not in forbidden database (DBX),
1438 // and Image Hash is in allowed database (DB).
1440 Status
= EFI_SUCCESS
;
1442 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1443 Status
= EFI_ACCESS_DENIED
;
1445 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1447 // Executable signature verification passes, but is found in forbidden signature database.
1449 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1450 Status
= EFI_ACCESS_DENIED
;
1451 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1453 // Executable signature is found in authorized signature database.
1455 Status
= EFI_SUCCESS
;
1458 // Executable signature verification passes, but cannot be found in authorized signature database.
1459 // Get platform policy to determine the action.
1461 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED
;
1462 Status
= ImageAuthorization (Policy
);
1466 if (Status
!= EFI_SUCCESS
) {
1468 // Policy decides to defer or reject the image; add its information in image executable information table.
1470 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1473 if (SignatureList
!= NULL
) {
1474 FreePool (SignatureList
);
1477 FreePool (SetupMode
);
1483 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1485 @param[in] Event Event whose notification function is being invoked.
1486 @param[in] Context Pointer to the notification function's context.
1491 VariableWriteCallBack (
1496 UINT8 SecureBootMode
;
1497 UINT8
*SecureBootModePtr
;
1499 VOID
*ProtocolPointer
;
1501 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1502 if (EFI_ERROR (Status
)) {
1507 // Check whether "SecureBoot" variable exists.
1508 // If this library is built-in, it means firmware has capability to perform
1509 // driver signing verification.
1511 SecureBootModePtr
= GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME
);
1512 if (SecureBootModePtr
== NULL
) {
1513 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1515 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1518 EFI_SECURE_BOOT_MODE_NAME
,
1519 &gEfiGlobalVariableGuid
,
1520 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1525 FreePool (SecureBootModePtr
);
1530 Register security measurement handler.
1532 @param ImageHandle ImageHandle of the loaded driver.
1533 @param SystemTable Pointer to the EFI System Table.
1535 @retval EFI_SUCCESS The handlers were registered successfully.
1539 DxeImageVerificationLibConstructor (
1540 IN EFI_HANDLE ImageHandle
,
1541 IN EFI_SYSTEM_TABLE
*SystemTable
1547 // Register callback function upon VariableWriteArchProtocol.
1549 EfiCreateProtocolNotifyEvent (
1550 &gEfiVariableWriteArchProtocolGuid
,
1552 VariableWriteCallBack
,
1557 return RegisterSecurityHandler (
1558 DxeImageVerificationHandler
,
1559 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED