2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2016, 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
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
67 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
68 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
69 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
70 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
74 // Variable Definitions
76 UINT32 mPeCoffHeaderOffset
= 0;
77 WIN_CERTIFICATE
*mCertificate
= NULL
;
78 IMAGE_TYPE mImageType
;
79 UINT8
*mImageBase
= NULL
;
81 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
82 UINTN mImageDigestSize
;
84 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
85 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
88 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
90 CHAR16
* mDerEncodedSuffix
[] = {
96 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
98 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
101 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
103 @param[in] FileSuffix The suffix of the input certificate file
105 @retval TRUE It's a DER-encoded certificate.
106 @retval FALSE It's NOT a DER-encoded certificate.
110 IsDerEncodeCertificate (
111 IN CONST CHAR16
*FileSuffix
115 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
116 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
124 Set Secure Boot option into variable space.
126 @param[in] VarValue The option of Secure Boot.
128 @retval EFI_SUCCESS The operation is finished successfully.
129 @retval Others Other errors as indicated.
133 SaveSecureBootVariable (
139 Status
= gRT
->SetVariable (
140 EFI_SECURE_BOOT_ENABLE_NAME
,
141 &gEfiSecureBootEnableDisableGuid
,
142 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
150 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
151 descriptor with the input data. NO authentication is required in this function.
153 @param[in, out] DataSize On input, the size of Data buffer in bytes.
154 On output, the size of data returned in Data
156 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
157 pointer to NULL to wrap an empty payload.
158 On output, Pointer to the new payload date buffer allocated from pool,
159 it's caller's responsibility to free the memory when finish using it.
161 @retval EFI_SUCCESS Create time based payload successfully.
162 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
163 @retval EFI_INVALID_PARAMETER The parameter is invalid.
164 @retval Others Unexpected error happens.
168 CreateTimeBasedPayload (
169 IN OUT UINTN
*DataSize
,
177 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
178 UINTN DescriptorSize
;
181 if (Data
== NULL
|| DataSize
== NULL
) {
182 return EFI_INVALID_PARAMETER
;
186 // In Setup mode or Custom mode, the variable does not need to be signed but the
187 // parameters to the SetVariable() call still need to be prepared as authenticated
188 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
192 PayloadSize
= *DataSize
;
194 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
195 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
196 if (NewData
== NULL
) {
197 return EFI_OUT_OF_RESOURCES
;
200 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
201 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
204 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
206 ZeroMem (&Time
, sizeof (EFI_TIME
));
207 Status
= gRT
->GetTime (&Time
, NULL
);
208 if (EFI_ERROR (Status
)) {
217 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
219 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
220 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
221 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
222 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
224 if (Payload
!= NULL
) {
228 *DataSize
= DescriptorSize
+ PayloadSize
;
234 Internal helper function to delete a Variable given its name and GUID, NO authentication
237 @param[in] VariableName Name of the Variable.
238 @param[in] VendorGuid GUID of the Variable.
240 @retval EFI_SUCCESS Variable deleted successfully.
241 @retval Others The driver failed to start the device.
246 IN CHAR16
*VariableName
,
247 IN EFI_GUID
*VendorGuid
256 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
257 if (Variable
== NULL
) {
264 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
265 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
267 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
268 if (EFI_ERROR (Status
)) {
269 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
273 Status
= gRT
->SetVariable (
288 Set the platform secure boot mode into "Custom" or "Standard" mode.
290 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
291 CUSTOM_SECURE_BOOT_MODE.
293 @return EFI_SUCCESS The platform has switched to the special mode successfully.
294 @return other Fail to operate the secure boot mode.
299 IN UINT8 SecureBootMode
302 return gRT
->SetVariable (
303 EFI_CUSTOM_MODE_NAME
,
304 &gEfiCustomModeEnableGuid
,
305 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
312 Generate the PK signature list from the X509 Certificate storing file (.cer)
314 @param[in] X509File FileHandle of X509 Certificate storing file.
315 @param[out] PkCert Point to the data buffer to store the signature list.
317 @return EFI_UNSUPPORTED Unsupported Key Length.
318 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
322 CreatePkX509SignatureList (
323 IN EFI_FILE_HANDLE X509File
,
324 OUT EFI_SIGNATURE_LIST
**PkCert
330 EFI_SIGNATURE_DATA
*PkCertData
;
336 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
337 if (EFI_ERROR (Status
)) {
340 ASSERT (X509Data
!= NULL
);
343 // Allocate space for PK certificate list and initialize it.
344 // Create PK database entry with SignatureHeaderSize equals 0.
346 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
347 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
350 if (*PkCert
== NULL
) {
351 Status
= EFI_OUT_OF_RESOURCES
;
355 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
356 + sizeof(EFI_SIGNATURE_DATA
) - 1
358 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
359 (*PkCert
)->SignatureHeaderSize
= 0;
360 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
361 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
362 + sizeof(EFI_SIGNATURE_LIST
)
363 + (*PkCert
)->SignatureHeaderSize
);
364 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
366 // Fill the PK database with PKpub data from X509 certificate file.
368 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
372 if (X509Data
!= NULL
) {
376 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
385 Enroll new PK into the System without original PK's authentication.
387 The SignatureOwner GUID will be the same with PK's vendorguid.
389 @param[in] PrivateData The module's private data.
391 @retval EFI_SUCCESS New PK enrolled successfully.
392 @retval EFI_INVALID_PARAMETER The parameter is invalid.
393 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
398 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
404 EFI_SIGNATURE_LIST
*PkCert
;
408 if (Private
->FileContext
->FileName
== NULL
) {
409 return EFI_INVALID_PARAMETER
;
414 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
415 if (EFI_ERROR (Status
)) {
420 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
422 NameLength
= StrLen (Private
->FileContext
->FileName
);
423 if (NameLength
<= 4) {
424 return EFI_INVALID_PARAMETER
;
426 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
427 if (!IsDerEncodeCertificate(FilePostFix
)) {
428 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
429 return EFI_INVALID_PARAMETER
;
431 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
432 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
435 // Prase the selected PK file and generature PK certificate list.
437 Status
= CreatePkX509SignatureList (
438 Private
->FileContext
->FHandle
,
441 if (EFI_ERROR (Status
)) {
444 ASSERT (PkCert
!= NULL
);
447 // Set Platform Key variable.
449 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
450 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
451 DataSize
= PkCert
->SignatureListSize
;
452 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
453 if (EFI_ERROR (Status
)) {
454 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
458 Status
= gRT
->SetVariable(
459 EFI_PLATFORM_KEY_NAME
,
460 &gEfiGlobalVariableGuid
,
465 if (EFI_ERROR (Status
)) {
466 if (Status
== EFI_OUT_OF_RESOURCES
) {
467 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
474 if (PkCert
!= NULL
) {
478 if (Private
->FileContext
->FHandle
!= NULL
) {
479 CloseFile (Private
->FileContext
->FHandle
);
480 Private
->FileContext
->FHandle
= NULL
;
487 Remove the PK variable.
489 @retval EFI_SUCCESS Delete PK successfully.
490 @retval Others Could not allow to delete PK.
500 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
501 if (EFI_ERROR (Status
)) {
505 Status
= DeleteVariable (
506 EFI_PLATFORM_KEY_NAME
,
507 &gEfiGlobalVariableGuid
513 Enroll a new KEK item from public key storing file (*.pbk).
515 @param[in] PrivateData The module's private data.
517 @retval EFI_SUCCESS New KEK enrolled successfully.
518 @retval EFI_INVALID_PARAMETER The parameter is invalid.
519 @retval EFI_UNSUPPORTED Unsupported command.
520 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
525 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
531 EFI_SIGNATURE_LIST
*KekSigList
;
534 CPL_KEY_INFO
*KeyInfo
;
535 EFI_SIGNATURE_DATA
*KEKSigData
;
536 UINTN KekSigListSize
;
551 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
552 // First, We have to parse out public key data from the pbk key file.
554 Status
= ReadFileContent (
555 Private
->FileContext
->FHandle
,
560 if (EFI_ERROR (Status
)) {
563 ASSERT (KeyBlob
!= NULL
);
564 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
565 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
566 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
567 Status
= EFI_UNSUPPORTED
;
572 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
574 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
575 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
576 if (KeyBuffer
== NULL
) {
577 Status
= EFI_OUT_OF_RESOURCES
;
581 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
582 KeyLenInBytes
/ sizeof (UINTN
),
586 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
589 // Form an new EFI_SIGNATURE_LIST.
591 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
592 + sizeof(EFI_SIGNATURE_DATA
) - 1
593 + WIN_CERT_UEFI_RSA2048_SIZE
;
595 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
596 if (KekSigList
== NULL
) {
597 Status
= EFI_OUT_OF_RESOURCES
;
601 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
602 + sizeof(EFI_SIGNATURE_DATA
) - 1
603 + WIN_CERT_UEFI_RSA2048_SIZE
;
604 KekSigList
->SignatureHeaderSize
= 0;
605 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
606 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
608 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
609 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
611 KEKSigData
->SignatureData
,
612 KeyBlob
+ sizeof(CPL_KEY_INFO
),
613 WIN_CERT_UEFI_RSA2048_SIZE
617 // Check if KEK entry has been already existed.
618 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
619 // new KEK to original variable.
621 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
622 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
623 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
624 if (EFI_ERROR (Status
)) {
625 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
629 Status
= gRT
->GetVariable(
630 EFI_KEY_EXCHANGE_KEY_NAME
,
631 &gEfiGlobalVariableGuid
,
636 if (Status
== EFI_BUFFER_TOO_SMALL
) {
637 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
638 } else if (Status
!= EFI_NOT_FOUND
) {
643 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
645 Status
= gRT
->SetVariable(
646 EFI_KEY_EXCHANGE_KEY_NAME
,
647 &gEfiGlobalVariableGuid
,
652 if (EFI_ERROR (Status
)) {
658 CloseFile (Private
->FileContext
->FHandle
);
659 Private
->FileContext
->FHandle
= NULL
;
661 if (Private
->FileContext
->FileName
!= NULL
){
662 FreePool(Private
->FileContext
->FileName
);
663 Private
->FileContext
->FileName
= NULL
;
666 if (Private
->SignatureGUID
!= NULL
) {
667 FreePool (Private
->SignatureGUID
);
668 Private
->SignatureGUID
= NULL
;
671 if (KeyBlob
!= NULL
) {
674 if (KeyBuffer
!= NULL
) {
675 FreePool (KeyBuffer
);
677 if (KekSigList
!= NULL
) {
678 FreePool (KekSigList
);
685 Enroll a new KEK item from X509 certificate file.
687 @param[in] PrivateData The module's private data.
689 @retval EFI_SUCCESS New X509 is enrolled successfully.
690 @retval EFI_INVALID_PARAMETER The parameter is invalid.
691 @retval EFI_UNSUPPORTED Unsupported command.
692 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
697 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
703 EFI_SIGNATURE_DATA
*KEKSigData
;
704 EFI_SIGNATURE_LIST
*KekSigList
;
706 UINTN KekSigListSize
;
716 Status
= ReadFileContent (
717 Private
->FileContext
->FHandle
,
722 if (EFI_ERROR (Status
)) {
725 ASSERT (X509Data
!= NULL
);
727 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
728 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
729 if (KekSigList
== NULL
) {
730 Status
= EFI_OUT_OF_RESOURCES
;
735 // Fill Certificate Database parameters.
737 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
738 KekSigList
->SignatureHeaderSize
= 0;
739 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
740 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
742 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
743 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
744 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
747 // Check if KEK been already existed.
748 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
749 // new kek to original variable
751 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
752 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
753 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
754 if (EFI_ERROR (Status
)) {
755 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
759 Status
= gRT
->GetVariable(
760 EFI_KEY_EXCHANGE_KEY_NAME
,
761 &gEfiGlobalVariableGuid
,
766 if (Status
== EFI_BUFFER_TOO_SMALL
) {
767 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
768 } else if (Status
!= EFI_NOT_FOUND
) {
772 Status
= gRT
->SetVariable(
773 EFI_KEY_EXCHANGE_KEY_NAME
,
774 &gEfiGlobalVariableGuid
,
779 if (EFI_ERROR (Status
)) {
785 CloseFile (Private
->FileContext
->FHandle
);
786 if (Private
->FileContext
->FileName
!= NULL
){
787 FreePool(Private
->FileContext
->FileName
);
788 Private
->FileContext
->FileName
= NULL
;
791 Private
->FileContext
->FHandle
= NULL
;
793 if (Private
->SignatureGUID
!= NULL
) {
794 FreePool (Private
->SignatureGUID
);
795 Private
->SignatureGUID
= NULL
;
798 if (KekSigList
!= NULL
) {
799 FreePool (KekSigList
);
806 Enroll new KEK into the System without PK's authentication.
807 The SignatureOwner GUID will be Private->SignatureGUID.
809 @param[in] PrivateData The module's private data.
811 @retval EFI_SUCCESS New KEK enrolled successful.
812 @retval EFI_INVALID_PARAMETER The parameter is invalid.
813 @retval others Fail to enroll KEK data.
817 EnrollKeyExchangeKey (
818 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
825 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
826 return EFI_INVALID_PARAMETER
;
829 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
830 if (EFI_ERROR (Status
)) {
835 // Parse the file's postfix. Supports DER-encoded X509 certificate,
836 // and .pbk as RSA public key file.
838 NameLength
= StrLen (Private
->FileContext
->FileName
);
839 if (NameLength
<= 4) {
840 return EFI_INVALID_PARAMETER
;
842 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
843 if (IsDerEncodeCertificate(FilePostFix
)) {
844 return EnrollX509ToKek (Private
);
845 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
846 return EnrollRsa2048ToKek (Private
);
848 return EFI_INVALID_PARAMETER
;
853 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
854 KEK's authentication.
856 @param[in] PrivateData The module's private data.
857 @param[in] VariableName Variable name of signature database, must be
858 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
860 @retval EFI_SUCCESS New X509 is enrolled successfully.
861 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
866 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
867 IN CHAR16
*VariableName
873 EFI_SIGNATURE_LIST
*SigDBCert
;
874 EFI_SIGNATURE_DATA
*SigDBCertData
;
885 SigDBCertData
= NULL
;
888 Status
= ReadFileContent (
889 Private
->FileContext
->FHandle
,
894 if (EFI_ERROR (Status
)) {
897 ASSERT (X509Data
!= NULL
);
899 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
901 Data
= AllocateZeroPool (SigDBSize
);
903 Status
= EFI_OUT_OF_RESOURCES
;
908 // Fill Certificate Database parameters.
910 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
911 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
912 SigDBCert
->SignatureHeaderSize
= 0;
913 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
914 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
916 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
917 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
918 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
921 // Check if signature database entry has been already existed.
922 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
923 // new signature data to original variable
925 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
926 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
927 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
928 if (EFI_ERROR (Status
)) {
929 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
933 Status
= gRT
->GetVariable(
935 &gEfiImageSecurityDatabaseGuid
,
940 if (Status
== EFI_BUFFER_TOO_SMALL
) {
941 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
942 } else if (Status
!= EFI_NOT_FOUND
) {
946 Status
= gRT
->SetVariable(
948 &gEfiImageSecurityDatabaseGuid
,
953 if (EFI_ERROR (Status
)) {
959 CloseFile (Private
->FileContext
->FHandle
);
960 if (Private
->FileContext
->FileName
!= NULL
){
961 FreePool(Private
->FileContext
->FileName
);
962 Private
->FileContext
->FileName
= NULL
;
965 Private
->FileContext
->FHandle
= NULL
;
967 if (Private
->SignatureGUID
!= NULL
) {
968 FreePool (Private
->SignatureGUID
);
969 Private
->SignatureGUID
= NULL
;
976 if (X509Data
!= NULL
) {
984 Check whether signature is in specified database.
986 @param[in] VariableName Name of database variable that is searched in.
987 @param[in] Signature Pointer to signature that is searched for.
988 @param[in] SignatureSize Size of Signature.
990 @return TRUE Found the signature in the variable database.
991 @return FALSE Not found the signature in the variable database.
995 IsSignatureFoundInDatabase (
996 IN CHAR16
*VariableName
,
998 IN UINTN SignatureSize
1002 EFI_SIGNATURE_LIST
*CertList
;
1003 EFI_SIGNATURE_DATA
*Cert
;
1011 // Read signature database variable.
1016 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1017 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1021 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1026 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1027 if (EFI_ERROR (Status
)) {
1032 // Enumerate all signature data in SigDB to check if executable's signature exists.
1034 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1035 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1036 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1037 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1038 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1039 for (Index
= 0; Index
< CertCount
; Index
++) {
1040 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1042 // Find the signature in database.
1047 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1055 DataSize
-= CertList
->SignatureListSize
;
1056 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1068 Calculate the hash of a certificate data with the specified hash algorithm.
1070 @param[in] CertData The certificate data to be hashed.
1071 @param[in] CertSize The certificate size in bytes.
1072 @param[in] HashAlg The specified hash algorithm.
1073 @param[out] CertHash The output digest of the certificate
1075 @retval TRUE Successfully got the hash of the CertData.
1076 @retval FALSE Failed to get the hash of CertData.
1096 if (HashAlg
>= HASHALG_MAX
) {
1101 // Retrieve the TBSCertificate for Hash Calculation.
1103 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1108 // 1. Initialize context of hash.
1110 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1111 HashCtx
= AllocatePool (CtxSize
);
1112 ASSERT (HashCtx
!= NULL
);
1115 // 2. Initialize a hash context.
1117 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1123 // 3. Calculate the hash.
1125 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1131 // 4. Get the hash result.
1133 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1134 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1137 if (HashCtx
!= NULL
) {
1145 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1147 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1148 @param[in] CertSize Size of X.509 Certificate.
1150 @return TRUE Found the certificate hash in the forbidden database.
1151 @return FALSE Certificate hash is Not found in the forbidden database.
1155 IsCertHashFoundInDbx (
1156 IN UINT8
*Certificate
,
1162 EFI_SIGNATURE_LIST
*DbxList
;
1163 EFI_SIGNATURE_DATA
*CertHash
;
1164 UINTN CertHashCount
;
1167 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1169 UINTN SiglistHeaderSize
;
1174 HashAlg
= HASHALG_MAX
;
1178 // Read signature database variable.
1181 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1182 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1186 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1191 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1192 if (EFI_ERROR (Status
)) {
1197 // Check whether the certificate hash exists in the forbidden database.
1199 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1200 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1202 // Determine Hash Algorithm of Certificate in the forbidden database.
1204 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1205 HashAlg
= HASHALG_SHA256
;
1206 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1207 HashAlg
= HASHALG_SHA384
;
1208 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1209 HashAlg
= HASHALG_SHA512
;
1211 DataSize
-= DbxList
->SignatureListSize
;
1212 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1217 // Calculate the hash value of current db certificate for comparision.
1219 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1223 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1224 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1225 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1226 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1228 // Iterate each Signature Data Node within this CertList for verify.
1230 DbxCertHash
= CertHash
->SignatureData
;
1231 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1233 // Hash of Certificate is found in forbidden database.
1238 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1241 DataSize
-= DbxList
->SignatureListSize
;
1242 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1254 Check whether the signature list exists in given variable data.
1256 It searches the signature list for the ceritificate hash by CertType.
1257 If the signature list is found, get the offset of Database for the
1258 next hash of a certificate.
1260 @param[in] Database Variable data to save signature list.
1261 @param[in] DatabaseSize Variable size.
1262 @param[in] SignatureType The type of the signature.
1263 @param[out] Offset The offset to save a new hash of certificate.
1265 @return TRUE The signature list is found in the forbidden database.
1266 @return FALSE The signature list is not found in the forbidden database.
1269 GetSignaturelistOffset (
1270 IN EFI_SIGNATURE_LIST
*Database
,
1271 IN UINTN DatabaseSize
,
1272 IN EFI_GUID
*SignatureType
,
1276 EFI_SIGNATURE_LIST
*SigList
;
1279 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1285 SiglistSize
= DatabaseSize
;
1286 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1287 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1288 *Offset
= DatabaseSize
- SiglistSize
;
1291 SiglistSize
-= SigList
->SignatureListSize
;
1292 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1299 Enroll a new X509 certificate hash into Signature Database (dbx) without
1300 KEK's authentication.
1302 @param[in] PrivateData The module's private data.
1303 @param[in] HashAlg The hash algorithm to enroll the certificate.
1304 @param[in] RevocationDate The revocation date of the certificate.
1305 @param[in] RevocationTime The revocation time of the certificate.
1306 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1308 @retval EFI_SUCCESS New X509 is enrolled successfully.
1309 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1310 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1314 EnrollX509HashtoSigDB (
1315 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1317 IN EFI_HII_DATE
*RevocationDate
,
1318 IN EFI_HII_TIME
*RevocationTime
,
1319 IN BOOLEAN AlwaysRevocation
1325 EFI_SIGNATURE_LIST
*SignatureList
;
1326 UINTN SignatureListSize
;
1332 EFI_SIGNATURE_DATA
*SignatureData
;
1333 UINTN SignatureSize
;
1334 EFI_GUID SignatureType
;
1336 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1337 UINT16
* FilePostFix
;
1344 SignatureData
= NULL
;
1345 SignatureList
= NULL
;
1349 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1350 return EFI_INVALID_PARAMETER
;
1353 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1354 if (EFI_ERROR (Status
)) {
1359 // Parse the file's postfix.
1361 NameLength
= StrLen (Private
->FileContext
->FileName
);
1362 if (NameLength
<= 4) {
1363 return EFI_INVALID_PARAMETER
;
1365 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1366 if (!IsDerEncodeCertificate(FilePostFix
)) {
1368 // Only supports DER-encoded X509 certificate.
1370 return EFI_INVALID_PARAMETER
;
1374 // Get the certificate from file and calculate its hash.
1376 Status
= ReadFileContent (
1377 Private
->FileContext
->FHandle
,
1382 if (EFI_ERROR (Status
)) {
1385 ASSERT (X509Data
!= NULL
);
1387 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1392 // Get the variable for enrollment.
1395 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1396 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1397 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1399 return EFI_OUT_OF_RESOURCES
;
1402 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1403 if (EFI_ERROR (Status
)) {
1409 // Allocate memory for Signature and fill the Signature
1411 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1412 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1413 if (SignatureData
== NULL
) {
1414 return EFI_OUT_OF_RESOURCES
;
1416 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1417 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1422 if (!AlwaysRevocation
) {
1423 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1424 Time
->Year
= RevocationDate
->Year
;
1425 Time
->Month
= RevocationDate
->Month
;
1426 Time
->Day
= RevocationDate
->Day
;
1427 Time
->Hour
= RevocationTime
->Hour
;
1428 Time
->Minute
= RevocationTime
->Minute
;
1429 Time
->Second
= RevocationTime
->Second
;
1433 // Determine the GUID for certificate hash.
1436 case HASHALG_SHA256
:
1437 SignatureType
= gEfiCertX509Sha256Guid
;
1439 case HASHALG_SHA384
:
1440 SignatureType
= gEfiCertX509Sha384Guid
;
1442 case HASHALG_SHA512
:
1443 SignatureType
= gEfiCertX509Sha512Guid
;
1450 // Add signature into the new variable data buffer
1452 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1454 // Add the signature to the found signaturelist.
1456 DbSize
= DataSize
+ SignatureSize
;
1457 NewData
= AllocateZeroPool (DbSize
);
1458 if (NewData
== NULL
) {
1459 Status
= EFI_OUT_OF_RESOURCES
;
1463 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1464 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1465 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1467 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1468 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1470 Offset
+= SignatureListSize
;
1471 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1472 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1479 // Create a new signaturelist, and add the signature into the signaturelist.
1481 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1482 NewData
= AllocateZeroPool (DbSize
);
1483 if (NewData
== NULL
) {
1484 Status
= EFI_OUT_OF_RESOURCES
;
1488 // Fill Certificate Database parameters.
1490 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1491 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1492 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1493 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1494 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1495 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1496 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1497 CopyMem (NewData
, Data
, DataSize
);
1504 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1505 if (EFI_ERROR (Status
)) {
1509 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1510 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1511 Status
= gRT
->SetVariable(
1512 EFI_IMAGE_SECURITY_DATABASE1
,
1513 &gEfiImageSecurityDatabaseGuid
,
1518 if (EFI_ERROR (Status
)) {
1523 CloseFile (Private
->FileContext
->FHandle
);
1524 if (Private
->FileContext
->FileName
!= NULL
){
1525 FreePool(Private
->FileContext
->FileName
);
1526 Private
->FileContext
->FileName
= NULL
;
1529 Private
->FileContext
->FHandle
= NULL
;
1531 if (Private
->SignatureGUID
!= NULL
) {
1532 FreePool (Private
->SignatureGUID
);
1533 Private
->SignatureGUID
= NULL
;
1540 if (SignatureData
!= NULL
) {
1541 FreePool (SignatureData
);
1544 if (X509Data
!= NULL
) {
1545 FreePool (X509Data
);
1552 Check whether a certificate from a file exists in dbx.
1554 @param[in] PrivateData The module's private data.
1555 @param[in] VariableName Variable name of signature database, must be
1556 EFI_IMAGE_SECURITY_DATABASE1.
1558 @retval TRUE The X509 certificate is found in dbx successfully.
1559 @retval FALSE The X509 certificate is not found in dbx.
1563 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1564 IN CHAR16
*VariableName
1573 // Read the certificate from file
1577 Status
= ReadFileContent (
1578 Private
->FileContext
->FHandle
,
1583 if (EFI_ERROR (Status
)) {
1588 // Check the raw certificate.
1591 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1597 // Check the hash of certificate.
1599 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1605 if (X509Data
!= NULL
) {
1606 FreePool (X509Data
);
1613 Reads contents of a PE/COFF image in memory buffer.
1615 Caution: This function may receive untrusted input.
1616 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1617 read is within the image buffer.
1619 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1620 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1621 @param ReadSize On input, the size in bytes of the requested read operation.
1622 On output, the number of bytes actually read.
1623 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1625 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1629 SecureBootConfigImageRead (
1630 IN VOID
*FileHandle
,
1631 IN UINTN FileOffset
,
1632 IN OUT UINTN
*ReadSize
,
1638 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1639 return EFI_INVALID_PARAMETER
;
1642 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1643 return EFI_INVALID_PARAMETER
;
1646 EndPosition
= FileOffset
+ *ReadSize
;
1647 if (EndPosition
> mImageSize
) {
1648 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1651 if (FileOffset
>= mImageSize
) {
1655 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1661 Load PE/COFF image information into internal buffer and check its validity.
1663 @retval EFI_SUCCESS Successful
1664 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1665 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1673 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1674 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1675 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1676 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1682 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1683 ImageContext
.Handle
= (VOID
*) mImageBase
;
1684 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1687 // Get information about the image being loaded
1689 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1690 if (EFI_ERROR (Status
)) {
1692 // The information can't be got from the invalid PeImage
1694 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1699 // Read the Dos header
1701 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1702 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1705 // DOS image header is present,
1706 // So read the PE header after the DOS image header
1708 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1712 mPeCoffHeaderOffset
= 0;
1716 // Read PE header and check the signature validity and machine compatibility
1718 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1719 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1721 return EFI_UNSUPPORTED
;
1724 mNtHeader
.Pe32
= NtHeader32
;
1727 // Check the architecture field of PE header and get the Certificate Data Directory data
1728 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1730 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1731 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1732 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1734 // 32-bits Architecture
1736 mImageType
= ImageType_IA32
;
1737 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1739 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1740 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1741 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1743 // 64-bits Architecture
1745 mImageType
= ImageType_X64
;
1746 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1747 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1749 return EFI_UNSUPPORTED
;
1756 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1757 PE/COFF Specification 8.0 Appendix A
1759 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1760 the function LoadPeImage ().
1762 @param[in] HashAlg Hash algorithm type.
1764 @retval TRUE Successfully hash image.
1765 @retval FALSE Fail in hash image.
1775 EFI_IMAGE_SECTION_HEADER
*Section
;
1780 UINTN SumOfBytesHashed
;
1781 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1786 SectionHeader
= NULL
;
1789 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1794 // Initialize context of hash.
1796 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1798 if (HashAlg
== HASHALG_SHA1
) {
1799 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1800 mCertType
= gEfiCertSha1Guid
;
1801 } else if (HashAlg
== HASHALG_SHA256
) {
1802 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1803 mCertType
= gEfiCertSha256Guid
;
1806 CtxSize
= mHash
[HashAlg
].GetContextSize();
1808 HashCtx
= AllocatePool (CtxSize
);
1809 ASSERT (HashCtx
!= NULL
);
1811 // 1. Load the image header into memory.
1813 // 2. Initialize a SHA hash context.
1814 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1819 // Measuring PE/COFF Image Header;
1820 // But CheckSum field and SECURITY data directory (certificate) are excluded
1822 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1824 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1825 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1826 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1827 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1829 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1832 // Get the magic value from the PE/COFF Optional Header
1834 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1838 // 3. Calculate the distance from the base of the image header to the image checksum address.
1839 // 4. Hash the image header from its base to beginning of the image checksum.
1841 HashBase
= mImageBase
;
1842 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1846 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1849 // Use PE32+ offset.
1851 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1854 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1859 // 5. Skip over the image checksum (it occupies a single ULONG).
1860 // 6. Get the address of the beginning of the Cert Directory.
1861 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1863 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1867 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1868 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1871 // Use PE32+ offset.
1873 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1874 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1877 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1882 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1883 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1885 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1889 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1890 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1893 // Use PE32+ offset.
1895 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1896 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1899 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1904 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1906 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1910 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1915 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1919 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1920 // structures in the image. The 'NumberOfSections' field of the image
1921 // header indicates how big the table should be. Do not include any
1922 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1924 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1925 ASSERT (SectionHeader
!= NULL
);
1927 // 12. Using the 'PointerToRawData' in the referenced section headers as
1928 // a key, arrange the elements in the table in ascending order. In other
1929 // words, sort the section headers according to the disk-file offset of
1932 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1934 mPeCoffHeaderOffset
+
1936 sizeof (EFI_IMAGE_FILE_HEADER
) +
1937 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1939 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1941 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1942 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1945 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1950 // 13. Walk through the sorted table, bring the corresponding section
1951 // into memory, and hash the entire section (using the 'SizeOfRawData'
1952 // field in the section header to determine the amount of data to hash).
1953 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1954 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1956 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1957 Section
= &SectionHeader
[Index
];
1958 if (Section
->SizeOfRawData
== 0) {
1961 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1962 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1964 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1969 SumOfBytesHashed
+= HashSize
;
1973 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1974 // data in the file that needs to be added to the hash. This data begins
1975 // at file offset SUM_OF_BYTES_HASHED and its length is:
1976 // FileSize - (CertDirectory->Size)
1978 if (mImageSize
> SumOfBytesHashed
) {
1979 HashBase
= mImageBase
+ SumOfBytesHashed
;
1980 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1986 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1990 // Use PE32+ offset.
1994 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1998 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2004 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2007 if (HashCtx
!= NULL
) {
2010 if (SectionHeader
!= NULL
) {
2011 FreePool (SectionHeader
);
2017 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2018 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2021 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2022 @retval EFI_SUCCESS Hash successfully.
2031 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2033 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2035 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2037 // Check the Hash algorithm in PE/COFF Authenticode.
2038 // According to PKCS#7 Definition:
2039 // SignedData ::= SEQUENCE {
2041 // digestAlgorithms DigestAlgorithmIdentifiers,
2042 // contentInfo ContentInfo,
2044 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2045 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2046 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2048 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2050 // Only support two bytes of Long Form of Length Encoding.
2056 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2061 if (Index
== HASHALG_MAX
) {
2062 return EFI_UNSUPPORTED
;
2066 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2068 if (!HashPeImage(Index
)) {
2069 return EFI_UNSUPPORTED
;
2076 Enroll a new executable's signature into Signature Database.
2078 @param[in] PrivateData The module's private data.
2079 @param[in] VariableName Variable name of signature database, must be
2080 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2081 or EFI_IMAGE_SECURITY_DATABASE2.
2083 @retval EFI_SUCCESS New signature is enrolled successfully.
2084 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2085 @retval EFI_UNSUPPORTED Unsupported command.
2086 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2090 EnrollImageSignatureToSigDB (
2091 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2092 IN CHAR16
*VariableName
2096 EFI_SIGNATURE_LIST
*SigDBCert
;
2097 EFI_SIGNATURE_DATA
*SigDBCertData
;
2102 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2105 GuidCertData
= NULL
;
2107 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2108 return EFI_UNSUPPORTED
;
2112 // Form the SigDB certificate list.
2113 // Format the data item into EFI_SIGNATURE_LIST type.
2115 // We need to parse executable's signature data from specified signed executable file.
2116 // In current implementation, we simply trust the pass-in signed executable file.
2117 // In reality, it's OS's responsibility to verify the signed executable file.
2121 // Read the whole file content
2123 Status
= ReadFileContent(
2124 Private
->FileContext
->FHandle
,
2125 (VOID
**) &mImageBase
,
2129 if (EFI_ERROR (Status
)) {
2132 ASSERT (mImageBase
!= NULL
);
2134 Status
= LoadPeImage ();
2135 if (EFI_ERROR (Status
)) {
2139 if (mSecDataDir
->SizeOfCert
== 0) {
2140 if (!HashPeImage (HASHALG_SHA256
)) {
2141 Status
= EFI_SECURITY_VIOLATION
;
2147 // Read the certificate data
2149 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2151 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2152 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2153 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2154 Status
= EFI_ABORTED
;
2158 if (!HashPeImage (HASHALG_SHA256
)) {
2159 Status
= EFI_ABORTED
;
2163 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2165 Status
= HashPeImageByType ();
2166 if (EFI_ERROR (Status
)) {
2170 Status
= EFI_ABORTED
;
2176 // Create a new SigDB entry.
2178 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2179 + sizeof(EFI_SIGNATURE_DATA
) - 1
2180 + (UINT32
) mImageDigestSize
;
2182 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2184 Status
= EFI_OUT_OF_RESOURCES
;
2189 // Adjust the Certificate Database parameters.
2191 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2192 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2193 SigDBCert
->SignatureHeaderSize
= 0;
2194 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2195 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2197 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2198 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2199 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2201 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2202 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2203 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2204 if (EFI_ERROR (Status
)) {
2205 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2210 // Check if SigDB variable has been already existed.
2211 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2212 // new signature data to original variable
2215 Status
= gRT
->GetVariable(
2217 &gEfiImageSecurityDatabaseGuid
,
2222 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2223 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2224 } else if (Status
!= EFI_NOT_FOUND
) {
2229 // Enroll the variable.
2231 Status
= gRT
->SetVariable(
2233 &gEfiImageSecurityDatabaseGuid
,
2238 if (EFI_ERROR (Status
)) {
2244 CloseFile (Private
->FileContext
->FHandle
);
2245 Private
->FileContext
->FHandle
= NULL
;
2247 if (Private
->FileContext
->FileName
!= NULL
){
2248 FreePool(Private
->FileContext
->FileName
);
2249 Private
->FileContext
->FileName
= NULL
;
2252 if (Private
->SignatureGUID
!= NULL
) {
2253 FreePool (Private
->SignatureGUID
);
2254 Private
->SignatureGUID
= NULL
;
2261 if (mImageBase
!= NULL
) {
2262 FreePool (mImageBase
);
2270 Enroll signature into DB/DBX/DBT without KEK's authentication.
2271 The SignatureOwner GUID will be Private->SignatureGUID.
2273 @param[in] PrivateData The module's private data.
2274 @param[in] VariableName Variable name of signature database, must be
2275 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2277 @retval EFI_SUCCESS New signature enrolled successfully.
2278 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2279 @retval others Fail to enroll signature data.
2283 EnrollSignatureDatabase (
2284 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2285 IN CHAR16
*VariableName
2288 UINT16
* FilePostFix
;
2292 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2293 return EFI_INVALID_PARAMETER
;
2296 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2297 if (EFI_ERROR (Status
)) {
2302 // Parse the file's postfix.
2304 NameLength
= StrLen (Private
->FileContext
->FileName
);
2305 if (NameLength
<= 4) {
2306 return EFI_INVALID_PARAMETER
;
2308 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2309 if (IsDerEncodeCertificate (FilePostFix
)) {
2311 // Supports DER-encoded X509 certificate.
2313 return EnrollX509toSigDB (Private
, VariableName
);
2316 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2320 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2321 by GUID in the page for user to select and delete as needed.
2323 @param[in] PrivateData Module's private data.
2324 @param[in] VariableName The variable name of the vendor's signature database.
2325 @param[in] VendorGuid A unique identifier for the vendor.
2326 @param[in] LabelNumber Label number to insert opcodes.
2327 @param[in] FormId Form ID of current page.
2328 @param[in] QuestionIdBase Base question id of the signature list.
2330 @retval EFI_SUCCESS Success to update the signature list page
2331 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2336 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2337 IN CHAR16
*VariableName
,
2338 IN EFI_GUID
*VendorGuid
,
2339 IN UINT16 LabelNumber
,
2340 IN EFI_FORM_ID FormId
,
2341 IN EFI_QUESTION_ID QuestionIdBase
2348 VOID
*StartOpCodeHandle
;
2349 VOID
*EndOpCodeHandle
;
2350 EFI_IFR_GUID_LABEL
*StartLabel
;
2351 EFI_IFR_GUID_LABEL
*EndLabel
;
2354 EFI_SIGNATURE_LIST
*CertList
;
2355 EFI_SIGNATURE_DATA
*Cert
;
2356 UINT32 ItemDataSize
;
2358 EFI_STRING_ID GuidID
;
2365 StartOpCodeHandle
= NULL
;
2366 EndOpCodeHandle
= NULL
;
2369 // Initialize the container for dynamic opcodes.
2371 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2372 if (StartOpCodeHandle
== NULL
) {
2373 Status
= EFI_OUT_OF_RESOURCES
;
2377 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2378 if (EndOpCodeHandle
== NULL
) {
2379 Status
= EFI_OUT_OF_RESOURCES
;
2384 // Create Hii Extend Label OpCode.
2386 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2390 sizeof (EFI_IFR_GUID_LABEL
)
2392 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2393 StartLabel
->Number
= LabelNumber
;
2395 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2399 sizeof (EFI_IFR_GUID_LABEL
)
2401 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2402 EndLabel
->Number
= LABEL_END
;
2408 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2409 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2413 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2415 Status
= EFI_OUT_OF_RESOURCES
;
2419 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2420 if (EFI_ERROR (Status
)) {
2424 GuidStr
= AllocateZeroPool (100);
2425 if (GuidStr
== NULL
) {
2426 Status
= EFI_OUT_OF_RESOURCES
;
2431 // Enumerate all KEK pub data.
2433 ItemDataSize
= (UINT32
) DataSize
;
2434 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2437 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2439 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2440 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2441 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2442 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2443 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2444 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2445 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2446 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2447 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2448 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2449 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2450 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2451 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2452 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2455 // The signature type is not supported in current implementation.
2457 ItemDataSize
-= CertList
->SignatureListSize
;
2458 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2462 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2463 for (Index
= 0; Index
< CertCount
; Index
++) {
2464 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2465 + sizeof (EFI_SIGNATURE_LIST
)
2466 + CertList
->SignatureHeaderSize
2467 + Index
* CertList
->SignatureSize
);
2469 // Display GUID and help
2471 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2472 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2473 HiiCreateCheckBoxOpCode (
2475 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2480 EFI_IFR_FLAG_CALLBACK
,
2486 ItemDataSize
-= CertList
->SignatureListSize
;
2487 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2492 PrivateData
->HiiHandle
,
2493 &gSecureBootConfigFormSetGuid
,
2499 if (StartOpCodeHandle
!= NULL
) {
2500 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2503 if (EndOpCodeHandle
!= NULL
) {
2504 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2511 if (GuidStr
!= NULL
) {
2519 Delete a KEK entry from KEK database.
2521 @param[in] PrivateData Module's private data.
2522 @param[in] QuestionId Question id of the KEK item to delete.
2524 @retval EFI_SUCCESS Delete kek item successfully.
2525 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2529 DeleteKeyExchangeKey (
2530 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2531 IN EFI_QUESTION_ID QuestionId
2540 EFI_SIGNATURE_LIST
*CertList
;
2541 EFI_SIGNATURE_LIST
*NewCertList
;
2542 EFI_SIGNATURE_DATA
*Cert
;
2545 BOOLEAN IsKEKItemFound
;
2547 UINTN DeleteKekIndex
;
2555 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2557 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2558 if (EFI_ERROR (Status
)) {
2563 // Get original KEK variable.
2566 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2567 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2571 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2572 if (OldData
== NULL
) {
2573 Status
= EFI_OUT_OF_RESOURCES
;
2577 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2578 if (EFI_ERROR(Status
)) {
2583 // Allocate space for new variable.
2585 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2587 Status
= EFI_OUT_OF_RESOURCES
;
2592 // Enumerate all KEK pub data and erasing the target item.
2594 IsKEKItemFound
= FALSE
;
2595 KekDataSize
= (UINT32
) DataSize
;
2596 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2599 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2600 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2601 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2602 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2603 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2604 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2605 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2606 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2607 for (Index
= 0; Index
< CertCount
; Index
++) {
2608 if (GuidIndex
== DeleteKekIndex
) {
2610 // Find it! Skip it!
2612 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2613 IsKEKItemFound
= TRUE
;
2616 // This item doesn't match. Copy it to the Data buffer.
2618 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2619 Offset
+= CertList
->SignatureSize
;
2622 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2626 // This List doesn't match. Copy it to the Data buffer.
2628 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2629 Offset
+= CertList
->SignatureListSize
;
2632 KekDataSize
-= CertList
->SignatureListSize
;
2633 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2636 if (!IsKEKItemFound
) {
2638 // Doesn't find the Kek Item!
2640 Status
= EFI_NOT_FOUND
;
2645 // Delete the Signature header if there is no signature in the list.
2647 KekDataSize
= Offset
;
2648 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2650 ZeroMem (OldData
, KekDataSize
);
2651 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2652 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2653 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2654 if (CertCount
!= 0) {
2655 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2656 Offset
+= CertList
->SignatureListSize
;
2658 KekDataSize
-= CertList
->SignatureListSize
;
2659 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2663 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2664 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2665 if (EFI_ERROR (Status
)) {
2666 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2671 Status
= gRT
->SetVariable(
2672 EFI_KEY_EXCHANGE_KEY_NAME
,
2673 &gEfiGlobalVariableGuid
,
2678 if (EFI_ERROR (Status
)) {
2679 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2688 if (OldData
!= NULL
) {
2692 return UpdateDeletePage (
2694 EFI_KEY_EXCHANGE_KEY_NAME
,
2695 &gEfiGlobalVariableGuid
,
2697 FORMID_DELETE_KEK_FORM
,
2698 OPTION_DEL_KEK_QUESTION_ID
2703 Delete a signature entry from siganture database.
2705 @param[in] PrivateData Module's private data.
2706 @param[in] VariableName The variable name of the vendor's signature database.
2707 @param[in] VendorGuid A unique identifier for the vendor.
2708 @param[in] LabelNumber Label number to insert opcodes.
2709 @param[in] FormId Form ID of current page.
2710 @param[in] QuestionIdBase Base question id of the signature list.
2711 @param[in] DeleteIndex Signature index to delete.
2713 @retval EFI_SUCCESS Delete siganture successfully.
2714 @retval EFI_NOT_FOUND Can't find the signature item,
2715 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2719 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2720 IN CHAR16
*VariableName
,
2721 IN EFI_GUID
*VendorGuid
,
2722 IN UINT16 LabelNumber
,
2723 IN EFI_FORM_ID FormId
,
2724 IN EFI_QUESTION_ID QuestionIdBase
,
2725 IN UINTN DeleteIndex
2734 EFI_SIGNATURE_LIST
*CertList
;
2735 EFI_SIGNATURE_LIST
*NewCertList
;
2736 EFI_SIGNATURE_DATA
*Cert
;
2739 BOOLEAN IsItemFound
;
2740 UINT32 ItemDataSize
;
2749 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2750 if (EFI_ERROR (Status
)) {
2755 // Get original signature list data.
2758 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2759 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2763 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2764 if (OldData
== NULL
) {
2765 Status
= EFI_OUT_OF_RESOURCES
;
2769 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2770 if (EFI_ERROR(Status
)) {
2775 // Allocate space for new variable.
2777 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2779 Status
= EFI_OUT_OF_RESOURCES
;
2784 // Enumerate all signature data and erasing the target item.
2786 IsItemFound
= FALSE
;
2787 ItemDataSize
= (UINT32
) DataSize
;
2788 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2791 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2792 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2793 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2794 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2795 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2796 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2797 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2798 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2801 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2803 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2804 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2805 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2806 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2807 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2808 for (Index
= 0; Index
< CertCount
; Index
++) {
2809 if (GuidIndex
== DeleteIndex
) {
2811 // Find it! Skip it!
2813 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2817 // This item doesn't match. Copy it to the Data buffer.
2819 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2820 Offset
+= CertList
->SignatureSize
;
2823 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2827 // This List doesn't match. Just copy it to the Data buffer.
2829 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2830 Offset
+= CertList
->SignatureListSize
;
2833 ItemDataSize
-= CertList
->SignatureListSize
;
2834 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2839 // Doesn't find the signature Item!
2841 Status
= EFI_NOT_FOUND
;
2846 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2848 ItemDataSize
= Offset
;
2849 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2851 ZeroMem (OldData
, ItemDataSize
);
2852 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2853 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2854 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2855 if (CertCount
!= 0) {
2856 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2857 Offset
+= CertList
->SignatureListSize
;
2859 ItemDataSize
-= CertList
->SignatureListSize
;
2860 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2864 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2865 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2866 if (EFI_ERROR (Status
)) {
2867 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2872 Status
= gRT
->SetVariable(
2879 if (EFI_ERROR (Status
)) {
2880 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2889 if (OldData
!= NULL
) {
2893 return UpdateDeletePage (
2905 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
2906 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
2908 @param[in] PrivateData Module's private data.
2910 @return EFI_SUCCESS Update secure boot strings successfully.
2911 @return other Fail to update secure boot strings.
2915 UpdateSecureBootString(
2916 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
2924 // Get current secure boot state.
2926 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2927 if (SecureBoot
== NULL
) {
2928 return EFI_NOT_FOUND
;
2931 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2932 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
2934 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
2937 FreePool(SecureBoot
);
2943 This function extracts configuration from variable.
2945 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2949 SecureBootExtractConfigFromVariable (
2950 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2953 UINT8
*SecureBootEnable
;
2955 UINT8
*SecureBootMode
;
2958 SecureBootEnable
= NULL
;
2960 SecureBootMode
= NULL
;
2963 // Initilize the Date and Time using system time.
2965 ConfigData
->CertificateFormat
= HASHALG_RAW
;
2966 ConfigData
->AlwaysRevocation
= TRUE
;
2967 gRT
->GetTime (&CurrTime
, NULL
);
2968 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
2969 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
2970 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
2971 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
2972 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
2973 ConfigData
->RevocationTime
.Second
= 0;
2977 // If it is Physical Presence User, set the PhysicalPresent to true.
2979 if (UserPhysicalPresent()) {
2980 ConfigData
->PhysicalPresent
= TRUE
;
2982 ConfigData
->PhysicalPresent
= FALSE
;
2986 // If there is no PK then the Delete Pk button will be gray.
2988 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2989 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2990 ConfigData
->HasPk
= FALSE
;
2992 ConfigData
->HasPk
= TRUE
;
2996 // Check SecureBootEnable & Pk status, fix the inconsistence.
2997 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3000 ConfigData
->AttemptSecureBoot
= FALSE
;
3001 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3004 // Fix Pk, SecureBootEnable inconsistence
3006 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3007 ConfigData
->HideSecureBoot
= FALSE
;
3008 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3009 ConfigData
->AttemptSecureBoot
= TRUE
;
3012 ConfigData
->HideSecureBoot
= TRUE
;
3016 // Get the SecureBootMode from CustomMode variable.
3018 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3019 if (SecureBootMode
== NULL
) {
3020 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3022 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3025 if (SecureBootEnable
!= NULL
) {
3026 FreePool (SecureBootEnable
);
3028 if (SetupMode
!= NULL
) {
3029 FreePool (SetupMode
);
3031 if (SecureBootMode
!= NULL
) {
3032 FreePool (SecureBootMode
);
3037 This function allows a caller to extract the current configuration for one
3038 or more named elements from the target driver.
3040 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3041 @param[in] Request A null-terminated Unicode string in
3042 <ConfigRequest> format.
3043 @param[out] Progress On return, points to a character in the Request
3044 string. Points to the string's null terminator if
3045 request was successful. Points to the most recent
3046 '&' before the first failing name/value pair (or
3047 the beginning of the string if the failure is in
3048 the first name/value pair) if the request was not
3050 @param[out] Results A null-terminated Unicode string in
3051 <ConfigAltResp> format which has all values filled
3052 in for the names in the Request string. String to
3053 be allocated by the called function.
3055 @retval EFI_SUCCESS The Results is filled with the requested values.
3056 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3057 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3058 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3064 SecureBootExtractConfig (
3065 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3066 IN CONST EFI_STRING Request
,
3067 OUT EFI_STRING
*Progress
,
3068 OUT EFI_STRING
*Results
3074 SECUREBOOT_CONFIGURATION Configuration
;
3075 EFI_STRING ConfigRequest
;
3076 EFI_STRING ConfigRequestHdr
;
3077 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3078 BOOLEAN AllocatedRequest
;
3080 if (Progress
== NULL
|| Results
== NULL
) {
3081 return EFI_INVALID_PARAMETER
;
3084 AllocatedRequest
= FALSE
;
3085 ConfigRequestHdr
= NULL
;
3086 ConfigRequest
= NULL
;
3089 ZeroMem (&Configuration
, sizeof (Configuration
));
3090 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3091 *Progress
= Request
;
3093 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3094 return EFI_NOT_FOUND
;
3098 // Get Configuration from Variable.
3100 SecureBootExtractConfigFromVariable (&Configuration
);
3102 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3103 ConfigRequest
= Request
;
3104 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3106 // Request is set to NULL or OFFSET is NULL, construct full request string.
3108 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3109 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3111 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3112 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3113 ConfigRequest
= AllocateZeroPool (Size
);
3114 ASSERT (ConfigRequest
!= NULL
);
3115 AllocatedRequest
= TRUE
;
3116 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3117 FreePool (ConfigRequestHdr
);
3118 ConfigRequestHdr
= NULL
;
3121 Status
= gHiiConfigRouting
->BlockToConfig (
3124 (UINT8
*) &Configuration
,
3131 // Free the allocated config request string.
3133 if (AllocatedRequest
) {
3134 FreePool (ConfigRequest
);
3138 // Set Progress string to the original request string.
3140 if (Request
== NULL
) {
3142 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3143 *Progress
= Request
+ StrLen (Request
);
3150 This function processes the results of changes in configuration.
3152 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3153 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3155 @param[out] Progress A pointer to a string filled in with the offset of
3156 the most recent '&' before the first failing
3157 name/value pair (or the beginning of the string if
3158 the failure is in the first name/value pair) or
3159 the terminating NULL if all was successful.
3161 @retval EFI_SUCCESS The Results is processed successfully.
3162 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3163 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3169 SecureBootRouteConfig (
3170 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3171 IN CONST EFI_STRING Configuration
,
3172 OUT EFI_STRING
*Progress
3175 SECUREBOOT_CONFIGURATION IfrNvData
;
3179 if (Configuration
== NULL
|| Progress
== NULL
) {
3180 return EFI_INVALID_PARAMETER
;
3183 *Progress
= Configuration
;
3184 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3185 return EFI_NOT_FOUND
;
3189 // Get Configuration from Variable.
3191 SecureBootExtractConfigFromVariable (&IfrNvData
);
3194 // Map the Configuration to the configuration block.
3196 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3197 Status
= gHiiConfigRouting
->ConfigToBlock (
3200 (UINT8
*)&IfrNvData
,
3204 if (EFI_ERROR (Status
)) {
3209 // Store Buffer Storage back to EFI variable if needed
3211 if (!IfrNvData
.HideSecureBoot
) {
3212 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3213 if (EFI_ERROR (Status
)) {
3218 *Progress
= Configuration
+ StrLen (Configuration
);
3223 This function is called to provide results data to the driver.
3225 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3226 @param[in] Action Specifies the type of action taken by the browser.
3227 @param[in] QuestionId A unique value which is sent to the original
3228 exporting driver so that it can identify the type
3230 @param[in] Type The type of value for the question.
3231 @param[in] Value A pointer to the data being sent to the original
3233 @param[out] ActionRequest On return, points to the action requested by the
3236 @retval EFI_SUCCESS The callback successfully handled the action.
3237 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3238 variable and its data.
3239 @retval EFI_DEVICE_ERROR The variable could not be saved.
3240 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3246 SecureBootCallback (
3247 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3248 IN EFI_BROWSER_ACTION Action
,
3249 IN EFI_QUESTION_ID QuestionId
,
3251 IN EFI_IFR_TYPE_VALUE
*Value
,
3252 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3257 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3259 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3261 UINT8
*SecureBootEnable
;
3263 UINT8
*SecureBootMode
;
3265 CHAR16 PromptString
[100];
3266 EFI_DEVICE_PATH_PROTOCOL
*File
;
3268 Status
= EFI_SUCCESS
;
3269 SecureBootEnable
= NULL
;
3270 SecureBootMode
= NULL
;
3274 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3275 return EFI_INVALID_PARAMETER
;
3278 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3280 gSecureBootPrivateData
= Private
;
3283 // Retrieve uncommitted data from Browser
3285 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3286 IfrNvData
= AllocateZeroPool (BufferSize
);
3287 if (IfrNvData
== NULL
) {
3288 return EFI_OUT_OF_RESOURCES
;
3291 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3293 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3294 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3296 // Update secure boot strings when opening this form
3298 Status
= UpdateSecureBootString(Private
);
3299 SecureBootExtractConfigFromVariable (IfrNvData
);
3300 mIsEnterSecureBootForm
= TRUE
;
3305 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3306 Status
= EFI_UNSUPPORTED
;
3307 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3308 if (mIsEnterSecureBootForm
) {
3309 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3310 Status
= EFI_SUCCESS
;
3316 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3317 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3318 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3319 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3320 Status
= EFI_UNSUPPORTED
;
3324 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3326 switch (QuestionId
) {
3327 case KEY_SECURE_BOOT_ENABLE
:
3328 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3329 if (NULL
!= SecureBootEnable
) {
3330 FreePool (SecureBootEnable
);
3331 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3333 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3335 L
"Only Physical Presence User could disable secure boot!",
3338 Status
= EFI_UNSUPPORTED
;
3341 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3343 L
"Configuration changed, please reset the platform to take effect!",
3350 case KEY_SECURE_BOOT_KEK_OPTION
:
3351 case KEY_SECURE_BOOT_DB_OPTION
:
3352 case KEY_SECURE_BOOT_DBX_OPTION
:
3353 case KEY_SECURE_BOOT_DBT_OPTION
:
3355 // Clear Signature GUID.
3357 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3358 if (Private
->SignatureGUID
== NULL
) {
3359 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3360 if (Private
->SignatureGUID
== NULL
) {
3361 return EFI_OUT_OF_RESOURCES
;
3365 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3366 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3367 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3368 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3369 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3370 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3372 LabelId
= FORMID_ENROLL_KEK_FORM
;
3376 // Refresh selected file.
3378 CleanUpPage (LabelId
, Private
);
3380 case KEY_SECURE_BOOT_PK_OPTION
:
3381 LabelId
= FORMID_ENROLL_PK_FORM
;
3383 // Refresh selected file.
3385 CleanUpPage (LabelId
, Private
);
3388 case FORMID_ENROLL_PK_FORM
:
3389 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
3392 case FORMID_ENROLL_KEK_FORM
:
3393 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
3396 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3397 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
3400 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3401 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
3404 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3405 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
3408 case KEY_SECURE_BOOT_DELETE_PK
:
3411 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3413 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3414 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3417 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3418 Status
= DeletePlatformKey ();
3419 if (EFI_ERROR (Status
)) {
3421 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3423 L
"Only Physical Presence User could delete PK in custom mode!",
3431 case KEY_DELETE_KEK
:
3434 EFI_KEY_EXCHANGE_KEY_NAME
,
3435 &gEfiGlobalVariableGuid
,
3437 FORMID_DELETE_KEK_FORM
,
3438 OPTION_DEL_KEK_QUESTION_ID
3442 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3445 EFI_IMAGE_SECURITY_DATABASE
,
3446 &gEfiImageSecurityDatabaseGuid
,
3448 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3449 OPTION_DEL_DB_QUESTION_ID
3453 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3456 EFI_IMAGE_SECURITY_DATABASE1
,
3457 &gEfiImageSecurityDatabaseGuid
,
3459 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3460 OPTION_DEL_DBX_QUESTION_ID
3465 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3468 EFI_IMAGE_SECURITY_DATABASE2
,
3469 &gEfiImageSecurityDatabaseGuid
,
3471 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3472 OPTION_DEL_DBT_QUESTION_ID
3477 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3478 Status
= EnrollKeyExchangeKey (Private
);
3479 if (EFI_ERROR (Status
)) {
3481 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3483 L
"ERROR: Unsupported file type!",
3484 L
"Only supports DER-encoded X509 certificate",
3490 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3491 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3492 if (EFI_ERROR (Status
)) {
3494 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3496 L
"ERROR: Unsupported file type!",
3497 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3503 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3504 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3506 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3508 L
"Enrollment failed! Same certificate had already been in the dbx!",
3514 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3515 Status
= EnrollX509HashtoSigDB (
3517 IfrNvData
->CertificateFormat
,
3518 &IfrNvData
->RevocationDate
,
3519 &IfrNvData
->RevocationTime
,
3520 IfrNvData
->AlwaysRevocation
3523 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3525 if (EFI_ERROR (Status
)) {
3527 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3529 L
"ERROR: Unsupported file type!",
3530 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3536 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3537 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3538 if (EFI_ERROR (Status
)) {
3540 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3542 L
"ERROR: Unsupported file type!",
3543 L
"Only supports DER-encoded X509 certificate.",
3548 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3549 Status
= EnrollPlatformKey (Private
);
3550 if (EFI_ERROR (Status
)) {
3553 sizeof (PromptString
),
3554 L
"Only DER encoded certificate file (%s) is supported.",
3558 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3560 L
"ERROR: Unsupported file type!",
3567 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3568 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3569 DeleteKeyExchangeKey (Private
, QuestionId
);
3570 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3571 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3574 EFI_IMAGE_SECURITY_DATABASE
,
3575 &gEfiImageSecurityDatabaseGuid
,
3577 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3578 OPTION_DEL_DB_QUESTION_ID
,
3579 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3581 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3582 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3585 EFI_IMAGE_SECURITY_DATABASE1
,
3586 &gEfiImageSecurityDatabaseGuid
,
3588 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3589 OPTION_DEL_DBX_QUESTION_ID
,
3590 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3592 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3593 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3596 EFI_IMAGE_SECURITY_DATABASE2
,
3597 &gEfiImageSecurityDatabaseGuid
,
3599 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3600 OPTION_DEL_DBT_QUESTION_ID
,
3601 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3606 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3607 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3608 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3609 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3610 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3611 if (Private
->FileContext
->FHandle
!= NULL
) {
3612 CloseFile (Private
->FileContext
->FHandle
);
3613 Private
->FileContext
->FHandle
= NULL
;
3614 if (Private
->FileContext
->FileName
!= NULL
){
3615 FreePool(Private
->FileContext
->FileName
);
3616 Private
->FileContext
->FileName
= NULL
;
3620 if (Private
->SignatureGUID
!= NULL
) {
3621 FreePool (Private
->SignatureGUID
);
3622 Private
->SignatureGUID
= NULL
;
3626 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3627 switch (QuestionId
) {
3628 case KEY_SECURE_BOOT_ENABLE
:
3629 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3631 case KEY_SECURE_BOOT_MODE
:
3632 mIsEnterSecureBootForm
= FALSE
;
3634 case KEY_SECURE_BOOT_KEK_GUID
:
3635 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3636 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3637 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3638 ASSERT (Private
->SignatureGUID
!= NULL
);
3639 Status
= StringToGuid (
3640 IfrNvData
->SignatureGuid
,
3641 StrLen (IfrNvData
->SignatureGuid
),
3642 Private
->SignatureGUID
3644 if (EFI_ERROR (Status
)) {
3648 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3651 case KEY_SECURE_BOOT_DELETE_PK
:
3652 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3653 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3654 IfrNvData
->DeletePk
= TRUE
;
3655 IfrNvData
->HasPk
= FALSE
;
3656 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3658 IfrNvData
->DeletePk
= FALSE
;
3659 IfrNvData
->HasPk
= TRUE
;
3660 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3662 if (SetupMode
!= NULL
) {
3663 FreePool (SetupMode
);
3669 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3670 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3671 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
3673 IfrNvData
->HideSecureBoot
= TRUE
;
3676 IfrNvData
->HideSecureBoot
= FALSE
;
3678 Value
->b
= IfrNvData
->HideSecureBoot
;
3680 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3682 // Force the platform back to Standard Mode once user leave the setup screen.
3684 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3685 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3686 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3687 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3689 if (SecureBootMode
!= NULL
) {
3690 FreePool (SecureBootMode
);
3696 if (!EFI_ERROR (Status
)) {
3697 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3698 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3701 FreePool (IfrNvData
);
3712 This function publish the SecureBoot configuration Form.
3714 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3716 @retval EFI_SUCCESS HII Form is installed successfully.
3717 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3718 @retval Others Other errors as indicated.
3722 InstallSecureBootConfigForm (
3723 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3727 EFI_HII_HANDLE HiiHandle
;
3728 EFI_HANDLE DriverHandle
;
3729 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3731 DriverHandle
= NULL
;
3732 ConfigAccess
= &PrivateData
->ConfigAccess
;
3733 Status
= gBS
->InstallMultipleProtocolInterfaces (
3735 &gEfiDevicePathProtocolGuid
,
3736 &mSecureBootHiiVendorDevicePath
,
3737 &gEfiHiiConfigAccessProtocolGuid
,
3741 if (EFI_ERROR (Status
)) {
3745 PrivateData
->DriverHandle
= DriverHandle
;
3748 // Publish the HII package list
3750 HiiHandle
= HiiAddPackages (
3751 &gSecureBootConfigFormSetGuid
,
3753 SecureBootConfigDxeStrings
,
3754 SecureBootConfigBin
,
3757 if (HiiHandle
== NULL
) {
3758 gBS
->UninstallMultipleProtocolInterfaces (
3760 &gEfiDevicePathProtocolGuid
,
3761 &mSecureBootHiiVendorDevicePath
,
3762 &gEfiHiiConfigAccessProtocolGuid
,
3766 return EFI_OUT_OF_RESOURCES
;
3769 PrivateData
->HiiHandle
= HiiHandle
;
3771 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
3773 if (PrivateData
->FileContext
== NULL
) {
3774 UninstallSecureBootConfigForm (PrivateData
);
3775 return EFI_OUT_OF_RESOURCES
;
3779 // Init OpCode Handle and Allocate space for creation of Buffer
3781 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3782 if (mStartOpCodeHandle
== NULL
) {
3783 UninstallSecureBootConfigForm (PrivateData
);
3784 return EFI_OUT_OF_RESOURCES
;
3787 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3788 if (mEndOpCodeHandle
== NULL
) {
3789 UninstallSecureBootConfigForm (PrivateData
);
3790 return EFI_OUT_OF_RESOURCES
;
3794 // Create Hii Extend Label OpCode as the start opcode
3796 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
3800 sizeof (EFI_IFR_GUID_LABEL
)
3802 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3805 // Create Hii Extend Label OpCode as the end opcode
3807 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
3811 sizeof (EFI_IFR_GUID_LABEL
)
3813 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3814 mEndLabel
->Number
= LABEL_END
;
3820 This function removes SecureBoot configuration Form.
3822 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3826 UninstallSecureBootConfigForm (
3827 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3831 // Uninstall HII package list
3833 if (PrivateData
->HiiHandle
!= NULL
) {
3834 HiiRemovePackages (PrivateData
->HiiHandle
);
3835 PrivateData
->HiiHandle
= NULL
;
3839 // Uninstall HII Config Access Protocol
3841 if (PrivateData
->DriverHandle
!= NULL
) {
3842 gBS
->UninstallMultipleProtocolInterfaces (
3843 PrivateData
->DriverHandle
,
3844 &gEfiDevicePathProtocolGuid
,
3845 &mSecureBootHiiVendorDevicePath
,
3846 &gEfiHiiConfigAccessProtocolGuid
,
3847 &PrivateData
->ConfigAccess
,
3850 PrivateData
->DriverHandle
= NULL
;
3853 if (PrivateData
->SignatureGUID
!= NULL
) {
3854 FreePool (PrivateData
->SignatureGUID
);
3857 if (PrivateData
->FileContext
!= NULL
) {
3858 FreePool (PrivateData
->FileContext
);
3861 FreePool (PrivateData
);
3863 if (mStartOpCodeHandle
!= NULL
) {
3864 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
3867 if (mEndOpCodeHandle
!= NULL
) {
3868 HiiFreeOpCodeHandle (mEndOpCodeHandle
);