2 Implement image verification services for secure boot service in UEFI2.3.1.
4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "DxeImageVerificationLib.h"
17 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
19 UINT32 mPeCoffHeaderOffset
;
20 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
21 UINTN mImageDigestSize
;
22 EFI_IMAGE_DATA_DIRECTORY
*mSecDataDir
= NULL
;
23 UINT8
*mImageBase
= NULL
;
27 // Notify string for authorization UI.
29 CHAR16 mNotifyString1
[MAX_NOTIFY_STRING_LEN
] = L
"Image verification pass but not found in authorized database!";
30 CHAR16 mNotifyString2
[MAX_NOTIFY_STRING_LEN
] = L
"Launch this image anyway? (Yes/Defer/No)";
32 // Public Exponent of RSA Key.
34 CONST UINT8 mRsaE
[] = { 0x01, 0x00, 0x01 };
38 // OID ASN.1 Value for Hash Algorithms
40 UINT8 mHashOidValue
[] = {
41 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
42 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
43 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
44 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
45 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
46 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
49 HASH_TABLE mHash
[] = {
50 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
51 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
52 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
53 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
54 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
58 Reads contents of a PE/COFF image in memory buffer.
60 @param FileHandle Pointer to the file handle to read the PE/COFF image.
61 @param FileOffset Offset into the PE/COFF image to begin the read operation.
62 @param ReadSize On input, the size in bytes of the requested read operation.
63 On output, the number of bytes actually read.
64 @param Buffer Output buffer that contains the data read from the PE/COFF image.
66 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
70 DxeImageVerificationLibImageRead (
73 IN OUT UINTN
*ReadSize
,
79 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
80 return EFI_INVALID_PARAMETER
;
83 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
84 return EFI_INVALID_PARAMETER
;
87 EndPosition
= FileOffset
+ *ReadSize
;
88 if (EndPosition
> mImageSize
) {
89 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
92 if (FileOffset
>= mImageSize
) {
96 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
105 @param[in] File This is a pointer to the device path of the file that is
108 @return UINT32 Image Type
113 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
117 EFI_HANDLE DeviceHandle
;
118 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
119 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
122 // First check to see if File is from a Firmware Volume
125 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
126 Status
= gBS
->LocateDevicePath (
127 &gEfiFirmwareVolume2ProtocolGuid
,
131 if (!EFI_ERROR (Status
)) {
132 Status
= gBS
->OpenProtocol (
134 &gEfiFirmwareVolume2ProtocolGuid
,
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
140 if (!EFI_ERROR (Status
)) {
141 return IMAGE_FROM_FV
;
146 // Next check to see if File is from a Block I/O device
149 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
150 Status
= gBS
->LocateDevicePath (
151 &gEfiBlockIoProtocolGuid
,
155 if (!EFI_ERROR (Status
)) {
157 Status
= gBS
->OpenProtocol (
159 &gEfiBlockIoProtocolGuid
,
163 EFI_OPEN_PROTOCOL_GET_PROTOCOL
165 if (!EFI_ERROR (Status
) && BlockIo
!= NULL
) {
166 if (BlockIo
->Media
!= NULL
) {
167 if (BlockIo
->Media
->RemovableMedia
) {
169 // Block I/O is present and specifies the media is removable
171 return IMAGE_FROM_REMOVABLE_MEDIA
;
174 // Block I/O is present and specifies the media is not removable
176 return IMAGE_FROM_FIXED_MEDIA
;
183 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
184 // the device path supports the Simple File System Protocol.
187 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
188 Status
= gBS
->LocateDevicePath (
189 &gEfiSimpleFileSystemProtocolGuid
,
193 if (!EFI_ERROR (Status
)) {
195 // Simple File System is present without Block I/O, so assume media is fixed.
197 return IMAGE_FROM_FIXED_MEDIA
;
201 // File is not from an FV, Block I/O or Simple File System, so the only options
202 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
204 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
205 while (!IsDevicePathEndType (TempDevicePath
)) {
206 switch (DevicePathType (TempDevicePath
)) {
208 case MEDIA_DEVICE_PATH
:
209 if (DevicePathSubType (TempDevicePath
) == MEDIA_RELATIVE_OFFSET_RANGE_DP
) {
210 return IMAGE_FROM_OPTION_ROM
;
214 case MESSAGING_DEVICE_PATH
:
215 if (DevicePathSubType(TempDevicePath
) == MSG_MAC_ADDR_DP
) {
216 return IMAGE_FROM_REMOVABLE_MEDIA
;
223 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
225 return IMAGE_UNKNOWN
;
229 Caculate hash of Pe/Coff image based on the authenticode image hashing in
230 PE/COFF Specification 8.0 Appendix A
232 @param[in] HashAlg Hash algorithm type.
234 @retval TRUE Successfully hash image.
235 @retval FALSE Fail in hash image.
245 EFI_IMAGE_SECTION_HEADER
*Section
;
250 UINTN SumOfBytesHashed
;
251 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
255 UINT32 NumberOfRvaAndSizes
;
258 SectionHeader
= NULL
;
261 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
266 // Initialize context of hash.
268 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
270 if (HashAlg
== HASHALG_SHA1
) {
271 mImageDigestSize
= SHA1_DIGEST_SIZE
;
272 mCertType
= gEfiCertSha1Guid
;
273 } else if (HashAlg
== HASHALG_SHA256
) {
274 mImageDigestSize
= SHA256_DIGEST_SIZE
;
275 mCertType
= gEfiCertSha256Guid
;
280 CtxSize
= mHash
[HashAlg
].GetContextSize();
282 HashCtx
= AllocatePool (CtxSize
);
283 if (HashCtx
== NULL
) {
287 // 1. Load the image header into memory.
289 // 2. Initialize a SHA hash context.
290 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
297 // Measuring PE/COFF Image Header;
298 // But CheckSum field and SECURITY data directory (certificate) are excluded
300 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
302 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
303 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
304 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
305 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
307 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
310 // Get the magic value from the PE/COFF Optional Header
312 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
316 // 3. Calculate the distance from the base of the image header to the image checksum address.
317 // 4. Hash the image header from its base to beginning of the image checksum.
319 HashBase
= mImageBase
;
320 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
324 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
325 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
326 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
330 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
331 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
334 // Invalid header magic number.
340 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
346 // 5. Skip over the image checksum (it occupies a single ULONG).
348 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
350 // 6. Since there is no Cert Directory in optional header, hash everything
351 // from the end of the checksum to the end of image header.
353 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
357 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
358 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
363 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
364 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
368 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
375 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
377 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
381 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
382 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
387 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
388 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
392 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
399 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
400 // 9. Hash everything from the end of the Cert Directory to the end of image header.
402 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
406 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
407 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
412 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
413 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- mImageBase
);
417 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
425 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
427 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
431 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
436 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
440 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
442 mPeCoffHeaderOffset
+
444 sizeof (EFI_IMAGE_FILE_HEADER
) +
445 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
449 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
450 // structures in the image. The 'NumberOfSections' field of the image
451 // header indicates how big the table should be. Do not include any
452 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
454 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
455 if (SectionHeader
== NULL
) {
460 // 12. Using the 'PointerToRawData' in the referenced section headers as
461 // a key, arrange the elements in the table in ascending order. In other
462 // words, sort the section headers according to the disk-file offset of
465 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
467 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
468 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
471 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
476 // 13. Walk through the sorted table, bring the corresponding section
477 // into memory, and hash the entire section (using the 'SizeOfRawData'
478 // field in the section header to determine the amount of data to hash).
479 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
480 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
482 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
483 Section
= &SectionHeader
[Index
];
484 if (Section
->SizeOfRawData
== 0) {
487 HashBase
= mImageBase
+ Section
->PointerToRawData
;
488 HashSize
= (UINTN
) Section
->SizeOfRawData
;
490 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
495 SumOfBytesHashed
+= HashSize
;
499 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
500 // data in the file that needs to be added to the hash. This data begins
501 // at file offset SUM_OF_BYTES_HASHED and its length is:
502 // FileSize - (CertDirectory->Size)
504 if (mImageSize
> SumOfBytesHashed
) {
505 HashBase
= mImageBase
+ SumOfBytesHashed
;
507 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
510 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
514 CertSize
= mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
519 CertSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
523 if (mImageSize
> CertSize
+ SumOfBytesHashed
) {
524 HashSize
= (UINTN
) (mImageSize
- CertSize
- SumOfBytesHashed
);
526 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
530 } else if (mImageSize
< CertSize
+ SumOfBytesHashed
) {
536 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
539 if (HashCtx
!= NULL
) {
542 if (SectionHeader
!= NULL
) {
543 FreePool (SectionHeader
);
549 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
550 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
553 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
554 @retval EFI_SUCCESS Hash successfully.
563 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
565 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
567 if (PkcsCertData
->Hdr
.dwLength
< sizeof (WIN_CERTIFICATE_EFI_PKCS
) + 32) {
568 return EFI_UNSUPPORTED
;
571 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
573 // Check the Hash algorithm in PE/COFF Authenticode.
574 // According to PKCS#7 Definition:
575 // SignedData ::= SEQUENCE {
577 // digestAlgorithms DigestAlgorithmIdentifiers,
578 // contentInfo ContentInfo,
580 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
581 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
582 // Fixed offset (+32) is calculated based on two bytes of length encoding.
584 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
586 // Only support two bytes of Long Form of Length Encoding.
591 if (PkcsCertData
->Hdr
.dwLength
< sizeof (WIN_CERTIFICATE_EFI_PKCS
) + 32 + mHash
[Index
].OidLength
) {
592 return EFI_UNSUPPORTED
;
595 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
600 if (Index
== HASHALG_MAX
) {
601 return EFI_UNSUPPORTED
;
605 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
607 if (!HashPeImage(Index
)) {
608 return EFI_UNSUPPORTED
;
616 Returns the size of a given image execution info table in bytes.
618 This function returns the size, in bytes, of the image execution info table specified by
619 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
621 @param ImageExeInfoTable A pointer to a image execution info table structure.
623 @retval 0 If ImageExeInfoTable is NULL.
624 @retval Others The size of a image execution info table in bytes.
628 GetImageExeInfoTableSize (
629 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
633 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoItem
;
636 if (ImageExeInfoTable
== NULL
) {
640 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoTable
+ sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
));
641 TotalSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
642 for (Index
= 0; Index
< ImageExeInfoTable
->NumberOfImages
; Index
++) {
643 TotalSize
+= ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
);
644 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoItem
+ ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
));
651 Create an Image Execution Information Table entry and add it to system configuration table.
653 @param[in] Action Describes the action taken by the firmware regarding this image.
654 @param[in] Name Input a null-terminated, user-friendly name.
655 @param[in] DevicePath Input device path pointer.
656 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
657 @param[in] SignatureSize Size of signature.
662 IN EFI_IMAGE_EXECUTION_ACTION Action
,
663 IN CHAR16
*Name OPTIONAL
,
664 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
665 IN EFI_SIGNATURE_LIST
*Signature OPTIONAL
,
666 IN UINTN SignatureSize
669 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
;
670 EFI_IMAGE_EXECUTION_INFO_TABLE
*NewImageExeInfoTable
;
671 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoEntry
;
672 UINTN ImageExeInfoTableSize
;
673 UINTN NewImageExeInfoEntrySize
;
675 UINTN DevicePathSize
;
677 ImageExeInfoTable
= NULL
;
678 NewImageExeInfoTable
= NULL
;
679 ImageExeInfoEntry
= NULL
;
682 if (DevicePath
== NULL
) {
687 NameStringLen
= StrSize (Name
);
690 ImageExeInfoTable
= NULL
;
691 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
**) &ImageExeInfoTable
);
692 if (ImageExeInfoTable
!= NULL
) {
694 // The table has been found!
695 // We must enlarge the table to accmodate the new exe info entry.
697 ImageExeInfoTableSize
= GetImageExeInfoTableSize (ImageExeInfoTable
);
701 // We should create a new table to append to the configuration table.
703 ImageExeInfoTableSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
706 DevicePathSize
= GetDevicePathSize (DevicePath
);
707 NewImageExeInfoEntrySize
= sizeof (EFI_IMAGE_EXECUTION_INFO
) + NameStringLen
+ DevicePathSize
+ SignatureSize
;
708 NewImageExeInfoTable
= (EFI_IMAGE_EXECUTION_INFO_TABLE
*) AllocateRuntimePool (ImageExeInfoTableSize
+ NewImageExeInfoEntrySize
);
709 if (NewImageExeInfoTable
== NULL
) {
713 if (ImageExeInfoTable
!= NULL
) {
714 CopyMem (NewImageExeInfoTable
, ImageExeInfoTable
, ImageExeInfoTableSize
);
716 NewImageExeInfoTable
->NumberOfImages
= 0;
718 NewImageExeInfoTable
->NumberOfImages
++;
719 ImageExeInfoEntry
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) NewImageExeInfoTable
+ ImageExeInfoTableSize
);
721 // Update new item's infomation.
723 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->Action
, Action
);
724 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->InfoSize
, (UINT32
) NewImageExeInfoEntrySize
);
727 CopyMem ((UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
), Name
, NameStringLen
);
730 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
,
734 if (Signature
!= NULL
) {
736 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
+ DevicePathSize
,
742 // Update/replace the image execution table.
744 gBS
->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
*) NewImageExeInfoTable
);
747 // Free Old table data!
749 if (ImageExeInfoTable
!= NULL
) {
750 FreePool (ImageExeInfoTable
);
755 Discover if the UEFI image is authorized by user's policy setting.
757 @param[in] Policy Specify platform's policy setting.
759 @retval EFI_ACCESS_DENIED Image is not allowed to run.
760 @retval EFI_SECURITY_VIOLATION Image is deferred.
761 @retval EFI_SUCCESS Image is authorized to run.
772 Status
= EFI_ACCESS_DENIED
;
776 case QUERY_USER_ON_SECURITY_VIOLATION
:
778 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, mNotifyString1
, mNotifyString2
, NULL
);
779 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
780 Status
= EFI_SUCCESS
;
782 } else if (Key
.UnicodeChar
== L
'N' || Key
.UnicodeChar
== L
'n') {
783 Status
= EFI_ACCESS_DENIED
;
785 } else if (Key
.UnicodeChar
== L
'D' || Key
.UnicodeChar
== L
'd') {
786 Status
= EFI_SECURITY_VIOLATION
;
792 case ALLOW_EXECUTE_ON_SECURITY_VIOLATION
:
793 Status
= EFI_SUCCESS
;
796 case DEFER_EXECUTE_ON_SECURITY_VIOLATION
:
797 Status
= EFI_SECURITY_VIOLATION
;
800 case DENY_EXECUTE_ON_SECURITY_VIOLATION
:
801 Status
= EFI_ACCESS_DENIED
;
809 Check whether signature is in specified database.
811 @param[in] VariableName Name of database variable that is searched in.
812 @param[in] Signature Pointer to signature that is searched for.
813 @param[in] CertType Pointer to hash algrithom.
814 @param[in] SignatureSize Size of Signature.
816 @return TRUE Found the signature in the variable database.
817 @return FALSE Not found the signature in the variable database.
821 IsSignatureFoundInDatabase (
822 IN CHAR16
*VariableName
,
824 IN EFI_GUID
*CertType
,
825 IN UINTN SignatureSize
829 EFI_SIGNATURE_LIST
*CertList
;
830 EFI_SIGNATURE_DATA
*Cert
;
837 // Read signature database variable.
842 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
843 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
847 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
852 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
853 if (EFI_ERROR (Status
)) {
857 // Enumerate all signature data in SigDB to check if executable's signature exists.
859 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
860 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
861 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
862 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
863 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
864 for (Index
= 0; Index
< CertCount
; Index
++) {
865 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
867 // Find the signature in database.
873 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
881 DataSize
-= CertList
->SignatureListSize
;
882 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
894 Verify PKCS#7 SignedData using certificate found in Variable which formatted
895 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
897 @param VariableName Name of Variable to search for Certificate.
898 @param VendorGuid Variable vendor GUID.
900 @retval TRUE Image pass verification.
901 @retval FALSE Image fail verification.
905 IsPkcsSignedDataVerifiedBySignatureList (
906 IN CHAR16
*VariableName
,
907 IN EFI_GUID
*VendorGuid
911 BOOLEAN VerifyStatus
;
912 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
913 EFI_SIGNATURE_LIST
*CertList
;
914 EFI_SIGNATURE_DATA
*Cert
;
927 VerifyStatus
= FALSE
;
928 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
931 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
932 if (Status
== EFI_BUFFER_TOO_SMALL
) {
933 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
938 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
939 if (EFI_ERROR (Status
)) {
944 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
946 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
947 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
948 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
949 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
950 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
951 for (Index
= 0; Index
< CertCount
; Index
++) {
953 // Iterate each Signature Data Node within this CertList for verify.
955 RootCert
= Cert
->SignatureData
;
956 RootCertSize
= CertList
->SignatureSize
;
959 // Call AuthenticodeVerify library to Verify Authenticode struct.
961 VerifyStatus
= AuthenticodeVerify (
962 PkcsCertData
->CertData
,
963 PkcsCertData
->Hdr
.dwLength
- sizeof(PkcsCertData
->Hdr
),
972 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
975 DataSize
-= CertList
->SignatureListSize
;
976 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
989 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
991 @retval EFI_SUCCESS Image pass verification.
992 @retval EFI_SECURITY_VIOLATION Image fail verification.
996 VerifyCertPkcsSignedData (
1001 // 1: Find certificate from DBX forbidden database for revoked certificate.
1003 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
1005 // DBX is forbidden database, if Authenticode verification pass with
1006 // one of the certificate in DBX, this image should be rejected.
1008 return EFI_SECURITY_VIOLATION
;
1012 // 2: Find certificate from KEK database and try to verify authenticode struct.
1014 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
)) {
1019 // 3: Find certificate from DB database and try to verify authenticode struct.
1021 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
1024 return EFI_SECURITY_VIOLATION
;
1029 Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
1031 @retval EFI_SUCCESS Image pass verification.
1032 @retval EFI_SECURITY_VIOLATION Image fail verification.
1033 @retval other error value
1037 VerifyCertUefiGuid (
1042 WIN_CERTIFICATE_UEFI_GUID
*EfiCert
;
1043 EFI_SIGNATURE_LIST
*KekList
;
1044 EFI_SIGNATURE_DATA
*KekItem
;
1045 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1062 EfiCert
= (WIN_CERTIFICATE_UEFI_GUID
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1063 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) EfiCert
->CertData
;
1064 if (!CompareGuid (&EfiCert
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
)) {
1066 // Invalid Certificate Data Type.
1068 return EFI_SECURITY_VIOLATION
;
1072 // Get KEK database variable data size
1074 Result
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &KekDataSize
, NULL
);
1075 if (Result
!= EFI_BUFFER_TOO_SMALL
) {
1076 return EFI_SECURITY_VIOLATION
;
1080 // Get KEK database variable.
1082 GetEfiGlobalVariable2 (EFI_KEY_EXCHANGE_KEY_NAME
, (VOID
**)&KekList
, NULL
);
1083 if (KekList
== NULL
) {
1084 return EFI_SECURITY_VIOLATION
;
1088 // Enumerate all Kek items in this list to verify the variable certificate data.
1089 // If anyone is authenticated successfully, it means the variable is correct!
1091 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
1092 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1093 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
1094 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
1095 for (Index
= 0; Index
< KekCount
; Index
++) {
1096 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1100 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1103 KekDataSize
-= KekList
->SignatureListSize
;
1104 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1109 // Signed key is not a trust one.
1115 // Now, we found the corresponding security policy.
1116 // Verify the data payload.
1125 // Set RSA Key Components.
1126 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
1128 Status
= RsaSetKey (Rsa
, RsaKeyN
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
1132 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
1137 // Verify the signature.
1139 Status
= RsaPkcs1Verify (
1143 CertBlock
->Signature
,
1144 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
1148 if (KekList
!= NULL
) {
1157 return EFI_SECURITY_VIOLATION
;
1162 Provide verification service for signed images, which include both signature validation
1163 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1164 MSFT Authenticode type signatures are supported.
1166 In this implementation, only verify external executables when in USER MODE.
1167 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1169 The image verification process is:
1170 Is the Image signed?
1172 Does the image verify against a certificate (root or intermediate) in the allowed db?
1174 Image verification fail
1175 Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
1178 Is the Image's Hash in the forbidden database (DBX)?
1181 Is the Image's Hash in the allowed database (DB)?
1187 @param[in] AuthenticationStatus
1188 This is the authentication status returned from the security
1189 measurement services for the input file.
1190 @param[in] File This is a pointer to the device path of the file that is
1191 being dispatched. This will optionally be used for logging.
1192 @param[in] FileBuffer File buffer matches the input file device path.
1193 @param[in] FileSize Size of File buffer matches the input file device path.
1195 @retval EFI_SUCCESS The file specified by File did authenticate, and the
1196 platform policy dictates that the DXE Core may use File.
1197 @retval EFI_INVALID_PARAMETER Input argument is incorrect.
1198 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1199 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1200 the platform policy dictates that File should be placed
1201 in the untrusted state. A file may be promoted from
1202 the untrusted to the trusted state at a future time
1203 with a call to the Trust() DXE Service.
1204 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
1205 the platform policy dictates that File should not be
1206 used for any purpose.
1211 DxeImageVerificationHandler (
1212 IN UINT32 AuthenticationStatus
,
1213 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1214 IN VOID
*FileBuffer
,
1220 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1221 EFI_STATUS VerifyStatus
;
1223 EFI_SIGNATURE_LIST
*SignatureList
;
1224 UINTN SignatureListSize
;
1225 EFI_SIGNATURE_DATA
*Signature
;
1226 EFI_IMAGE_EXECUTION_ACTION Action
;
1227 WIN_CERTIFICATE
*WinCertificate
;
1229 UINT8
*SecureBootEnable
;
1230 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1231 UINT32 NumberOfRvaAndSizes
;
1235 return EFI_INVALID_PARAMETER
;
1238 SignatureList
= NULL
;
1239 SignatureListSize
= 0;
1240 WinCertificate
= NULL
;
1241 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1242 Status
= EFI_ACCESS_DENIED
;
1244 // Check the image type and get policy setting.
1246 switch (GetImageType (File
)) {
1249 Policy
= ALWAYS_EXECUTE
;
1252 case IMAGE_FROM_OPTION_ROM
:
1253 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1256 case IMAGE_FROM_REMOVABLE_MEDIA
:
1257 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1260 case IMAGE_FROM_FIXED_MEDIA
:
1261 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1265 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1269 // If policy is always/never execute, return directly.
1271 if (Policy
== ALWAYS_EXECUTE
) {
1273 } else if (Policy
== NEVER_EXECUTE
) {
1274 return EFI_ACCESS_DENIED
;
1277 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
1279 // Skip verification if SecureBootEnable variable doesn't exist.
1281 if (SecureBootEnable
== NULL
) {
1286 // Skip verification if SecureBootEnable is disabled.
1288 if (*SecureBootEnable
== SECURE_BOOT_DISABLE
) {
1289 FreePool (SecureBootEnable
);
1293 FreePool (SecureBootEnable
);
1295 GetEfiGlobalVariable2 (EFI_SETUP_MODE_NAME
, (VOID
**)&SetupMode
, NULL
);
1298 // SetupMode doesn't exist means no AuthVar driver is dispatched,
1299 // skip verification.
1301 if (SetupMode
== NULL
) {
1306 // If platform is in SETUP MODE, skip verification.
1308 if (*SetupMode
== SETUP_MODE
) {
1309 FreePool (SetupMode
);
1313 FreePool (SetupMode
);
1316 // Read the Dos header.
1318 if (FileBuffer
== NULL
) {
1319 return EFI_INVALID_PARAMETER
;
1322 mImageBase
= (UINT8
*) FileBuffer
;
1323 mImageSize
= FileSize
;
1325 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1326 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1327 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeImageVerificationLibImageRead
;
1330 // Get information about the image being loaded
1332 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1333 if (EFI_ERROR (Status
)) {
1335 // The information can't be got from the invalid PeImage
1340 Status
= EFI_ACCESS_DENIED
;
1342 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1343 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1345 // DOS image header is present,
1346 // so read the PE header after the DOS image header.
1348 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1350 mPeCoffHeaderOffset
= 0;
1353 // Check PE/COFF image.
1355 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1356 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1358 // It is not a valid Pe/Coff file.
1363 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1365 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1366 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1367 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1368 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1370 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1373 // Get the magic value from the PE/COFF Optional Header
1375 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1378 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1382 NumberOfRvaAndSizes
= mNtHeader
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1383 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1384 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1388 // Use PE32+ offset.
1390 NumberOfRvaAndSizes
= mNtHeader
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1391 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
1392 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1396 if ((mSecDataDir
== NULL
) || ((mSecDataDir
!= NULL
) && (mSecDataDir
->Size
== 0))) {
1398 // This image is not signed.
1400 if (!HashPeImage (HASHALG_SHA256
)) {
1404 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1406 // Image Hash is in forbidden database (DBX).
1411 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1413 // Image Hash is in allowed database (DB).
1419 // Image Hash is not found in both forbidden and allowed database.
1425 // Verify signature of executables.
1427 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1429 CertSize
= sizeof (WIN_CERTIFICATE
);
1431 if ((mSecDataDir
->Size
<= CertSize
) || (mSecDataDir
->Size
< WinCertificate
->dwLength
)) {
1435 switch (WinCertificate
->wCertificateType
) {
1437 case WIN_CERT_TYPE_EFI_GUID
:
1438 CertSize
= sizeof (WIN_CERTIFICATE_UEFI_GUID
) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256
) - sizeof (UINT8
);
1439 if (WinCertificate
->dwLength
< CertSize
) {
1444 // Verify UEFI GUID type.
1446 if (!HashPeImage (HASHALG_SHA256
)) {
1450 VerifyStatus
= VerifyCertUefiGuid ();
1453 case WIN_CERT_TYPE_PKCS_SIGNED_DATA
:
1455 // Verify Pkcs signed data type.
1457 Status
= HashPeImageByType();
1458 if (EFI_ERROR (Status
)) {
1462 VerifyStatus
= VerifyCertPkcsSignedData ();
1465 // For image verification against enrolled certificate(root or intermediate),
1466 // no need to check image's hash in the allowed database.
1468 if (!EFI_ERROR (VerifyStatus
)) {
1469 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1479 // Get image hash value as executable's signature.
1481 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1482 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1483 if (SignatureList
== NULL
) {
1484 Status
= EFI_OUT_OF_RESOURCES
;
1487 SignatureList
->SignatureHeaderSize
= 0;
1488 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1489 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1490 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1491 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1492 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1494 // Signature database check after verification.
1496 if (EFI_ERROR (VerifyStatus
)) {
1498 // Verification failure.
1500 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1501 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1503 // Verification fail, Image Hash is not in forbidden database (DBX),
1504 // and Image Hash is in allowed database (DB).
1506 Status
= EFI_SUCCESS
;
1508 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1509 Status
= EFI_ACCESS_DENIED
;
1511 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1513 // Executable signature verification passes, but is found in forbidden signature database.
1515 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1516 Status
= EFI_ACCESS_DENIED
;
1517 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1519 // Executable signature is found in authorized signature database.
1521 Status
= EFI_SUCCESS
;
1524 // Executable signature verification passes, but cannot be found in authorized signature database.
1525 // Get platform policy to determine the action.
1527 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED
;
1528 Status
= ImageAuthorization (Policy
);
1532 if (Status
!= EFI_SUCCESS
) {
1534 // Policy decides to defer or reject the image; add its information in image executable information table.
1536 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1539 if (SignatureList
!= NULL
) {
1540 FreePool (SignatureList
);
1547 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1549 @param[in] Event Event whose notification function is being invoked.
1550 @param[in] Context Pointer to the notification function's context.
1555 VariableWriteCallBack (
1560 UINT8 SecureBootMode
;
1561 UINT8
*SecureBootModePtr
;
1563 VOID
*ProtocolPointer
;
1565 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1566 if (EFI_ERROR (Status
)) {
1571 // Check whether "SecureBoot" variable exists.
1572 // If this library is built-in, it means firmware has capability to perform
1573 // driver signing verification.
1575 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME
, (VOID
**)&SecureBootModePtr
, NULL
);
1576 if (SecureBootModePtr
== NULL
) {
1577 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1579 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1582 EFI_SECURE_BOOT_MODE_NAME
,
1583 &gEfiGlobalVariableGuid
,
1584 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1589 FreePool (SecureBootModePtr
);
1594 Register security measurement handler.
1596 @param ImageHandle ImageHandle of the loaded driver.
1597 @param SystemTable Pointer to the EFI System Table.
1599 @retval EFI_SUCCESS The handlers were registered successfully.
1603 DxeImageVerificationLibConstructor (
1604 IN EFI_HANDLE ImageHandle
,
1605 IN EFI_SYSTEM_TABLE
*SystemTable
1611 // Register callback function upon VariableWriteArchProtocol.
1613 EfiCreateProtocolNotifyEvent (
1614 &gEfiVariableWriteArchProtocolGuid
,
1616 VariableWriteCallBack
,
1621 return RegisterSecurityHandler (
1622 DxeImageVerificationHandler
,
1623 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED