2 Implement image verification services for secure boot service in UEFI2.3.1.
4 Caution: This file requires additional review when modified.
5 This library will have external input - PE/COFF image.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
9 DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content
10 read is within the image buffer.
12 DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
13 untrusted PE/COFF image and validate its data structure within this image buffer before use.
15 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
16 This program and the accompanying materials
17 are licensed and made available under the terms and conditions of the BSD License
18 which accompanies this distribution. The full text of the license may be found at
19 http://opensource.org/licenses/bsd-license.php
21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include "DxeImageVerificationLib.h"
29 // Caution: This is used by a function which may receive untrusted input.
30 // These global variables hold PE/COFF image data, and they should be validated before use.
32 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
33 UINT32 mPeCoffHeaderOffset
;
37 // Information on current PE/COFF image
40 UINT8
*mImageBase
= NULL
;
41 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
42 UINTN mImageDigestSize
;
45 // Notify string for authorization UI.
47 CHAR16 mNotifyString1
[MAX_NOTIFY_STRING_LEN
] = L
"Image verification pass but not found in authorized database!";
48 CHAR16 mNotifyString2
[MAX_NOTIFY_STRING_LEN
] = L
"Launch this image anyway? (Yes/Defer/No)";
50 // Public Exponent of RSA Key.
52 CONST UINT8 mRsaE
[] = { 0x01, 0x00, 0x01 };
56 // OID ASN.1 Value for Hash Algorithms
58 UINT8 mHashOidValue
[] = {
59 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
66 HASH_TABLE mHash
[] = {
67 { L
"SHA1", 20, &mHashOidValue
[0], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
68 { L
"SHA224", 28, &mHashOidValue
[5], 9, NULL
, NULL
, NULL
, NULL
},
69 { L
"SHA256", 32, &mHashOidValue
[14], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
70 { L
"SHA384", 48, &mHashOidValue
[23], 9, NULL
, NULL
, NULL
, NULL
},
71 { L
"SHA512", 64, &mHashOidValue
[32], 9, NULL
, NULL
, NULL
, NULL
}
75 Reads contents of a PE/COFF image in memory buffer.
77 Caution: This function may receive untrusted input.
78 PE/COFF image is external input, so this function will make sure the PE/COFF image content
79 read is within the image buffer.
81 @param FileHandle Pointer to the file handle to read the PE/COFF image.
82 @param FileOffset Offset into the PE/COFF image to begin the read operation.
83 @param ReadSize On input, the size in bytes of the requested read operation.
84 On output, the number of bytes actually read.
85 @param Buffer Output buffer that contains the data read from the PE/COFF image.
87 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
91 DxeImageVerificationLibImageRead (
94 IN OUT UINTN
*ReadSize
,
100 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
101 return EFI_INVALID_PARAMETER
;
104 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
105 return EFI_INVALID_PARAMETER
;
108 EndPosition
= FileOffset
+ *ReadSize
;
109 if (EndPosition
> mImageSize
) {
110 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
113 if (FileOffset
>= mImageSize
) {
117 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
126 @param[in] File This is a pointer to the device path of the file that is
129 @return UINT32 Image Type
134 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
138 EFI_HANDLE DeviceHandle
;
139 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
140 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
143 return IMAGE_UNKNOWN
;
147 // First check to see if File is from a Firmware Volume
150 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
151 Status
= gBS
->LocateDevicePath (
152 &gEfiFirmwareVolume2ProtocolGuid
,
156 if (!EFI_ERROR (Status
)) {
157 Status
= gBS
->OpenProtocol (
159 &gEfiFirmwareVolume2ProtocolGuid
,
163 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
165 if (!EFI_ERROR (Status
)) {
166 return IMAGE_FROM_FV
;
171 // Next check to see if File is from a Block I/O device
174 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
175 Status
= gBS
->LocateDevicePath (
176 &gEfiBlockIoProtocolGuid
,
180 if (!EFI_ERROR (Status
)) {
182 Status
= gBS
->OpenProtocol (
184 &gEfiBlockIoProtocolGuid
,
188 EFI_OPEN_PROTOCOL_GET_PROTOCOL
190 if (!EFI_ERROR (Status
) && BlockIo
!= NULL
) {
191 if (BlockIo
->Media
!= NULL
) {
192 if (BlockIo
->Media
->RemovableMedia
) {
194 // Block I/O is present and specifies the media is removable
196 return IMAGE_FROM_REMOVABLE_MEDIA
;
199 // Block I/O is present and specifies the media is not removable
201 return IMAGE_FROM_FIXED_MEDIA
;
208 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
209 // the device path supports the Simple File System Protocol.
212 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
213 Status
= gBS
->LocateDevicePath (
214 &gEfiSimpleFileSystemProtocolGuid
,
218 if (!EFI_ERROR (Status
)) {
220 // Simple File System is present without Block I/O, so assume media is fixed.
222 return IMAGE_FROM_FIXED_MEDIA
;
226 // File is not from an FV, Block I/O or Simple File System, so the only options
227 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
229 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
230 while (!IsDevicePathEndType (TempDevicePath
)) {
231 switch (DevicePathType (TempDevicePath
)) {
233 case MEDIA_DEVICE_PATH
:
234 if (DevicePathSubType (TempDevicePath
) == MEDIA_RELATIVE_OFFSET_RANGE_DP
) {
235 return IMAGE_FROM_OPTION_ROM
;
239 case MESSAGING_DEVICE_PATH
:
240 if (DevicePathSubType(TempDevicePath
) == MSG_MAC_ADDR_DP
) {
241 return IMAGE_FROM_REMOVABLE_MEDIA
;
248 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
250 return IMAGE_UNKNOWN
;
254 Caculate hash of Pe/Coff image based on the authenticode image hashing in
255 PE/COFF Specification 8.0 Appendix A
257 Caution: This function may receive untrusted input.
258 PE/COFF image is external input, so this function will validate its data structure
259 within this image buffer before use.
261 @param[in] HashAlg Hash algorithm type.
263 @retval TRUE Successfully hash image.
264 @retval FALSE Fail in hash image.
274 EFI_IMAGE_SECTION_HEADER
*Section
;
279 UINTN SumOfBytesHashed
;
280 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
284 UINT32 NumberOfRvaAndSizes
;
287 SectionHeader
= NULL
;
290 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
295 // Initialize context of hash.
297 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
299 if (HashAlg
== HASHALG_SHA1
) {
300 mImageDigestSize
= SHA1_DIGEST_SIZE
;
301 mCertType
= gEfiCertSha1Guid
;
302 } else if (HashAlg
== HASHALG_SHA256
) {
303 mImageDigestSize
= SHA256_DIGEST_SIZE
;
304 mCertType
= gEfiCertSha256Guid
;
309 CtxSize
= mHash
[HashAlg
].GetContextSize();
311 HashCtx
= AllocatePool (CtxSize
);
312 if (HashCtx
== NULL
) {
316 // 1. Load the image header into memory.
318 // 2. Initialize a SHA hash context.
319 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
326 // Measuring PE/COFF Image Header;
327 // But CheckSum field and SECURITY data directory (certificate) are excluded
329 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
331 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
332 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
333 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
334 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
336 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
339 // Get the magic value from the PE/COFF Optional Header
341 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
345 // 3. Calculate the distance from the base of the image header to the image checksum address.
346 // 4. Hash the image header from its base to beginning of the image checksum.
348 HashBase
= mImageBase
;
349 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
353 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
354 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
355 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
359 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
360 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
363 // Invalid header magic number.
369 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
375 // 5. Skip over the image checksum (it occupies a single ULONG).
377 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
379 // 6. Since there is no Cert Directory in optional header, hash everything
380 // from the end of the checksum to the end of image header.
382 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
386 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
387 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
392 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
393 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
397 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
404 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
406 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
410 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
411 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
416 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
417 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
421 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
428 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
429 // 9. Hash everything from the end of the Cert Directory to the end of image header.
431 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
435 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
436 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
441 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
442 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
446 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
454 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
456 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
460 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
465 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
469 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
471 mPeCoffHeaderOffset
+
473 sizeof (EFI_IMAGE_FILE_HEADER
) +
474 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
478 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
479 // structures in the image. The 'NumberOfSections' field of the image
480 // header indicates how big the table should be. Do not include any
481 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
483 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
484 if (SectionHeader
== NULL
) {
489 // 12. Using the 'PointerToRawData' in the referenced section headers as
490 // a key, arrange the elements in the table in ascending order. In other
491 // words, sort the section headers according to the disk-file offset of
494 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
496 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
497 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
500 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
505 // 13. Walk through the sorted table, bring the corresponding section
506 // into memory, and hash the entire section (using the 'SizeOfRawData'
507 // field in the section header to determine the amount of data to hash).
508 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
509 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
511 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
512 Section
= &SectionHeader
[Index
];
513 if (Section
->SizeOfRawData
== 0) {
516 HashBase
= mImageBase
+ Section
->PointerToRawData
;
517 HashSize
= (UINTN
) Section
->SizeOfRawData
;
519 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
524 SumOfBytesHashed
+= HashSize
;
528 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
529 // data in the file that needs to be added to the hash. This data begins
530 // at file offset SUM_OF_BYTES_HASHED and its length is:
531 // FileSize - (CertDirectory->Size)
533 if (mImageSize
> SumOfBytesHashed
) {
534 HashBase
= mImageBase
+ SumOfBytesHashed
;
536 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
539 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
543 CertSize
= mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
548 CertSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
552 if (mImageSize
> CertSize
+ SumOfBytesHashed
) {
553 HashSize
= (UINTN
) (mImageSize
- CertSize
- SumOfBytesHashed
);
555 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
559 } else if (mImageSize
< CertSize
+ SumOfBytesHashed
) {
565 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
568 if (HashCtx
!= NULL
) {
571 if (SectionHeader
!= NULL
) {
572 FreePool (SectionHeader
);
578 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
579 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
582 Caution: This function may receive untrusted input.
583 PE/COFF image is external input, so this function will validate its data structure
584 within this image buffer before use.
586 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
587 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
589 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
590 @retval EFI_SUCCESS Hash successfully.
596 IN UINTN AuthDataSize
601 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
603 // Check the Hash algorithm in PE/COFF Authenticode.
604 // According to PKCS#7 Definition:
605 // SignedData ::= SEQUENCE {
607 // digestAlgorithms DigestAlgorithmIdentifiers,
608 // contentInfo ContentInfo,
610 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
611 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
612 // Fixed offset (+32) is calculated based on two bytes of length encoding.
614 if ((*(AuthData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
616 // Only support two bytes of Long Form of Length Encoding.
621 if (AuthDataSize
< 32 + mHash
[Index
].OidLength
) {
622 return EFI_UNSUPPORTED
;
625 if (CompareMem (AuthData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
630 if (Index
== HASHALG_MAX
) {
631 return EFI_UNSUPPORTED
;
635 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
637 if (!HashPeImage(Index
)) {
638 return EFI_UNSUPPORTED
;
646 Returns the size of a given image execution info table in bytes.
648 This function returns the size, in bytes, of the image execution info table specified by
649 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
651 @param ImageExeInfoTable A pointer to a image execution info table structure.
653 @retval 0 If ImageExeInfoTable is NULL.
654 @retval Others The size of a image execution info table in bytes.
658 GetImageExeInfoTableSize (
659 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
663 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoItem
;
666 if (ImageExeInfoTable
== NULL
) {
670 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoTable
+ sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
));
671 TotalSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
672 for (Index
= 0; Index
< ImageExeInfoTable
->NumberOfImages
; Index
++) {
673 TotalSize
+= ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
);
674 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoItem
+ ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
));
681 Create an Image Execution Information Table entry and add it to system configuration table.
683 @param[in] Action Describes the action taken by the firmware regarding this image.
684 @param[in] Name Input a null-terminated, user-friendly name.
685 @param[in] DevicePath Input device path pointer.
686 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
687 @param[in] SignatureSize Size of signature.
692 IN EFI_IMAGE_EXECUTION_ACTION Action
,
693 IN CHAR16
*Name OPTIONAL
,
694 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
695 IN EFI_SIGNATURE_LIST
*Signature OPTIONAL
,
696 IN UINTN SignatureSize
699 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
;
700 EFI_IMAGE_EXECUTION_INFO_TABLE
*NewImageExeInfoTable
;
701 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoEntry
;
702 UINTN ImageExeInfoTableSize
;
703 UINTN NewImageExeInfoEntrySize
;
705 UINTN DevicePathSize
;
707 ImageExeInfoTable
= NULL
;
708 NewImageExeInfoTable
= NULL
;
709 ImageExeInfoEntry
= NULL
;
712 if (DevicePath
== NULL
) {
717 NameStringLen
= StrSize (Name
);
720 ImageExeInfoTable
= NULL
;
721 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
**) &ImageExeInfoTable
);
722 if (ImageExeInfoTable
!= NULL
) {
724 // The table has been found!
725 // We must enlarge the table to accmodate the new exe info entry.
727 ImageExeInfoTableSize
= GetImageExeInfoTableSize (ImageExeInfoTable
);
731 // We should create a new table to append to the configuration table.
733 ImageExeInfoTableSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
736 DevicePathSize
= GetDevicePathSize (DevicePath
);
737 NewImageExeInfoEntrySize
= sizeof (EFI_IMAGE_EXECUTION_INFO
) + NameStringLen
+ DevicePathSize
+ SignatureSize
;
738 NewImageExeInfoTable
= (EFI_IMAGE_EXECUTION_INFO_TABLE
*) AllocateRuntimePool (ImageExeInfoTableSize
+ NewImageExeInfoEntrySize
);
739 if (NewImageExeInfoTable
== NULL
) {
743 if (ImageExeInfoTable
!= NULL
) {
744 CopyMem (NewImageExeInfoTable
, ImageExeInfoTable
, ImageExeInfoTableSize
);
746 NewImageExeInfoTable
->NumberOfImages
= 0;
748 NewImageExeInfoTable
->NumberOfImages
++;
749 ImageExeInfoEntry
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) NewImageExeInfoTable
+ ImageExeInfoTableSize
);
751 // Update new item's infomation.
753 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->Action
, Action
);
754 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->InfoSize
, (UINT32
) NewImageExeInfoEntrySize
);
757 CopyMem ((UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
), Name
, NameStringLen
);
760 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
,
764 if (Signature
!= NULL
) {
766 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
+ DevicePathSize
,
772 // Update/replace the image execution table.
774 gBS
->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
*) NewImageExeInfoTable
);
777 // Free Old table data!
779 if (ImageExeInfoTable
!= NULL
) {
780 FreePool (ImageExeInfoTable
);
785 Check whether signature is in specified database.
787 @param[in] VariableName Name of database variable that is searched in.
788 @param[in] Signature Pointer to signature that is searched for.
789 @param[in] CertType Pointer to hash algrithom.
790 @param[in] SignatureSize Size of Signature.
792 @return TRUE Found the signature in the variable database.
793 @return FALSE Not found the signature in the variable database.
797 IsSignatureFoundInDatabase (
798 IN CHAR16
*VariableName
,
800 IN EFI_GUID
*CertType
,
801 IN UINTN SignatureSize
805 EFI_SIGNATURE_LIST
*CertList
;
806 EFI_SIGNATURE_DATA
*Cert
;
813 // Read signature database variable.
818 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
819 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
823 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
828 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
829 if (EFI_ERROR (Status
)) {
833 // Enumerate all signature data in SigDB to check if executable's signature exists.
835 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
836 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
837 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
838 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
839 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
840 for (Index
= 0; Index
< CertCount
; Index
++) {
841 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
843 // Find the signature in database.
849 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
857 DataSize
-= CertList
->SignatureListSize
;
858 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
870 Verify PKCS#7 SignedData using certificate found in Variable which formatted
871 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
873 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
874 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
875 @param[in] VariableName Name of Variable to search for Certificate.
876 @param[in] VendorGuid Variable vendor GUID.
878 @retval TRUE Image pass verification.
879 @retval FALSE Image fail verification.
883 IsPkcsSignedDataVerifiedBySignatureList (
885 IN UINTN AuthDataSize
,
886 IN CHAR16
*VariableName
,
887 IN EFI_GUID
*VendorGuid
891 BOOLEAN VerifyStatus
;
892 EFI_SIGNATURE_LIST
*CertList
;
893 EFI_SIGNATURE_DATA
*Cert
;
906 VerifyStatus
= FALSE
;
909 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
910 if (Status
== EFI_BUFFER_TOO_SMALL
) {
911 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
916 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
917 if (EFI_ERROR (Status
)) {
922 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
924 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
925 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
926 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
927 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
928 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
929 for (Index
= 0; Index
< CertCount
; Index
++) {
931 // Iterate each Signature Data Node within this CertList for verify.
933 RootCert
= Cert
->SignatureData
;
934 RootCertSize
= CertList
->SignatureSize
- sizeof (EFI_GUID
);
937 // Call AuthenticodeVerify library to Verify Authenticode struct.
939 VerifyStatus
= AuthenticodeVerify (
950 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
953 DataSize
-= CertList
->SignatureListSize
;
954 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
967 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
969 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
970 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
972 @retval EFI_SUCCESS Image pass verification.
973 @retval EFI_SECURITY_VIOLATION Image fail verification.
977 VerifyCertPkcsSignedData (
979 IN UINTN AuthDataSize
983 // 1: Find certificate from DBX forbidden database for revoked certificate.
985 if (IsPkcsSignedDataVerifiedBySignatureList (AuthData
, AuthDataSize
, EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
987 // DBX is forbidden database, if Authenticode verification pass with
988 // one of the certificate in DBX, this image should be rejected.
990 return EFI_SECURITY_VIOLATION
;
994 // 2: Find certificate from DB database and try to verify authenticode struct.
996 if (IsPkcsSignedDataVerifiedBySignatureList (AuthData
, AuthDataSize
, EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
999 return EFI_SECURITY_VIOLATION
;
1004 Provide verification service for signed images, which include both signature validation
1005 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1006 MSFT Authenticode type signatures are supported.
1008 In this implementation, only verify external executables when in USER MODE.
1009 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1011 The image verification process is:
1012 If the image is signed,
1013 If the image's certificate verifies against a certificate (root or intermediate) in the allowed
1014 database (DB) and not in the forbidden database (DBX), the certificate verification is passed.
1015 If the image's hash digest is in DBX,
1019 If the Image's certificate verification failed.
1020 If the Image's Hash is in DB and not in DBX,
1024 Otherwise, the image is not signed,
1025 Is the Image's Hash in DBX?
1026 If yes, deny execution.
1027 If not, is the Image's Hash in DB?
1029 If not, deny execution.
1031 Caution: This function may receive untrusted input.
1032 PE/COFF image is external input, so this function will validate its data structure
1033 within this image buffer before use.
1035 @param[in] AuthenticationStatus
1036 This is the authentication status returned from the security
1037 measurement services for the input file.
1038 @param[in] File This is a pointer to the device path of the file that is
1039 being dispatched. This will optionally be used for logging.
1040 @param[in] FileBuffer File buffer matches the input file device path.
1041 @param[in] FileSize Size of File buffer matches the input file device path.
1042 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
1044 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
1045 FileBuffer did authenticate, and the platform policy dictates
1046 that the DXE Foundation may use the file.
1047 @retval EFI_SUCCESS The device path specified by NULL device path DevicePath
1048 and non-NULL FileBuffer did authenticate, and the platform
1049 policy dictates that the DXE Foundation may execute the image in
1051 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1052 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1053 the platform policy dictates that File should be placed
1054 in the untrusted state. The image has been added to the file
1056 @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not
1057 authenticate, and the platform policy dictates that the DXE
1058 Foundation many not use File.
1063 DxeImageVerificationHandler (
1064 IN UINT32 AuthenticationStatus
,
1065 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1066 IN VOID
*FileBuffer
,
1068 IN BOOLEAN BootPolicy
1073 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1074 EFI_STATUS VerifyStatus
;
1075 EFI_SIGNATURE_LIST
*SignatureList
;
1076 UINTN SignatureListSize
;
1077 EFI_SIGNATURE_DATA
*Signature
;
1078 EFI_IMAGE_EXECUTION_ACTION Action
;
1079 WIN_CERTIFICATE
*WinCertificate
;
1082 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1083 UINT32 NumberOfRvaAndSizes
;
1085 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1086 WIN_CERTIFICATE_UEFI_GUID
*WinCertUefiGuid
;
1089 EFI_IMAGE_DATA_DIRECTORY
*SecDataDir
;
1091 SignatureList
= NULL
;
1092 SignatureListSize
= 0;
1093 WinCertificate
= NULL
;
1095 PkcsCertData
= NULL
;
1096 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1097 Status
= EFI_ACCESS_DENIED
;
1099 // Check the image type and get policy setting.
1101 switch (GetImageType (File
)) {
1104 Policy
= ALWAYS_EXECUTE
;
1107 case IMAGE_FROM_OPTION_ROM
:
1108 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1111 case IMAGE_FROM_REMOVABLE_MEDIA
:
1112 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1115 case IMAGE_FROM_FIXED_MEDIA
:
1116 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1120 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1124 // If policy is always/never execute, return directly.
1126 if (Policy
== ALWAYS_EXECUTE
) {
1128 } else if (Policy
== NEVER_EXECUTE
) {
1129 return EFI_ACCESS_DENIED
;
1132 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBoot
, NULL
);
1134 // Skip verification if SecureBoot variable doesn't exist.
1136 if (SecureBoot
== NULL
) {
1141 // Skip verification if SecureBoot is disabled.
1143 if (*SecureBoot
== SECURE_BOOT_MODE_DISABLE
) {
1144 FreePool (SecureBoot
);
1147 FreePool (SecureBoot
);
1150 // Read the Dos header.
1152 if (FileBuffer
== NULL
) {
1153 return EFI_INVALID_PARAMETER
;
1156 mImageBase
= (UINT8
*) FileBuffer
;
1157 mImageSize
= FileSize
;
1159 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1160 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1161 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeImageVerificationLibImageRead
;
1164 // Get information about the image being loaded
1166 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1167 if (EFI_ERROR (Status
)) {
1169 // The information can't be got from the invalid PeImage
1174 Status
= EFI_ACCESS_DENIED
;
1176 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1177 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1179 // DOS image header is present,
1180 // so read the PE header after the DOS image header.
1182 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1184 mPeCoffHeaderOffset
= 0;
1187 // Check PE/COFF image.
1189 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1190 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1192 // It is not a valid Pe/Coff file.
1197 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1199 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1200 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1201 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1202 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1204 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1207 // Get the magic value from the PE/COFF Optional Header
1209 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1212 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1216 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1217 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1218 SecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1222 // Use PE32+ offset.
1224 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1225 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1226 SecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1230 if ((SecDataDir
== NULL
) || ((SecDataDir
!= NULL
) && (SecDataDir
->Size
== 0))) {
1232 // This image is not signed.
1234 if (!HashPeImage (HASHALG_SHA256
)) {
1238 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1240 // Image Hash is in forbidden database (DBX).
1245 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1247 // Image Hash is in allowed database (DB).
1253 // Image Hash is not found in both forbidden and allowed database.
1259 // Verify signature of executables.
1261 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ SecDataDir
->VirtualAddress
);
1263 CertSize
= sizeof (WIN_CERTIFICATE
);
1265 if ((SecDataDir
->Size
<= CertSize
) || (SecDataDir
->Size
< WinCertificate
->dwLength
)) {
1270 // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
1272 if (WinCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1274 // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
1275 // Authenticode specification.
1277 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) WinCertificate
;
1278 if (PkcsCertData
->Hdr
.dwLength
<= sizeof (PkcsCertData
->Hdr
)) {
1281 AuthData
= PkcsCertData
->CertData
;
1282 AuthDataSize
= PkcsCertData
->Hdr
.dwLength
- sizeof(PkcsCertData
->Hdr
);
1284 Status
= HashPeImageByType (AuthData
, AuthDataSize
);
1285 if (EFI_ERROR (Status
)) {
1289 VerifyStatus
= VerifyCertPkcsSignedData (AuthData
, AuthDataSize
);
1290 } else if (WinCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1292 // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
1294 WinCertUefiGuid
= (WIN_CERTIFICATE_UEFI_GUID
*) WinCertificate
;
1295 if (!CompareGuid(&WinCertUefiGuid
->CertType
, &gEfiCertPkcs7Guid
) ||
1296 (WinCertUefiGuid
->Hdr
.dwLength
<= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID
, CertData
))) {
1299 AuthData
= WinCertUefiGuid
->CertData
;
1300 AuthDataSize
= WinCertUefiGuid
->Hdr
.dwLength
- OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID
, CertData
);
1302 Status
= HashPeImageByType (AuthData
, AuthDataSize
);
1303 if (EFI_ERROR (Status
)) {
1306 VerifyStatus
= VerifyCertPkcsSignedData (AuthData
, AuthDataSize
);
1311 if (!EFI_ERROR (VerifyStatus
)) {
1313 // Verification is passed.
1314 // Continue to check the image digest in signature database.
1316 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1318 // Executable signature verification passes, but is found in forbidden signature database.
1320 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1321 Status
= EFI_ACCESS_DENIED
;
1324 // For image verification against enrolled X.509 certificate(root or intermediate),
1325 // no need to check image's hash in the allowed database.
1331 // Verification failure.
1333 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1334 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1336 // Verification fail, Image Hash is not in forbidden database (DBX),
1337 // and Image Hash is in allowed database (DB).
1339 Status
= EFI_SUCCESS
;
1341 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1342 Status
= EFI_ACCESS_DENIED
;
1346 if (EFI_ERROR (Status
)) {
1348 // Get image hash value as executable's signature.
1350 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1351 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1352 if (SignatureList
== NULL
) {
1353 Status
= EFI_OUT_OF_RESOURCES
;
1356 SignatureList
->SignatureHeaderSize
= 0;
1357 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1358 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1359 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1360 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1361 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1365 if (Status
!= EFI_SUCCESS
) {
1367 // Policy decides to defer or reject the image; add its information in image executable information table.
1369 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1370 Status
= EFI_SECURITY_VIOLATION
;
1373 if (SignatureList
!= NULL
) {
1374 FreePool (SignatureList
);
1381 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1383 @param[in] Event Event whose notification function is being invoked.
1384 @param[in] Context Pointer to the notification function's context.
1389 VariableWriteCallBack (
1394 UINT8 SecureBootMode
;
1395 UINT8
*SecureBootModePtr
;
1397 VOID
*ProtocolPointer
;
1399 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1400 if (EFI_ERROR (Status
)) {
1405 // Check whether "SecureBoot" variable exists.
1406 // If this library is built-in, it means firmware has capability to perform
1407 // driver signing verification.
1409 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBootModePtr
, NULL
);
1410 if (SecureBootModePtr
== NULL
) {
1411 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1413 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1416 EFI_SECURE_BOOT_MODE_NAME
,
1417 &gEfiGlobalVariableGuid
,
1418 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1423 FreePool (SecureBootModePtr
);
1428 Register security measurement handler.
1430 @param ImageHandle ImageHandle of the loaded driver.
1431 @param SystemTable Pointer to the EFI System Table.
1433 @retval EFI_SUCCESS The handlers were registered successfully.
1437 DxeImageVerificationLibConstructor (
1438 IN EFI_HANDLE ImageHandle
,
1439 IN EFI_SYSTEM_TABLE
*SystemTable
1445 // Register callback function upon VariableWriteArchProtocol.
1447 EfiCreateProtocolNotifyEvent (
1448 &gEfiVariableWriteArchProtocolGuid
,
1450 VariableWriteCallBack
,
1455 return RegisterSecurity2Handler (
1456 DxeImageVerificationHandler
,
1457 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED