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
;
34 EFI_IMAGE_DATA_DIRECTORY
*mSecDataDir
= NULL
;
38 // Information on current PE/COFF image
41 UINT8
*mImageBase
= NULL
;
42 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
43 UINTN mImageDigestSize
;
46 // Notify string for authorization UI.
48 CHAR16 mNotifyString1
[MAX_NOTIFY_STRING_LEN
] = L
"Image verification pass but not found in authorized database!";
49 CHAR16 mNotifyString2
[MAX_NOTIFY_STRING_LEN
] = L
"Launch this image anyway? (Yes/Defer/No)";
51 // Public Exponent of RSA Key.
53 CONST UINT8 mRsaE
[] = { 0x01, 0x00, 0x01 };
57 // OID ASN.1 Value for Hash Algorithms
59 UINT8 mHashOidValue
[] = {
60 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
61 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
64 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
65 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
68 HASH_TABLE mHash
[] = {
69 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
70 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
71 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
72 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
73 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
77 Reads contents of a PE/COFF image in memory buffer.
79 Caution: This function may receive untrusted input.
80 PE/COFF image is external input, so this function will make sure the PE/COFF image content
81 read is within the image buffer.
83 @param FileHandle Pointer to the file handle to read the PE/COFF image.
84 @param FileOffset Offset into the PE/COFF image to begin the read operation.
85 @param ReadSize On input, the size in bytes of the requested read operation.
86 On output, the number of bytes actually read.
87 @param Buffer Output buffer that contains the data read from the PE/COFF image.
89 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
93 DxeImageVerificationLibImageRead (
96 IN OUT UINTN
*ReadSize
,
102 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
103 return EFI_INVALID_PARAMETER
;
106 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
107 return EFI_INVALID_PARAMETER
;
110 EndPosition
= FileOffset
+ *ReadSize
;
111 if (EndPosition
> mImageSize
) {
112 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
115 if (FileOffset
>= mImageSize
) {
119 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
128 @param[in] File This is a pointer to the device path of the file that is
131 @return UINT32 Image Type
136 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
140 EFI_HANDLE DeviceHandle
;
141 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
142 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
145 // First check to see if File is from a Firmware Volume
148 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
149 Status
= gBS
->LocateDevicePath (
150 &gEfiFirmwareVolume2ProtocolGuid
,
154 if (!EFI_ERROR (Status
)) {
155 Status
= gBS
->OpenProtocol (
157 &gEfiFirmwareVolume2ProtocolGuid
,
161 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
163 if (!EFI_ERROR (Status
)) {
164 return IMAGE_FROM_FV
;
169 // Next check to see if File is from a Block I/O device
172 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
173 Status
= gBS
->LocateDevicePath (
174 &gEfiBlockIoProtocolGuid
,
178 if (!EFI_ERROR (Status
)) {
180 Status
= gBS
->OpenProtocol (
182 &gEfiBlockIoProtocolGuid
,
186 EFI_OPEN_PROTOCOL_GET_PROTOCOL
188 if (!EFI_ERROR (Status
) && BlockIo
!= NULL
) {
189 if (BlockIo
->Media
!= NULL
) {
190 if (BlockIo
->Media
->RemovableMedia
) {
192 // Block I/O is present and specifies the media is removable
194 return IMAGE_FROM_REMOVABLE_MEDIA
;
197 // Block I/O is present and specifies the media is not removable
199 return IMAGE_FROM_FIXED_MEDIA
;
206 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
207 // the device path supports the Simple File System Protocol.
210 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
211 Status
= gBS
->LocateDevicePath (
212 &gEfiSimpleFileSystemProtocolGuid
,
216 if (!EFI_ERROR (Status
)) {
218 // Simple File System is present without Block I/O, so assume media is fixed.
220 return IMAGE_FROM_FIXED_MEDIA
;
224 // File is not from an FV, Block I/O or Simple File System, so the only options
225 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
227 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
228 while (!IsDevicePathEndType (TempDevicePath
)) {
229 switch (DevicePathType (TempDevicePath
)) {
231 case MEDIA_DEVICE_PATH
:
232 if (DevicePathSubType (TempDevicePath
) == MEDIA_RELATIVE_OFFSET_RANGE_DP
) {
233 return IMAGE_FROM_OPTION_ROM
;
237 case MESSAGING_DEVICE_PATH
:
238 if (DevicePathSubType(TempDevicePath
) == MSG_MAC_ADDR_DP
) {
239 return IMAGE_FROM_REMOVABLE_MEDIA
;
246 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
248 return IMAGE_UNKNOWN
;
252 Caculate hash of Pe/Coff image based on the authenticode image hashing in
253 PE/COFF Specification 8.0 Appendix A
255 Caution: This function may receive untrusted input.
256 PE/COFF image is external input, so this function will validate its data structure
257 within this image buffer before use.
259 @param[in] HashAlg Hash algorithm type.
261 @retval TRUE Successfully hash image.
262 @retval FALSE Fail in hash image.
272 EFI_IMAGE_SECTION_HEADER
*Section
;
277 UINTN SumOfBytesHashed
;
278 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
282 UINT32 NumberOfRvaAndSizes
;
285 SectionHeader
= NULL
;
288 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
293 // Initialize context of hash.
295 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
297 if (HashAlg
== HASHALG_SHA1
) {
298 mImageDigestSize
= SHA1_DIGEST_SIZE
;
299 mCertType
= gEfiCertSha1Guid
;
300 } else if (HashAlg
== HASHALG_SHA256
) {
301 mImageDigestSize
= SHA256_DIGEST_SIZE
;
302 mCertType
= gEfiCertSha256Guid
;
307 CtxSize
= mHash
[HashAlg
].GetContextSize();
309 HashCtx
= AllocatePool (CtxSize
);
310 if (HashCtx
== NULL
) {
314 // 1. Load the image header into memory.
316 // 2. Initialize a SHA hash context.
317 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
324 // Measuring PE/COFF Image Header;
325 // But CheckSum field and SECURITY data directory (certificate) are excluded
327 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
329 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
330 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
331 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
332 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
334 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
337 // Get the magic value from the PE/COFF Optional Header
339 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
343 // 3. Calculate the distance from the base of the image header to the image checksum address.
344 // 4. Hash the image header from its base to beginning of the image checksum.
346 HashBase
= mImageBase
;
347 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
351 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
352 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
353 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
357 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
358 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
361 // Invalid header magic number.
367 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
373 // 5. Skip over the image checksum (it occupies a single ULONG).
375 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
377 // 6. Since there is no Cert Directory in optional header, hash everything
378 // from the end of the checksum to the end of image header.
380 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
384 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
385 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
390 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
391 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
395 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
402 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
404 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
408 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
409 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
414 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
415 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
419 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
426 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
427 // 9. Hash everything from the end of the Cert Directory to the end of image header.
429 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
433 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
434 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
439 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
440 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
444 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
452 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
454 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
458 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
463 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
467 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
469 mPeCoffHeaderOffset
+
471 sizeof (EFI_IMAGE_FILE_HEADER
) +
472 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
476 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
477 // structures in the image. The 'NumberOfSections' field of the image
478 // header indicates how big the table should be. Do not include any
479 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
481 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
482 if (SectionHeader
== NULL
) {
487 // 12. Using the 'PointerToRawData' in the referenced section headers as
488 // a key, arrange the elements in the table in ascending order. In other
489 // words, sort the section headers according to the disk-file offset of
492 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
494 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
495 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
498 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
503 // 13. Walk through the sorted table, bring the corresponding section
504 // into memory, and hash the entire section (using the 'SizeOfRawData'
505 // field in the section header to determine the amount of data to hash).
506 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
507 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
509 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
510 Section
= &SectionHeader
[Index
];
511 if (Section
->SizeOfRawData
== 0) {
514 HashBase
= mImageBase
+ Section
->PointerToRawData
;
515 HashSize
= (UINTN
) Section
->SizeOfRawData
;
517 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
522 SumOfBytesHashed
+= HashSize
;
526 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
527 // data in the file that needs to be added to the hash. This data begins
528 // at file offset SUM_OF_BYTES_HASHED and its length is:
529 // FileSize - (CertDirectory->Size)
531 if (mImageSize
> SumOfBytesHashed
) {
532 HashBase
= mImageBase
+ SumOfBytesHashed
;
534 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
537 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
541 CertSize
= mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
546 CertSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
550 if (mImageSize
> CertSize
+ SumOfBytesHashed
) {
551 HashSize
= (UINTN
) (mImageSize
- CertSize
- SumOfBytesHashed
);
553 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
557 } else if (mImageSize
< CertSize
+ SumOfBytesHashed
) {
563 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
566 if (HashCtx
!= NULL
) {
569 if (SectionHeader
!= NULL
) {
570 FreePool (SectionHeader
);
576 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
577 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
580 Caution: This function may receive untrusted input.
581 PE/COFF image is external input, so this function will validate its data structure
582 within this image buffer before use.
584 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
585 @retval EFI_SUCCESS Hash successfully.
594 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
596 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
598 if (PkcsCertData
->Hdr
.dwLength
< sizeof (WIN_CERTIFICATE_EFI_PKCS
) + 32) {
599 return EFI_UNSUPPORTED
;
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 ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
617 // Only support two bytes of Long Form of Length Encoding.
622 if (PkcsCertData
->Hdr
.dwLength
< sizeof (WIN_CERTIFICATE_EFI_PKCS
) + 32 + mHash
[Index
].OidLength
) {
623 return EFI_UNSUPPORTED
;
626 if (CompareMem (PkcsCertData
->CertData
+ 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 Discover if the UEFI image is authorized by user's policy setting.
788 @param[in] Policy Specify platform's policy setting.
790 @retval EFI_ACCESS_DENIED Image is not allowed to run.
791 @retval EFI_SECURITY_VIOLATION Image is deferred.
792 @retval EFI_SUCCESS Image is authorized to run.
803 Status
= EFI_ACCESS_DENIED
;
807 case QUERY_USER_ON_SECURITY_VIOLATION
:
809 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, mNotifyString1
, mNotifyString2
, NULL
);
810 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
811 Status
= EFI_SUCCESS
;
813 } else if (Key
.UnicodeChar
== L
'N' || Key
.UnicodeChar
== L
'n') {
814 Status
= EFI_ACCESS_DENIED
;
816 } else if (Key
.UnicodeChar
== L
'D' || Key
.UnicodeChar
== L
'd') {
817 Status
= EFI_SECURITY_VIOLATION
;
823 case ALLOW_EXECUTE_ON_SECURITY_VIOLATION
:
824 Status
= EFI_SUCCESS
;
827 case DEFER_EXECUTE_ON_SECURITY_VIOLATION
:
828 Status
= EFI_SECURITY_VIOLATION
;
831 case DENY_EXECUTE_ON_SECURITY_VIOLATION
:
832 Status
= EFI_ACCESS_DENIED
;
840 Check whether signature is in specified database.
842 @param[in] VariableName Name of database variable that is searched in.
843 @param[in] Signature Pointer to signature that is searched for.
844 @param[in] CertType Pointer to hash algrithom.
845 @param[in] SignatureSize Size of Signature.
847 @return TRUE Found the signature in the variable database.
848 @return FALSE Not found the signature in the variable database.
852 IsSignatureFoundInDatabase (
853 IN CHAR16
*VariableName
,
855 IN EFI_GUID
*CertType
,
856 IN UINTN SignatureSize
860 EFI_SIGNATURE_LIST
*CertList
;
861 EFI_SIGNATURE_DATA
*Cert
;
868 // Read signature database variable.
873 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
874 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
878 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
883 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
884 if (EFI_ERROR (Status
)) {
888 // Enumerate all signature data in SigDB to check if executable's signature exists.
890 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
891 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
892 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
893 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
894 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
895 for (Index
= 0; Index
< CertCount
; Index
++) {
896 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
898 // Find the signature in database.
904 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
912 DataSize
-= CertList
->SignatureListSize
;
913 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
925 Verify PKCS#7 SignedData using certificate found in Variable which formatted
926 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
928 @param VariableName Name of Variable to search for Certificate.
929 @param VendorGuid Variable vendor GUID.
931 @retval TRUE Image pass verification.
932 @retval FALSE Image fail verification.
936 IsPkcsSignedDataVerifiedBySignatureList (
937 IN CHAR16
*VariableName
,
938 IN EFI_GUID
*VendorGuid
942 BOOLEAN VerifyStatus
;
943 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
944 EFI_SIGNATURE_LIST
*CertList
;
945 EFI_SIGNATURE_DATA
*Cert
;
958 VerifyStatus
= FALSE
;
959 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
962 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
963 if (Status
== EFI_BUFFER_TOO_SMALL
) {
964 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
969 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
970 if (EFI_ERROR (Status
)) {
975 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
977 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
978 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
979 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
980 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
981 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
982 for (Index
= 0; Index
< CertCount
; Index
++) {
984 // Iterate each Signature Data Node within this CertList for verify.
986 RootCert
= Cert
->SignatureData
;
987 RootCertSize
= CertList
->SignatureSize
- sizeof (EFI_GUID
);
990 // Call AuthenticodeVerify library to Verify Authenticode struct.
992 VerifyStatus
= AuthenticodeVerify (
993 PkcsCertData
->CertData
,
994 PkcsCertData
->Hdr
.dwLength
- sizeof(PkcsCertData
->Hdr
),
1003 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1006 DataSize
-= CertList
->SignatureListSize
;
1007 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1016 return VerifyStatus
;
1020 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
1022 @retval EFI_SUCCESS Image pass verification.
1023 @retval EFI_SECURITY_VIOLATION Image fail verification.
1027 VerifyCertPkcsSignedData (
1032 // 1: Find certificate from DBX forbidden database for revoked certificate.
1034 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
1036 // DBX is forbidden database, if Authenticode verification pass with
1037 // one of the certificate in DBX, this image should be rejected.
1039 return EFI_SECURITY_VIOLATION
;
1043 // 2: Find certificate from KEK database and try to verify authenticode struct.
1045 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
)) {
1050 // 3: Find certificate from DB database and try to verify authenticode struct.
1052 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
1055 return EFI_SECURITY_VIOLATION
;
1060 Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
1062 @retval EFI_SUCCESS Image pass verification.
1063 @retval EFI_SECURITY_VIOLATION Image fail verification.
1064 @retval other error value
1068 VerifyCertUefiGuid (
1073 WIN_CERTIFICATE_UEFI_GUID
*EfiCert
;
1074 EFI_SIGNATURE_LIST
*KekList
;
1075 EFI_SIGNATURE_DATA
*KekItem
;
1076 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1093 EfiCert
= (WIN_CERTIFICATE_UEFI_GUID
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1094 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) EfiCert
->CertData
;
1095 if (!CompareGuid (&EfiCert
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
)) {
1097 // Invalid Certificate Data Type.
1099 return EFI_SECURITY_VIOLATION
;
1103 // Get KEK database variable data size
1105 Result
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &KekDataSize
, NULL
);
1106 if (Result
!= EFI_BUFFER_TOO_SMALL
) {
1107 return EFI_SECURITY_VIOLATION
;
1111 // Get KEK database variable.
1113 GetEfiGlobalVariable2 (EFI_KEY_EXCHANGE_KEY_NAME
, (VOID
**)&KekList
, NULL
);
1114 if (KekList
== NULL
) {
1115 return EFI_SECURITY_VIOLATION
;
1119 // Enumerate all Kek items in this list to verify the variable certificate data.
1120 // If anyone is authenticated successfully, it means the variable is correct!
1122 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
1123 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1124 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
1125 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
1126 for (Index
= 0; Index
< KekCount
; Index
++) {
1127 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1131 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1134 KekDataSize
-= KekList
->SignatureListSize
;
1135 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1140 // Signed key is not a trust one.
1146 // Now, we found the corresponding security policy.
1147 // Verify the data payload.
1156 // Set RSA Key Components.
1157 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
1159 Status
= RsaSetKey (Rsa
, RsaKeyN
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
1163 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
1168 // Verify the signature.
1170 Status
= RsaPkcs1Verify (
1174 CertBlock
->Signature
,
1175 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
1179 if (KekList
!= NULL
) {
1188 return EFI_SECURITY_VIOLATION
;
1193 Provide verification service for signed images, which include both signature validation
1194 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1195 MSFT Authenticode type signatures are supported.
1197 In this implementation, only verify external executables when in USER MODE.
1198 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1200 The image verification process is:
1201 Is the Image signed?
1203 Does the image verify against a certificate (root or intermediate) in the allowed db?
1205 Image verification fail
1206 Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
1209 Is the Image's Hash in the forbidden database (DBX)?
1212 Is the Image's Hash in the allowed database (DB)?
1218 Caution: This function may receive untrusted input.
1219 PE/COFF image is external input, so this function will validate its data structure
1220 within this image buffer before use.
1222 @param[in] AuthenticationStatus
1223 This is the authentication status returned from the security
1224 measurement services for the input file.
1225 @param[in] File This is a pointer to the device path of the file that is
1226 being dispatched. This will optionally be used for logging.
1227 @param[in] FileBuffer File buffer matches the input file device path.
1228 @param[in] FileSize Size of File buffer matches the input file device path.
1230 @retval EFI_SUCCESS The file specified by File did authenticate, and the
1231 platform policy dictates that the DXE Core may use File.
1232 @retval EFI_INVALID_PARAMETER Input argument is incorrect.
1233 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1234 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1235 the platform policy dictates that File should be placed
1236 in the untrusted state. A file may be promoted from
1237 the untrusted to the trusted state at a future time
1238 with a call to the Trust() DXE Service.
1239 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
1240 the platform policy dictates that File should not be
1241 used for any purpose.
1246 DxeImageVerificationHandler (
1247 IN UINT32 AuthenticationStatus
,
1248 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1249 IN VOID
*FileBuffer
,
1255 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1256 EFI_STATUS VerifyStatus
;
1257 EFI_SIGNATURE_LIST
*SignatureList
;
1258 UINTN SignatureListSize
;
1259 EFI_SIGNATURE_DATA
*Signature
;
1260 EFI_IMAGE_EXECUTION_ACTION Action
;
1261 WIN_CERTIFICATE
*WinCertificate
;
1264 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1265 UINT32 NumberOfRvaAndSizes
;
1269 return EFI_INVALID_PARAMETER
;
1272 SignatureList
= NULL
;
1273 SignatureListSize
= 0;
1274 WinCertificate
= NULL
;
1275 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1276 Status
= EFI_ACCESS_DENIED
;
1278 // Check the image type and get policy setting.
1280 switch (GetImageType (File
)) {
1283 Policy
= ALWAYS_EXECUTE
;
1286 case IMAGE_FROM_OPTION_ROM
:
1287 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1290 case IMAGE_FROM_REMOVABLE_MEDIA
:
1291 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1294 case IMAGE_FROM_FIXED_MEDIA
:
1295 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1299 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1303 // If policy is always/never execute, return directly.
1305 if (Policy
== ALWAYS_EXECUTE
) {
1307 } else if (Policy
== NEVER_EXECUTE
) {
1308 return EFI_ACCESS_DENIED
;
1311 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBoot
, NULL
);
1313 // Skip verification if SecureBoot variable doesn't exist.
1315 if (SecureBoot
== NULL
) {
1320 // Skip verification if SecureBoot is disabled.
1322 if (*SecureBoot
== SECURE_BOOT_MODE_DISABLE
) {
1323 FreePool (SecureBoot
);
1326 FreePool (SecureBoot
);
1329 // Read the Dos header.
1331 if (FileBuffer
== NULL
) {
1332 return EFI_INVALID_PARAMETER
;
1335 mImageBase
= (UINT8
*) FileBuffer
;
1336 mImageSize
= FileSize
;
1338 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1339 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1340 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeImageVerificationLibImageRead
;
1343 // Get information about the image being loaded
1345 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1346 if (EFI_ERROR (Status
)) {
1348 // The information can't be got from the invalid PeImage
1353 Status
= EFI_ACCESS_DENIED
;
1355 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1356 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1358 // DOS image header is present,
1359 // so read the PE header after the DOS image header.
1361 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1363 mPeCoffHeaderOffset
= 0;
1366 // Check PE/COFF image.
1368 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1369 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1371 // It is not a valid Pe/Coff file.
1376 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1378 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1379 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1380 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1381 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1383 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1386 // Get the magic value from the PE/COFF Optional Header
1388 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1391 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1395 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1396 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1397 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1401 // Use PE32+ offset.
1403 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1404 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1405 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1409 if ((mSecDataDir
== NULL
) || ((mSecDataDir
!= NULL
) && (mSecDataDir
->Size
== 0))) {
1411 // This image is not signed.
1413 if (!HashPeImage (HASHALG_SHA256
)) {
1417 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1419 // Image Hash is in forbidden database (DBX).
1424 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1426 // Image Hash is in allowed database (DB).
1432 // Image Hash is not found in both forbidden and allowed database.
1438 // Verify signature of executables.
1440 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1442 CertSize
= sizeof (WIN_CERTIFICATE
);
1444 if ((mSecDataDir
->Size
<= CertSize
) || (mSecDataDir
->Size
< WinCertificate
->dwLength
)) {
1448 switch (WinCertificate
->wCertificateType
) {
1450 case WIN_CERT_TYPE_EFI_GUID
:
1451 CertSize
= sizeof (WIN_CERTIFICATE_UEFI_GUID
) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256
) - sizeof (UINT8
);
1452 if (WinCertificate
->dwLength
< CertSize
) {
1457 // Verify UEFI GUID type.
1459 if (!HashPeImage (HASHALG_SHA256
)) {
1463 VerifyStatus
= VerifyCertUefiGuid ();
1466 case WIN_CERT_TYPE_PKCS_SIGNED_DATA
:
1468 // Verify Pkcs signed data type.
1470 Status
= HashPeImageByType();
1471 if (EFI_ERROR (Status
)) {
1475 VerifyStatus
= VerifyCertPkcsSignedData ();
1478 // For image verification against enrolled certificate(root or intermediate),
1479 // no need to check image's hash in the allowed database.
1481 if (!EFI_ERROR (VerifyStatus
)) {
1482 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1492 // Get image hash value as executable's signature.
1494 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1495 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1496 if (SignatureList
== NULL
) {
1497 Status
= EFI_OUT_OF_RESOURCES
;
1500 SignatureList
->SignatureHeaderSize
= 0;
1501 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1502 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1503 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1504 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1505 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1507 // Signature database check after verification.
1509 if (EFI_ERROR (VerifyStatus
)) {
1511 // Verification failure.
1513 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1514 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1516 // Verification fail, Image Hash is not in forbidden database (DBX),
1517 // and Image Hash is in allowed database (DB).
1519 Status
= EFI_SUCCESS
;
1521 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1522 Status
= EFI_ACCESS_DENIED
;
1524 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1526 // Executable signature verification passes, but is found in forbidden signature database.
1528 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1529 Status
= EFI_ACCESS_DENIED
;
1530 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1532 // Executable signature is found in authorized signature database.
1534 Status
= EFI_SUCCESS
;
1537 // Executable signature verification passes, but cannot be found in authorized signature database.
1538 // Get platform policy to determine the action.
1540 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED
;
1541 Status
= ImageAuthorization (Policy
);
1545 if (Status
!= EFI_SUCCESS
) {
1547 // Policy decides to defer or reject the image; add its information in image executable information table.
1549 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1552 if (SignatureList
!= NULL
) {
1553 FreePool (SignatureList
);
1560 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1562 @param[in] Event Event whose notification function is being invoked.
1563 @param[in] Context Pointer to the notification function's context.
1568 VariableWriteCallBack (
1573 UINT8 SecureBootMode
;
1574 UINT8
*SecureBootModePtr
;
1576 VOID
*ProtocolPointer
;
1578 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1579 if (EFI_ERROR (Status
)) {
1584 // Check whether "SecureBoot" variable exists.
1585 // If this library is built-in, it means firmware has capability to perform
1586 // driver signing verification.
1588 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBootModePtr
, NULL
);
1589 if (SecureBootModePtr
== NULL
) {
1590 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1592 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1595 EFI_SECURE_BOOT_MODE_NAME
,
1596 &gEfiGlobalVariableGuid
,
1597 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1602 FreePool (SecureBootModePtr
);
1607 Register security measurement handler.
1609 @param ImageHandle ImageHandle of the loaded driver.
1610 @param SystemTable Pointer to the EFI System Table.
1612 @retval EFI_SUCCESS The handlers were registered successfully.
1616 DxeImageVerificationLibConstructor (
1617 IN EFI_HANDLE ImageHandle
,
1618 IN EFI_SYSTEM_TABLE
*SystemTable
1624 // Register callback function upon VariableWriteArchProtocol.
1626 EfiCreateProtocolNotifyEvent (
1627 &gEfiVariableWriteArchProtocolGuid
,
1629 VariableWriteCallBack
,
1634 return RegisterSecurityHandler (
1635 DxeImageVerificationHandler
,
1636 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED