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 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
60 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
64 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
67 HASH_TABLE mHash
[] = {
68 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
69 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
70 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
71 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
72 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
76 Reads contents of a PE/COFF image in memory buffer.
78 Caution: This function may receive untrusted input.
79 PE/COFF image is external input, so this function will make sure the PE/COFF image content
80 read is within the image buffer.
82 @param FileHandle Pointer to the file handle to read the PE/COFF image.
83 @param FileOffset Offset into the PE/COFF image to begin the read operation.
84 @param ReadSize On input, the size in bytes of the requested read operation.
85 On output, the number of bytes actually read.
86 @param Buffer Output buffer that contains the data read from the PE/COFF image.
88 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
92 DxeImageVerificationLibImageRead (
95 IN OUT UINTN
*ReadSize
,
101 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
102 return EFI_INVALID_PARAMETER
;
105 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
106 return EFI_INVALID_PARAMETER
;
109 EndPosition
= FileOffset
+ *ReadSize
;
110 if (EndPosition
> mImageSize
) {
111 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
114 if (FileOffset
>= mImageSize
) {
118 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
127 @param[in] File This is a pointer to the device path of the file that is
130 @return UINT32 Image Type
135 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
139 EFI_HANDLE DeviceHandle
;
140 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
141 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
144 return IMAGE_UNKNOWN
;
148 // First check to see if File is from a Firmware Volume
151 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
152 Status
= gBS
->LocateDevicePath (
153 &gEfiFirmwareVolume2ProtocolGuid
,
157 if (!EFI_ERROR (Status
)) {
158 Status
= gBS
->OpenProtocol (
160 &gEfiFirmwareVolume2ProtocolGuid
,
164 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
166 if (!EFI_ERROR (Status
)) {
167 return IMAGE_FROM_FV
;
172 // Next check to see if File is from a Block I/O device
175 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
176 Status
= gBS
->LocateDevicePath (
177 &gEfiBlockIoProtocolGuid
,
181 if (!EFI_ERROR (Status
)) {
183 Status
= gBS
->OpenProtocol (
185 &gEfiBlockIoProtocolGuid
,
189 EFI_OPEN_PROTOCOL_GET_PROTOCOL
191 if (!EFI_ERROR (Status
) && BlockIo
!= NULL
) {
192 if (BlockIo
->Media
!= NULL
) {
193 if (BlockIo
->Media
->RemovableMedia
) {
195 // Block I/O is present and specifies the media is removable
197 return IMAGE_FROM_REMOVABLE_MEDIA
;
200 // Block I/O is present and specifies the media is not removable
202 return IMAGE_FROM_FIXED_MEDIA
;
209 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
210 // the device path supports the Simple File System Protocol.
213 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
214 Status
= gBS
->LocateDevicePath (
215 &gEfiSimpleFileSystemProtocolGuid
,
219 if (!EFI_ERROR (Status
)) {
221 // Simple File System is present without Block I/O, so assume media is fixed.
223 return IMAGE_FROM_FIXED_MEDIA
;
227 // File is not from an FV, Block I/O or Simple File System, so the only options
228 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
230 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
231 while (!IsDevicePathEndType (TempDevicePath
)) {
232 switch (DevicePathType (TempDevicePath
)) {
234 case MEDIA_DEVICE_PATH
:
235 if (DevicePathSubType (TempDevicePath
) == MEDIA_RELATIVE_OFFSET_RANGE_DP
) {
236 return IMAGE_FROM_OPTION_ROM
;
240 case MESSAGING_DEVICE_PATH
:
241 if (DevicePathSubType(TempDevicePath
) == MSG_MAC_ADDR_DP
) {
242 return IMAGE_FROM_REMOVABLE_MEDIA
;
249 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
251 return IMAGE_UNKNOWN
;
255 Caculate hash of Pe/Coff image based on the authenticode image hashing in
256 PE/COFF Specification 8.0 Appendix A
258 Caution: This function may receive untrusted input.
259 PE/COFF image is external input, so this function will validate its data structure
260 within this image buffer before use.
262 @param[in] HashAlg Hash algorithm type.
264 @retval TRUE Successfully hash image.
265 @retval FALSE Fail in hash image.
275 EFI_IMAGE_SECTION_HEADER
*Section
;
280 UINTN SumOfBytesHashed
;
281 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
285 UINT32 NumberOfRvaAndSizes
;
288 SectionHeader
= NULL
;
291 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
296 // Initialize context of hash.
298 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
300 if (HashAlg
== HASHALG_SHA1
) {
301 mImageDigestSize
= SHA1_DIGEST_SIZE
;
302 mCertType
= gEfiCertSha1Guid
;
303 } else if (HashAlg
== HASHALG_SHA256
) {
304 mImageDigestSize
= SHA256_DIGEST_SIZE
;
305 mCertType
= gEfiCertSha256Guid
;
310 CtxSize
= mHash
[HashAlg
].GetContextSize();
312 HashCtx
= AllocatePool (CtxSize
);
313 if (HashCtx
== NULL
) {
317 // 1. Load the image header into memory.
319 // 2. Initialize a SHA hash context.
320 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
327 // Measuring PE/COFF Image Header;
328 // But CheckSum field and SECURITY data directory (certificate) are excluded
330 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
332 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
333 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
334 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
335 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
337 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
340 // Get the magic value from the PE/COFF Optional Header
342 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
346 // 3. Calculate the distance from the base of the image header to the image checksum address.
347 // 4. Hash the image header from its base to beginning of the image checksum.
349 HashBase
= mImageBase
;
350 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
354 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
355 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
356 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
360 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
361 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
364 // Invalid header magic number.
370 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
376 // 5. Skip over the image checksum (it occupies a single ULONG).
378 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
380 // 6. Since there is no Cert Directory in optional header, hash everything
381 // from the end of the checksum to the end of image header.
383 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
387 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
388 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
393 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
394 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
398 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
405 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
407 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
411 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
412 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
417 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
418 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
422 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
429 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
430 // 9. Hash everything from the end of the Cert Directory to the end of image header.
432 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
436 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
437 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
442 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
443 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
447 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
455 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
457 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
461 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
466 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
470 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
472 mPeCoffHeaderOffset
+
474 sizeof (EFI_IMAGE_FILE_HEADER
) +
475 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
479 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
480 // structures in the image. The 'NumberOfSections' field of the image
481 // header indicates how big the table should be. Do not include any
482 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
484 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
485 if (SectionHeader
== NULL
) {
490 // 12. Using the 'PointerToRawData' in the referenced section headers as
491 // a key, arrange the elements in the table in ascending order. In other
492 // words, sort the section headers according to the disk-file offset of
495 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
497 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
498 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
501 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
506 // 13. Walk through the sorted table, bring the corresponding section
507 // into memory, and hash the entire section (using the 'SizeOfRawData'
508 // field in the section header to determine the amount of data to hash).
509 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
510 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
512 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
513 Section
= &SectionHeader
[Index
];
514 if (Section
->SizeOfRawData
== 0) {
517 HashBase
= mImageBase
+ Section
->PointerToRawData
;
518 HashSize
= (UINTN
) Section
->SizeOfRawData
;
520 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
525 SumOfBytesHashed
+= HashSize
;
529 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
530 // data in the file that needs to be added to the hash. This data begins
531 // at file offset SUM_OF_BYTES_HASHED and its length is:
532 // FileSize - (CertDirectory->Size)
534 if (mImageSize
> SumOfBytesHashed
) {
535 HashBase
= mImageBase
+ SumOfBytesHashed
;
537 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
540 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
544 CertSize
= mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
549 CertSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
553 if (mImageSize
> CertSize
+ SumOfBytesHashed
) {
554 HashSize
= (UINTN
) (mImageSize
- CertSize
- SumOfBytesHashed
);
556 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
560 } else if (mImageSize
< CertSize
+ SumOfBytesHashed
) {
566 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
569 if (HashCtx
!= NULL
) {
572 if (SectionHeader
!= NULL
) {
573 FreePool (SectionHeader
);
579 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
580 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
583 Caution: This function may receive untrusted input.
584 PE/COFF image is external input, so this function will validate its data structure
585 within this image buffer before use.
587 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
588 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
590 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
591 @retval EFI_SUCCESS Hash successfully.
597 IN UINTN AuthDataSize
602 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
604 // Check the Hash algorithm in PE/COFF Authenticode.
605 // According to PKCS#7 Definition:
606 // SignedData ::= SEQUENCE {
608 // digestAlgorithms DigestAlgorithmIdentifiers,
609 // contentInfo ContentInfo,
611 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
612 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
613 // Fixed offset (+32) is calculated based on two bytes of length encoding.
615 if ((*(AuthData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
617 // Only support two bytes of Long Form of Length Encoding.
622 if (AuthDataSize
< 32 + mHash
[Index
].OidLength
) {
623 return EFI_UNSUPPORTED
;
626 if (CompareMem (AuthData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
631 if (Index
== HASHALG_MAX
) {
632 return EFI_UNSUPPORTED
;
636 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
638 if (!HashPeImage(Index
)) {
639 return EFI_UNSUPPORTED
;
647 Returns the size of a given image execution info table in bytes.
649 This function returns the size, in bytes, of the image execution info table specified by
650 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
652 @param ImageExeInfoTable A pointer to a image execution info table structure.
654 @retval 0 If ImageExeInfoTable is NULL.
655 @retval Others The size of a image execution info table in bytes.
659 GetImageExeInfoTableSize (
660 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
664 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoItem
;
667 if (ImageExeInfoTable
== NULL
) {
671 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoTable
+ sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
));
672 TotalSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
673 for (Index
= 0; Index
< ImageExeInfoTable
->NumberOfImages
; Index
++) {
674 TotalSize
+= ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
);
675 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoItem
+ ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
));
682 Create an Image Execution Information Table entry and add it to system configuration table.
684 @param[in] Action Describes the action taken by the firmware regarding this image.
685 @param[in] Name Input a null-terminated, user-friendly name.
686 @param[in] DevicePath Input device path pointer.
687 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
688 @param[in] SignatureSize Size of signature.
693 IN EFI_IMAGE_EXECUTION_ACTION Action
,
694 IN CHAR16
*Name OPTIONAL
,
695 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
696 IN EFI_SIGNATURE_LIST
*Signature OPTIONAL
,
697 IN UINTN SignatureSize
700 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
;
701 EFI_IMAGE_EXECUTION_INFO_TABLE
*NewImageExeInfoTable
;
702 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoEntry
;
703 UINTN ImageExeInfoTableSize
;
704 UINTN NewImageExeInfoEntrySize
;
706 UINTN DevicePathSize
;
708 ImageExeInfoTable
= NULL
;
709 NewImageExeInfoTable
= NULL
;
710 ImageExeInfoEntry
= NULL
;
713 if (DevicePath
== NULL
) {
718 NameStringLen
= StrSize (Name
);
721 ImageExeInfoTable
= NULL
;
722 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
**) &ImageExeInfoTable
);
723 if (ImageExeInfoTable
!= NULL
) {
725 // The table has been found!
726 // We must enlarge the table to accmodate the new exe info entry.
728 ImageExeInfoTableSize
= GetImageExeInfoTableSize (ImageExeInfoTable
);
732 // We should create a new table to append to the configuration table.
734 ImageExeInfoTableSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
737 DevicePathSize
= GetDevicePathSize (DevicePath
);
738 NewImageExeInfoEntrySize
= sizeof (EFI_IMAGE_EXECUTION_INFO
) + NameStringLen
+ DevicePathSize
+ SignatureSize
;
739 NewImageExeInfoTable
= (EFI_IMAGE_EXECUTION_INFO_TABLE
*) AllocateRuntimePool (ImageExeInfoTableSize
+ NewImageExeInfoEntrySize
);
740 if (NewImageExeInfoTable
== NULL
) {
744 if (ImageExeInfoTable
!= NULL
) {
745 CopyMem (NewImageExeInfoTable
, ImageExeInfoTable
, ImageExeInfoTableSize
);
747 NewImageExeInfoTable
->NumberOfImages
= 0;
749 NewImageExeInfoTable
->NumberOfImages
++;
750 ImageExeInfoEntry
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) NewImageExeInfoTable
+ ImageExeInfoTableSize
);
752 // Update new item's infomation.
754 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->Action
, Action
);
755 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->InfoSize
, (UINT32
) NewImageExeInfoEntrySize
);
758 CopyMem ((UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
), Name
, NameStringLen
);
761 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
,
765 if (Signature
!= NULL
) {
767 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
+ DevicePathSize
,
773 // Update/replace the image execution table.
775 gBS
->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
*) NewImageExeInfoTable
);
778 // Free Old table data!
780 if (ImageExeInfoTable
!= NULL
) {
781 FreePool (ImageExeInfoTable
);
786 Check whether signature is in specified database.
788 @param[in] VariableName Name of database variable that is searched in.
789 @param[in] Signature Pointer to signature that is searched for.
790 @param[in] CertType Pointer to hash algrithom.
791 @param[in] SignatureSize Size of Signature.
793 @return TRUE Found the signature in the variable database.
794 @return FALSE Not found the signature in the variable database.
798 IsSignatureFoundInDatabase (
799 IN CHAR16
*VariableName
,
801 IN EFI_GUID
*CertType
,
802 IN UINTN SignatureSize
806 EFI_SIGNATURE_LIST
*CertList
;
807 EFI_SIGNATURE_DATA
*Cert
;
814 // Read signature database variable.
819 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
820 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
824 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
829 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
830 if (EFI_ERROR (Status
)) {
834 // Enumerate all signature data in SigDB to check if executable's signature exists.
836 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
837 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
838 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
839 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
840 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
841 for (Index
= 0; Index
< CertCount
; Index
++) {
842 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
844 // Find the signature in database.
850 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
858 DataSize
-= CertList
->SignatureListSize
;
859 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
871 Verify PKCS#7 SignedData using certificate found in Variable which formatted
872 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
874 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
875 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
876 @param[in] VariableName Name of Variable to search for Certificate.
877 @param[in] VendorGuid Variable vendor GUID.
879 @retval TRUE Image pass verification.
880 @retval FALSE Image fail verification.
884 IsPkcsSignedDataVerifiedBySignatureList (
886 IN UINTN AuthDataSize
,
887 IN CHAR16
*VariableName
,
888 IN EFI_GUID
*VendorGuid
892 BOOLEAN VerifyStatus
;
893 EFI_SIGNATURE_LIST
*CertList
;
894 EFI_SIGNATURE_DATA
*Cert
;
907 VerifyStatus
= FALSE
;
910 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
911 if (Status
== EFI_BUFFER_TOO_SMALL
) {
912 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
917 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
918 if (EFI_ERROR (Status
)) {
923 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
925 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
926 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
927 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
928 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
929 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
930 for (Index
= 0; Index
< CertCount
; Index
++) {
932 // Iterate each Signature Data Node within this CertList for verify.
934 RootCert
= Cert
->SignatureData
;
935 RootCertSize
= CertList
->SignatureSize
- sizeof (EFI_GUID
);
938 // Call AuthenticodeVerify library to Verify Authenticode struct.
940 VerifyStatus
= AuthenticodeVerify (
951 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
954 DataSize
-= CertList
->SignatureListSize
;
955 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
968 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
970 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
971 @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
973 @retval EFI_SUCCESS Image pass verification.
974 @retval EFI_SECURITY_VIOLATION Image fail verification.
978 VerifyCertPkcsSignedData (
980 IN UINTN AuthDataSize
984 // 1: Find certificate from DBX forbidden database for revoked certificate.
986 if (IsPkcsSignedDataVerifiedBySignatureList (AuthData
, AuthDataSize
, EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
988 // DBX is forbidden database, if Authenticode verification pass with
989 // one of the certificate in DBX, this image should be rejected.
991 return EFI_SECURITY_VIOLATION
;
995 // 2: Find certificate from DB database and try to verify authenticode struct.
997 if (IsPkcsSignedDataVerifiedBySignatureList (AuthData
, AuthDataSize
, EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
1000 return EFI_SECURITY_VIOLATION
;
1005 Provide verification service for signed images, which include both signature validation
1006 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1007 MSFT Authenticode type signatures are supported.
1009 In this implementation, only verify external executables when in USER MODE.
1010 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1012 The image verification process is:
1013 If the image is signed,
1014 If the image's certificate verifies against a certificate (root or intermediate) in the allowed
1015 database (DB) and not in the forbidden database (DBX), the certificate verification is passed.
1016 If the image's hash digest is in DBX,
1020 If the Image's certificate verification failed.
1021 If the Image's Hash is in DB and not in DBX,
1025 Otherwise, the image is not signed,
1026 Is the Image's Hash in DBX?
1027 If yes, deny execution.
1028 If not, is the Image's Hash in DB?
1030 If not, deny execution.
1032 Caution: This function may receive untrusted input.
1033 PE/COFF image is external input, so this function will validate its data structure
1034 within this image buffer before use.
1036 @param[in] AuthenticationStatus
1037 This is the authentication status returned from the security
1038 measurement services for the input file.
1039 @param[in] File This is a pointer to the device path of the file that is
1040 being dispatched. This will optionally be used for logging.
1041 @param[in] FileBuffer File buffer matches the input file device path.
1042 @param[in] FileSize Size of File buffer matches the input file device path.
1043 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
1045 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
1046 FileBuffer did authenticate, and the platform policy dictates
1047 that the DXE Foundation may use the file.
1048 @retval EFI_SUCCESS The device path specified by NULL device path DevicePath
1049 and non-NULL FileBuffer did authenticate, and the platform
1050 policy dictates that the DXE Foundation may execute the image in
1052 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1053 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1054 the platform policy dictates that File should be placed
1055 in the untrusted state. The image has been added to the file
1057 @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not
1058 authenticate, and the platform policy dictates that the DXE
1059 Foundation many not use File.
1064 DxeImageVerificationHandler (
1065 IN UINT32 AuthenticationStatus
,
1066 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1067 IN VOID
*FileBuffer
,
1069 IN BOOLEAN BootPolicy
1074 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1075 EFI_STATUS VerifyStatus
;
1076 EFI_SIGNATURE_LIST
*SignatureList
;
1077 UINTN SignatureListSize
;
1078 EFI_SIGNATURE_DATA
*Signature
;
1079 EFI_IMAGE_EXECUTION_ACTION Action
;
1080 WIN_CERTIFICATE
*WinCertificate
;
1083 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1084 UINT32 NumberOfRvaAndSizes
;
1086 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1087 WIN_CERTIFICATE_UEFI_GUID
*WinCertUefiGuid
;
1090 EFI_IMAGE_DATA_DIRECTORY
*SecDataDir
;
1092 SignatureList
= NULL
;
1093 SignatureListSize
= 0;
1094 WinCertificate
= NULL
;
1096 PkcsCertData
= NULL
;
1097 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1098 Status
= EFI_ACCESS_DENIED
;
1100 // Check the image type and get policy setting.
1102 switch (GetImageType (File
)) {
1105 Policy
= ALWAYS_EXECUTE
;
1108 case IMAGE_FROM_OPTION_ROM
:
1109 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1112 case IMAGE_FROM_REMOVABLE_MEDIA
:
1113 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1116 case IMAGE_FROM_FIXED_MEDIA
:
1117 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1121 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1125 // If policy is always/never execute, return directly.
1127 if (Policy
== ALWAYS_EXECUTE
) {
1129 } else if (Policy
== NEVER_EXECUTE
) {
1130 return EFI_ACCESS_DENIED
;
1133 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBoot
, NULL
);
1135 // Skip verification if SecureBoot variable doesn't exist.
1137 if (SecureBoot
== NULL
) {
1142 // Skip verification if SecureBoot is disabled.
1144 if (*SecureBoot
== SECURE_BOOT_MODE_DISABLE
) {
1145 FreePool (SecureBoot
);
1148 FreePool (SecureBoot
);
1151 // Read the Dos header.
1153 if (FileBuffer
== NULL
) {
1154 return EFI_INVALID_PARAMETER
;
1157 mImageBase
= (UINT8
*) FileBuffer
;
1158 mImageSize
= FileSize
;
1160 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1161 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1162 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeImageVerificationLibImageRead
;
1165 // Get information about the image being loaded
1167 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1168 if (EFI_ERROR (Status
)) {
1170 // The information can't be got from the invalid PeImage
1175 Status
= EFI_ACCESS_DENIED
;
1177 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1178 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1180 // DOS image header is present,
1181 // so read the PE header after the DOS image header.
1183 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1185 mPeCoffHeaderOffset
= 0;
1188 // Check PE/COFF image.
1190 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1191 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1193 // It is not a valid Pe/Coff file.
1198 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1200 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1201 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1202 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1203 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1205 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1208 // Get the magic value from the PE/COFF Optional Header
1210 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1213 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1217 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1218 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1219 SecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1223 // Use PE32+ offset.
1225 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1226 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1227 SecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1231 if ((SecDataDir
== NULL
) || ((SecDataDir
!= NULL
) && (SecDataDir
->Size
== 0))) {
1233 // This image is not signed.
1235 if (!HashPeImage (HASHALG_SHA256
)) {
1239 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1241 // Image Hash is in forbidden database (DBX).
1246 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1248 // Image Hash is in allowed database (DB).
1254 // Image Hash is not found in both forbidden and allowed database.
1260 // Verify signature of executables.
1262 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ SecDataDir
->VirtualAddress
);
1264 CertSize
= sizeof (WIN_CERTIFICATE
);
1266 if ((SecDataDir
->Size
<= CertSize
) || (SecDataDir
->Size
< WinCertificate
->dwLength
)) {
1271 // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
1273 if (WinCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1275 // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
1276 // Authenticode specification.
1278 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) WinCertificate
;
1279 AuthData
= PkcsCertData
->CertData
;
1280 AuthDataSize
= PkcsCertData
->Hdr
.dwLength
- sizeof(PkcsCertData
->Hdr
);
1282 Status
= HashPeImageByType (AuthData
, AuthDataSize
);
1283 if (EFI_ERROR (Status
)) {
1287 VerifyStatus
= VerifyCertPkcsSignedData (AuthData
, AuthDataSize
);
1288 } else if (WinCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1290 // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
1292 WinCertUefiGuid
= (WIN_CERTIFICATE_UEFI_GUID
*) WinCertificate
;
1293 if (!CompareGuid(&WinCertUefiGuid
->CertType
, &gEfiCertPkcs7Guid
)) {
1296 AuthData
= WinCertUefiGuid
->CertData
;
1297 AuthDataSize
= WinCertUefiGuid
->Hdr
.dwLength
- OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID
, CertData
);
1299 Status
= HashPeImageByType (AuthData
, AuthDataSize
);
1300 if (EFI_ERROR (Status
)) {
1303 VerifyStatus
= VerifyCertPkcsSignedData (AuthData
, AuthDataSize
);
1308 if (!EFI_ERROR (VerifyStatus
)) {
1310 // Verification is passed.
1311 // Continue to check the image digest in signature database.
1313 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1315 // Executable signature verification passes, but is found in forbidden signature database.
1317 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1318 Status
= EFI_ACCESS_DENIED
;
1321 // For image verification against enrolled X.509 certificate(root or intermediate),
1322 // no need to check image's hash in the allowed database.
1328 // Verification failure.
1330 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1331 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1333 // Verification fail, Image Hash is not in forbidden database (DBX),
1334 // and Image Hash is in allowed database (DB).
1336 Status
= EFI_SUCCESS
;
1338 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1339 Status
= EFI_ACCESS_DENIED
;
1343 if (EFI_ERROR (Status
)) {
1345 // Get image hash value as executable's signature.
1347 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1348 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1349 if (SignatureList
== NULL
) {
1350 Status
= EFI_OUT_OF_RESOURCES
;
1353 SignatureList
->SignatureHeaderSize
= 0;
1354 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1355 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1356 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1357 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1358 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1362 if (Status
!= EFI_SUCCESS
) {
1364 // Policy decides to defer or reject the image; add its information in image executable information table.
1366 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1367 Status
= EFI_SECURITY_VIOLATION
;
1370 if (SignatureList
!= NULL
) {
1371 FreePool (SignatureList
);
1378 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1380 @param[in] Event Event whose notification function is being invoked.
1381 @param[in] Context Pointer to the notification function's context.
1386 VariableWriteCallBack (
1391 UINT8 SecureBootMode
;
1392 UINT8
*SecureBootModePtr
;
1394 VOID
*ProtocolPointer
;
1396 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1397 if (EFI_ERROR (Status
)) {
1402 // Check whether "SecureBoot" variable exists.
1403 // If this library is built-in, it means firmware has capability to perform
1404 // driver signing verification.
1406 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBootModePtr
, NULL
);
1407 if (SecureBootModePtr
== NULL
) {
1408 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1410 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1413 EFI_SECURE_BOOT_MODE_NAME
,
1414 &gEfiGlobalVariableGuid
,
1415 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1420 FreePool (SecureBootModePtr
);
1425 Register security measurement handler.
1427 @param ImageHandle ImageHandle of the loaded driver.
1428 @param SystemTable Pointer to the EFI System Table.
1430 @retval EFI_SUCCESS The handlers were registered successfully.
1434 DxeImageVerificationLibConstructor (
1435 IN EFI_HANDLE ImageHandle
,
1436 IN EFI_SYSTEM_TABLE
*SystemTable
1442 // Register callback function upon VariableWriteArchProtocol.
1444 EfiCreateProtocolNotifyEvent (
1445 &gEfiVariableWriteArchProtocolGuid
,
1447 VariableWriteCallBack
,
1452 return RegisterSecurity2Handler (
1453 DxeImageVerificationHandler
,
1454 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED