2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2017, 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 "SecureBootConfigImpl.h"
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
) (END_DEVICE_PATH_LENGTH
),
45 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
51 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
54 // OID ASN.1 Value for Hash Algorithms
56 UINT8 mHashOidValue
[] = {
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
65 HASH_TABLE mHash
[] = {
66 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
67 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
68 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
69 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
73 // Variable Definitions
75 UINT32 mPeCoffHeaderOffset
= 0;
76 WIN_CERTIFICATE
*mCertificate
= NULL
;
77 IMAGE_TYPE mImageType
;
78 UINT8
*mImageBase
= NULL
;
80 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
81 UINTN mImageDigestSize
;
83 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
84 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
87 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
89 CHAR16
* mDerEncodedSuffix
[] = {
95 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
97 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
100 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
102 @param[in] FileSuffix The suffix of the input certificate file
104 @retval TRUE It's a DER-encoded certificate.
105 @retval FALSE It's NOT a DER-encoded certificate.
109 IsDerEncodeCertificate (
110 IN CONST CHAR16
*FileSuffix
114 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
115 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
123 Set Secure Boot option into variable space.
125 @param[in] VarValue The option of Secure Boot.
127 @retval EFI_SUCCESS The operation is finished successfully.
128 @retval Others Other errors as indicated.
132 SaveSecureBootVariable (
138 Status
= gRT
->SetVariable (
139 EFI_SECURE_BOOT_ENABLE_NAME
,
140 &gEfiSecureBootEnableDisableGuid
,
141 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
149 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
150 descriptor with the input data. NO authentication is required in this function.
152 @param[in, out] DataSize On input, the size of Data buffer in bytes.
153 On output, the size of data returned in Data
155 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
156 pointer to NULL to wrap an empty payload.
157 On output, Pointer to the new payload date buffer allocated from pool,
158 it's caller's responsibility to free the memory when finish using it.
160 @retval EFI_SUCCESS Create time based payload successfully.
161 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
162 @retval EFI_INVALID_PARAMETER The parameter is invalid.
163 @retval Others Unexpected error happens.
167 CreateTimeBasedPayload (
168 IN OUT UINTN
*DataSize
,
176 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
177 UINTN DescriptorSize
;
180 if (Data
== NULL
|| DataSize
== NULL
) {
181 return EFI_INVALID_PARAMETER
;
185 // In Setup mode or Custom mode, the variable does not need to be signed but the
186 // parameters to the SetVariable() call still need to be prepared as authenticated
187 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
191 PayloadSize
= *DataSize
;
193 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
194 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
195 if (NewData
== NULL
) {
196 return EFI_OUT_OF_RESOURCES
;
199 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
200 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
203 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
205 ZeroMem (&Time
, sizeof (EFI_TIME
));
206 Status
= gRT
->GetTime (&Time
, NULL
);
207 if (EFI_ERROR (Status
)) {
216 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
218 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
219 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
220 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
221 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
223 if (Payload
!= NULL
) {
227 *DataSize
= DescriptorSize
+ PayloadSize
;
233 Internal helper function to delete a Variable given its name and GUID, NO authentication
236 @param[in] VariableName Name of the Variable.
237 @param[in] VendorGuid GUID of the Variable.
239 @retval EFI_SUCCESS Variable deleted successfully.
240 @retval Others The driver failed to start the device.
245 IN CHAR16
*VariableName
,
246 IN EFI_GUID
*VendorGuid
255 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
256 if (Variable
== NULL
) {
263 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
264 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
266 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
267 if (EFI_ERROR (Status
)) {
268 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
272 Status
= gRT
->SetVariable (
287 Set the platform secure boot mode into "Custom" or "Standard" mode.
289 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
290 CUSTOM_SECURE_BOOT_MODE.
292 @return EFI_SUCCESS The platform has switched to the special mode successfully.
293 @return other Fail to operate the secure boot mode.
298 IN UINT8 SecureBootMode
301 return gRT
->SetVariable (
302 EFI_CUSTOM_MODE_NAME
,
303 &gEfiCustomModeEnableGuid
,
304 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
311 Generate the PK signature list from the X509 Certificate storing file (.cer)
313 @param[in] X509File FileHandle of X509 Certificate storing file.
314 @param[out] PkCert Point to the data buffer to store the signature list.
316 @return EFI_UNSUPPORTED Unsupported Key Length.
317 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
321 CreatePkX509SignatureList (
322 IN EFI_FILE_HANDLE X509File
,
323 OUT EFI_SIGNATURE_LIST
**PkCert
329 EFI_SIGNATURE_DATA
*PkCertData
;
335 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
336 if (EFI_ERROR (Status
)) {
339 ASSERT (X509Data
!= NULL
);
342 // Allocate space for PK certificate list and initialize it.
343 // Create PK database entry with SignatureHeaderSize equals 0.
345 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
346 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
349 if (*PkCert
== NULL
) {
350 Status
= EFI_OUT_OF_RESOURCES
;
354 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
355 + sizeof(EFI_SIGNATURE_DATA
) - 1
357 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
358 (*PkCert
)->SignatureHeaderSize
= 0;
359 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
360 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
361 + sizeof(EFI_SIGNATURE_LIST
)
362 + (*PkCert
)->SignatureHeaderSize
);
363 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
365 // Fill the PK database with PKpub data from X509 certificate file.
367 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
371 if (X509Data
!= NULL
) {
375 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
384 Enroll new PK into the System without original PK's authentication.
386 The SignatureOwner GUID will be the same with PK's vendorguid.
388 @param[in] PrivateData The module's private data.
390 @retval EFI_SUCCESS New PK enrolled successfully.
391 @retval EFI_INVALID_PARAMETER The parameter is invalid.
392 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
397 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
403 EFI_SIGNATURE_LIST
*PkCert
;
407 if (Private
->FileContext
->FileName
== NULL
) {
408 return EFI_INVALID_PARAMETER
;
413 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
414 if (EFI_ERROR (Status
)) {
419 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
421 NameLength
= StrLen (Private
->FileContext
->FileName
);
422 if (NameLength
<= 4) {
423 return EFI_INVALID_PARAMETER
;
425 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
426 if (!IsDerEncodeCertificate(FilePostFix
)) {
427 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
428 return EFI_INVALID_PARAMETER
;
430 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
431 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
434 // Prase the selected PK file and generature PK certificate list.
436 Status
= CreatePkX509SignatureList (
437 Private
->FileContext
->FHandle
,
440 if (EFI_ERROR (Status
)) {
443 ASSERT (PkCert
!= NULL
);
446 // Set Platform Key variable.
448 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
449 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
450 DataSize
= PkCert
->SignatureListSize
;
451 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
452 if (EFI_ERROR (Status
)) {
453 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
457 Status
= gRT
->SetVariable(
458 EFI_PLATFORM_KEY_NAME
,
459 &gEfiGlobalVariableGuid
,
464 if (EFI_ERROR (Status
)) {
465 if (Status
== EFI_OUT_OF_RESOURCES
) {
466 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
473 if (PkCert
!= NULL
) {
477 if (Private
->FileContext
->FHandle
!= NULL
) {
478 CloseFile (Private
->FileContext
->FHandle
);
479 Private
->FileContext
->FHandle
= NULL
;
486 Remove the PK variable.
488 @retval EFI_SUCCESS Delete PK successfully.
489 @retval Others Could not allow to delete PK.
499 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
500 if (EFI_ERROR (Status
)) {
504 Status
= DeleteVariable (
505 EFI_PLATFORM_KEY_NAME
,
506 &gEfiGlobalVariableGuid
512 Enroll a new KEK item from public key storing file (*.pbk).
514 @param[in] PrivateData The module's private data.
516 @retval EFI_SUCCESS New KEK enrolled successfully.
517 @retval EFI_INVALID_PARAMETER The parameter is invalid.
518 @retval EFI_UNSUPPORTED Unsupported command.
519 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
524 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
530 EFI_SIGNATURE_LIST
*KekSigList
;
533 CPL_KEY_INFO
*KeyInfo
;
534 EFI_SIGNATURE_DATA
*KEKSigData
;
535 UINTN KekSigListSize
;
550 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
551 // First, We have to parse out public key data from the pbk key file.
553 Status
= ReadFileContent (
554 Private
->FileContext
->FHandle
,
559 if (EFI_ERROR (Status
)) {
562 ASSERT (KeyBlob
!= NULL
);
563 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
564 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
565 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
566 Status
= EFI_UNSUPPORTED
;
571 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
573 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
574 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
575 if (KeyBuffer
== NULL
) {
576 Status
= EFI_OUT_OF_RESOURCES
;
580 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
581 KeyLenInBytes
/ sizeof (UINTN
),
585 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
588 // Form an new EFI_SIGNATURE_LIST.
590 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
591 + sizeof(EFI_SIGNATURE_DATA
) - 1
592 + WIN_CERT_UEFI_RSA2048_SIZE
;
594 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
595 if (KekSigList
== NULL
) {
596 Status
= EFI_OUT_OF_RESOURCES
;
600 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
601 + sizeof(EFI_SIGNATURE_DATA
) - 1
602 + WIN_CERT_UEFI_RSA2048_SIZE
;
603 KekSigList
->SignatureHeaderSize
= 0;
604 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
605 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
607 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
608 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
610 KEKSigData
->SignatureData
,
611 KeyBlob
+ sizeof(CPL_KEY_INFO
),
612 WIN_CERT_UEFI_RSA2048_SIZE
616 // Check if KEK entry has been already existed.
617 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
618 // new KEK to original variable.
620 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
621 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
622 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
623 if (EFI_ERROR (Status
)) {
624 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
628 Status
= gRT
->GetVariable(
629 EFI_KEY_EXCHANGE_KEY_NAME
,
630 &gEfiGlobalVariableGuid
,
635 if (Status
== EFI_BUFFER_TOO_SMALL
) {
636 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
637 } else if (Status
!= EFI_NOT_FOUND
) {
642 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
644 Status
= gRT
->SetVariable(
645 EFI_KEY_EXCHANGE_KEY_NAME
,
646 &gEfiGlobalVariableGuid
,
651 if (EFI_ERROR (Status
)) {
657 CloseFile (Private
->FileContext
->FHandle
);
658 Private
->FileContext
->FHandle
= NULL
;
660 if (Private
->FileContext
->FileName
!= NULL
){
661 FreePool(Private
->FileContext
->FileName
);
662 Private
->FileContext
->FileName
= NULL
;
665 if (Private
->SignatureGUID
!= NULL
) {
666 FreePool (Private
->SignatureGUID
);
667 Private
->SignatureGUID
= NULL
;
670 if (KeyBlob
!= NULL
) {
673 if (KeyBuffer
!= NULL
) {
674 FreePool (KeyBuffer
);
676 if (KekSigList
!= NULL
) {
677 FreePool (KekSigList
);
684 Enroll a new KEK item from X509 certificate file.
686 @param[in] PrivateData The module's private data.
688 @retval EFI_SUCCESS New X509 is enrolled successfully.
689 @retval EFI_INVALID_PARAMETER The parameter is invalid.
690 @retval EFI_UNSUPPORTED Unsupported command.
691 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
696 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
702 EFI_SIGNATURE_DATA
*KEKSigData
;
703 EFI_SIGNATURE_LIST
*KekSigList
;
705 UINTN KekSigListSize
;
715 Status
= ReadFileContent (
716 Private
->FileContext
->FHandle
,
721 if (EFI_ERROR (Status
)) {
724 ASSERT (X509Data
!= NULL
);
726 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
727 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
728 if (KekSigList
== NULL
) {
729 Status
= EFI_OUT_OF_RESOURCES
;
734 // Fill Certificate Database parameters.
736 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
737 KekSigList
->SignatureHeaderSize
= 0;
738 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
739 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
741 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
742 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
743 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
746 // Check if KEK been already existed.
747 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
748 // new kek to original variable
750 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
751 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
752 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
753 if (EFI_ERROR (Status
)) {
754 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
758 Status
= gRT
->GetVariable(
759 EFI_KEY_EXCHANGE_KEY_NAME
,
760 &gEfiGlobalVariableGuid
,
765 if (Status
== EFI_BUFFER_TOO_SMALL
) {
766 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
767 } else if (Status
!= EFI_NOT_FOUND
) {
771 Status
= gRT
->SetVariable(
772 EFI_KEY_EXCHANGE_KEY_NAME
,
773 &gEfiGlobalVariableGuid
,
778 if (EFI_ERROR (Status
)) {
784 CloseFile (Private
->FileContext
->FHandle
);
785 if (Private
->FileContext
->FileName
!= NULL
){
786 FreePool(Private
->FileContext
->FileName
);
787 Private
->FileContext
->FileName
= NULL
;
790 Private
->FileContext
->FHandle
= NULL
;
792 if (Private
->SignatureGUID
!= NULL
) {
793 FreePool (Private
->SignatureGUID
);
794 Private
->SignatureGUID
= NULL
;
797 if (KekSigList
!= NULL
) {
798 FreePool (KekSigList
);
805 Enroll new KEK into the System without PK's authentication.
806 The SignatureOwner GUID will be Private->SignatureGUID.
808 @param[in] PrivateData The module's private data.
810 @retval EFI_SUCCESS New KEK enrolled successful.
811 @retval EFI_INVALID_PARAMETER The parameter is invalid.
812 @retval others Fail to enroll KEK data.
816 EnrollKeyExchangeKey (
817 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
824 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
825 return EFI_INVALID_PARAMETER
;
828 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
829 if (EFI_ERROR (Status
)) {
834 // Parse the file's postfix. Supports DER-encoded X509 certificate,
835 // and .pbk as RSA public key file.
837 NameLength
= StrLen (Private
->FileContext
->FileName
);
838 if (NameLength
<= 4) {
839 return EFI_INVALID_PARAMETER
;
841 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
842 if (IsDerEncodeCertificate(FilePostFix
)) {
843 return EnrollX509ToKek (Private
);
844 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
845 return EnrollRsa2048ToKek (Private
);
847 return EFI_INVALID_PARAMETER
;
852 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
853 KEK's authentication.
855 @param[in] PrivateData The module's private data.
856 @param[in] VariableName Variable name of signature database, must be
857 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
859 @retval EFI_SUCCESS New X509 is enrolled successfully.
860 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
865 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
866 IN CHAR16
*VariableName
872 EFI_SIGNATURE_LIST
*SigDBCert
;
873 EFI_SIGNATURE_DATA
*SigDBCertData
;
884 SigDBCertData
= NULL
;
887 Status
= ReadFileContent (
888 Private
->FileContext
->FHandle
,
893 if (EFI_ERROR (Status
)) {
896 ASSERT (X509Data
!= NULL
);
898 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
900 Data
= AllocateZeroPool (SigDBSize
);
902 Status
= EFI_OUT_OF_RESOURCES
;
907 // Fill Certificate Database parameters.
909 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
910 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
911 SigDBCert
->SignatureHeaderSize
= 0;
912 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
913 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
915 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
916 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
917 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
920 // Check if signature database entry has been already existed.
921 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
922 // new signature data to original variable
924 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
925 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
926 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
927 if (EFI_ERROR (Status
)) {
928 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
932 Status
= gRT
->GetVariable(
934 &gEfiImageSecurityDatabaseGuid
,
939 if (Status
== EFI_BUFFER_TOO_SMALL
) {
940 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
941 } else if (Status
!= EFI_NOT_FOUND
) {
945 Status
= gRT
->SetVariable(
947 &gEfiImageSecurityDatabaseGuid
,
952 if (EFI_ERROR (Status
)) {
958 CloseFile (Private
->FileContext
->FHandle
);
959 if (Private
->FileContext
->FileName
!= NULL
){
960 FreePool(Private
->FileContext
->FileName
);
961 Private
->FileContext
->FileName
= NULL
;
964 Private
->FileContext
->FHandle
= NULL
;
966 if (Private
->SignatureGUID
!= NULL
) {
967 FreePool (Private
->SignatureGUID
);
968 Private
->SignatureGUID
= NULL
;
975 if (X509Data
!= NULL
) {
983 Check whether signature is in specified database.
985 @param[in] VariableName Name of database variable that is searched in.
986 @param[in] Signature Pointer to signature that is searched for.
987 @param[in] SignatureSize Size of Signature.
989 @return TRUE Found the signature in the variable database.
990 @return FALSE Not found the signature in the variable database.
994 IsSignatureFoundInDatabase (
995 IN CHAR16
*VariableName
,
997 IN UINTN SignatureSize
1001 EFI_SIGNATURE_LIST
*CertList
;
1002 EFI_SIGNATURE_DATA
*Cert
;
1010 // Read signature database variable.
1015 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1016 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1020 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1025 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1026 if (EFI_ERROR (Status
)) {
1031 // Enumerate all signature data in SigDB to check if executable's signature exists.
1033 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1034 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1035 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1036 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1037 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1038 for (Index
= 0; Index
< CertCount
; Index
++) {
1039 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1041 // Find the signature in database.
1046 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1054 DataSize
-= CertList
->SignatureListSize
;
1055 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1067 Calculate the hash of a certificate data with the specified hash algorithm.
1069 @param[in] CertData The certificate data to be hashed.
1070 @param[in] CertSize The certificate size in bytes.
1071 @param[in] HashAlg The specified hash algorithm.
1072 @param[out] CertHash The output digest of the certificate
1074 @retval TRUE Successfully got the hash of the CertData.
1075 @retval FALSE Failed to get the hash of CertData.
1095 if (HashAlg
>= HASHALG_MAX
) {
1100 // Retrieve the TBSCertificate for Hash Calculation.
1102 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1107 // 1. Initialize context of hash.
1109 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1110 HashCtx
= AllocatePool (CtxSize
);
1111 ASSERT (HashCtx
!= NULL
);
1114 // 2. Initialize a hash context.
1116 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1122 // 3. Calculate the hash.
1124 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1130 // 4. Get the hash result.
1132 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1133 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1136 if (HashCtx
!= NULL
) {
1144 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1146 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1147 @param[in] CertSize Size of X.509 Certificate.
1149 @return TRUE Found the certificate hash in the forbidden database.
1150 @return FALSE Certificate hash is Not found in the forbidden database.
1154 IsCertHashFoundInDbx (
1155 IN UINT8
*Certificate
,
1161 EFI_SIGNATURE_LIST
*DbxList
;
1162 EFI_SIGNATURE_DATA
*CertHash
;
1163 UINTN CertHashCount
;
1166 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1168 UINTN SiglistHeaderSize
;
1173 HashAlg
= HASHALG_MAX
;
1177 // Read signature database variable.
1180 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1181 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1185 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1190 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1191 if (EFI_ERROR (Status
)) {
1196 // Check whether the certificate hash exists in the forbidden database.
1198 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1199 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1201 // Determine Hash Algorithm of Certificate in the forbidden database.
1203 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1204 HashAlg
= HASHALG_SHA256
;
1205 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1206 HashAlg
= HASHALG_SHA384
;
1207 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1208 HashAlg
= HASHALG_SHA512
;
1210 DataSize
-= DbxList
->SignatureListSize
;
1211 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1216 // Calculate the hash value of current db certificate for comparision.
1218 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1222 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1223 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1224 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1225 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1227 // Iterate each Signature Data Node within this CertList for verify.
1229 DbxCertHash
= CertHash
->SignatureData
;
1230 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1232 // Hash of Certificate is found in forbidden database.
1237 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1240 DataSize
-= DbxList
->SignatureListSize
;
1241 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1253 Check whether the signature list exists in given variable data.
1255 It searches the signature list for the ceritificate hash by CertType.
1256 If the signature list is found, get the offset of Database for the
1257 next hash of a certificate.
1259 @param[in] Database Variable data to save signature list.
1260 @param[in] DatabaseSize Variable size.
1261 @param[in] SignatureType The type of the signature.
1262 @param[out] Offset The offset to save a new hash of certificate.
1264 @return TRUE The signature list is found in the forbidden database.
1265 @return FALSE The signature list is not found in the forbidden database.
1268 GetSignaturelistOffset (
1269 IN EFI_SIGNATURE_LIST
*Database
,
1270 IN UINTN DatabaseSize
,
1271 IN EFI_GUID
*SignatureType
,
1275 EFI_SIGNATURE_LIST
*SigList
;
1278 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1284 SiglistSize
= DatabaseSize
;
1285 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1286 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1287 *Offset
= DatabaseSize
- SiglistSize
;
1290 SiglistSize
-= SigList
->SignatureListSize
;
1291 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1298 Enroll a new X509 certificate hash into Signature Database (dbx) without
1299 KEK's authentication.
1301 @param[in] PrivateData The module's private data.
1302 @param[in] HashAlg The hash algorithm to enroll the certificate.
1303 @param[in] RevocationDate The revocation date of the certificate.
1304 @param[in] RevocationTime The revocation time of the certificate.
1305 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1307 @retval EFI_SUCCESS New X509 is enrolled successfully.
1308 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1309 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1313 EnrollX509HashtoSigDB (
1314 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1316 IN EFI_HII_DATE
*RevocationDate
,
1317 IN EFI_HII_TIME
*RevocationTime
,
1318 IN BOOLEAN AlwaysRevocation
1324 EFI_SIGNATURE_LIST
*SignatureList
;
1325 UINTN SignatureListSize
;
1331 EFI_SIGNATURE_DATA
*SignatureData
;
1332 UINTN SignatureSize
;
1333 EFI_GUID SignatureType
;
1335 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1336 UINT16
* FilePostFix
;
1343 SignatureData
= NULL
;
1344 SignatureList
= NULL
;
1348 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1349 return EFI_INVALID_PARAMETER
;
1352 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1353 if (EFI_ERROR (Status
)) {
1358 // Parse the file's postfix.
1360 NameLength
= StrLen (Private
->FileContext
->FileName
);
1361 if (NameLength
<= 4) {
1362 return EFI_INVALID_PARAMETER
;
1364 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1365 if (!IsDerEncodeCertificate(FilePostFix
)) {
1367 // Only supports DER-encoded X509 certificate.
1369 return EFI_INVALID_PARAMETER
;
1373 // Get the certificate from file and calculate its hash.
1375 Status
= ReadFileContent (
1376 Private
->FileContext
->FHandle
,
1381 if (EFI_ERROR (Status
)) {
1384 ASSERT (X509Data
!= NULL
);
1386 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1391 // Get the variable for enrollment.
1394 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1395 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1396 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1398 return EFI_OUT_OF_RESOURCES
;
1401 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1402 if (EFI_ERROR (Status
)) {
1408 // Allocate memory for Signature and fill the Signature
1410 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1411 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1412 if (SignatureData
== NULL
) {
1413 return EFI_OUT_OF_RESOURCES
;
1415 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1416 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1421 if (!AlwaysRevocation
) {
1422 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1423 Time
->Year
= RevocationDate
->Year
;
1424 Time
->Month
= RevocationDate
->Month
;
1425 Time
->Day
= RevocationDate
->Day
;
1426 Time
->Hour
= RevocationTime
->Hour
;
1427 Time
->Minute
= RevocationTime
->Minute
;
1428 Time
->Second
= RevocationTime
->Second
;
1432 // Determine the GUID for certificate hash.
1435 case HASHALG_SHA256
:
1436 SignatureType
= gEfiCertX509Sha256Guid
;
1438 case HASHALG_SHA384
:
1439 SignatureType
= gEfiCertX509Sha384Guid
;
1441 case HASHALG_SHA512
:
1442 SignatureType
= gEfiCertX509Sha512Guid
;
1449 // Add signature into the new variable data buffer
1451 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1453 // Add the signature to the found signaturelist.
1455 DbSize
= DataSize
+ SignatureSize
;
1456 NewData
= AllocateZeroPool (DbSize
);
1457 if (NewData
== NULL
) {
1458 Status
= EFI_OUT_OF_RESOURCES
;
1462 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1463 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1464 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1466 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1467 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1469 Offset
+= SignatureListSize
;
1470 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1471 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1478 // Create a new signaturelist, and add the signature into the signaturelist.
1480 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1481 NewData
= AllocateZeroPool (DbSize
);
1482 if (NewData
== NULL
) {
1483 Status
= EFI_OUT_OF_RESOURCES
;
1487 // Fill Certificate Database parameters.
1489 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1490 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1491 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1492 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1493 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1494 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1495 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1496 CopyMem (NewData
, Data
, DataSize
);
1503 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1504 if (EFI_ERROR (Status
)) {
1508 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1509 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1510 Status
= gRT
->SetVariable(
1511 EFI_IMAGE_SECURITY_DATABASE1
,
1512 &gEfiImageSecurityDatabaseGuid
,
1517 if (EFI_ERROR (Status
)) {
1522 CloseFile (Private
->FileContext
->FHandle
);
1523 if (Private
->FileContext
->FileName
!= NULL
){
1524 FreePool(Private
->FileContext
->FileName
);
1525 Private
->FileContext
->FileName
= NULL
;
1528 Private
->FileContext
->FHandle
= NULL
;
1530 if (Private
->SignatureGUID
!= NULL
) {
1531 FreePool (Private
->SignatureGUID
);
1532 Private
->SignatureGUID
= NULL
;
1539 if (SignatureData
!= NULL
) {
1540 FreePool (SignatureData
);
1543 if (X509Data
!= NULL
) {
1544 FreePool (X509Data
);
1551 Check whether a certificate from a file exists in dbx.
1553 @param[in] PrivateData The module's private data.
1554 @param[in] VariableName Variable name of signature database, must be
1555 EFI_IMAGE_SECURITY_DATABASE1.
1557 @retval TRUE The X509 certificate is found in dbx successfully.
1558 @retval FALSE The X509 certificate is not found in dbx.
1562 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1563 IN CHAR16
*VariableName
1572 // Read the certificate from file
1576 Status
= ReadFileContent (
1577 Private
->FileContext
->FHandle
,
1582 if (EFI_ERROR (Status
)) {
1587 // Check the raw certificate.
1590 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1596 // Check the hash of certificate.
1598 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1604 if (X509Data
!= NULL
) {
1605 FreePool (X509Data
);
1612 Reads contents of a PE/COFF image in memory buffer.
1614 Caution: This function may receive untrusted input.
1615 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1616 read is within the image buffer.
1618 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1619 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1620 @param ReadSize On input, the size in bytes of the requested read operation.
1621 On output, the number of bytes actually read.
1622 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1624 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1628 SecureBootConfigImageRead (
1629 IN VOID
*FileHandle
,
1630 IN UINTN FileOffset
,
1631 IN OUT UINTN
*ReadSize
,
1637 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1638 return EFI_INVALID_PARAMETER
;
1641 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1642 return EFI_INVALID_PARAMETER
;
1645 EndPosition
= FileOffset
+ *ReadSize
;
1646 if (EndPosition
> mImageSize
) {
1647 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1650 if (FileOffset
>= mImageSize
) {
1654 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1660 Load PE/COFF image information into internal buffer and check its validity.
1662 @retval EFI_SUCCESS Successful
1663 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1664 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1672 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1673 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1674 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1675 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1681 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1682 ImageContext
.Handle
= (VOID
*) mImageBase
;
1683 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1686 // Get information about the image being loaded
1688 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1689 if (EFI_ERROR (Status
)) {
1691 // The information can't be got from the invalid PeImage
1693 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1698 // Read the Dos header
1700 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1701 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1704 // DOS image header is present,
1705 // So read the PE header after the DOS image header
1707 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1711 mPeCoffHeaderOffset
= 0;
1715 // Read PE header and check the signature validity and machine compatibility
1717 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1718 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1720 return EFI_UNSUPPORTED
;
1723 mNtHeader
.Pe32
= NtHeader32
;
1726 // Check the architecture field of PE header and get the Certificate Data Directory data
1727 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1729 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1730 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1731 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1733 // 32-bits Architecture
1735 mImageType
= ImageType_IA32
;
1736 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1738 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1739 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1740 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1742 // 64-bits Architecture
1744 mImageType
= ImageType_X64
;
1745 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1746 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1748 return EFI_UNSUPPORTED
;
1755 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1756 PE/COFF Specification 8.0 Appendix A
1758 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1759 the function LoadPeImage ().
1761 @param[in] HashAlg Hash algorithm type.
1763 @retval TRUE Successfully hash image.
1764 @retval FALSE Fail in hash image.
1774 EFI_IMAGE_SECTION_HEADER
*Section
;
1779 UINTN SumOfBytesHashed
;
1780 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1785 SectionHeader
= NULL
;
1788 if (HashAlg
!= HASHALG_SHA256
) {
1793 // Initialize context of hash.
1795 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1797 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1798 mCertType
= gEfiCertSha256Guid
;
1800 CtxSize
= mHash
[HashAlg
].GetContextSize();
1802 HashCtx
= AllocatePool (CtxSize
);
1803 ASSERT (HashCtx
!= NULL
);
1805 // 1. Load the image header into memory.
1807 // 2. Initialize a SHA hash context.
1808 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1813 // Measuring PE/COFF Image Header;
1814 // But CheckSum field and SECURITY data directory (certificate) are excluded
1816 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1818 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1819 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1820 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1821 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1823 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1826 // Get the magic value from the PE/COFF Optional Header
1828 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1832 // 3. Calculate the distance from the base of the image header to the image checksum address.
1833 // 4. Hash the image header from its base to beginning of the image checksum.
1835 HashBase
= mImageBase
;
1836 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1840 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1843 // Use PE32+ offset.
1845 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1848 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1853 // 5. Skip over the image checksum (it occupies a single ULONG).
1854 // 6. Get the address of the beginning of the Cert Directory.
1855 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1857 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1861 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1862 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1865 // Use PE32+ offset.
1867 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1868 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1871 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1876 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1877 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1879 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1883 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1884 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1887 // Use PE32+ offset.
1889 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1890 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1893 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1898 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1900 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1904 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1909 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1913 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1914 // structures in the image. The 'NumberOfSections' field of the image
1915 // header indicates how big the table should be. Do not include any
1916 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1918 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1919 ASSERT (SectionHeader
!= NULL
);
1921 // 12. Using the 'PointerToRawData' in the referenced section headers as
1922 // a key, arrange the elements in the table in ascending order. In other
1923 // words, sort the section headers according to the disk-file offset of
1926 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1928 mPeCoffHeaderOffset
+
1930 sizeof (EFI_IMAGE_FILE_HEADER
) +
1931 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1933 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1935 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1936 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1939 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1944 // 13. Walk through the sorted table, bring the corresponding section
1945 // into memory, and hash the entire section (using the 'SizeOfRawData'
1946 // field in the section header to determine the amount of data to hash).
1947 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1948 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1950 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1951 Section
= &SectionHeader
[Index
];
1952 if (Section
->SizeOfRawData
== 0) {
1955 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1956 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1958 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1963 SumOfBytesHashed
+= HashSize
;
1967 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1968 // data in the file that needs to be added to the hash. This data begins
1969 // at file offset SUM_OF_BYTES_HASHED and its length is:
1970 // FileSize - (CertDirectory->Size)
1972 if (mImageSize
> SumOfBytesHashed
) {
1973 HashBase
= mImageBase
+ SumOfBytesHashed
;
1974 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1980 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1984 // Use PE32+ offset.
1988 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1992 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1998 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2001 if (HashCtx
!= NULL
) {
2004 if (SectionHeader
!= NULL
) {
2005 FreePool (SectionHeader
);
2011 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2012 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2015 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2016 @retval EFI_SUCCESS Hash successfully.
2025 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2027 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2029 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2031 // Check the Hash algorithm in PE/COFF Authenticode.
2032 // According to PKCS#7 Definition:
2033 // SignedData ::= SEQUENCE {
2035 // digestAlgorithms DigestAlgorithmIdentifiers,
2036 // contentInfo ContentInfo,
2038 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2039 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2040 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2042 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2044 // Only support two bytes of Long Form of Length Encoding.
2050 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2055 if (Index
== HASHALG_MAX
) {
2056 return EFI_UNSUPPORTED
;
2060 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2062 if (!HashPeImage(Index
)) {
2063 return EFI_UNSUPPORTED
;
2070 Enroll a new executable's signature into Signature Database.
2072 @param[in] PrivateData The module's private data.
2073 @param[in] VariableName Variable name of signature database, must be
2074 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2075 or EFI_IMAGE_SECURITY_DATABASE2.
2077 @retval EFI_SUCCESS New signature is enrolled successfully.
2078 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2079 @retval EFI_UNSUPPORTED Unsupported command.
2080 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2084 EnrollImageSignatureToSigDB (
2085 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2086 IN CHAR16
*VariableName
2090 EFI_SIGNATURE_LIST
*SigDBCert
;
2091 EFI_SIGNATURE_DATA
*SigDBCertData
;
2096 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2099 GuidCertData
= NULL
;
2101 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2102 return EFI_UNSUPPORTED
;
2106 // Form the SigDB certificate list.
2107 // Format the data item into EFI_SIGNATURE_LIST type.
2109 // We need to parse executable's signature data from specified signed executable file.
2110 // In current implementation, we simply trust the pass-in signed executable file.
2111 // In reality, it's OS's responsibility to verify the signed executable file.
2115 // Read the whole file content
2117 Status
= ReadFileContent(
2118 Private
->FileContext
->FHandle
,
2119 (VOID
**) &mImageBase
,
2123 if (EFI_ERROR (Status
)) {
2126 ASSERT (mImageBase
!= NULL
);
2128 Status
= LoadPeImage ();
2129 if (EFI_ERROR (Status
)) {
2133 if (mSecDataDir
->SizeOfCert
== 0) {
2134 if (!HashPeImage (HASHALG_SHA256
)) {
2135 Status
= EFI_SECURITY_VIOLATION
;
2141 // Read the certificate data
2143 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2145 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2146 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2147 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2148 Status
= EFI_ABORTED
;
2152 if (!HashPeImage (HASHALG_SHA256
)) {
2153 Status
= EFI_ABORTED
;
2157 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2159 Status
= HashPeImageByType ();
2160 if (EFI_ERROR (Status
)) {
2164 Status
= EFI_ABORTED
;
2170 // Create a new SigDB entry.
2172 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2173 + sizeof(EFI_SIGNATURE_DATA
) - 1
2174 + (UINT32
) mImageDigestSize
;
2176 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2178 Status
= EFI_OUT_OF_RESOURCES
;
2183 // Adjust the Certificate Database parameters.
2185 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2186 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2187 SigDBCert
->SignatureHeaderSize
= 0;
2188 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2189 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2191 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2192 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2193 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2195 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2196 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2197 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2198 if (EFI_ERROR (Status
)) {
2199 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2204 // Check if SigDB variable has been already existed.
2205 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2206 // new signature data to original variable
2209 Status
= gRT
->GetVariable(
2211 &gEfiImageSecurityDatabaseGuid
,
2216 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2217 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2218 } else if (Status
!= EFI_NOT_FOUND
) {
2223 // Enroll the variable.
2225 Status
= gRT
->SetVariable(
2227 &gEfiImageSecurityDatabaseGuid
,
2232 if (EFI_ERROR (Status
)) {
2238 CloseFile (Private
->FileContext
->FHandle
);
2239 Private
->FileContext
->FHandle
= NULL
;
2241 if (Private
->FileContext
->FileName
!= NULL
){
2242 FreePool(Private
->FileContext
->FileName
);
2243 Private
->FileContext
->FileName
= NULL
;
2246 if (Private
->SignatureGUID
!= NULL
) {
2247 FreePool (Private
->SignatureGUID
);
2248 Private
->SignatureGUID
= NULL
;
2255 if (mImageBase
!= NULL
) {
2256 FreePool (mImageBase
);
2264 Enroll signature into DB/DBX/DBT without KEK's authentication.
2265 The SignatureOwner GUID will be Private->SignatureGUID.
2267 @param[in] PrivateData The module's private data.
2268 @param[in] VariableName Variable name of signature database, must be
2269 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2271 @retval EFI_SUCCESS New signature enrolled successfully.
2272 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2273 @retval others Fail to enroll signature data.
2277 EnrollSignatureDatabase (
2278 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2279 IN CHAR16
*VariableName
2282 UINT16
* FilePostFix
;
2286 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2287 return EFI_INVALID_PARAMETER
;
2290 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2291 if (EFI_ERROR (Status
)) {
2296 // Parse the file's postfix.
2298 NameLength
= StrLen (Private
->FileContext
->FileName
);
2299 if (NameLength
<= 4) {
2300 return EFI_INVALID_PARAMETER
;
2302 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2303 if (IsDerEncodeCertificate (FilePostFix
)) {
2305 // Supports DER-encoded X509 certificate.
2307 return EnrollX509toSigDB (Private
, VariableName
);
2310 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2314 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2315 by GUID in the page for user to select and delete as needed.
2317 @param[in] PrivateData Module's private data.
2318 @param[in] VariableName The variable name of the vendor's signature database.
2319 @param[in] VendorGuid A unique identifier for the vendor.
2320 @param[in] LabelNumber Label number to insert opcodes.
2321 @param[in] FormId Form ID of current page.
2322 @param[in] QuestionIdBase Base question id of the signature list.
2324 @retval EFI_SUCCESS Success to update the signature list page
2325 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2330 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2331 IN CHAR16
*VariableName
,
2332 IN EFI_GUID
*VendorGuid
,
2333 IN UINT16 LabelNumber
,
2334 IN EFI_FORM_ID FormId
,
2335 IN EFI_QUESTION_ID QuestionIdBase
2342 VOID
*StartOpCodeHandle
;
2343 VOID
*EndOpCodeHandle
;
2344 EFI_IFR_GUID_LABEL
*StartLabel
;
2345 EFI_IFR_GUID_LABEL
*EndLabel
;
2348 EFI_SIGNATURE_LIST
*CertList
;
2349 EFI_SIGNATURE_DATA
*Cert
;
2350 UINT32 ItemDataSize
;
2352 EFI_STRING_ID GuidID
;
2359 StartOpCodeHandle
= NULL
;
2360 EndOpCodeHandle
= NULL
;
2363 // Initialize the container for dynamic opcodes.
2365 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2366 if (StartOpCodeHandle
== NULL
) {
2367 Status
= EFI_OUT_OF_RESOURCES
;
2371 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2372 if (EndOpCodeHandle
== NULL
) {
2373 Status
= EFI_OUT_OF_RESOURCES
;
2378 // Create Hii Extend Label OpCode.
2380 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2384 sizeof (EFI_IFR_GUID_LABEL
)
2386 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2387 StartLabel
->Number
= LabelNumber
;
2389 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2393 sizeof (EFI_IFR_GUID_LABEL
)
2395 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2396 EndLabel
->Number
= LABEL_END
;
2402 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2403 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2407 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2409 Status
= EFI_OUT_OF_RESOURCES
;
2413 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2414 if (EFI_ERROR (Status
)) {
2418 GuidStr
= AllocateZeroPool (100);
2419 if (GuidStr
== NULL
) {
2420 Status
= EFI_OUT_OF_RESOURCES
;
2425 // Enumerate all KEK pub data.
2427 ItemDataSize
= (UINT32
) DataSize
;
2428 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2431 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2433 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2434 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2435 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2436 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2437 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2438 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2439 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2440 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2441 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2442 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2443 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2444 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2445 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2446 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2449 // The signature type is not supported in current implementation.
2451 ItemDataSize
-= CertList
->SignatureListSize
;
2452 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2456 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2457 for (Index
= 0; Index
< CertCount
; Index
++) {
2458 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2459 + sizeof (EFI_SIGNATURE_LIST
)
2460 + CertList
->SignatureHeaderSize
2461 + Index
* CertList
->SignatureSize
);
2463 // Display GUID and help
2465 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2466 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2467 HiiCreateCheckBoxOpCode (
2469 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2474 EFI_IFR_FLAG_CALLBACK
,
2480 ItemDataSize
-= CertList
->SignatureListSize
;
2481 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2486 PrivateData
->HiiHandle
,
2487 &gSecureBootConfigFormSetGuid
,
2493 if (StartOpCodeHandle
!= NULL
) {
2494 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2497 if (EndOpCodeHandle
!= NULL
) {
2498 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2505 if (GuidStr
!= NULL
) {
2513 Delete a KEK entry from KEK database.
2515 @param[in] PrivateData Module's private data.
2516 @param[in] QuestionId Question id of the KEK item to delete.
2518 @retval EFI_SUCCESS Delete kek item successfully.
2519 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2523 DeleteKeyExchangeKey (
2524 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2525 IN EFI_QUESTION_ID QuestionId
2534 EFI_SIGNATURE_LIST
*CertList
;
2535 EFI_SIGNATURE_LIST
*NewCertList
;
2536 EFI_SIGNATURE_DATA
*Cert
;
2539 BOOLEAN IsKEKItemFound
;
2541 UINTN DeleteKekIndex
;
2549 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2551 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2552 if (EFI_ERROR (Status
)) {
2557 // Get original KEK variable.
2560 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2561 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2565 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2566 if (OldData
== NULL
) {
2567 Status
= EFI_OUT_OF_RESOURCES
;
2571 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2572 if (EFI_ERROR(Status
)) {
2577 // Allocate space for new variable.
2579 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2581 Status
= EFI_OUT_OF_RESOURCES
;
2586 // Enumerate all KEK pub data and erasing the target item.
2588 IsKEKItemFound
= FALSE
;
2589 KekDataSize
= (UINT32
) DataSize
;
2590 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2593 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2594 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2595 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2596 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2597 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2598 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2599 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2600 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2601 for (Index
= 0; Index
< CertCount
; Index
++) {
2602 if (GuidIndex
== DeleteKekIndex
) {
2604 // Find it! Skip it!
2606 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2607 IsKEKItemFound
= TRUE
;
2610 // This item doesn't match. Copy it to the Data buffer.
2612 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2613 Offset
+= CertList
->SignatureSize
;
2616 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2620 // This List doesn't match. Copy it to the Data buffer.
2622 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2623 Offset
+= CertList
->SignatureListSize
;
2626 KekDataSize
-= CertList
->SignatureListSize
;
2627 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2630 if (!IsKEKItemFound
) {
2632 // Doesn't find the Kek Item!
2634 Status
= EFI_NOT_FOUND
;
2639 // Delete the Signature header if there is no signature in the list.
2641 KekDataSize
= Offset
;
2642 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2644 ZeroMem (OldData
, KekDataSize
);
2645 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2646 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2647 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2648 if (CertCount
!= 0) {
2649 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2650 Offset
+= CertList
->SignatureListSize
;
2652 KekDataSize
-= CertList
->SignatureListSize
;
2653 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2657 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2658 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2659 if (EFI_ERROR (Status
)) {
2660 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2665 Status
= gRT
->SetVariable(
2666 EFI_KEY_EXCHANGE_KEY_NAME
,
2667 &gEfiGlobalVariableGuid
,
2672 if (EFI_ERROR (Status
)) {
2673 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2682 if (OldData
!= NULL
) {
2686 return UpdateDeletePage (
2688 EFI_KEY_EXCHANGE_KEY_NAME
,
2689 &gEfiGlobalVariableGuid
,
2691 FORMID_DELETE_KEK_FORM
,
2692 OPTION_DEL_KEK_QUESTION_ID
2697 Delete a signature entry from siganture database.
2699 @param[in] PrivateData Module's private data.
2700 @param[in] VariableName The variable name of the vendor's signature database.
2701 @param[in] VendorGuid A unique identifier for the vendor.
2702 @param[in] LabelNumber Label number to insert opcodes.
2703 @param[in] FormId Form ID of current page.
2704 @param[in] QuestionIdBase Base question id of the signature list.
2705 @param[in] DeleteIndex Signature index to delete.
2707 @retval EFI_SUCCESS Delete siganture successfully.
2708 @retval EFI_NOT_FOUND Can't find the signature item,
2709 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2713 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2714 IN CHAR16
*VariableName
,
2715 IN EFI_GUID
*VendorGuid
,
2716 IN UINT16 LabelNumber
,
2717 IN EFI_FORM_ID FormId
,
2718 IN EFI_QUESTION_ID QuestionIdBase
,
2719 IN UINTN DeleteIndex
2728 EFI_SIGNATURE_LIST
*CertList
;
2729 EFI_SIGNATURE_LIST
*NewCertList
;
2730 EFI_SIGNATURE_DATA
*Cert
;
2733 BOOLEAN IsItemFound
;
2734 UINT32 ItemDataSize
;
2743 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2744 if (EFI_ERROR (Status
)) {
2749 // Get original signature list data.
2752 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2753 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2757 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2758 if (OldData
== NULL
) {
2759 Status
= EFI_OUT_OF_RESOURCES
;
2763 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2764 if (EFI_ERROR(Status
)) {
2769 // Allocate space for new variable.
2771 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2773 Status
= EFI_OUT_OF_RESOURCES
;
2778 // Enumerate all signature data and erasing the target item.
2780 IsItemFound
= FALSE
;
2781 ItemDataSize
= (UINT32
) DataSize
;
2782 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2785 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2786 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2787 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2788 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2789 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2790 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2791 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2792 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2795 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2797 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2798 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2799 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2800 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2801 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2802 for (Index
= 0; Index
< CertCount
; Index
++) {
2803 if (GuidIndex
== DeleteIndex
) {
2805 // Find it! Skip it!
2807 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2811 // This item doesn't match. Copy it to the Data buffer.
2813 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2814 Offset
+= CertList
->SignatureSize
;
2817 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2821 // This List doesn't match. Just copy it to the Data buffer.
2823 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2824 Offset
+= CertList
->SignatureListSize
;
2827 ItemDataSize
-= CertList
->SignatureListSize
;
2828 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2833 // Doesn't find the signature Item!
2835 Status
= EFI_NOT_FOUND
;
2840 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2842 ItemDataSize
= Offset
;
2843 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2845 ZeroMem (OldData
, ItemDataSize
);
2846 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2847 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2848 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2849 if (CertCount
!= 0) {
2850 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2851 Offset
+= CertList
->SignatureListSize
;
2853 ItemDataSize
-= CertList
->SignatureListSize
;
2854 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2858 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2859 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2860 if (EFI_ERROR (Status
)) {
2861 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2866 Status
= gRT
->SetVariable(
2873 if (EFI_ERROR (Status
)) {
2874 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2883 if (OldData
!= NULL
) {
2887 return UpdateDeletePage (
2899 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
2900 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
2902 @param[in] PrivateData Module's private data.
2904 @return EFI_SUCCESS Update secure boot strings successfully.
2905 @return other Fail to update secure boot strings.
2909 UpdateSecureBootString(
2910 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
2918 // Get current secure boot state.
2920 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2921 if (SecureBoot
== NULL
) {
2922 return EFI_NOT_FOUND
;
2925 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2926 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
2928 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
2931 FreePool(SecureBoot
);
2937 This function extracts configuration from variable.
2939 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2943 SecureBootExtractConfigFromVariable (
2944 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2947 UINT8
*SecureBootEnable
;
2949 UINT8
*SecureBootMode
;
2952 SecureBootEnable
= NULL
;
2954 SecureBootMode
= NULL
;
2957 // Initilize the Date and Time using system time.
2959 ConfigData
->CertificateFormat
= HASHALG_RAW
;
2960 ConfigData
->AlwaysRevocation
= TRUE
;
2961 gRT
->GetTime (&CurrTime
, NULL
);
2962 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
2963 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
2964 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
2965 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
2966 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
2967 ConfigData
->RevocationTime
.Second
= 0;
2971 // If it is Physical Presence User, set the PhysicalPresent to true.
2973 if (UserPhysicalPresent()) {
2974 ConfigData
->PhysicalPresent
= TRUE
;
2976 ConfigData
->PhysicalPresent
= FALSE
;
2980 // If there is no PK then the Delete Pk button will be gray.
2982 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2983 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2984 ConfigData
->HasPk
= FALSE
;
2986 ConfigData
->HasPk
= TRUE
;
2990 // Check SecureBootEnable & Pk status, fix the inconsistence.
2991 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2994 ConfigData
->AttemptSecureBoot
= FALSE
;
2995 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2998 // Fix Pk, SecureBootEnable inconsistence
3000 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3001 ConfigData
->HideSecureBoot
= FALSE
;
3002 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3003 ConfigData
->AttemptSecureBoot
= TRUE
;
3006 ConfigData
->HideSecureBoot
= TRUE
;
3010 // Get the SecureBootMode from CustomMode variable.
3012 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3013 if (SecureBootMode
== NULL
) {
3014 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3016 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3019 if (SecureBootEnable
!= NULL
) {
3020 FreePool (SecureBootEnable
);
3022 if (SetupMode
!= NULL
) {
3023 FreePool (SetupMode
);
3025 if (SecureBootMode
!= NULL
) {
3026 FreePool (SecureBootMode
);
3031 This function allows a caller to extract the current configuration for one
3032 or more named elements from the target driver.
3034 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3035 @param[in] Request A null-terminated Unicode string in
3036 <ConfigRequest> format.
3037 @param[out] Progress On return, points to a character in the Request
3038 string. Points to the string's null terminator if
3039 request was successful. Points to the most recent
3040 '&' before the first failing name/value pair (or
3041 the beginning of the string if the failure is in
3042 the first name/value pair) if the request was not
3044 @param[out] Results A null-terminated Unicode string in
3045 <ConfigAltResp> format which has all values filled
3046 in for the names in the Request string. String to
3047 be allocated by the called function.
3049 @retval EFI_SUCCESS The Results is filled with the requested values.
3050 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3051 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3052 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3058 SecureBootExtractConfig (
3059 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3060 IN CONST EFI_STRING Request
,
3061 OUT EFI_STRING
*Progress
,
3062 OUT EFI_STRING
*Results
3068 SECUREBOOT_CONFIGURATION Configuration
;
3069 EFI_STRING ConfigRequest
;
3070 EFI_STRING ConfigRequestHdr
;
3071 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3072 BOOLEAN AllocatedRequest
;
3074 if (Progress
== NULL
|| Results
== NULL
) {
3075 return EFI_INVALID_PARAMETER
;
3078 AllocatedRequest
= FALSE
;
3079 ConfigRequestHdr
= NULL
;
3080 ConfigRequest
= NULL
;
3083 ZeroMem (&Configuration
, sizeof (Configuration
));
3084 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3085 *Progress
= Request
;
3087 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3088 return EFI_NOT_FOUND
;
3092 // Get Configuration from Variable.
3094 SecureBootExtractConfigFromVariable (&Configuration
);
3096 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3097 ConfigRequest
= Request
;
3098 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3100 // Request is set to NULL or OFFSET is NULL, construct full request string.
3102 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3103 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3105 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3106 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3107 ConfigRequest
= AllocateZeroPool (Size
);
3108 ASSERT (ConfigRequest
!= NULL
);
3109 AllocatedRequest
= TRUE
;
3110 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3111 FreePool (ConfigRequestHdr
);
3112 ConfigRequestHdr
= NULL
;
3115 Status
= gHiiConfigRouting
->BlockToConfig (
3118 (UINT8
*) &Configuration
,
3125 // Free the allocated config request string.
3127 if (AllocatedRequest
) {
3128 FreePool (ConfigRequest
);
3132 // Set Progress string to the original request string.
3134 if (Request
== NULL
) {
3136 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3137 *Progress
= Request
+ StrLen (Request
);
3144 This function processes the results of changes in configuration.
3146 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3147 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3149 @param[out] Progress A pointer to a string filled in with the offset of
3150 the most recent '&' before the first failing
3151 name/value pair (or the beginning of the string if
3152 the failure is in the first name/value pair) or
3153 the terminating NULL if all was successful.
3155 @retval EFI_SUCCESS The Results is processed successfully.
3156 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3157 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3163 SecureBootRouteConfig (
3164 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3165 IN CONST EFI_STRING Configuration
,
3166 OUT EFI_STRING
*Progress
3169 SECUREBOOT_CONFIGURATION IfrNvData
;
3173 if (Configuration
== NULL
|| Progress
== NULL
) {
3174 return EFI_INVALID_PARAMETER
;
3177 *Progress
= Configuration
;
3178 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3179 return EFI_NOT_FOUND
;
3183 // Get Configuration from Variable.
3185 SecureBootExtractConfigFromVariable (&IfrNvData
);
3188 // Map the Configuration to the configuration block.
3190 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3191 Status
= gHiiConfigRouting
->ConfigToBlock (
3194 (UINT8
*)&IfrNvData
,
3198 if (EFI_ERROR (Status
)) {
3203 // Store Buffer Storage back to EFI variable if needed
3205 if (!IfrNvData
.HideSecureBoot
) {
3206 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3207 if (EFI_ERROR (Status
)) {
3212 *Progress
= Configuration
+ StrLen (Configuration
);
3217 This function is called to provide results data to the driver.
3219 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3220 @param[in] Action Specifies the type of action taken by the browser.
3221 @param[in] QuestionId A unique value which is sent to the original
3222 exporting driver so that it can identify the type
3224 @param[in] Type The type of value for the question.
3225 @param[in] Value A pointer to the data being sent to the original
3227 @param[out] ActionRequest On return, points to the action requested by the
3230 @retval EFI_SUCCESS The callback successfully handled the action.
3231 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3232 variable and its data.
3233 @retval EFI_DEVICE_ERROR The variable could not be saved.
3234 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3240 SecureBootCallback (
3241 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3242 IN EFI_BROWSER_ACTION Action
,
3243 IN EFI_QUESTION_ID QuestionId
,
3245 IN EFI_IFR_TYPE_VALUE
*Value
,
3246 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3251 RETURN_STATUS RStatus
;
3252 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3254 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3256 UINT8
*SecureBootEnable
;
3258 UINT8
*SecureBootMode
;
3260 CHAR16 PromptString
[100];
3261 EFI_DEVICE_PATH_PROTOCOL
*File
;
3263 Status
= EFI_SUCCESS
;
3264 SecureBootEnable
= NULL
;
3265 SecureBootMode
= NULL
;
3269 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3270 return EFI_INVALID_PARAMETER
;
3273 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3275 gSecureBootPrivateData
= Private
;
3278 // Retrieve uncommitted data from Browser
3280 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3281 IfrNvData
= AllocateZeroPool (BufferSize
);
3282 if (IfrNvData
== NULL
) {
3283 return EFI_OUT_OF_RESOURCES
;
3286 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3288 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3289 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3291 // Update secure boot strings when opening this form
3293 Status
= UpdateSecureBootString(Private
);
3294 SecureBootExtractConfigFromVariable (IfrNvData
);
3295 mIsEnterSecureBootForm
= TRUE
;
3300 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3301 Status
= EFI_UNSUPPORTED
;
3302 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3303 if (mIsEnterSecureBootForm
) {
3304 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3305 Status
= EFI_SUCCESS
;
3311 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3312 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3313 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3314 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3315 Status
= EFI_UNSUPPORTED
;
3319 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3321 switch (QuestionId
) {
3322 case KEY_SECURE_BOOT_ENABLE
:
3323 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3324 if (NULL
!= SecureBootEnable
) {
3325 FreePool (SecureBootEnable
);
3326 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3328 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3330 L
"Only Physical Presence User could disable secure boot!",
3333 Status
= EFI_UNSUPPORTED
;
3336 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3338 L
"Configuration changed, please reset the platform to take effect!",
3345 case KEY_SECURE_BOOT_KEK_OPTION
:
3346 case KEY_SECURE_BOOT_DB_OPTION
:
3347 case KEY_SECURE_BOOT_DBX_OPTION
:
3348 case KEY_SECURE_BOOT_DBT_OPTION
:
3350 // Clear Signature GUID.
3352 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3353 if (Private
->SignatureGUID
== NULL
) {
3354 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3355 if (Private
->SignatureGUID
== NULL
) {
3356 return EFI_OUT_OF_RESOURCES
;
3360 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3361 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3362 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3363 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3364 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3365 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3367 LabelId
= FORMID_ENROLL_KEK_FORM
;
3371 // Refresh selected file.
3373 CleanUpPage (LabelId
, Private
);
3375 case KEY_SECURE_BOOT_PK_OPTION
:
3376 LabelId
= FORMID_ENROLL_PK_FORM
;
3378 // Refresh selected file.
3380 CleanUpPage (LabelId
, Private
);
3383 case FORMID_ENROLL_PK_FORM
:
3384 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
3387 case FORMID_ENROLL_KEK_FORM
:
3388 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
3391 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3392 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
3395 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3396 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
3399 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3400 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
3403 case KEY_SECURE_BOOT_DELETE_PK
:
3406 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3408 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3409 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3412 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3413 Status
= DeletePlatformKey ();
3414 if (EFI_ERROR (Status
)) {
3416 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3418 L
"Only Physical Presence User could delete PK in custom mode!",
3426 case KEY_DELETE_KEK
:
3429 EFI_KEY_EXCHANGE_KEY_NAME
,
3430 &gEfiGlobalVariableGuid
,
3432 FORMID_DELETE_KEK_FORM
,
3433 OPTION_DEL_KEK_QUESTION_ID
3437 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3440 EFI_IMAGE_SECURITY_DATABASE
,
3441 &gEfiImageSecurityDatabaseGuid
,
3443 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3444 OPTION_DEL_DB_QUESTION_ID
3448 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3451 EFI_IMAGE_SECURITY_DATABASE1
,
3452 &gEfiImageSecurityDatabaseGuid
,
3454 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3455 OPTION_DEL_DBX_QUESTION_ID
3460 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3463 EFI_IMAGE_SECURITY_DATABASE2
,
3464 &gEfiImageSecurityDatabaseGuid
,
3466 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3467 OPTION_DEL_DBT_QUESTION_ID
3472 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3473 Status
= EnrollKeyExchangeKey (Private
);
3474 if (EFI_ERROR (Status
)) {
3476 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3478 L
"ERROR: Unsupported file type!",
3479 L
"Only supports DER-encoded X509 certificate",
3485 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3486 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3487 if (EFI_ERROR (Status
)) {
3489 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3491 L
"ERROR: Unsupported file type!",
3492 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3498 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3499 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3501 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3503 L
"Enrollment failed! Same certificate had already been in the dbx!",
3509 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3510 Status
= EnrollX509HashtoSigDB (
3512 IfrNvData
->CertificateFormat
,
3513 &IfrNvData
->RevocationDate
,
3514 &IfrNvData
->RevocationTime
,
3515 IfrNvData
->AlwaysRevocation
3518 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3520 if (EFI_ERROR (Status
)) {
3522 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3524 L
"ERROR: Unsupported file type!",
3525 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3531 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3532 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3533 if (EFI_ERROR (Status
)) {
3535 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3537 L
"ERROR: Unsupported file type!",
3538 L
"Only supports DER-encoded X509 certificate.",
3543 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3544 Status
= EnrollPlatformKey (Private
);
3545 if (EFI_ERROR (Status
)) {
3548 sizeof (PromptString
),
3549 L
"Only DER encoded certificate file (%s) is supported.",
3553 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3555 L
"ERROR: Unsupported file type!",
3562 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3563 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3564 DeleteKeyExchangeKey (Private
, QuestionId
);
3565 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3566 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3569 EFI_IMAGE_SECURITY_DATABASE
,
3570 &gEfiImageSecurityDatabaseGuid
,
3572 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3573 OPTION_DEL_DB_QUESTION_ID
,
3574 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3576 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3577 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3580 EFI_IMAGE_SECURITY_DATABASE1
,
3581 &gEfiImageSecurityDatabaseGuid
,
3583 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3584 OPTION_DEL_DBX_QUESTION_ID
,
3585 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3587 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3588 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3591 EFI_IMAGE_SECURITY_DATABASE2
,
3592 &gEfiImageSecurityDatabaseGuid
,
3594 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3595 OPTION_DEL_DBT_QUESTION_ID
,
3596 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3601 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3602 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3603 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3604 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3605 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3606 if (Private
->FileContext
->FHandle
!= NULL
) {
3607 CloseFile (Private
->FileContext
->FHandle
);
3608 Private
->FileContext
->FHandle
= NULL
;
3609 if (Private
->FileContext
->FileName
!= NULL
){
3610 FreePool(Private
->FileContext
->FileName
);
3611 Private
->FileContext
->FileName
= NULL
;
3615 if (Private
->SignatureGUID
!= NULL
) {
3616 FreePool (Private
->SignatureGUID
);
3617 Private
->SignatureGUID
= NULL
;
3621 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3622 switch (QuestionId
) {
3623 case KEY_SECURE_BOOT_ENABLE
:
3624 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3626 case KEY_SECURE_BOOT_MODE
:
3627 mIsEnterSecureBootForm
= FALSE
;
3629 case KEY_SECURE_BOOT_KEK_GUID
:
3630 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3631 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3632 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3633 ASSERT (Private
->SignatureGUID
!= NULL
);
3634 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
3635 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
3636 Status
= EFI_INVALID_PARAMETER
;
3640 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3643 case KEY_SECURE_BOOT_DELETE_PK
:
3644 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3645 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3646 IfrNvData
->DeletePk
= TRUE
;
3647 IfrNvData
->HasPk
= FALSE
;
3648 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3650 IfrNvData
->DeletePk
= FALSE
;
3651 IfrNvData
->HasPk
= TRUE
;
3652 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3654 if (SetupMode
!= NULL
) {
3655 FreePool (SetupMode
);
3661 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3662 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3663 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
3665 IfrNvData
->HideSecureBoot
= TRUE
;
3668 IfrNvData
->HideSecureBoot
= FALSE
;
3670 Value
->b
= IfrNvData
->HideSecureBoot
;
3672 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3674 // Force the platform back to Standard Mode once user leave the setup screen.
3676 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3677 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3678 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3679 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3681 if (SecureBootMode
!= NULL
) {
3682 FreePool (SecureBootMode
);
3688 if (!EFI_ERROR (Status
)) {
3689 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3690 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3693 FreePool (IfrNvData
);
3704 This function publish the SecureBoot configuration Form.
3706 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3708 @retval EFI_SUCCESS HII Form is installed successfully.
3709 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3710 @retval Others Other errors as indicated.
3714 InstallSecureBootConfigForm (
3715 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3719 EFI_HII_HANDLE HiiHandle
;
3720 EFI_HANDLE DriverHandle
;
3721 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3723 DriverHandle
= NULL
;
3724 ConfigAccess
= &PrivateData
->ConfigAccess
;
3725 Status
= gBS
->InstallMultipleProtocolInterfaces (
3727 &gEfiDevicePathProtocolGuid
,
3728 &mSecureBootHiiVendorDevicePath
,
3729 &gEfiHiiConfigAccessProtocolGuid
,
3733 if (EFI_ERROR (Status
)) {
3737 PrivateData
->DriverHandle
= DriverHandle
;
3740 // Publish the HII package list
3742 HiiHandle
= HiiAddPackages (
3743 &gSecureBootConfigFormSetGuid
,
3745 SecureBootConfigDxeStrings
,
3746 SecureBootConfigBin
,
3749 if (HiiHandle
== NULL
) {
3750 gBS
->UninstallMultipleProtocolInterfaces (
3752 &gEfiDevicePathProtocolGuid
,
3753 &mSecureBootHiiVendorDevicePath
,
3754 &gEfiHiiConfigAccessProtocolGuid
,
3758 return EFI_OUT_OF_RESOURCES
;
3761 PrivateData
->HiiHandle
= HiiHandle
;
3763 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
3765 if (PrivateData
->FileContext
== NULL
) {
3766 UninstallSecureBootConfigForm (PrivateData
);
3767 return EFI_OUT_OF_RESOURCES
;
3771 // Init OpCode Handle and Allocate space for creation of Buffer
3773 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3774 if (mStartOpCodeHandle
== NULL
) {
3775 UninstallSecureBootConfigForm (PrivateData
);
3776 return EFI_OUT_OF_RESOURCES
;
3779 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3780 if (mEndOpCodeHandle
== NULL
) {
3781 UninstallSecureBootConfigForm (PrivateData
);
3782 return EFI_OUT_OF_RESOURCES
;
3786 // Create Hii Extend Label OpCode as the start opcode
3788 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
3792 sizeof (EFI_IFR_GUID_LABEL
)
3794 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3797 // Create Hii Extend Label OpCode as the end opcode
3799 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
3803 sizeof (EFI_IFR_GUID_LABEL
)
3805 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3806 mEndLabel
->Number
= LABEL_END
;
3812 This function removes SecureBoot configuration Form.
3814 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3818 UninstallSecureBootConfigForm (
3819 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3823 // Uninstall HII package list
3825 if (PrivateData
->HiiHandle
!= NULL
) {
3826 HiiRemovePackages (PrivateData
->HiiHandle
);
3827 PrivateData
->HiiHandle
= NULL
;
3831 // Uninstall HII Config Access Protocol
3833 if (PrivateData
->DriverHandle
!= NULL
) {
3834 gBS
->UninstallMultipleProtocolInterfaces (
3835 PrivateData
->DriverHandle
,
3836 &gEfiDevicePathProtocolGuid
,
3837 &mSecureBootHiiVendorDevicePath
,
3838 &gEfiHiiConfigAccessProtocolGuid
,
3839 &PrivateData
->ConfigAccess
,
3842 PrivateData
->DriverHandle
= NULL
;
3845 if (PrivateData
->SignatureGUID
!= NULL
) {
3846 FreePool (PrivateData
->SignatureGUID
);
3849 if (PrivateData
->FileContext
!= NULL
) {
3850 FreePool (PrivateData
->FileContext
);
3853 FreePool (PrivateData
);
3855 if (mStartOpCodeHandle
!= NULL
) {
3856 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
3859 if (mEndOpCodeHandle
!= NULL
) {
3860 HiiFreeOpCodeHandle (mEndOpCodeHandle
);