2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2013, 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)
52 // OID ASN.1 Value for Hash Algorithms
54 UINT8 mHashOidValue
[] = {
55 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
56 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
63 HASH_TABLE mHash
[] = {
64 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
65 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
66 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
67 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
68 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
72 // Variable Definitions
74 UINT32 mPeCoffHeaderOffset
= 0;
75 WIN_CERTIFICATE
*mCertificate
= NULL
;
76 IMAGE_TYPE mImageType
;
77 UINT8
*mImageBase
= NULL
;
79 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
80 UINTN mImageDigestSize
;
82 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
83 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
86 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
88 CHAR16
* mDerEncodedSuffix
[] = {
94 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
97 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
99 @param[in] FileSuffix The suffix of the input certificate file
101 @retval TRUE It's a DER-encoded certificate.
102 @retval FALSE It's NOT a DER-encoded certificate.
106 IsDerEncodeCertificate (
107 IN CONST CHAR16
*FileSuffix
111 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
112 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
120 Set Secure Boot option into variable space.
122 @param[in] VarValue The option of Secure Boot.
124 @retval EFI_SUCCESS The operation is finished successfully.
125 @retval Others Other errors as indicated.
129 SaveSecureBootVariable (
135 Status
= gRT
->SetVariable (
136 EFI_SECURE_BOOT_ENABLE_NAME
,
137 &gEfiSecureBootEnableDisableGuid
,
138 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
146 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
147 descriptor with the input data. NO authentication is required in this function.
149 @param[in, out] DataSize On input, the size of Data buffer in bytes.
150 On output, the size of data returned in Data
152 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
153 pointer to NULL to wrap an empty payload.
154 On output, Pointer to the new payload date buffer allocated from pool,
155 it's caller's responsibility to free the memory when finish using it.
157 @retval EFI_SUCCESS Create time based payload successfully.
158 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
159 @retval EFI_INVALID_PARAMETER The parameter is invalid.
160 @retval Others Unexpected error happens.
164 CreateTimeBasedPayload (
165 IN OUT UINTN
*DataSize
,
173 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
174 UINTN DescriptorSize
;
177 if (Data
== NULL
|| DataSize
== NULL
) {
178 return EFI_INVALID_PARAMETER
;
182 // In Setup mode or Custom mode, the variable does not need to be signed but the
183 // parameters to the SetVariable() call still need to be prepared as authenticated
184 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
188 PayloadSize
= *DataSize
;
190 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
191 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
192 if (NewData
== NULL
) {
193 return EFI_OUT_OF_RESOURCES
;
196 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
197 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
200 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
202 ZeroMem (&Time
, sizeof (EFI_TIME
));
203 Status
= gRT
->GetTime (&Time
, NULL
);
204 if (EFI_ERROR (Status
)) {
213 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
215 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
216 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
217 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
218 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
220 if (Payload
!= NULL
) {
224 *DataSize
= DescriptorSize
+ PayloadSize
;
230 Internal helper function to delete a Variable given its name and GUID, NO authentication
233 @param[in] VariableName Name of the Variable.
234 @param[in] VendorGuid GUID of the Variable.
236 @retval EFI_SUCCESS Variable deleted successfully.
237 @retval Others The driver failed to start the device.
242 IN CHAR16
*VariableName
,
243 IN EFI_GUID
*VendorGuid
252 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
253 if (Variable
== NULL
) {
260 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
261 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
263 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
264 if (EFI_ERROR (Status
)) {
265 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
269 Status
= gRT
->SetVariable (
284 Set the platform secure boot mode into "Custom" or "Standard" mode.
286 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
287 CUSTOM_SECURE_BOOT_MODE.
289 @return EFI_SUCCESS The platform has switched to the special mode successfully.
290 @return other Fail to operate the secure boot mode.
295 IN UINT8 SecureBootMode
298 return gRT
->SetVariable (
299 EFI_CUSTOM_MODE_NAME
,
300 &gEfiCustomModeEnableGuid
,
301 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
308 Generate the PK signature list from the X509 Certificate storing file (.cer)
310 @param[in] X509File FileHandle of X509 Certificate storing file.
311 @param[out] PkCert Point to the data buffer to store the signature list.
313 @return EFI_UNSUPPORTED Unsupported Key Length.
314 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
318 CreatePkX509SignatureList (
319 IN EFI_FILE_HANDLE X509File
,
320 OUT EFI_SIGNATURE_LIST
**PkCert
326 EFI_SIGNATURE_DATA
*PkCertData
;
332 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
333 if (EFI_ERROR (Status
)) {
336 ASSERT (X509Data
!= NULL
);
339 // Allocate space for PK certificate list and initialize it.
340 // Create PK database entry with SignatureHeaderSize equals 0.
342 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
343 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
346 if (*PkCert
== NULL
) {
347 Status
= EFI_OUT_OF_RESOURCES
;
351 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
352 + sizeof(EFI_SIGNATURE_DATA
) - 1
354 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
355 (*PkCert
)->SignatureHeaderSize
= 0;
356 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
357 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
358 + sizeof(EFI_SIGNATURE_LIST
)
359 + (*PkCert
)->SignatureHeaderSize
);
360 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
362 // Fill the PK database with PKpub data from X509 certificate file.
364 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
368 if (X509Data
!= NULL
) {
372 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
381 Enroll new PK into the System without original PK's authentication.
383 The SignatureOwner GUID will be the same with PK's vendorguid.
385 @param[in] PrivateData The module's private data.
387 @retval EFI_SUCCESS New PK enrolled successfully.
388 @retval EFI_INVALID_PARAMETER The parameter is invalid.
389 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
394 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
400 EFI_SIGNATURE_LIST
*PkCert
;
403 if (Private
->FileContext
->FileName
== NULL
) {
404 return EFI_INVALID_PARAMETER
;
409 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
410 if (EFI_ERROR (Status
)) {
415 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
417 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
418 if (!IsDerEncodeCertificate(FilePostFix
)) {
419 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
420 return EFI_INVALID_PARAMETER
;
422 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
423 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
426 // Prase the selected PK file and generature PK certificate list.
428 Status
= CreatePkX509SignatureList (
429 Private
->FileContext
->FHandle
,
432 if (EFI_ERROR (Status
)) {
435 ASSERT (PkCert
!= NULL
);
438 // Set Platform Key variable.
440 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
441 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
442 DataSize
= PkCert
->SignatureListSize
;
443 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
444 if (EFI_ERROR (Status
)) {
445 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
449 Status
= gRT
->SetVariable(
450 EFI_PLATFORM_KEY_NAME
,
451 &gEfiGlobalVariableGuid
,
456 if (EFI_ERROR (Status
)) {
457 if (Status
== EFI_OUT_OF_RESOURCES
) {
458 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
465 if (PkCert
!= NULL
) {
469 if (Private
->FileContext
->FHandle
!= NULL
) {
470 CloseFile (Private
->FileContext
->FHandle
);
471 Private
->FileContext
->FHandle
= NULL
;
478 Remove the PK variable.
480 @retval EFI_SUCCESS Delete PK successfully.
481 @retval Others Could not allow to delete PK.
491 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
492 if (EFI_ERROR (Status
)) {
496 Status
= DeleteVariable (
497 EFI_PLATFORM_KEY_NAME
,
498 &gEfiGlobalVariableGuid
504 Enroll a new KEK item from public key storing file (*.pbk).
506 @param[in] PrivateData The module's private data.
508 @retval EFI_SUCCESS New KEK enrolled successfully.
509 @retval EFI_INVALID_PARAMETER The parameter is invalid.
510 @retval EFI_UNSUPPORTED Unsupported command.
511 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
516 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
522 EFI_SIGNATURE_LIST
*KekSigList
;
525 CPL_KEY_INFO
*KeyInfo
;
526 EFI_SIGNATURE_DATA
*KEKSigData
;
527 UINTN KekSigListSize
;
542 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
543 // First, We have to parse out public key data from the pbk key file.
545 Status
= ReadFileContent (
546 Private
->FileContext
->FHandle
,
551 if (EFI_ERROR (Status
)) {
554 ASSERT (KeyBlob
!= NULL
);
555 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
556 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
557 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
558 Status
= EFI_UNSUPPORTED
;
563 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
565 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
566 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
567 if (KeyBuffer
== NULL
) {
568 Status
= EFI_OUT_OF_RESOURCES
;
572 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
573 KeyLenInBytes
/ sizeof (UINTN
),
577 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
580 // Form an new EFI_SIGNATURE_LIST.
582 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
583 + sizeof(EFI_SIGNATURE_DATA
) - 1
584 + WIN_CERT_UEFI_RSA2048_SIZE
;
586 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
587 if (KekSigList
== NULL
) {
588 Status
= EFI_OUT_OF_RESOURCES
;
592 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
593 + sizeof(EFI_SIGNATURE_DATA
) - 1
594 + WIN_CERT_UEFI_RSA2048_SIZE
;
595 KekSigList
->SignatureHeaderSize
= 0;
596 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
597 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
599 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
600 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
602 KEKSigData
->SignatureData
,
603 KeyBlob
+ sizeof(CPL_KEY_INFO
),
604 WIN_CERT_UEFI_RSA2048_SIZE
608 // Check if KEK entry has been already existed.
609 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
610 // new KEK to original variable.
612 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
613 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
614 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
615 if (EFI_ERROR (Status
)) {
616 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
620 Status
= gRT
->GetVariable(
621 EFI_KEY_EXCHANGE_KEY_NAME
,
622 &gEfiGlobalVariableGuid
,
627 if (Status
== EFI_BUFFER_TOO_SMALL
) {
628 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
629 } else if (Status
!= EFI_NOT_FOUND
) {
634 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
636 Status
= gRT
->SetVariable(
637 EFI_KEY_EXCHANGE_KEY_NAME
,
638 &gEfiGlobalVariableGuid
,
643 if (EFI_ERROR (Status
)) {
649 CloseFile (Private
->FileContext
->FHandle
);
650 Private
->FileContext
->FHandle
= NULL
;
651 Private
->FileContext
->FileName
= NULL
;
653 if (Private
->SignatureGUID
!= NULL
) {
654 FreePool (Private
->SignatureGUID
);
655 Private
->SignatureGUID
= NULL
;
658 if (KeyBlob
!= NULL
) {
661 if (KeyBuffer
!= NULL
) {
662 FreePool (KeyBuffer
);
664 if (KekSigList
!= NULL
) {
665 FreePool (KekSigList
);
672 Enroll a new KEK item from X509 certificate file.
674 @param[in] PrivateData The module's private data.
676 @retval EFI_SUCCESS New X509 is enrolled successfully.
677 @retval EFI_INVALID_PARAMETER The parameter is invalid.
678 @retval EFI_UNSUPPORTED Unsupported command.
679 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
684 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
690 EFI_SIGNATURE_DATA
*KEKSigData
;
691 EFI_SIGNATURE_LIST
*KekSigList
;
693 UINTN KekSigListSize
;
703 Status
= ReadFileContent (
704 Private
->FileContext
->FHandle
,
709 if (EFI_ERROR (Status
)) {
712 ASSERT (X509Data
!= NULL
);
714 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
715 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
716 if (KekSigList
== NULL
) {
717 Status
= EFI_OUT_OF_RESOURCES
;
722 // Fill Certificate Database parameters.
724 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
725 KekSigList
->SignatureHeaderSize
= 0;
726 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
727 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
729 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
730 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
731 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
734 // Check if KEK been already existed.
735 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
736 // new kek to original variable
738 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
739 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
740 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
741 if (EFI_ERROR (Status
)) {
742 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
746 Status
= gRT
->GetVariable(
747 EFI_KEY_EXCHANGE_KEY_NAME
,
748 &gEfiGlobalVariableGuid
,
753 if (Status
== EFI_BUFFER_TOO_SMALL
) {
754 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
755 } else if (Status
!= EFI_NOT_FOUND
) {
759 Status
= gRT
->SetVariable(
760 EFI_KEY_EXCHANGE_KEY_NAME
,
761 &gEfiGlobalVariableGuid
,
766 if (EFI_ERROR (Status
)) {
772 CloseFile (Private
->FileContext
->FHandle
);
773 Private
->FileContext
->FileName
= NULL
;
774 Private
->FileContext
->FHandle
= NULL
;
776 if (Private
->SignatureGUID
!= NULL
) {
777 FreePool (Private
->SignatureGUID
);
778 Private
->SignatureGUID
= NULL
;
781 if (KekSigList
!= NULL
) {
782 FreePool (KekSigList
);
789 Enroll new KEK into the System without PK's authentication.
790 The SignatureOwner GUID will be Private->SignatureGUID.
792 @param[in] PrivateData The module's private data.
794 @retval EFI_SUCCESS New KEK enrolled successful.
795 @retval EFI_INVALID_PARAMETER The parameter is invalid.
796 @retval others Fail to enroll KEK data.
800 EnrollKeyExchangeKey (
801 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
807 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
808 return EFI_INVALID_PARAMETER
;
811 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
812 if (EFI_ERROR (Status
)) {
817 // Parse the file's postfix. Supports DER-encoded X509 certificate,
818 // and .pbk as RSA public key file.
820 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
821 if (IsDerEncodeCertificate(FilePostFix
)) {
822 return EnrollX509ToKek (Private
);
823 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
824 return EnrollRsa2048ToKek (Private
);
826 return EFI_INVALID_PARAMETER
;
831 Enroll a new X509 certificate into Signature Database (DB or DBX) without
832 KEK's authentication.
834 @param[in] PrivateData The module's private data.
835 @param[in] VariableName Variable name of signature database, must be
836 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
838 @retval EFI_SUCCESS New X509 is enrolled successfully.
839 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
844 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
845 IN CHAR16
*VariableName
851 EFI_SIGNATURE_LIST
*SigDBCert
;
852 EFI_SIGNATURE_DATA
*SigDBCertData
;
863 SigDBCertData
= NULL
;
866 Status
= ReadFileContent (
867 Private
->FileContext
->FHandle
,
872 if (EFI_ERROR (Status
)) {
875 ASSERT (X509Data
!= NULL
);
877 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
879 Data
= AllocateZeroPool (SigDBSize
);
881 Status
= EFI_OUT_OF_RESOURCES
;
886 // Fill Certificate Database parameters.
888 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
889 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
890 SigDBCert
->SignatureHeaderSize
= 0;
891 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
892 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
894 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
895 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
896 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
899 // Check if signature database entry has been already existed.
900 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
901 // new signature data to original variable
903 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
904 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
905 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
906 if (EFI_ERROR (Status
)) {
907 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
911 Status
= gRT
->GetVariable(
913 &gEfiImageSecurityDatabaseGuid
,
918 if (Status
== EFI_BUFFER_TOO_SMALL
) {
919 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
920 } else if (Status
!= EFI_NOT_FOUND
) {
924 Status
= gRT
->SetVariable(
926 &gEfiImageSecurityDatabaseGuid
,
931 if (EFI_ERROR (Status
)) {
937 CloseFile (Private
->FileContext
->FHandle
);
938 Private
->FileContext
->FileName
= NULL
;
939 Private
->FileContext
->FHandle
= NULL
;
941 if (Private
->SignatureGUID
!= NULL
) {
942 FreePool (Private
->SignatureGUID
);
943 Private
->SignatureGUID
= NULL
;
950 if (X509Data
!= NULL
) {
958 Load PE/COFF image information into internal buffer and check its validity.
960 @retval EFI_SUCCESS Successful
961 @retval EFI_UNSUPPORTED Invalid PE/COFF file
962 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
970 EFI_IMAGE_DOS_HEADER
*DosHdr
;
971 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
972 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
977 // Read the Dos header
979 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
980 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
983 // DOS image header is present,
984 // So read the PE header after the DOS image header
986 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
990 mPeCoffHeaderOffset
= 0;
994 // Read PE header and check the signature validity and machine compatibility
996 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
997 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
999 return EFI_UNSUPPORTED
;
1002 mNtHeader
.Pe32
= NtHeader32
;
1005 // Check the architecture field of PE header and get the Certificate Data Directory data
1006 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1008 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1009 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
1011 // IA-32 Architecture
1013 mImageType
= ImageType_IA32
;
1014 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1016 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1017 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
1019 // 64-bits Architecture
1021 mImageType
= ImageType_X64
;
1022 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1023 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1025 return EFI_UNSUPPORTED
;
1032 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1033 PE/COFF Specification 8.0 Appendix A
1035 @param[in] HashAlg Hash algorithm type.
1037 @retval TRUE Successfully hash image.
1038 @retval FALSE Fail in hash image.
1048 EFI_IMAGE_SECTION_HEADER
*Section
;
1053 UINTN SumOfBytesHashed
;
1054 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1059 SectionHeader
= NULL
;
1062 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1067 // Initialize context of hash.
1069 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1071 if (HashAlg
== HASHALG_SHA1
) {
1072 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1073 mCertType
= gEfiCertSha1Guid
;
1074 } else if (HashAlg
== HASHALG_SHA256
) {
1075 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1076 mCertType
= gEfiCertSha256Guid
;
1079 CtxSize
= mHash
[HashAlg
].GetContextSize();
1081 HashCtx
= AllocatePool (CtxSize
);
1082 ASSERT (HashCtx
!= NULL
);
1084 // 1. Load the image header into memory.
1086 // 2. Initialize a SHA hash context.
1087 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1092 // Measuring PE/COFF Image Header;
1093 // But CheckSum field and SECURITY data directory (certificate) are excluded
1095 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1097 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1098 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1099 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1100 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1102 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1105 // Get the magic value from the PE/COFF Optional Header
1107 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1111 // 3. Calculate the distance from the base of the image header to the image checksum address.
1112 // 4. Hash the image header from its base to beginning of the image checksum.
1114 HashBase
= mImageBase
;
1115 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1119 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1122 // Use PE32+ offset.
1124 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1127 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1132 // 5. Skip over the image checksum (it occupies a single ULONG).
1133 // 6. Get the address of the beginning of the Cert Directory.
1134 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1136 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1140 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1141 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1144 // Use PE32+ offset.
1146 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1147 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1150 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1155 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1156 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1158 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1162 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1163 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1166 // Use PE32+ offset.
1168 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1169 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1172 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1177 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1179 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1183 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1188 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1192 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1193 // structures in the image. The 'NumberOfSections' field of the image
1194 // header indicates how big the table should be. Do not include any
1195 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1197 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1198 ASSERT (SectionHeader
!= NULL
);
1200 // 12. Using the 'PointerToRawData' in the referenced section headers as
1201 // a key, arrange the elements in the table in ascending order. In other
1202 // words, sort the section headers according to the disk-file offset of
1205 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1207 mPeCoffHeaderOffset
+
1209 sizeof (EFI_IMAGE_FILE_HEADER
) +
1210 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1212 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1214 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1215 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1218 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1223 // 13. Walk through the sorted table, bring the corresponding section
1224 // into memory, and hash the entire section (using the 'SizeOfRawData'
1225 // field in the section header to determine the amount of data to hash).
1226 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1227 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1229 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1230 Section
= &SectionHeader
[Index
];
1231 if (Section
->SizeOfRawData
== 0) {
1234 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1235 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1237 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1242 SumOfBytesHashed
+= HashSize
;
1246 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1247 // data in the file that needs to be added to the hash. This data begins
1248 // at file offset SUM_OF_BYTES_HASHED and its length is:
1249 // FileSize - (CertDirectory->Size)
1251 if (mImageSize
> SumOfBytesHashed
) {
1252 HashBase
= mImageBase
+ SumOfBytesHashed
;
1253 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1259 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1263 // Use PE32+ offset.
1267 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1271 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1277 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1280 if (HashCtx
!= NULL
) {
1283 if (SectionHeader
!= NULL
) {
1284 FreePool (SectionHeader
);
1290 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1291 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1294 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1295 @retval EFI_SUCCESS Hash successfully.
1304 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1306 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1308 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1310 // Check the Hash algorithm in PE/COFF Authenticode.
1311 // According to PKCS#7 Definition:
1312 // SignedData ::= SEQUENCE {
1314 // digestAlgorithms DigestAlgorithmIdentifiers,
1315 // contentInfo ContentInfo,
1317 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1318 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1319 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1321 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1323 // Only support two bytes of Long Form of Length Encoding.
1329 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1334 if (Index
== HASHALG_MAX
) {
1335 return EFI_UNSUPPORTED
;
1339 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1341 if (!HashPeImage(Index
)) {
1342 return EFI_UNSUPPORTED
;
1349 Enroll a new executable's signature into Signature Database.
1351 @param[in] PrivateData The module's private data.
1352 @param[in] VariableName Variable name of signature database, must be
1353 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1355 @retval EFI_SUCCESS New signature is enrolled successfully.
1356 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1357 @retval EFI_UNSUPPORTED Unsupported command.
1358 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1362 EnrollImageSignatureToSigDB (
1363 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1364 IN CHAR16
*VariableName
1368 EFI_SIGNATURE_LIST
*SigDBCert
;
1369 EFI_SIGNATURE_DATA
*SigDBCertData
;
1374 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
1377 GuidCertData
= NULL
;
1380 // Form the SigDB certificate list.
1381 // Format the data item into EFI_SIGNATURE_LIST type.
1383 // We need to parse executable's signature data from specified signed executable file.
1384 // In current implementation, we simply trust the pass-in signed executable file.
1385 // In reality, it's OS's responsibility to verify the signed executable file.
1389 // Read the whole file content
1391 Status
= ReadFileContent(
1392 Private
->FileContext
->FHandle
,
1393 (VOID
**) &mImageBase
,
1397 if (EFI_ERROR (Status
)) {
1400 ASSERT (mImageBase
!= NULL
);
1402 Status
= LoadPeImage ();
1403 if (EFI_ERROR (Status
)) {
1407 if (mSecDataDir
->SizeOfCert
== 0) {
1408 if (!HashPeImage (HASHALG_SHA256
)) {
1409 Status
= EFI_SECURITY_VIOLATION
;
1415 // Read the certificate data
1417 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
1419 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1420 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
1421 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
1422 Status
= EFI_ABORTED
;
1426 if (!HashPeImage (HASHALG_SHA256
)) {
1427 Status
= EFI_ABORTED
;
1431 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1433 Status
= HashPeImageByType ();
1434 if (EFI_ERROR (Status
)) {
1438 Status
= EFI_ABORTED
;
1444 // Create a new SigDB entry.
1446 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
1447 + sizeof(EFI_SIGNATURE_DATA
) - 1
1448 + (UINT32
) mImageDigestSize
;
1450 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
1452 Status
= EFI_OUT_OF_RESOURCES
;
1457 // Adjust the Certificate Database parameters.
1459 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1460 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1461 SigDBCert
->SignatureHeaderSize
= 0;
1462 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
1463 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
1465 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
1466 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1467 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
1469 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1470 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1471 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
1472 if (EFI_ERROR (Status
)) {
1473 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1478 // Check if SigDB variable has been already existed.
1479 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1480 // new signature data to original variable
1483 Status
= gRT
->GetVariable(
1485 &gEfiImageSecurityDatabaseGuid
,
1490 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1491 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1492 } else if (Status
!= EFI_NOT_FOUND
) {
1497 // Enroll the variable.
1499 Status
= gRT
->SetVariable(
1501 &gEfiImageSecurityDatabaseGuid
,
1506 if (EFI_ERROR (Status
)) {
1512 CloseFile (Private
->FileContext
->FHandle
);
1513 Private
->FileContext
->FHandle
= NULL
;
1514 Private
->FileContext
->FileName
= NULL
;
1516 if (Private
->SignatureGUID
!= NULL
) {
1517 FreePool (Private
->SignatureGUID
);
1518 Private
->SignatureGUID
= NULL
;
1525 if (mImageBase
!= NULL
) {
1526 FreePool (mImageBase
);
1534 Enroll signature into DB/DBX without KEK's authentication.
1535 The SignatureOwner GUID will be Private->SignatureGUID.
1537 @param[in] PrivateData The module's private data.
1538 @param[in] VariableName Variable name of signature database, must be
1539 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1541 @retval EFI_SUCCESS New signature enrolled successfully.
1542 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1543 @retval others Fail to enroll signature data.
1547 EnrollSignatureDatabase (
1548 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1549 IN CHAR16
*VariableName
1552 UINT16
* FilePostFix
;
1555 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1556 return EFI_INVALID_PARAMETER
;
1559 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
1560 if (EFI_ERROR (Status
)) {
1565 // Parse the file's postfix.
1567 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
1568 if (IsDerEncodeCertificate(FilePostFix
)) {
1570 // Supports DER-encoded X509 certificate.
1572 return EnrollX509toSigDB (Private
, VariableName
);
1575 return EnrollImageSignatureToSigDB (Private
, VariableName
);
1579 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1580 by GUID in the page for user to select and delete as needed.
1582 @param[in] PrivateData Module's private data.
1583 @param[in] VariableName The variable name of the vendor's signature database.
1584 @param[in] VendorGuid A unique identifier for the vendor.
1585 @param[in] LabelNumber Label number to insert opcodes.
1586 @param[in] FormId Form ID of current page.
1587 @param[in] QuestionIdBase Base question id of the signature list.
1589 @retval EFI_SUCCESS Success to update the signature list page
1590 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1595 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1596 IN CHAR16
*VariableName
,
1597 IN EFI_GUID
*VendorGuid
,
1598 IN UINT16 LabelNumber
,
1599 IN EFI_FORM_ID FormId
,
1600 IN EFI_QUESTION_ID QuestionIdBase
1607 VOID
*StartOpCodeHandle
;
1608 VOID
*EndOpCodeHandle
;
1609 EFI_IFR_GUID_LABEL
*StartLabel
;
1610 EFI_IFR_GUID_LABEL
*EndLabel
;
1613 EFI_SIGNATURE_LIST
*CertList
;
1614 EFI_SIGNATURE_DATA
*Cert
;
1615 UINT32 ItemDataSize
;
1617 EFI_STRING_ID GuidID
;
1624 StartOpCodeHandle
= NULL
;
1625 EndOpCodeHandle
= NULL
;
1628 // Initialize the container for dynamic opcodes.
1630 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1631 if (StartOpCodeHandle
== NULL
) {
1632 Status
= EFI_OUT_OF_RESOURCES
;
1636 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1637 if (EndOpCodeHandle
== NULL
) {
1638 Status
= EFI_OUT_OF_RESOURCES
;
1643 // Create Hii Extend Label OpCode.
1645 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1649 sizeof (EFI_IFR_GUID_LABEL
)
1651 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1652 StartLabel
->Number
= LabelNumber
;
1654 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1658 sizeof (EFI_IFR_GUID_LABEL
)
1660 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1661 EndLabel
->Number
= LABEL_END
;
1667 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1668 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1672 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1674 Status
= EFI_OUT_OF_RESOURCES
;
1678 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1679 if (EFI_ERROR (Status
)) {
1683 GuidStr
= AllocateZeroPool (100);
1684 if (GuidStr
== NULL
) {
1685 Status
= EFI_OUT_OF_RESOURCES
;
1690 // Enumerate all KEK pub data.
1692 ItemDataSize
= (UINT32
) DataSize
;
1693 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1696 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1698 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1699 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
1700 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1701 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
1702 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
1703 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
1704 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
1705 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
1708 // The signature type is not supported in current implementation.
1710 ItemDataSize
-= CertList
->SignatureListSize
;
1711 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1715 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1716 for (Index
= 0; Index
< CertCount
; Index
++) {
1717 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
1718 + sizeof (EFI_SIGNATURE_LIST
)
1719 + CertList
->SignatureHeaderSize
1720 + Index
* CertList
->SignatureSize
);
1722 // Display GUID and help
1724 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
1725 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
1726 HiiCreateCheckBoxOpCode (
1728 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
1733 EFI_IFR_FLAG_CALLBACK
,
1739 ItemDataSize
-= CertList
->SignatureListSize
;
1740 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1745 PrivateData
->HiiHandle
,
1746 &gSecureBootConfigFormSetGuid
,
1752 if (StartOpCodeHandle
!= NULL
) {
1753 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1756 if (EndOpCodeHandle
!= NULL
) {
1757 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1764 if (GuidStr
!= NULL
) {
1772 Delete a KEK entry from KEK database.
1774 @param[in] PrivateData Module's private data.
1775 @param[in] QuestionId Question id of the KEK item to delete.
1777 @retval EFI_SUCCESS Delete kek item successfully.
1778 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1782 DeleteKeyExchangeKey (
1783 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1784 IN EFI_QUESTION_ID QuestionId
1793 EFI_SIGNATURE_LIST
*CertList
;
1794 EFI_SIGNATURE_LIST
*NewCertList
;
1795 EFI_SIGNATURE_DATA
*Cert
;
1798 BOOLEAN IsKEKItemFound
;
1800 UINTN DeleteKekIndex
;
1808 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
1810 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
1811 if (EFI_ERROR (Status
)) {
1816 // Get original KEK variable.
1819 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
1820 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1824 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
1825 if (OldData
== NULL
) {
1826 Status
= EFI_OUT_OF_RESOURCES
;
1830 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
1831 if (EFI_ERROR(Status
)) {
1836 // Allocate space for new variable.
1838 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1840 Status
= EFI_OUT_OF_RESOURCES
;
1845 // Enumerate all KEK pub data and erasing the target item.
1847 IsKEKItemFound
= FALSE
;
1848 KekDataSize
= (UINT32
) DataSize
;
1849 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1852 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1853 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1854 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1855 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1856 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1857 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1858 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1859 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1860 for (Index
= 0; Index
< CertCount
; Index
++) {
1861 if (GuidIndex
== DeleteKekIndex
) {
1863 // Find it! Skip it!
1865 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1866 IsKEKItemFound
= TRUE
;
1869 // This item doesn't match. Copy it to the Data buffer.
1871 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
1872 Offset
+= CertList
->SignatureSize
;
1875 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1879 // This List doesn't match. Copy it to the Data buffer.
1881 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
1882 Offset
+= CertList
->SignatureListSize
;
1885 KekDataSize
-= CertList
->SignatureListSize
;
1886 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1889 if (!IsKEKItemFound
) {
1891 // Doesn't find the Kek Item!
1893 Status
= EFI_NOT_FOUND
;
1898 // Delete the Signature header if there is no signature in the list.
1900 KekDataSize
= Offset
;
1901 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1903 ZeroMem (OldData
, KekDataSize
);
1904 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1905 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1906 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1907 if (CertCount
!= 0) {
1908 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
1909 Offset
+= CertList
->SignatureListSize
;
1911 KekDataSize
-= CertList
->SignatureListSize
;
1912 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1916 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1917 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
1918 if (EFI_ERROR (Status
)) {
1919 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1924 Status
= gRT
->SetVariable(
1925 EFI_KEY_EXCHANGE_KEY_NAME
,
1926 &gEfiGlobalVariableGuid
,
1931 if (EFI_ERROR (Status
)) {
1932 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
1941 if (OldData
!= NULL
) {
1945 return UpdateDeletePage (
1947 EFI_KEY_EXCHANGE_KEY_NAME
,
1948 &gEfiGlobalVariableGuid
,
1950 FORMID_DELETE_KEK_FORM
,
1951 OPTION_DEL_KEK_QUESTION_ID
1956 Delete a signature entry from siganture database.
1958 @param[in] PrivateData Module's private data.
1959 @param[in] VariableName The variable name of the vendor's signature database.
1960 @param[in] VendorGuid A unique identifier for the vendor.
1961 @param[in] LabelNumber Label number to insert opcodes.
1962 @param[in] FormId Form ID of current page.
1963 @param[in] QuestionIdBase Base question id of the signature list.
1964 @param[in] DeleteIndex Signature index to delete.
1966 @retval EFI_SUCCESS Delete siganture successfully.
1967 @retval EFI_NOT_FOUND Can't find the signature item,
1968 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1972 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1973 IN CHAR16
*VariableName
,
1974 IN EFI_GUID
*VendorGuid
,
1975 IN UINT16 LabelNumber
,
1976 IN EFI_FORM_ID FormId
,
1977 IN EFI_QUESTION_ID QuestionIdBase
,
1978 IN UINTN DeleteIndex
1987 EFI_SIGNATURE_LIST
*CertList
;
1988 EFI_SIGNATURE_LIST
*NewCertList
;
1989 EFI_SIGNATURE_DATA
*Cert
;
1992 BOOLEAN IsItemFound
;
1993 UINT32 ItemDataSize
;
2002 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2003 if (EFI_ERROR (Status
)) {
2008 // Get original signature list data.
2011 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2012 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2016 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2017 if (OldData
== NULL
) {
2018 Status
= EFI_OUT_OF_RESOURCES
;
2022 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2023 if (EFI_ERROR(Status
)) {
2028 // Allocate space for new variable.
2030 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2032 Status
= EFI_OUT_OF_RESOURCES
;
2037 // Enumerate all signature data and erasing the target item.
2039 IsItemFound
= FALSE
;
2040 ItemDataSize
= (UINT32
) DataSize
;
2041 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2044 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2045 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2046 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2047 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2048 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)
2051 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2053 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2054 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2055 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2056 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2057 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2058 for (Index
= 0; Index
< CertCount
; Index
++) {
2059 if (GuidIndex
== DeleteIndex
) {
2061 // Find it! Skip it!
2063 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2067 // This item doesn't match. Copy it to the Data buffer.
2069 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2070 Offset
+= CertList
->SignatureSize
;
2073 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2077 // This List doesn't match. Just copy it to the Data buffer.
2079 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2080 Offset
+= CertList
->SignatureListSize
;
2083 ItemDataSize
-= CertList
->SignatureListSize
;
2084 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2089 // Doesn't find the signature Item!
2091 Status
= EFI_NOT_FOUND
;
2096 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2098 ItemDataSize
= Offset
;
2099 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2101 ZeroMem (OldData
, ItemDataSize
);
2102 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2103 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2104 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
2105 if (CertCount
!= 0) {
2106 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2107 Offset
+= CertList
->SignatureListSize
;
2109 ItemDataSize
-= CertList
->SignatureListSize
;
2110 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2114 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2115 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2116 if (EFI_ERROR (Status
)) {
2117 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2122 Status
= gRT
->SetVariable(
2129 if (EFI_ERROR (Status
)) {
2130 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2139 if (OldData
!= NULL
) {
2143 return UpdateDeletePage (
2154 This function extracts configuration from variable.
2156 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2160 SecureBootExtractConfigFromVariable (
2161 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2164 UINT8
*SecureBootEnable
;
2166 UINT8
*SecureBootMode
;
2168 SecureBootEnable
= NULL
;
2170 SecureBootMode
= NULL
;
2173 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2176 ConfigData
->AttemptSecureBoot
= FALSE
;
2177 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2178 if (SecureBootEnable
== NULL
) {
2179 ConfigData
->HideSecureBoot
= TRUE
;
2181 ConfigData
->HideSecureBoot
= FALSE
;
2182 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
2183 ConfigData
->AttemptSecureBoot
= TRUE
;
2188 // If it is Physical Presence User, set the PhysicalPresent to true.
2190 if (UserPhysicalPresent()) {
2191 ConfigData
->PhysicalPresent
= TRUE
;
2193 ConfigData
->PhysicalPresent
= FALSE
;
2197 // If there is no PK then the Delete Pk button will be gray.
2199 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2200 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2201 ConfigData
->HasPk
= FALSE
;
2203 ConfigData
->HasPk
= TRUE
;
2207 // Get the SecureBootMode from CustomMode variable.
2209 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2210 if (SecureBootMode
== NULL
) {
2211 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2213 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2216 if (SecureBootEnable
!= NULL
) {
2217 FreePool (SecureBootEnable
);
2219 if (SetupMode
!= NULL
) {
2220 FreePool (SetupMode
);
2222 if (SecureBootMode
!= NULL
) {
2223 FreePool (SecureBootMode
);
2228 This function allows a caller to extract the current configuration for one
2229 or more named elements from the target driver.
2231 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2232 @param[in] Request A null-terminated Unicode string in
2233 <ConfigRequest> format.
2234 @param[out] Progress On return, points to a character in the Request
2235 string. Points to the string's null terminator if
2236 request was successful. Points to the most recent
2237 '&' before the first failing name/value pair (or
2238 the beginning of the string if the failure is in
2239 the first name/value pair) if the request was not
2241 @param[out] Results A null-terminated Unicode string in
2242 <ConfigAltResp> format which has all values filled
2243 in for the names in the Request string. String to
2244 be allocated by the called function.
2246 @retval EFI_SUCCESS The Results is filled with the requested values.
2247 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2248 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2249 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2255 SecureBootExtractConfig (
2256 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2257 IN CONST EFI_STRING Request
,
2258 OUT EFI_STRING
*Progress
,
2259 OUT EFI_STRING
*Results
2265 SECUREBOOT_CONFIGURATION Configuration
;
2266 EFI_STRING ConfigRequest
;
2267 EFI_STRING ConfigRequestHdr
;
2268 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2269 BOOLEAN AllocatedRequest
;
2272 if (Progress
== NULL
|| Results
== NULL
) {
2273 return EFI_INVALID_PARAMETER
;
2276 AllocatedRequest
= FALSE
;
2277 ConfigRequestHdr
= NULL
;
2278 ConfigRequest
= NULL
;
2282 ZeroMem (&Configuration
, sizeof (Configuration
));
2283 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2284 *Progress
= Request
;
2286 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2287 return EFI_NOT_FOUND
;
2291 // Get Configuration from Variable.
2293 SecureBootExtractConfigFromVariable (&Configuration
);
2296 // Update current secure boot state.
2298 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2299 if (SecureBoot
!= NULL
&& *SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2300 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
2302 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
2304 if (SecureBoot
!= NULL
) {
2305 FreePool (SecureBoot
);
2308 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2309 ConfigRequest
= Request
;
2310 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2312 // Request is set to NULL or OFFSET is NULL, construct full request string.
2314 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2315 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2317 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2318 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2319 ConfigRequest
= AllocateZeroPool (Size
);
2320 ASSERT (ConfigRequest
!= NULL
);
2321 AllocatedRequest
= TRUE
;
2322 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2323 FreePool (ConfigRequestHdr
);
2324 ConfigRequestHdr
= NULL
;
2327 Status
= gHiiConfigRouting
->BlockToConfig (
2330 (UINT8
*) &Configuration
,
2337 // Free the allocated config request string.
2339 if (AllocatedRequest
) {
2340 FreePool (ConfigRequest
);
2344 // Set Progress string to the original request string.
2346 if (Request
== NULL
) {
2348 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2349 *Progress
= Request
+ StrLen (Request
);
2356 This function processes the results of changes in configuration.
2358 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2359 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2361 @param[out] Progress A pointer to a string filled in with the offset of
2362 the most recent '&' before the first failing
2363 name/value pair (or the beginning of the string if
2364 the failure is in the first name/value pair) or
2365 the terminating NULL if all was successful.
2367 @retval EFI_SUCCESS The Results is processed successfully.
2368 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2369 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2375 SecureBootRouteConfig (
2376 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2377 IN CONST EFI_STRING Configuration
,
2378 OUT EFI_STRING
*Progress
2381 UINT8
*SecureBootEnable
;
2382 SECUREBOOT_CONFIGURATION IfrNvData
;
2386 if (Configuration
== NULL
|| Progress
== NULL
) {
2387 return EFI_INVALID_PARAMETER
;
2390 *Progress
= Configuration
;
2391 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2392 return EFI_NOT_FOUND
;
2395 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2396 Status
= gHiiConfigRouting
->ConfigToBlock (
2399 (UINT8
*)&IfrNvData
,
2403 if (EFI_ERROR (Status
)) {
2408 // Store Buffer Storage back to EFI variable if needed
2410 SecureBootEnable
= NULL
;
2411 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2412 if (NULL
!= SecureBootEnable
) {
2413 FreePool (SecureBootEnable
);
2414 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
2415 if (EFI_ERROR (Status
)) {
2420 *Progress
= Configuration
+ StrLen (Configuration
);
2425 This function is called to provide results data to the driver.
2427 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2428 @param[in] Action Specifies the type of action taken by the browser.
2429 @param[in] QuestionId A unique value which is sent to the original
2430 exporting driver so that it can identify the type
2432 @param[in] Type The type of value for the question.
2433 @param[in] Value A pointer to the data being sent to the original
2435 @param[out] ActionRequest On return, points to the action requested by the
2438 @retval EFI_SUCCESS The callback successfully handled the action.
2439 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2440 variable and its data.
2441 @retval EFI_DEVICE_ERROR The variable could not be saved.
2442 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2448 SecureBootCallback (
2449 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2450 IN EFI_BROWSER_ACTION Action
,
2451 IN EFI_QUESTION_ID QuestionId
,
2453 IN EFI_IFR_TYPE_VALUE
*Value
,
2454 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2459 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
2461 SECUREBOOT_CONFIGURATION
*IfrNvData
;
2463 UINT8
*SecureBootEnable
;
2464 UINT8
*SecureBootMode
;
2466 CHAR16 PromptString
[100];
2468 SecureBootEnable
= NULL
;
2469 SecureBootMode
= NULL
;
2472 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
2473 return EFI_INVALID_PARAMETER
;
2476 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
2477 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
2478 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
2479 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
2480 return EFI_UNSUPPORTED
;
2483 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2486 // Retrieve uncommitted data from Browser
2488 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2489 IfrNvData
= AllocateZeroPool (BufferSize
);
2490 if (IfrNvData
== NULL
) {
2491 return EFI_OUT_OF_RESOURCES
;
2494 Status
= EFI_SUCCESS
;
2496 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2498 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2500 switch (QuestionId
) {
2501 case KEY_SECURE_BOOT_ENABLE
:
2502 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2503 if (NULL
!= SecureBootEnable
) {
2504 FreePool (SecureBootEnable
);
2505 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
2507 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2509 L
"Only Physical Presence User could disable secure boot!",
2512 Status
= EFI_UNSUPPORTED
;
2515 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2517 L
"Configuration changed, please reset the platform to take effect!",
2524 case KEY_SECURE_BOOT_OPTION
:
2525 FreeMenu (&DirectoryMenu
);
2526 FreeMenu (&FsOptionMenu
);
2529 case KEY_SECURE_BOOT_KEK_OPTION
:
2530 case KEY_SECURE_BOOT_DB_OPTION
:
2531 case KEY_SECURE_BOOT_DBX_OPTION
:
2533 // Clear Signature GUID.
2535 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
2536 if (Private
->SignatureGUID
== NULL
) {
2537 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
2538 if (Private
->SignatureGUID
== NULL
) {
2539 return EFI_OUT_OF_RESOURCES
;
2543 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
2544 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
2545 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
2546 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
2548 LabelId
= FORMID_ENROLL_KEK_FORM
;
2552 // Refresh selected file.
2554 CleanUpPage (LabelId
, Private
);
2557 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
2558 case FORMID_ENROLL_KEK_FORM
:
2559 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
2560 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
2561 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
2562 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
2563 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
2564 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
2565 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
2566 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
2568 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
2571 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2572 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
2573 UpdateFileExplorer (Private
, 0);
2576 case KEY_SECURE_BOOT_DELETE_PK
:
2579 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2581 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
2582 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
2585 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
2586 Status
= DeletePlatformKey ();
2587 if (EFI_ERROR (Status
)) {
2589 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2591 L
"Only Physical Presence User could delete PK in custom mode!",
2599 case KEY_DELETE_KEK
:
2602 EFI_KEY_EXCHANGE_KEY_NAME
,
2603 &gEfiGlobalVariableGuid
,
2605 FORMID_DELETE_KEK_FORM
,
2606 OPTION_DEL_KEK_QUESTION_ID
2610 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
2613 EFI_IMAGE_SECURITY_DATABASE
,
2614 &gEfiImageSecurityDatabaseGuid
,
2616 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2617 OPTION_DEL_DB_QUESTION_ID
2621 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
2624 EFI_IMAGE_SECURITY_DATABASE1
,
2625 &gEfiImageSecurityDatabaseGuid
,
2627 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2628 OPTION_DEL_DBX_QUESTION_ID
2633 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
2634 Status
= EnrollKeyExchangeKey (Private
);
2637 case KEY_VALUE_SAVE_AND_EXIT_DB
:
2638 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
2641 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
2642 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
2646 if (QuestionId
>= FILE_OPTION_OFFSET
) {
2647 UpdateFileExplorer (Private
, QuestionId
);
2648 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
2649 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2650 DeleteKeyExchangeKey (Private
, QuestionId
);
2651 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
2652 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2655 EFI_IMAGE_SECURITY_DATABASE
,
2656 &gEfiImageSecurityDatabaseGuid
,
2658 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2659 OPTION_DEL_DB_QUESTION_ID
,
2660 QuestionId
- OPTION_DEL_DB_QUESTION_ID
2662 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
2663 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2666 EFI_IMAGE_SECURITY_DATABASE1
,
2667 &gEfiImageSecurityDatabaseGuid
,
2669 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2670 OPTION_DEL_DBX_QUESTION_ID
,
2671 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
2676 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2677 switch (QuestionId
) {
2678 case KEY_SECURE_BOOT_ENABLE
:
2679 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2681 case KEY_VALUE_SAVE_AND_EXIT_PK
:
2682 Status
= EnrollPlatformKey (Private
);
2685 sizeof (PromptString
),
2686 L
"Only DER encoded certificate file (%s) is supported.",
2689 if (EFI_ERROR (Status
)) {
2691 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2693 L
"ERROR: Unsupported file type!",
2698 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
2702 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
2703 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
2704 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
2705 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
2706 if (Private
->FileContext
->FHandle
!= NULL
) {
2707 CloseFile (Private
->FileContext
->FHandle
);
2708 Private
->FileContext
->FHandle
= NULL
;
2709 Private
->FileContext
->FileName
= NULL
;
2712 if (Private
->SignatureGUID
!= NULL
) {
2713 FreePool (Private
->SignatureGUID
);
2714 Private
->SignatureGUID
= NULL
;
2716 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2719 case KEY_SECURE_BOOT_MODE
:
2720 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2721 if (NULL
!= SecureBootMode
) {
2722 Status
= gRT
->SetVariable (
2723 EFI_CUSTOM_MODE_NAME
,
2724 &gEfiCustomModeEnableGuid
,
2725 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2729 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2730 IfrNvData
->SecureBootMode
= Value
->u8
;
2731 FreePool (SecureBootMode
);
2735 case KEY_SECURE_BOOT_KEK_GUID
:
2736 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
2737 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
2738 ASSERT (Private
->SignatureGUID
!= NULL
);
2739 Status
= StringToGuid (
2740 IfrNvData
->SignatureGuid
,
2741 StrLen (IfrNvData
->SignatureGuid
),
2742 Private
->SignatureGUID
2744 if (EFI_ERROR (Status
)) {
2748 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2751 case KEY_SECURE_BOOT_DELETE_PK
:
2752 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2753 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2754 IfrNvData
->DeletePk
= TRUE
;
2755 IfrNvData
->HasPk
= FALSE
;
2756 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2758 IfrNvData
->DeletePk
= FALSE
;
2759 IfrNvData
->HasPk
= TRUE
;
2760 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2762 if (SetupMode
!= NULL
) {
2763 FreePool (SetupMode
);
2767 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
2768 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
2769 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2770 if (SecureBootEnable
== NULL
) {
2771 IfrNvData
->HideSecureBoot
= TRUE
;
2773 FreePool (SecureBootEnable
);
2774 IfrNvData
->HideSecureBoot
= FALSE
;
2776 Value
->b
= IfrNvData
->HideSecureBoot
;
2778 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
2780 // Force the platform back to Standard Mode once user leave the setup screen.
2782 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2783 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
2784 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2785 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
2787 if (SecureBootMode
!= NULL
) {
2788 FreePool (SecureBootMode
);
2792 if (!EFI_ERROR (Status
)) {
2793 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2794 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2796 FreePool (IfrNvData
);
2802 This function publish the SecureBoot configuration Form.
2804 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2806 @retval EFI_SUCCESS HII Form is installed successfully.
2807 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2808 @retval Others Other errors as indicated.
2812 InstallSecureBootConfigForm (
2813 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2817 EFI_HII_HANDLE HiiHandle
;
2818 EFI_HANDLE DriverHandle
;
2819 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2821 DriverHandle
= NULL
;
2822 ConfigAccess
= &PrivateData
->ConfigAccess
;
2823 Status
= gBS
->InstallMultipleProtocolInterfaces (
2825 &gEfiDevicePathProtocolGuid
,
2826 &mSecureBootHiiVendorDevicePath
,
2827 &gEfiHiiConfigAccessProtocolGuid
,
2831 if (EFI_ERROR (Status
)) {
2835 PrivateData
->DriverHandle
= DriverHandle
;
2838 // Publish the HII package list
2840 HiiHandle
= HiiAddPackages (
2841 &gSecureBootConfigFormSetGuid
,
2843 SecureBootConfigDxeStrings
,
2844 SecureBootConfigBin
,
2847 if (HiiHandle
== NULL
) {
2848 gBS
->UninstallMultipleProtocolInterfaces (
2850 &gEfiDevicePathProtocolGuid
,
2851 &mSecureBootHiiVendorDevicePath
,
2852 &gEfiHiiConfigAccessProtocolGuid
,
2856 return EFI_OUT_OF_RESOURCES
;
2859 PrivateData
->HiiHandle
= HiiHandle
;
2861 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
2862 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
2864 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
2865 UninstallSecureBootConfigForm (PrivateData
);
2866 return EFI_OUT_OF_RESOURCES
;
2869 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
2870 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2872 InitializeListHead (&FsOptionMenu
.Head
);
2873 InitializeListHead (&DirectoryMenu
.Head
);
2876 // Init OpCode Handle and Allocate space for creation of Buffer
2878 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2879 if (mStartOpCodeHandle
== NULL
) {
2880 UninstallSecureBootConfigForm (PrivateData
);
2881 return EFI_OUT_OF_RESOURCES
;
2884 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2885 if (mEndOpCodeHandle
== NULL
) {
2886 UninstallSecureBootConfigForm (PrivateData
);
2887 return EFI_OUT_OF_RESOURCES
;
2891 // Create Hii Extend Label OpCode as the start opcode
2893 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2897 sizeof (EFI_IFR_GUID_LABEL
)
2899 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2902 // Create Hii Extend Label OpCode as the end opcode
2904 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2908 sizeof (EFI_IFR_GUID_LABEL
)
2910 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2911 mEndLabel
->Number
= LABEL_END
;
2917 This function removes SecureBoot configuration Form.
2919 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2923 UninstallSecureBootConfigForm (
2924 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2928 // Uninstall HII package list
2930 if (PrivateData
->HiiHandle
!= NULL
) {
2931 HiiRemovePackages (PrivateData
->HiiHandle
);
2932 PrivateData
->HiiHandle
= NULL
;
2936 // Uninstall HII Config Access Protocol
2938 if (PrivateData
->DriverHandle
!= NULL
) {
2939 gBS
->UninstallMultipleProtocolInterfaces (
2940 PrivateData
->DriverHandle
,
2941 &gEfiDevicePathProtocolGuid
,
2942 &mSecureBootHiiVendorDevicePath
,
2943 &gEfiHiiConfigAccessProtocolGuid
,
2944 &PrivateData
->ConfigAccess
,
2947 PrivateData
->DriverHandle
= NULL
;
2950 if (PrivateData
->SignatureGUID
!= NULL
) {
2951 FreePool (PrivateData
->SignatureGUID
);
2954 if (PrivateData
->MenuEntry
!= NULL
) {
2955 FreePool (PrivateData
->MenuEntry
);
2958 if (PrivateData
->FileContext
!= NULL
) {
2959 FreePool (PrivateData
->FileContext
);
2962 FreePool (PrivateData
);
2964 FreeMenu (&DirectoryMenu
);
2965 FreeMenu (&FsOptionMenu
);
2967 if (mStartOpCodeHandle
!= NULL
) {
2968 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
2971 if (mEndOpCodeHandle
!= NULL
) {
2972 HiiFreeOpCodeHandle (mEndOpCodeHandle
);