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
}
61 @param[in] File This is a pointer to the device path of the file that is
64 @return UINT32 Image Type
69 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
73 EFI_HANDLE DeviceHandle
;
74 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
75 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
78 // First check to see if File is from a Firmware Volume
81 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
82 Status
= gBS
->LocateDevicePath (
83 &gEfiFirmwareVolume2ProtocolGuid
,
87 if (!EFI_ERROR (Status
)) {
88 Status
= gBS
->OpenProtocol (
90 &gEfiFirmwareVolume2ProtocolGuid
,
94 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
96 if (!EFI_ERROR (Status
)) {
102 // Next check to see if File is from a Block I/O device
105 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
106 Status
= gBS
->LocateDevicePath (
107 &gEfiBlockIoProtocolGuid
,
111 if (!EFI_ERROR (Status
)) {
113 Status
= gBS
->OpenProtocol (
115 &gEfiBlockIoProtocolGuid
,
119 EFI_OPEN_PROTOCOL_GET_PROTOCOL
121 if (!EFI_ERROR (Status
) && BlockIo
!= NULL
) {
122 if (BlockIo
->Media
!= NULL
) {
123 if (BlockIo
->Media
->RemovableMedia
) {
125 // Block I/O is present and specifies the media is removable
127 return IMAGE_FROM_REMOVABLE_MEDIA
;
130 // Block I/O is present and specifies the media is not removable
132 return IMAGE_FROM_FIXED_MEDIA
;
139 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
140 // the device path supports the Simple File System Protocol.
143 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
144 Status
= gBS
->LocateDevicePath (
145 &gEfiSimpleFileSystemProtocolGuid
,
149 if (!EFI_ERROR (Status
)) {
151 // Simple File System is present without Block I/O, so assume media is fixed.
153 return IMAGE_FROM_FIXED_MEDIA
;
157 // File is not from an FV, Block I/O or Simple File System, so the only options
158 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
160 TempDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) File
;
161 while (!IsDevicePathEndType (TempDevicePath
)) {
162 switch (DevicePathType (TempDevicePath
)) {
164 case MEDIA_DEVICE_PATH
:
165 if (DevicePathSubType (TempDevicePath
) == MEDIA_RELATIVE_OFFSET_RANGE_DP
) {
166 return IMAGE_FROM_OPTION_ROM
;
170 case MESSAGING_DEVICE_PATH
:
171 if (DevicePathSubType(TempDevicePath
) == MSG_MAC_ADDR_DP
) {
172 return IMAGE_FROM_REMOVABLE_MEDIA
;
179 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
181 return IMAGE_UNKNOWN
;
185 Caculate hash of Pe/Coff image based on the authenticode image hashing in
186 PE/COFF Specification 8.0 Appendix A
188 @param[in] HashAlg Hash algorithm type.
190 @retval TRUE Successfully hash image.
191 @retval FALSE Fail in hash image.
201 EFI_IMAGE_SECTION_HEADER
*Section
;
206 UINTN SumOfBytesHashed
;
207 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
210 UINTN SumOfSectionBytes
;
211 EFI_IMAGE_SECTION_HEADER
*SectionCache
;
214 SectionHeader
= NULL
;
217 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
222 // Initialize context of hash.
224 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
226 if (HashAlg
== HASHALG_SHA1
) {
227 mImageDigestSize
= SHA1_DIGEST_SIZE
;
228 mCertType
= gEfiCertSha1Guid
;
229 } else if (HashAlg
== HASHALG_SHA256
) {
230 mImageDigestSize
= SHA256_DIGEST_SIZE
;
231 mCertType
= gEfiCertSha256Guid
;
236 CtxSize
= mHash
[HashAlg
].GetContextSize();
238 HashCtx
= AllocatePool (CtxSize
);
239 if (HashCtx
== NULL
) {
243 // 1. Load the image header into memory.
245 // 2. Initialize a SHA hash context.
246 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
252 // Measuring PE/COFF Image Header;
253 // But CheckSum field and SECURITY data directory (certificate) are excluded
255 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
257 // 3. Calculate the distance from the base of the image header to the image checksum address.
258 // 4. Hash the image header from its base to beginning of the image checksum.
260 HashBase
= mImageBase
;
261 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
265 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
266 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
270 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
273 // Invalid header magic number.
279 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
284 // 5. Skip over the image checksum (it occupies a single ULONG).
285 // 6. Get the address of the beginning of the Cert Directory.
286 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
288 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
292 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
293 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
298 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
299 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
302 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
307 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
308 // 9. Hash everything from the end of the Cert Directory to the end of image header.
310 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
314 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
315 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
320 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
321 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
324 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
329 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
331 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
335 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
340 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
344 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
346 mPeCoffHeaderOffset
+
348 sizeof (EFI_IMAGE_FILE_HEADER
) +
349 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
352 SectionCache
= Section
;
353 for (Index
= 0, SumOfSectionBytes
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++, SectionCache
++) {
354 SumOfSectionBytes
+= SectionCache
->SizeOfRawData
;
358 // Sanity check for file corruption. Sections raw data size should be smaller
361 if (SumOfSectionBytes
>= mImageSize
) {
367 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
368 // structures in the image. The 'NumberOfSections' field of the image
369 // header indicates how big the table should be. Do not include any
370 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
372 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
373 if (SectionHeader
== NULL
) {
378 // 12. Using the 'PointerToRawData' in the referenced section headers as
379 // a key, arrange the elements in the table in ascending order. In other
380 // words, sort the section headers according to the disk-file offset of
383 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
385 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
386 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
389 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
394 // 13. Walk through the sorted table, bring the corresponding section
395 // into memory, and hash the entire section (using the 'SizeOfRawData'
396 // field in the section header to determine the amount of data to hash).
397 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
398 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
400 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
401 Section
= &SectionHeader
[Index
];
402 if (Section
->SizeOfRawData
== 0) {
405 HashBase
= mImageBase
+ Section
->PointerToRawData
;
406 HashSize
= (UINTN
) Section
->SizeOfRawData
;
408 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
413 SumOfBytesHashed
+= HashSize
;
417 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
418 // data in the file that needs to be added to the hash. This data begins
419 // at file offset SUM_OF_BYTES_HASHED and its length is:
420 // FileSize - (CertDirectory->Size)
422 if (mImageSize
> SumOfBytesHashed
) {
423 HashBase
= mImageBase
+ SumOfBytesHashed
;
424 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
430 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
438 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
442 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
447 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
450 if (HashCtx
!= NULL
) {
453 if (SectionHeader
!= NULL
) {
454 FreePool (SectionHeader
);
460 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
461 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
464 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
465 @retval EFI_SUCCESS Hash successfully.
474 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
476 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
478 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
480 // Check the Hash algorithm in PE/COFF Authenticode.
481 // According to PKCS#7 Definition:
482 // SignedData ::= SEQUENCE {
484 // digestAlgorithms DigestAlgorithmIdentifiers,
485 // contentInfo ContentInfo,
487 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
488 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
489 // Fixed offset (+32) is calculated based on two bytes of length encoding.
491 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
493 // Only support two bytes of Long Form of Length Encoding.
498 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
503 if (Index
== HASHALG_MAX
) {
504 return EFI_UNSUPPORTED
;
508 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
510 if (!HashPeImage(Index
)) {
511 return EFI_UNSUPPORTED
;
519 Returns the size of a given image execution info table in bytes.
521 This function returns the size, in bytes, of the image execution info table specified by
522 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
524 @param ImageExeInfoTable A pointer to a image execution info table structure.
526 @retval 0 If ImageExeInfoTable is NULL.
527 @retval Others The size of a image execution info table in bytes.
531 GetImageExeInfoTableSize (
532 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
536 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoItem
;
539 if (ImageExeInfoTable
== NULL
) {
543 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoTable
+ sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
));
544 TotalSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
545 for (Index
= 0; Index
< ImageExeInfoTable
->NumberOfImages
; Index
++) {
546 TotalSize
+= ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
);
547 ImageExeInfoItem
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) ImageExeInfoItem
+ ReadUnaligned32 ((UINT32
*) &ImageExeInfoItem
->InfoSize
));
554 Create an Image Execution Information Table entry and add it to system configuration table.
556 @param[in] Action Describes the action taken by the firmware regarding this image.
557 @param[in] Name Input a null-terminated, user-friendly name.
558 @param[in] DevicePath Input device path pointer.
559 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
560 @param[in] SignatureSize Size of signature.
565 IN EFI_IMAGE_EXECUTION_ACTION Action
,
566 IN CHAR16
*Name OPTIONAL
,
567 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
568 IN EFI_SIGNATURE_LIST
*Signature OPTIONAL
,
569 IN UINTN SignatureSize
572 EFI_IMAGE_EXECUTION_INFO_TABLE
*ImageExeInfoTable
;
573 EFI_IMAGE_EXECUTION_INFO_TABLE
*NewImageExeInfoTable
;
574 EFI_IMAGE_EXECUTION_INFO
*ImageExeInfoEntry
;
575 UINTN ImageExeInfoTableSize
;
576 UINTN NewImageExeInfoEntrySize
;
578 UINTN DevicePathSize
;
580 ImageExeInfoTable
= NULL
;
581 NewImageExeInfoTable
= NULL
;
582 ImageExeInfoEntry
= NULL
;
585 if (DevicePath
== NULL
) {
590 NameStringLen
= StrSize (Name
);
593 ImageExeInfoTable
= NULL
;
594 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
**) &ImageExeInfoTable
);
595 if (ImageExeInfoTable
!= NULL
) {
597 // The table has been found!
598 // We must enlarge the table to accmodate the new exe info entry.
600 ImageExeInfoTableSize
= GetImageExeInfoTableSize (ImageExeInfoTable
);
604 // We should create a new table to append to the configuration table.
606 ImageExeInfoTableSize
= sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE
);
609 DevicePathSize
= GetDevicePathSize (DevicePath
);
610 NewImageExeInfoEntrySize
= sizeof (EFI_IMAGE_EXECUTION_INFO
) + NameStringLen
+ DevicePathSize
+ SignatureSize
;
611 NewImageExeInfoTable
= (EFI_IMAGE_EXECUTION_INFO_TABLE
*) AllocateRuntimePool (ImageExeInfoTableSize
+ NewImageExeInfoEntrySize
);
612 if (NewImageExeInfoTable
== NULL
) {
616 if (ImageExeInfoTable
!= NULL
) {
617 CopyMem (NewImageExeInfoTable
, ImageExeInfoTable
, ImageExeInfoTableSize
);
619 NewImageExeInfoTable
->NumberOfImages
= 0;
621 NewImageExeInfoTable
->NumberOfImages
++;
622 ImageExeInfoEntry
= (EFI_IMAGE_EXECUTION_INFO
*) ((UINT8
*) NewImageExeInfoTable
+ ImageExeInfoTableSize
);
624 // Update new item's infomation.
626 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->Action
, Action
);
627 WriteUnaligned32 ((UINT32
*) &ImageExeInfoEntry
->InfoSize
, (UINT32
) NewImageExeInfoEntrySize
);
630 CopyMem ((UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
), Name
, NameStringLen
);
633 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
,
637 if (Signature
!= NULL
) {
639 (UINT8
*) &ImageExeInfoEntry
->InfoSize
+ sizeof (UINT32
) + NameStringLen
+ DevicePathSize
,
645 // Update/replace the image execution table.
647 gBS
->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid
, (VOID
*) NewImageExeInfoTable
);
650 // Free Old table data!
652 if (ImageExeInfoTable
!= NULL
) {
653 FreePool (ImageExeInfoTable
);
658 Discover if the UEFI image is authorized by user's policy setting.
660 @param[in] Policy Specify platform's policy setting.
662 @retval EFI_ACCESS_DENIED Image is not allowed to run.
663 @retval EFI_SECURITY_VIOLATION Image is deferred.
664 @retval EFI_SUCCESS Image is authorized to run.
675 Status
= EFI_ACCESS_DENIED
;
679 case QUERY_USER_ON_SECURITY_VIOLATION
:
681 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, mNotifyString1
, mNotifyString2
, NULL
);
682 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
683 Status
= EFI_SUCCESS
;
685 } else if (Key
.UnicodeChar
== L
'N' || Key
.UnicodeChar
== L
'n') {
686 Status
= EFI_ACCESS_DENIED
;
688 } else if (Key
.UnicodeChar
== L
'D' || Key
.UnicodeChar
== L
'd') {
689 Status
= EFI_SECURITY_VIOLATION
;
695 case ALLOW_EXECUTE_ON_SECURITY_VIOLATION
:
696 Status
= EFI_SUCCESS
;
699 case DEFER_EXECUTE_ON_SECURITY_VIOLATION
:
700 Status
= EFI_SECURITY_VIOLATION
;
703 case DENY_EXECUTE_ON_SECURITY_VIOLATION
:
704 Status
= EFI_ACCESS_DENIED
;
712 Check whether signature is in specified database.
714 @param[in] VariableName Name of database variable that is searched in.
715 @param[in] Signature Pointer to signature that is searched for.
716 @param[in] CertType Pointer to hash algrithom.
717 @param[in] SignatureSize Size of Signature.
719 @return TRUE Found the signature in the variable database.
720 @return FALSE Not found the signature in the variable database.
724 IsSignatureFoundInDatabase (
725 IN CHAR16
*VariableName
,
727 IN EFI_GUID
*CertType
,
728 IN UINTN SignatureSize
732 EFI_SIGNATURE_LIST
*CertList
;
733 EFI_SIGNATURE_DATA
*Cert
;
740 // Read signature database variable.
745 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
746 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
750 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
755 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
756 if (EFI_ERROR (Status
)) {
760 // Enumerate all signature data in SigDB to check if executable's signature exists.
762 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
763 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
764 CertCount
= (CertList
->SignatureListSize
- CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
765 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
766 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, CertType
))) {
767 for (Index
= 0; Index
< CertCount
; Index
++) {
768 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
770 // Find the signature in database.
776 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
784 DataSize
-= CertList
->SignatureListSize
;
785 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
797 Verify PKCS#7 SignedData using certificate found in Variable which formatted
798 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
800 @param VariableName Name of Variable to search for Certificate.
801 @param VendorGuid Variable vendor GUID.
803 @retval TRUE Image pass verification.
804 @retval FALSE Image fail verification.
808 IsPkcsSignedDataVerifiedBySignatureList (
809 IN CHAR16
*VariableName
,
810 IN EFI_GUID
*VendorGuid
814 BOOLEAN VerifyStatus
;
815 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
816 EFI_SIGNATURE_LIST
*CertList
;
817 EFI_SIGNATURE_DATA
*Cert
;
830 VerifyStatus
= FALSE
;
831 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
834 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
835 if (Status
== EFI_BUFFER_TOO_SMALL
) {
836 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
841 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, (VOID
*) Data
);
842 if (EFI_ERROR (Status
)) {
847 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
849 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
850 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
851 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
852 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
853 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
854 for (Index
= 0; Index
< CertCount
; Index
++) {
856 // Iterate each Signature Data Node within this CertList for verify.
858 RootCert
= Cert
->SignatureData
;
859 RootCertSize
= CertList
->SignatureSize
;
862 // Call AuthenticodeVerify library to Verify Authenticode struct.
864 VerifyStatus
= AuthenticodeVerify (
865 PkcsCertData
->CertData
,
866 mSecDataDir
->Size
- sizeof(PkcsCertData
->Hdr
),
875 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
878 DataSize
-= CertList
->SignatureListSize
;
879 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
892 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
894 @retval EFI_SUCCESS Image pass verification.
895 @retval EFI_SECURITY_VIOLATION Image fail verification.
899 VerifyCertPkcsSignedData (
904 // 1: Find certificate from DBX forbidden database for revoked certificate.
906 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
)) {
908 // DBX is forbidden database, if Authenticode verification pass with
909 // one of the certificate in DBX, this image should be rejected.
911 return EFI_SECURITY_VIOLATION
;
915 // 2: Find certificate from KEK database and try to verify authenticode struct.
917 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
)) {
922 // 3: Find certificate from DB database and try to verify authenticode struct.
924 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
)) {
927 return EFI_SECURITY_VIOLATION
;
932 Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
934 @retval EFI_SUCCESS Image pass verification.
935 @retval EFI_SECURITY_VIOLATION Image fail verification.
936 @retval other error value
945 WIN_CERTIFICATE_UEFI_GUID
*EfiCert
;
946 EFI_SIGNATURE_LIST
*KekList
;
947 EFI_SIGNATURE_DATA
*KekItem
;
948 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
965 EfiCert
= (WIN_CERTIFICATE_UEFI_GUID
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
966 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) EfiCert
->CertData
;
967 if (!CompareGuid (&EfiCert
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
)) {
969 // Invalid Certificate Data Type.
971 return EFI_SECURITY_VIOLATION
;
975 // Get KEK database variable data size
977 Result
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &KekDataSize
, NULL
);
978 if (Result
!= EFI_BUFFER_TOO_SMALL
) {
979 return EFI_SECURITY_VIOLATION
;
983 // Get KEK database variable.
985 KekList
= GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME
);
986 if (KekList
== NULL
) {
987 return EFI_SECURITY_VIOLATION
;
991 // Enumerate all Kek items in this list to verify the variable certificate data.
992 // If anyone is authenticated successfully, it means the variable is correct!
994 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
995 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
996 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
997 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
998 for (Index
= 0; Index
< KekCount
; Index
++) {
999 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1003 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1006 KekDataSize
-= KekList
->SignatureListSize
;
1007 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1012 // Signed key is not a trust one.
1018 // Now, we found the corresponding security policy.
1019 // Verify the data payload.
1028 // Set RSA Key Components.
1029 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
1031 Status
= RsaSetKey (Rsa
, RsaKeyN
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
1035 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
1040 // Verify the signature.
1042 Status
= RsaPkcs1Verify (
1046 CertBlock
->Signature
,
1047 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
1051 if (KekList
!= NULL
) {
1060 return EFI_SECURITY_VIOLATION
;
1065 Provide verification service for signed images, which include both signature validation
1066 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1067 MSFT Authenticode type signatures are supported.
1069 In this implementation, only verify external executables when in USER MODE.
1070 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1072 The image verification process is:
1073 Is the Image signed?
1075 Does the image verify against a certificate (root or intermediate) in the allowed db?
1077 Image verification fail
1078 Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
1081 Is the Image's Hash in the forbidden database (DBX)?
1084 Is the Image's Hash in the allowed database (DB)?
1090 @param[in] AuthenticationStatus
1091 This is the authentication status returned from the security
1092 measurement services for the input file.
1093 @param[in] File This is a pointer to the device path of the file that is
1094 being dispatched. This will optionally be used for logging.
1095 @param[in] FileBuffer File buffer matches the input file device path.
1096 @param[in] FileSize Size of File buffer matches the input file device path.
1098 @retval EFI_SUCCESS The file specified by File did authenticate, and the
1099 platform policy dictates that the DXE Core may use File.
1100 @retval EFI_INVALID_PARAMETER Input argument is incorrect.
1101 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1102 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1103 the platform policy dictates that File should be placed
1104 in the untrusted state. A file may be promoted from
1105 the untrusted to the trusted state at a future time
1106 with a call to the Trust() DXE Service.
1107 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
1108 the platform policy dictates that File should not be
1109 used for any purpose.
1114 DxeImageVerificationHandler (
1115 IN UINT32 AuthenticationStatus
,
1116 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
1117 IN VOID
*FileBuffer
,
1123 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1124 EFI_STATUS VerifyStatus
;
1126 EFI_SIGNATURE_LIST
*SignatureList
;
1127 UINTN SignatureListSize
;
1128 EFI_SIGNATURE_DATA
*Signature
;
1129 EFI_IMAGE_EXECUTION_ACTION Action
;
1130 WIN_CERTIFICATE
*WinCertificate
;
1132 UINT8
*SecureBootEnable
;
1135 return EFI_INVALID_PARAMETER
;
1138 SignatureList
= NULL
;
1139 SignatureListSize
= 0;
1140 WinCertificate
= NULL
;
1141 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1142 Status
= EFI_ACCESS_DENIED
;
1144 // Check the image type and get policy setting.
1146 switch (GetImageType (File
)) {
1149 Policy
= ALWAYS_EXECUTE
;
1152 case IMAGE_FROM_OPTION_ROM
:
1153 Policy
= PcdGet32 (PcdOptionRomImageVerificationPolicy
);
1156 case IMAGE_FROM_REMOVABLE_MEDIA
:
1157 Policy
= PcdGet32 (PcdRemovableMediaImageVerificationPolicy
);
1160 case IMAGE_FROM_FIXED_MEDIA
:
1161 Policy
= PcdGet32 (PcdFixedMediaImageVerificationPolicy
);
1165 Policy
= DENY_EXECUTE_ON_SECURITY_VIOLATION
;
1169 // If policy is always/never execute, return directly.
1171 if (Policy
== ALWAYS_EXECUTE
) {
1173 } else if (Policy
== NEVER_EXECUTE
) {
1174 return EFI_ACCESS_DENIED
;
1177 SecureBootEnable
= GetVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
);
1179 // Skip verification if SecureBootEnable variable doesn't exist.
1181 if (SecureBootEnable
== NULL
) {
1186 // Skip verification if SecureBootEnable is disabled.
1188 if (*SecureBootEnable
== SECURE_BOOT_DISABLE
) {
1189 FreePool (SecureBootEnable
);
1193 SetupMode
= GetEfiGlobalVariable (EFI_SETUP_MODE_NAME
);
1196 // SetupMode doesn't exist means no AuthVar driver is dispatched,
1197 // skip verification.
1199 if (SetupMode
== NULL
) {
1204 // If platform is in SETUP MODE, skip verification.
1206 if (*SetupMode
== SETUP_MODE
) {
1207 FreePool (SetupMode
);
1211 // Read the Dos header.
1213 if (FileBuffer
== NULL
) {
1214 FreePool (SetupMode
);
1215 return EFI_INVALID_PARAMETER
;
1217 mImageBase
= (UINT8
*) FileBuffer
;
1218 mImageSize
= FileSize
;
1219 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) mImageBase
;
1220 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1222 // DOS image header is present,
1223 // so read the PE header after the DOS image header.
1225 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1227 mPeCoffHeaderOffset
= 0;
1230 // Check PE/COFF image.
1232 mNtHeader
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1233 if (mNtHeader
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1235 // It is not a valid Pe/Coff file.
1237 return EFI_ACCESS_DENIED
;
1240 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1241 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1245 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1246 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1248 // Use PE32+ offset.
1250 mSecDataDir
= (EFI_IMAGE_DATA_DIRECTORY
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
];
1253 // Invalid header magic number.
1255 Status
= EFI_INVALID_PARAMETER
;
1259 if (mSecDataDir
->VirtualAddress
>= mImageSize
) {
1261 // Sanity check to see if this file is corrupted.
1263 Status
= EFI_INVALID_PARAMETER
;
1267 if (mSecDataDir
->Size
== 0) {
1269 // This image is not signed.
1271 if (!HashPeImage (HASHALG_SHA256
)) {
1275 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1277 // Image Hash is in forbidden database (DBX).
1279 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1280 Status
= EFI_ACCESS_DENIED
;
1284 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1286 // Image Hash is in allowed database (DB).
1292 // Image Hash is not found in both forbidden and allowed database.
1294 Action
= EFI_IMAGE_EXECUTION_AUTH_UNTESTED
;
1295 Status
= EFI_ACCESS_DENIED
;
1300 // Verify signature of executables.
1302 WinCertificate
= (WIN_CERTIFICATE
*) (mImageBase
+ mSecDataDir
->VirtualAddress
);
1304 switch (WinCertificate
->wCertificateType
) {
1306 case WIN_CERT_TYPE_EFI_GUID
:
1308 // Verify UEFI GUID type.
1310 if (!HashPeImage (HASHALG_SHA256
)) {
1314 VerifyStatus
= VerifyCertUefiGuid ();
1317 case WIN_CERT_TYPE_PKCS_SIGNED_DATA
:
1319 // Verify Pkcs signed data type.
1321 Status
= HashPeImageByType();
1322 if (EFI_ERROR (Status
)) {
1326 VerifyStatus
= VerifyCertPkcsSignedData ();
1329 // For image verification against enrolled certificate(root or intermediate),
1330 // no need to check image's hash in the allowed database.
1332 if (!EFI_ERROR (VerifyStatus
)) {
1333 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1340 Status
= EFI_ACCESS_DENIED
;
1344 // Get image hash value as executable's signature.
1346 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + mImageDigestSize
;
1347 SignatureList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SignatureListSize
);
1348 if (SignatureList
== NULL
) {
1349 Status
= EFI_OUT_OF_RESOURCES
;
1352 SignatureList
->SignatureHeaderSize
= 0;
1353 SignatureList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1354 SignatureList
->SignatureSize
= (UINT32
) mImageDigestSize
;
1355 CopyMem (&SignatureList
->SignatureType
, &mCertType
, sizeof (EFI_GUID
));
1356 Signature
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
));
1357 CopyMem (Signature
->SignatureData
, mImageDigest
, mImageDigestSize
);
1359 // Signature database check after verification.
1361 if (EFI_ERROR (VerifyStatus
)) {
1363 // Verification failure.
1365 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, mImageDigest
, &mCertType
, mImageDigestSize
) &&
1366 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, mImageDigest
, &mCertType
, mImageDigestSize
)) {
1368 // Verification fail, Image Hash is not in forbidden database (DBX),
1369 // and Image Hash is in allowed database (DB).
1371 Status
= EFI_SUCCESS
;
1373 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
;
1374 Status
= EFI_ACCESS_DENIED
;
1376 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1378 // Executable signature verification passes, but is found in forbidden signature database.
1380 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
;
1381 Status
= EFI_ACCESS_DENIED
;
1382 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE
, Signature
->SignatureData
, &mCertType
, mImageDigestSize
)) {
1384 // Executable signature is found in authorized signature database.
1386 Status
= EFI_SUCCESS
;
1389 // Executable signature verification passes, but cannot be found in authorized signature database.
1390 // Get platform policy to determine the action.
1392 Action
= EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED
;
1393 Status
= ImageAuthorization (Policy
);
1397 if (Status
!= EFI_SUCCESS
) {
1399 // Policy decides to defer or reject the image; add its information in image executable information table.
1401 AddImageExeInfo (Action
, NULL
, File
, SignatureList
, SignatureListSize
);
1404 if (SignatureList
!= NULL
) {
1405 FreePool (SignatureList
);
1408 FreePool (SetupMode
);
1414 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1416 @param[in] Event Event whose notification function is being invoked.
1417 @param[in] Context Pointer to the notification function's context.
1422 VariableWriteCallBack (
1427 UINT8 SecureBootMode
;
1428 UINT8
*SecureBootModePtr
;
1430 VOID
*ProtocolPointer
;
1432 Status
= gBS
->LocateProtocol (&gEfiVariableWriteArchProtocolGuid
, NULL
, &ProtocolPointer
);
1433 if (EFI_ERROR (Status
)) {
1438 // Check whether "SecureBoot" variable exists.
1439 // If this library is built-in, it means firmware has capability to perform
1440 // driver signing verification.
1442 SecureBootModePtr
= GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME
);
1443 if (SecureBootModePtr
== NULL
) {
1444 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
1446 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1449 EFI_SECURE_BOOT_MODE_NAME
,
1450 &gEfiGlobalVariableGuid
,
1451 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1456 FreePool (SecureBootModePtr
);
1461 Register security measurement handler.
1463 @param ImageHandle ImageHandle of the loaded driver.
1464 @param SystemTable Pointer to the EFI System Table.
1466 @retval EFI_SUCCESS The handlers were registered successfully.
1470 DxeImageVerificationLibConstructor (
1471 IN EFI_HANDLE ImageHandle
,
1472 IN EFI_SYSTEM_TABLE
*SystemTable
1478 // Register callback function upon VariableWriteArchProtocol.
1480 EfiCreateProtocolNotifyEvent (
1481 &gEfiVariableWriteArchProtocolGuid
,
1483 VariableWriteCallBack
,
1488 return RegisterSecurityHandler (
1489 DxeImageVerificationHandler
,
1490 EFI_AUTH_OPERATION_VERIFY_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED