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
;
404 if (Private
->FileContext
->FileName
== NULL
) {
405 return EFI_INVALID_PARAMETER
;
410 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
411 if (EFI_ERROR (Status
)) {
416 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
418 NameLength
= StrLen (Private
->FileContext
->FileName
);
419 if (NameLength
<= 4) {
420 return EFI_INVALID_PARAMETER
;
422 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
423 if (!IsDerEncodeCertificate(FilePostFix
)) {
424 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
425 return EFI_INVALID_PARAMETER
;
427 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
428 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
431 // Prase the selected PK file and generature PK certificate list.
433 Status
= CreatePkX509SignatureList (
434 Private
->FileContext
->FHandle
,
437 if (EFI_ERROR (Status
)) {
440 ASSERT (PkCert
!= NULL
);
443 // Set Platform Key variable.
445 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
446 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
447 DataSize
= PkCert
->SignatureListSize
;
448 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
449 if (EFI_ERROR (Status
)) {
450 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
454 Status
= gRT
->SetVariable(
455 EFI_PLATFORM_KEY_NAME
,
456 &gEfiGlobalVariableGuid
,
461 if (EFI_ERROR (Status
)) {
462 if (Status
== EFI_OUT_OF_RESOURCES
) {
463 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
470 if (PkCert
!= NULL
) {
474 if (Private
->FileContext
->FHandle
!= NULL
) {
475 CloseFile (Private
->FileContext
->FHandle
);
476 Private
->FileContext
->FHandle
= NULL
;
483 Remove the PK variable.
485 @retval EFI_SUCCESS Delete PK successfully.
486 @retval Others Could not allow to delete PK.
496 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
497 if (EFI_ERROR (Status
)) {
501 Status
= DeleteVariable (
502 EFI_PLATFORM_KEY_NAME
,
503 &gEfiGlobalVariableGuid
509 Enroll a new KEK item from public key storing file (*.pbk).
511 @param[in] PrivateData The module's private data.
513 @retval EFI_SUCCESS New KEK enrolled successfully.
514 @retval EFI_INVALID_PARAMETER The parameter is invalid.
515 @retval EFI_UNSUPPORTED Unsupported command.
516 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
521 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
527 EFI_SIGNATURE_LIST
*KekSigList
;
530 CPL_KEY_INFO
*KeyInfo
;
531 EFI_SIGNATURE_DATA
*KEKSigData
;
532 UINTN KekSigListSize
;
547 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
548 // First, We have to parse out public key data from the pbk key file.
550 Status
= ReadFileContent (
551 Private
->FileContext
->FHandle
,
556 if (EFI_ERROR (Status
)) {
559 ASSERT (KeyBlob
!= NULL
);
560 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
561 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
562 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
563 Status
= EFI_UNSUPPORTED
;
568 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
570 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
571 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
572 if (KeyBuffer
== NULL
) {
573 Status
= EFI_OUT_OF_RESOURCES
;
577 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
578 KeyLenInBytes
/ sizeof (UINTN
),
582 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
585 // Form an new EFI_SIGNATURE_LIST.
587 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
588 + sizeof(EFI_SIGNATURE_DATA
) - 1
589 + WIN_CERT_UEFI_RSA2048_SIZE
;
591 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
592 if (KekSigList
== NULL
) {
593 Status
= EFI_OUT_OF_RESOURCES
;
597 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
598 + sizeof(EFI_SIGNATURE_DATA
) - 1
599 + WIN_CERT_UEFI_RSA2048_SIZE
;
600 KekSigList
->SignatureHeaderSize
= 0;
601 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
602 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
604 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
605 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
607 KEKSigData
->SignatureData
,
608 KeyBlob
+ sizeof(CPL_KEY_INFO
),
609 WIN_CERT_UEFI_RSA2048_SIZE
613 // Check if KEK entry has been already existed.
614 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
615 // new KEK to original variable.
617 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
618 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
619 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
620 if (EFI_ERROR (Status
)) {
621 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
625 Status
= gRT
->GetVariable(
626 EFI_KEY_EXCHANGE_KEY_NAME
,
627 &gEfiGlobalVariableGuid
,
632 if (Status
== EFI_BUFFER_TOO_SMALL
) {
633 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
634 } else if (Status
!= EFI_NOT_FOUND
) {
639 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
641 Status
= gRT
->SetVariable(
642 EFI_KEY_EXCHANGE_KEY_NAME
,
643 &gEfiGlobalVariableGuid
,
648 if (EFI_ERROR (Status
)) {
654 CloseFile (Private
->FileContext
->FHandle
);
655 Private
->FileContext
->FHandle
= NULL
;
656 Private
->FileContext
->FileName
= NULL
;
658 if (Private
->SignatureGUID
!= NULL
) {
659 FreePool (Private
->SignatureGUID
);
660 Private
->SignatureGUID
= NULL
;
663 if (KeyBlob
!= NULL
) {
666 if (KeyBuffer
!= NULL
) {
667 FreePool (KeyBuffer
);
669 if (KekSigList
!= NULL
) {
670 FreePool (KekSigList
);
677 Enroll a new KEK item from X509 certificate file.
679 @param[in] PrivateData The module's private data.
681 @retval EFI_SUCCESS New X509 is enrolled successfully.
682 @retval EFI_INVALID_PARAMETER The parameter is invalid.
683 @retval EFI_UNSUPPORTED Unsupported command.
684 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
689 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
695 EFI_SIGNATURE_DATA
*KEKSigData
;
696 EFI_SIGNATURE_LIST
*KekSigList
;
698 UINTN KekSigListSize
;
708 Status
= ReadFileContent (
709 Private
->FileContext
->FHandle
,
714 if (EFI_ERROR (Status
)) {
717 ASSERT (X509Data
!= NULL
);
719 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
720 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
721 if (KekSigList
== NULL
) {
722 Status
= EFI_OUT_OF_RESOURCES
;
727 // Fill Certificate Database parameters.
729 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
730 KekSigList
->SignatureHeaderSize
= 0;
731 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
732 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
734 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
735 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
736 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
739 // Check if KEK been already existed.
740 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
741 // new kek to original variable
743 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
744 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
745 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
746 if (EFI_ERROR (Status
)) {
747 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
751 Status
= gRT
->GetVariable(
752 EFI_KEY_EXCHANGE_KEY_NAME
,
753 &gEfiGlobalVariableGuid
,
758 if (Status
== EFI_BUFFER_TOO_SMALL
) {
759 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
760 } else if (Status
!= EFI_NOT_FOUND
) {
764 Status
= gRT
->SetVariable(
765 EFI_KEY_EXCHANGE_KEY_NAME
,
766 &gEfiGlobalVariableGuid
,
771 if (EFI_ERROR (Status
)) {
777 CloseFile (Private
->FileContext
->FHandle
);
778 Private
->FileContext
->FileName
= NULL
;
779 Private
->FileContext
->FHandle
= NULL
;
781 if (Private
->SignatureGUID
!= NULL
) {
782 FreePool (Private
->SignatureGUID
);
783 Private
->SignatureGUID
= NULL
;
786 if (KekSigList
!= NULL
) {
787 FreePool (KekSigList
);
794 Enroll new KEK into the System without PK's authentication.
795 The SignatureOwner GUID will be Private->SignatureGUID.
797 @param[in] PrivateData The module's private data.
799 @retval EFI_SUCCESS New KEK enrolled successful.
800 @retval EFI_INVALID_PARAMETER The parameter is invalid.
801 @retval others Fail to enroll KEK data.
805 EnrollKeyExchangeKey (
806 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
813 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
814 return EFI_INVALID_PARAMETER
;
817 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
818 if (EFI_ERROR (Status
)) {
823 // Parse the file's postfix. Supports DER-encoded X509 certificate,
824 // and .pbk as RSA public key file.
826 NameLength
= StrLen (Private
->FileContext
->FileName
);
827 if (NameLength
<= 4) {
828 return EFI_INVALID_PARAMETER
;
830 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
831 if (IsDerEncodeCertificate(FilePostFix
)) {
832 return EnrollX509ToKek (Private
);
833 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
834 return EnrollRsa2048ToKek (Private
);
836 return EFI_INVALID_PARAMETER
;
841 Enroll a new X509 certificate into Signature Database (DB or DBX) without
842 KEK's authentication.
844 @param[in] PrivateData The module's private data.
845 @param[in] VariableName Variable name of signature database, must be
846 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
848 @retval EFI_SUCCESS New X509 is enrolled successfully.
849 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
854 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
855 IN CHAR16
*VariableName
861 EFI_SIGNATURE_LIST
*SigDBCert
;
862 EFI_SIGNATURE_DATA
*SigDBCertData
;
873 SigDBCertData
= NULL
;
876 Status
= ReadFileContent (
877 Private
->FileContext
->FHandle
,
882 if (EFI_ERROR (Status
)) {
885 ASSERT (X509Data
!= NULL
);
887 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
889 Data
= AllocateZeroPool (SigDBSize
);
891 Status
= EFI_OUT_OF_RESOURCES
;
896 // Fill Certificate Database parameters.
898 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
899 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
900 SigDBCert
->SignatureHeaderSize
= 0;
901 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
902 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
904 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
905 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
906 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
909 // Check if signature database entry has been already existed.
910 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
911 // new signature data to original variable
913 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
914 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
915 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
916 if (EFI_ERROR (Status
)) {
917 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
921 Status
= gRT
->GetVariable(
923 &gEfiImageSecurityDatabaseGuid
,
928 if (Status
== EFI_BUFFER_TOO_SMALL
) {
929 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
930 } else if (Status
!= EFI_NOT_FOUND
) {
934 Status
= gRT
->SetVariable(
936 &gEfiImageSecurityDatabaseGuid
,
941 if (EFI_ERROR (Status
)) {
947 CloseFile (Private
->FileContext
->FHandle
);
948 Private
->FileContext
->FileName
= NULL
;
949 Private
->FileContext
->FHandle
= NULL
;
951 if (Private
->SignatureGUID
!= NULL
) {
952 FreePool (Private
->SignatureGUID
);
953 Private
->SignatureGUID
= NULL
;
960 if (X509Data
!= NULL
) {
968 Load PE/COFF image information into internal buffer and check its validity.
970 @retval EFI_SUCCESS Successful
971 @retval EFI_UNSUPPORTED Invalid PE/COFF file
972 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
980 EFI_IMAGE_DOS_HEADER
*DosHdr
;
981 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
982 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
987 // Read the Dos header
989 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
990 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
993 // DOS image header is present,
994 // So read the PE header after the DOS image header
996 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1000 mPeCoffHeaderOffset
= 0;
1004 // Read PE header and check the signature validity and machine compatibility
1006 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1007 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1009 return EFI_UNSUPPORTED
;
1012 mNtHeader
.Pe32
= NtHeader32
;
1015 // Check the architecture field of PE header and get the Certificate Data Directory data
1016 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1018 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1019 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
1021 // IA-32 Architecture
1023 mImageType
= ImageType_IA32
;
1024 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1026 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1027 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
1029 // 64-bits Architecture
1031 mImageType
= ImageType_X64
;
1032 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1033 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1035 return EFI_UNSUPPORTED
;
1042 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1043 PE/COFF Specification 8.0 Appendix A
1045 @param[in] HashAlg Hash algorithm type.
1047 @retval TRUE Successfully hash image.
1048 @retval FALSE Fail in hash image.
1058 EFI_IMAGE_SECTION_HEADER
*Section
;
1063 UINTN SumOfBytesHashed
;
1064 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1069 SectionHeader
= NULL
;
1072 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1077 // Initialize context of hash.
1079 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1081 if (HashAlg
== HASHALG_SHA1
) {
1082 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1083 mCertType
= gEfiCertSha1Guid
;
1084 } else if (HashAlg
== HASHALG_SHA256
) {
1085 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1086 mCertType
= gEfiCertSha256Guid
;
1089 CtxSize
= mHash
[HashAlg
].GetContextSize();
1091 HashCtx
= AllocatePool (CtxSize
);
1092 ASSERT (HashCtx
!= NULL
);
1094 // 1. Load the image header into memory.
1096 // 2. Initialize a SHA hash context.
1097 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1102 // Measuring PE/COFF Image Header;
1103 // But CheckSum field and SECURITY data directory (certificate) are excluded
1105 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1107 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1108 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1109 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1110 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1112 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1115 // Get the magic value from the PE/COFF Optional Header
1117 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1121 // 3. Calculate the distance from the base of the image header to the image checksum address.
1122 // 4. Hash the image header from its base to beginning of the image checksum.
1124 HashBase
= mImageBase
;
1125 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1129 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1132 // Use PE32+ offset.
1134 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1137 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1142 // 5. Skip over the image checksum (it occupies a single ULONG).
1143 // 6. Get the address of the beginning of the Cert Directory.
1144 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1146 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1150 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1151 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1154 // Use PE32+ offset.
1156 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1157 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1160 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1165 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1166 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1168 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1172 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1173 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1176 // Use PE32+ offset.
1178 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1179 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1182 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1187 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1189 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1193 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1198 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1202 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1203 // structures in the image. The 'NumberOfSections' field of the image
1204 // header indicates how big the table should be. Do not include any
1205 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1207 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1208 ASSERT (SectionHeader
!= NULL
);
1210 // 12. Using the 'PointerToRawData' in the referenced section headers as
1211 // a key, arrange the elements in the table in ascending order. In other
1212 // words, sort the section headers according to the disk-file offset of
1215 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1217 mPeCoffHeaderOffset
+
1219 sizeof (EFI_IMAGE_FILE_HEADER
) +
1220 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1222 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1224 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1225 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1228 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1233 // 13. Walk through the sorted table, bring the corresponding section
1234 // into memory, and hash the entire section (using the 'SizeOfRawData'
1235 // field in the section header to determine the amount of data to hash).
1236 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1237 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1239 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1240 Section
= &SectionHeader
[Index
];
1241 if (Section
->SizeOfRawData
== 0) {
1244 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1245 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1247 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1252 SumOfBytesHashed
+= HashSize
;
1256 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1257 // data in the file that needs to be added to the hash. This data begins
1258 // at file offset SUM_OF_BYTES_HASHED and its length is:
1259 // FileSize - (CertDirectory->Size)
1261 if (mImageSize
> SumOfBytesHashed
) {
1262 HashBase
= mImageBase
+ SumOfBytesHashed
;
1263 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1269 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1273 // Use PE32+ offset.
1277 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1281 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1287 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1290 if (HashCtx
!= NULL
) {
1293 if (SectionHeader
!= NULL
) {
1294 FreePool (SectionHeader
);
1300 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1301 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1304 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1305 @retval EFI_SUCCESS Hash successfully.
1314 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1316 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1318 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1320 // Check the Hash algorithm in PE/COFF Authenticode.
1321 // According to PKCS#7 Definition:
1322 // SignedData ::= SEQUENCE {
1324 // digestAlgorithms DigestAlgorithmIdentifiers,
1325 // contentInfo ContentInfo,
1327 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1328 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1329 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1331 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1333 // Only support two bytes of Long Form of Length Encoding.
1339 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1344 if (Index
== HASHALG_MAX
) {
1345 return EFI_UNSUPPORTED
;
1349 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1351 if (!HashPeImage(Index
)) {
1352 return EFI_UNSUPPORTED
;
1359 Enroll a new executable's signature into Signature Database.
1361 @param[in] PrivateData The module's private data.
1362 @param[in] VariableName Variable name of signature database, must be
1363 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1365 @retval EFI_SUCCESS New signature is enrolled successfully.
1366 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1367 @retval EFI_UNSUPPORTED Unsupported command.
1368 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1372 EnrollImageSignatureToSigDB (
1373 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1374 IN CHAR16
*VariableName
1378 EFI_SIGNATURE_LIST
*SigDBCert
;
1379 EFI_SIGNATURE_DATA
*SigDBCertData
;
1384 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
1387 GuidCertData
= NULL
;
1390 // Form the SigDB certificate list.
1391 // Format the data item into EFI_SIGNATURE_LIST type.
1393 // We need to parse executable's signature data from specified signed executable file.
1394 // In current implementation, we simply trust the pass-in signed executable file.
1395 // In reality, it's OS's responsibility to verify the signed executable file.
1399 // Read the whole file content
1401 Status
= ReadFileContent(
1402 Private
->FileContext
->FHandle
,
1403 (VOID
**) &mImageBase
,
1407 if (EFI_ERROR (Status
)) {
1410 ASSERT (mImageBase
!= NULL
);
1412 Status
= LoadPeImage ();
1413 if (EFI_ERROR (Status
)) {
1417 if (mSecDataDir
->SizeOfCert
== 0) {
1418 if (!HashPeImage (HASHALG_SHA256
)) {
1419 Status
= EFI_SECURITY_VIOLATION
;
1425 // Read the certificate data
1427 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
1429 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1430 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
1431 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
1432 Status
= EFI_ABORTED
;
1436 if (!HashPeImage (HASHALG_SHA256
)) {
1437 Status
= EFI_ABORTED
;
1441 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1443 Status
= HashPeImageByType ();
1444 if (EFI_ERROR (Status
)) {
1448 Status
= EFI_ABORTED
;
1454 // Create a new SigDB entry.
1456 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
1457 + sizeof(EFI_SIGNATURE_DATA
) - 1
1458 + (UINT32
) mImageDigestSize
;
1460 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
1462 Status
= EFI_OUT_OF_RESOURCES
;
1467 // Adjust the Certificate Database parameters.
1469 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1470 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1471 SigDBCert
->SignatureHeaderSize
= 0;
1472 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
1473 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
1475 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
1476 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1477 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
1479 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1480 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1481 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
1482 if (EFI_ERROR (Status
)) {
1483 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1488 // Check if SigDB variable has been already existed.
1489 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1490 // new signature data to original variable
1493 Status
= gRT
->GetVariable(
1495 &gEfiImageSecurityDatabaseGuid
,
1500 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1501 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1502 } else if (Status
!= EFI_NOT_FOUND
) {
1507 // Enroll the variable.
1509 Status
= gRT
->SetVariable(
1511 &gEfiImageSecurityDatabaseGuid
,
1516 if (EFI_ERROR (Status
)) {
1522 CloseFile (Private
->FileContext
->FHandle
);
1523 Private
->FileContext
->FHandle
= NULL
;
1524 Private
->FileContext
->FileName
= NULL
;
1526 if (Private
->SignatureGUID
!= NULL
) {
1527 FreePool (Private
->SignatureGUID
);
1528 Private
->SignatureGUID
= NULL
;
1535 if (mImageBase
!= NULL
) {
1536 FreePool (mImageBase
);
1544 Enroll signature into DB/DBX without KEK's authentication.
1545 The SignatureOwner GUID will be Private->SignatureGUID.
1547 @param[in] PrivateData The module's private data.
1548 @param[in] VariableName Variable name of signature database, must be
1549 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1551 @retval EFI_SUCCESS New signature enrolled successfully.
1552 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1553 @retval others Fail to enroll signature data.
1557 EnrollSignatureDatabase (
1558 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1559 IN CHAR16
*VariableName
1562 UINT16
* FilePostFix
;
1566 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1567 return EFI_INVALID_PARAMETER
;
1570 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
1571 if (EFI_ERROR (Status
)) {
1576 // Parse the file's postfix.
1578 NameLength
= StrLen (Private
->FileContext
->FileName
);
1579 if (NameLength
<= 4) {
1580 return EFI_INVALID_PARAMETER
;
1582 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1583 if (IsDerEncodeCertificate(FilePostFix
)) {
1585 // Supports DER-encoded X509 certificate.
1587 return EnrollX509toSigDB (Private
, VariableName
);
1590 return EnrollImageSignatureToSigDB (Private
, VariableName
);
1594 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1595 by GUID in the page for user to select and delete as needed.
1597 @param[in] PrivateData Module's private data.
1598 @param[in] VariableName The variable name of the vendor's signature database.
1599 @param[in] VendorGuid A unique identifier for the vendor.
1600 @param[in] LabelNumber Label number to insert opcodes.
1601 @param[in] FormId Form ID of current page.
1602 @param[in] QuestionIdBase Base question id of the signature list.
1604 @retval EFI_SUCCESS Success to update the signature list page
1605 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1610 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1611 IN CHAR16
*VariableName
,
1612 IN EFI_GUID
*VendorGuid
,
1613 IN UINT16 LabelNumber
,
1614 IN EFI_FORM_ID FormId
,
1615 IN EFI_QUESTION_ID QuestionIdBase
1622 VOID
*StartOpCodeHandle
;
1623 VOID
*EndOpCodeHandle
;
1624 EFI_IFR_GUID_LABEL
*StartLabel
;
1625 EFI_IFR_GUID_LABEL
*EndLabel
;
1628 EFI_SIGNATURE_LIST
*CertList
;
1629 EFI_SIGNATURE_DATA
*Cert
;
1630 UINT32 ItemDataSize
;
1632 EFI_STRING_ID GuidID
;
1639 StartOpCodeHandle
= NULL
;
1640 EndOpCodeHandle
= NULL
;
1643 // Initialize the container for dynamic opcodes.
1645 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1646 if (StartOpCodeHandle
== NULL
) {
1647 Status
= EFI_OUT_OF_RESOURCES
;
1651 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1652 if (EndOpCodeHandle
== NULL
) {
1653 Status
= EFI_OUT_OF_RESOURCES
;
1658 // Create Hii Extend Label OpCode.
1660 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1664 sizeof (EFI_IFR_GUID_LABEL
)
1666 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1667 StartLabel
->Number
= LabelNumber
;
1669 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1673 sizeof (EFI_IFR_GUID_LABEL
)
1675 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1676 EndLabel
->Number
= LABEL_END
;
1682 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1683 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1687 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1689 Status
= EFI_OUT_OF_RESOURCES
;
1693 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1694 if (EFI_ERROR (Status
)) {
1698 GuidStr
= AllocateZeroPool (100);
1699 if (GuidStr
== NULL
) {
1700 Status
= EFI_OUT_OF_RESOURCES
;
1705 // Enumerate all KEK pub data.
1707 ItemDataSize
= (UINT32
) DataSize
;
1708 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1711 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1713 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1714 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
1715 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1716 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
1717 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
1718 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
1719 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
1720 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
1723 // The signature type is not supported in current implementation.
1725 ItemDataSize
-= CertList
->SignatureListSize
;
1726 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1730 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1731 for (Index
= 0; Index
< CertCount
; Index
++) {
1732 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
1733 + sizeof (EFI_SIGNATURE_LIST
)
1734 + CertList
->SignatureHeaderSize
1735 + Index
* CertList
->SignatureSize
);
1737 // Display GUID and help
1739 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
1740 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
1741 HiiCreateCheckBoxOpCode (
1743 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
1748 EFI_IFR_FLAG_CALLBACK
,
1754 ItemDataSize
-= CertList
->SignatureListSize
;
1755 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1760 PrivateData
->HiiHandle
,
1761 &gSecureBootConfigFormSetGuid
,
1767 if (StartOpCodeHandle
!= NULL
) {
1768 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1771 if (EndOpCodeHandle
!= NULL
) {
1772 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1779 if (GuidStr
!= NULL
) {
1787 Delete a KEK entry from KEK database.
1789 @param[in] PrivateData Module's private data.
1790 @param[in] QuestionId Question id of the KEK item to delete.
1792 @retval EFI_SUCCESS Delete kek item successfully.
1793 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1797 DeleteKeyExchangeKey (
1798 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1799 IN EFI_QUESTION_ID QuestionId
1808 EFI_SIGNATURE_LIST
*CertList
;
1809 EFI_SIGNATURE_LIST
*NewCertList
;
1810 EFI_SIGNATURE_DATA
*Cert
;
1813 BOOLEAN IsKEKItemFound
;
1815 UINTN DeleteKekIndex
;
1823 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
1825 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
1826 if (EFI_ERROR (Status
)) {
1831 // Get original KEK variable.
1834 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
1835 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1839 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
1840 if (OldData
== NULL
) {
1841 Status
= EFI_OUT_OF_RESOURCES
;
1845 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
1846 if (EFI_ERROR(Status
)) {
1851 // Allocate space for new variable.
1853 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1855 Status
= EFI_OUT_OF_RESOURCES
;
1860 // Enumerate all KEK pub data and erasing the target item.
1862 IsKEKItemFound
= FALSE
;
1863 KekDataSize
= (UINT32
) DataSize
;
1864 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1867 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1868 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1869 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1870 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1871 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1872 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1873 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1874 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1875 for (Index
= 0; Index
< CertCount
; Index
++) {
1876 if (GuidIndex
== DeleteKekIndex
) {
1878 // Find it! Skip it!
1880 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1881 IsKEKItemFound
= TRUE
;
1884 // This item doesn't match. Copy it to the Data buffer.
1886 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
1887 Offset
+= CertList
->SignatureSize
;
1890 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1894 // This List doesn't match. Copy it to the Data buffer.
1896 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
1897 Offset
+= CertList
->SignatureListSize
;
1900 KekDataSize
-= CertList
->SignatureListSize
;
1901 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1904 if (!IsKEKItemFound
) {
1906 // Doesn't find the Kek Item!
1908 Status
= EFI_NOT_FOUND
;
1913 // Delete the Signature header if there is no signature in the list.
1915 KekDataSize
= Offset
;
1916 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1918 ZeroMem (OldData
, KekDataSize
);
1919 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1920 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1921 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1922 if (CertCount
!= 0) {
1923 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
1924 Offset
+= CertList
->SignatureListSize
;
1926 KekDataSize
-= CertList
->SignatureListSize
;
1927 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1931 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1932 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
1933 if (EFI_ERROR (Status
)) {
1934 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1939 Status
= gRT
->SetVariable(
1940 EFI_KEY_EXCHANGE_KEY_NAME
,
1941 &gEfiGlobalVariableGuid
,
1946 if (EFI_ERROR (Status
)) {
1947 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
1956 if (OldData
!= NULL
) {
1960 return UpdateDeletePage (
1962 EFI_KEY_EXCHANGE_KEY_NAME
,
1963 &gEfiGlobalVariableGuid
,
1965 FORMID_DELETE_KEK_FORM
,
1966 OPTION_DEL_KEK_QUESTION_ID
1971 Delete a signature entry from siganture database.
1973 @param[in] PrivateData Module's private data.
1974 @param[in] VariableName The variable name of the vendor's signature database.
1975 @param[in] VendorGuid A unique identifier for the vendor.
1976 @param[in] LabelNumber Label number to insert opcodes.
1977 @param[in] FormId Form ID of current page.
1978 @param[in] QuestionIdBase Base question id of the signature list.
1979 @param[in] DeleteIndex Signature index to delete.
1981 @retval EFI_SUCCESS Delete siganture successfully.
1982 @retval EFI_NOT_FOUND Can't find the signature item,
1983 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1987 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1988 IN CHAR16
*VariableName
,
1989 IN EFI_GUID
*VendorGuid
,
1990 IN UINT16 LabelNumber
,
1991 IN EFI_FORM_ID FormId
,
1992 IN EFI_QUESTION_ID QuestionIdBase
,
1993 IN UINTN DeleteIndex
2002 EFI_SIGNATURE_LIST
*CertList
;
2003 EFI_SIGNATURE_LIST
*NewCertList
;
2004 EFI_SIGNATURE_DATA
*Cert
;
2007 BOOLEAN IsItemFound
;
2008 UINT32 ItemDataSize
;
2017 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2018 if (EFI_ERROR (Status
)) {
2023 // Get original signature list data.
2026 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2027 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2031 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2032 if (OldData
== NULL
) {
2033 Status
= EFI_OUT_OF_RESOURCES
;
2037 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2038 if (EFI_ERROR(Status
)) {
2043 // Allocate space for new variable.
2045 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2047 Status
= EFI_OUT_OF_RESOURCES
;
2052 // Enumerate all signature data and erasing the target item.
2054 IsItemFound
= FALSE
;
2055 ItemDataSize
= (UINT32
) DataSize
;
2056 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2059 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2060 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2061 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2062 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2063 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)
2066 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2068 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2069 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2070 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2071 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2072 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2073 for (Index
= 0; Index
< CertCount
; Index
++) {
2074 if (GuidIndex
== DeleteIndex
) {
2076 // Find it! Skip it!
2078 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2082 // This item doesn't match. Copy it to the Data buffer.
2084 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2085 Offset
+= CertList
->SignatureSize
;
2088 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2092 // This List doesn't match. Just copy it to the Data buffer.
2094 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2095 Offset
+= CertList
->SignatureListSize
;
2098 ItemDataSize
-= CertList
->SignatureListSize
;
2099 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2104 // Doesn't find the signature Item!
2106 Status
= EFI_NOT_FOUND
;
2111 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2113 ItemDataSize
= Offset
;
2114 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2116 ZeroMem (OldData
, ItemDataSize
);
2117 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2118 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2119 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
2120 if (CertCount
!= 0) {
2121 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2122 Offset
+= CertList
->SignatureListSize
;
2124 ItemDataSize
-= CertList
->SignatureListSize
;
2125 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2129 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2130 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2131 if (EFI_ERROR (Status
)) {
2132 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2137 Status
= gRT
->SetVariable(
2144 if (EFI_ERROR (Status
)) {
2145 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2154 if (OldData
!= NULL
) {
2158 return UpdateDeletePage (
2169 This function extracts configuration from variable.
2171 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2175 SecureBootExtractConfigFromVariable (
2176 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2179 UINT8
*SecureBootEnable
;
2181 UINT8
*SecureBootMode
;
2183 SecureBootEnable
= NULL
;
2185 SecureBootMode
= NULL
;
2188 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2191 ConfigData
->AttemptSecureBoot
= FALSE
;
2192 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2193 if (SecureBootEnable
== NULL
) {
2194 ConfigData
->HideSecureBoot
= TRUE
;
2196 ConfigData
->HideSecureBoot
= FALSE
;
2197 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
2198 ConfigData
->AttemptSecureBoot
= TRUE
;
2203 // If it is Physical Presence User, set the PhysicalPresent to true.
2205 if (UserPhysicalPresent()) {
2206 ConfigData
->PhysicalPresent
= TRUE
;
2208 ConfigData
->PhysicalPresent
= FALSE
;
2212 // If there is no PK then the Delete Pk button will be gray.
2214 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2215 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2216 ConfigData
->HasPk
= FALSE
;
2218 ConfigData
->HasPk
= TRUE
;
2222 // Get the SecureBootMode from CustomMode variable.
2224 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2225 if (SecureBootMode
== NULL
) {
2226 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2228 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2231 if (SecureBootEnable
!= NULL
) {
2232 FreePool (SecureBootEnable
);
2234 if (SetupMode
!= NULL
) {
2235 FreePool (SetupMode
);
2237 if (SecureBootMode
!= NULL
) {
2238 FreePool (SecureBootMode
);
2243 This function allows a caller to extract the current configuration for one
2244 or more named elements from the target driver.
2246 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2247 @param[in] Request A null-terminated Unicode string in
2248 <ConfigRequest> format.
2249 @param[out] Progress On return, points to a character in the Request
2250 string. Points to the string's null terminator if
2251 request was successful. Points to the most recent
2252 '&' before the first failing name/value pair (or
2253 the beginning of the string if the failure is in
2254 the first name/value pair) if the request was not
2256 @param[out] Results A null-terminated Unicode string in
2257 <ConfigAltResp> format which has all values filled
2258 in for the names in the Request string. String to
2259 be allocated by the called function.
2261 @retval EFI_SUCCESS The Results is filled with the requested values.
2262 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2263 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2264 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2270 SecureBootExtractConfig (
2271 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2272 IN CONST EFI_STRING Request
,
2273 OUT EFI_STRING
*Progress
,
2274 OUT EFI_STRING
*Results
2280 SECUREBOOT_CONFIGURATION Configuration
;
2281 EFI_STRING ConfigRequest
;
2282 EFI_STRING ConfigRequestHdr
;
2283 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2284 BOOLEAN AllocatedRequest
;
2287 if (Progress
== NULL
|| Results
== NULL
) {
2288 return EFI_INVALID_PARAMETER
;
2291 AllocatedRequest
= FALSE
;
2292 ConfigRequestHdr
= NULL
;
2293 ConfigRequest
= NULL
;
2297 ZeroMem (&Configuration
, sizeof (Configuration
));
2298 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2299 *Progress
= Request
;
2301 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2302 return EFI_NOT_FOUND
;
2306 // Get Configuration from Variable.
2308 SecureBootExtractConfigFromVariable (&Configuration
);
2311 // Update current secure boot state.
2313 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2314 if (SecureBoot
!= NULL
&& *SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2315 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
2317 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
2319 if (SecureBoot
!= NULL
) {
2320 FreePool (SecureBoot
);
2323 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2324 ConfigRequest
= Request
;
2325 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2327 // Request is set to NULL or OFFSET is NULL, construct full request string.
2329 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2330 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2332 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2333 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2334 ConfigRequest
= AllocateZeroPool (Size
);
2335 ASSERT (ConfigRequest
!= NULL
);
2336 AllocatedRequest
= TRUE
;
2337 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2338 FreePool (ConfigRequestHdr
);
2339 ConfigRequestHdr
= NULL
;
2342 Status
= gHiiConfigRouting
->BlockToConfig (
2345 (UINT8
*) &Configuration
,
2352 // Free the allocated config request string.
2354 if (AllocatedRequest
) {
2355 FreePool (ConfigRequest
);
2359 // Set Progress string to the original request string.
2361 if (Request
== NULL
) {
2363 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2364 *Progress
= Request
+ StrLen (Request
);
2371 This function processes the results of changes in configuration.
2373 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2374 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2376 @param[out] Progress A pointer to a string filled in with the offset of
2377 the most recent '&' before the first failing
2378 name/value pair (or the beginning of the string if
2379 the failure is in the first name/value pair) or
2380 the terminating NULL if all was successful.
2382 @retval EFI_SUCCESS The Results is processed successfully.
2383 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2384 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2390 SecureBootRouteConfig (
2391 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2392 IN CONST EFI_STRING Configuration
,
2393 OUT EFI_STRING
*Progress
2396 UINT8
*SecureBootEnable
;
2397 SECUREBOOT_CONFIGURATION IfrNvData
;
2401 if (Configuration
== NULL
|| Progress
== NULL
) {
2402 return EFI_INVALID_PARAMETER
;
2405 *Progress
= Configuration
;
2406 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2407 return EFI_NOT_FOUND
;
2410 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2411 Status
= gHiiConfigRouting
->ConfigToBlock (
2414 (UINT8
*)&IfrNvData
,
2418 if (EFI_ERROR (Status
)) {
2423 // Store Buffer Storage back to EFI variable if needed
2425 SecureBootEnable
= NULL
;
2426 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2427 if (NULL
!= SecureBootEnable
) {
2428 FreePool (SecureBootEnable
);
2429 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
2430 if (EFI_ERROR (Status
)) {
2435 *Progress
= Configuration
+ StrLen (Configuration
);
2440 This function is called to provide results data to the driver.
2442 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2443 @param[in] Action Specifies the type of action taken by the browser.
2444 @param[in] QuestionId A unique value which is sent to the original
2445 exporting driver so that it can identify the type
2447 @param[in] Type The type of value for the question.
2448 @param[in] Value A pointer to the data being sent to the original
2450 @param[out] ActionRequest On return, points to the action requested by the
2453 @retval EFI_SUCCESS The callback successfully handled the action.
2454 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2455 variable and its data.
2456 @retval EFI_DEVICE_ERROR The variable could not be saved.
2457 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2463 SecureBootCallback (
2464 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2465 IN EFI_BROWSER_ACTION Action
,
2466 IN EFI_QUESTION_ID QuestionId
,
2468 IN EFI_IFR_TYPE_VALUE
*Value
,
2469 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2474 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
2476 SECUREBOOT_CONFIGURATION
*IfrNvData
;
2478 UINT8
*SecureBootEnable
;
2479 UINT8
*SecureBootMode
;
2481 CHAR16 PromptString
[100];
2483 SecureBootEnable
= NULL
;
2484 SecureBootMode
= NULL
;
2487 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
2488 return EFI_INVALID_PARAMETER
;
2491 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
2492 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
2493 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
2494 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
2495 return EFI_UNSUPPORTED
;
2498 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2501 // Retrieve uncommitted data from Browser
2503 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2504 IfrNvData
= AllocateZeroPool (BufferSize
);
2505 if (IfrNvData
== NULL
) {
2506 return EFI_OUT_OF_RESOURCES
;
2509 Status
= EFI_SUCCESS
;
2511 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2513 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2515 switch (QuestionId
) {
2516 case KEY_SECURE_BOOT_ENABLE
:
2517 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2518 if (NULL
!= SecureBootEnable
) {
2519 FreePool (SecureBootEnable
);
2520 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
2522 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2524 L
"Only Physical Presence User could disable secure boot!",
2527 Status
= EFI_UNSUPPORTED
;
2530 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2532 L
"Configuration changed, please reset the platform to take effect!",
2539 case KEY_SECURE_BOOT_OPTION
:
2540 FreeMenu (&DirectoryMenu
);
2541 FreeMenu (&FsOptionMenu
);
2544 case KEY_SECURE_BOOT_KEK_OPTION
:
2545 case KEY_SECURE_BOOT_DB_OPTION
:
2546 case KEY_SECURE_BOOT_DBX_OPTION
:
2548 // Clear Signature GUID.
2550 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
2551 if (Private
->SignatureGUID
== NULL
) {
2552 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
2553 if (Private
->SignatureGUID
== NULL
) {
2554 return EFI_OUT_OF_RESOURCES
;
2558 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
2559 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
2560 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
2561 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
2563 LabelId
= FORMID_ENROLL_KEK_FORM
;
2567 // Refresh selected file.
2569 CleanUpPage (LabelId
, Private
);
2572 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
2573 case FORMID_ENROLL_KEK_FORM
:
2574 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
2575 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
2576 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
2577 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
2578 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
2579 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
2580 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
2581 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
2583 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
2586 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2587 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
2588 UpdateFileExplorer (Private
, 0);
2591 case KEY_SECURE_BOOT_DELETE_PK
:
2594 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2596 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
2597 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
2600 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
2601 Status
= DeletePlatformKey ();
2602 if (EFI_ERROR (Status
)) {
2604 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2606 L
"Only Physical Presence User could delete PK in custom mode!",
2614 case KEY_DELETE_KEK
:
2617 EFI_KEY_EXCHANGE_KEY_NAME
,
2618 &gEfiGlobalVariableGuid
,
2620 FORMID_DELETE_KEK_FORM
,
2621 OPTION_DEL_KEK_QUESTION_ID
2625 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
2628 EFI_IMAGE_SECURITY_DATABASE
,
2629 &gEfiImageSecurityDatabaseGuid
,
2631 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2632 OPTION_DEL_DB_QUESTION_ID
2636 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
2639 EFI_IMAGE_SECURITY_DATABASE1
,
2640 &gEfiImageSecurityDatabaseGuid
,
2642 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2643 OPTION_DEL_DBX_QUESTION_ID
2648 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
2649 Status
= EnrollKeyExchangeKey (Private
);
2650 if (EFI_ERROR (Status
)) {
2652 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2654 L
"ERROR: Unsupported file type!",
2655 L
"Only supports DER-encoded X509 certificate",
2661 case KEY_VALUE_SAVE_AND_EXIT_DB
:
2662 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
2663 if (EFI_ERROR (Status
)) {
2665 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2667 L
"ERROR: Unsupported file type!",
2668 L
"Only supports DER-encoded X509 certificate and executable EFI image",
2674 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
2675 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
2676 if (EFI_ERROR (Status
)) {
2678 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2680 L
"ERROR: Unsupported file type!",
2681 L
"Only supports DER-encoded X509 certificate and executable EFI image",
2688 if (QuestionId
>= FILE_OPTION_OFFSET
) {
2689 UpdateFileExplorer (Private
, QuestionId
);
2690 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
2691 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2692 DeleteKeyExchangeKey (Private
, QuestionId
);
2693 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
2694 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2697 EFI_IMAGE_SECURITY_DATABASE
,
2698 &gEfiImageSecurityDatabaseGuid
,
2700 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2701 OPTION_DEL_DB_QUESTION_ID
,
2702 QuestionId
- OPTION_DEL_DB_QUESTION_ID
2704 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
2705 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2708 EFI_IMAGE_SECURITY_DATABASE1
,
2709 &gEfiImageSecurityDatabaseGuid
,
2711 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2712 OPTION_DEL_DBX_QUESTION_ID
,
2713 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
2718 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2719 switch (QuestionId
) {
2720 case KEY_SECURE_BOOT_ENABLE
:
2721 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2723 case KEY_VALUE_SAVE_AND_EXIT_PK
:
2724 Status
= EnrollPlatformKey (Private
);
2725 if (EFI_ERROR (Status
)) {
2728 sizeof (PromptString
),
2729 L
"Only DER encoded certificate file (%s) is supported.",
2733 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2735 L
"ERROR: Unsupported file type!",
2740 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
2744 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
2745 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
2746 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
2747 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
2748 if (Private
->FileContext
->FHandle
!= NULL
) {
2749 CloseFile (Private
->FileContext
->FHandle
);
2750 Private
->FileContext
->FHandle
= NULL
;
2751 Private
->FileContext
->FileName
= NULL
;
2754 if (Private
->SignatureGUID
!= NULL
) {
2755 FreePool (Private
->SignatureGUID
);
2756 Private
->SignatureGUID
= NULL
;
2758 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2761 case KEY_SECURE_BOOT_MODE
:
2762 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2763 if (NULL
!= SecureBootMode
) {
2764 Status
= gRT
->SetVariable (
2765 EFI_CUSTOM_MODE_NAME
,
2766 &gEfiCustomModeEnableGuid
,
2767 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2771 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2772 IfrNvData
->SecureBootMode
= Value
->u8
;
2773 FreePool (SecureBootMode
);
2777 case KEY_SECURE_BOOT_KEK_GUID
:
2778 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
2779 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
2780 ASSERT (Private
->SignatureGUID
!= NULL
);
2781 Status
= StringToGuid (
2782 IfrNvData
->SignatureGuid
,
2783 StrLen (IfrNvData
->SignatureGuid
),
2784 Private
->SignatureGUID
2786 if (EFI_ERROR (Status
)) {
2790 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2793 case KEY_SECURE_BOOT_DELETE_PK
:
2794 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2795 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2796 IfrNvData
->DeletePk
= TRUE
;
2797 IfrNvData
->HasPk
= FALSE
;
2798 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2800 IfrNvData
->DeletePk
= FALSE
;
2801 IfrNvData
->HasPk
= TRUE
;
2802 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2804 if (SetupMode
!= NULL
) {
2805 FreePool (SetupMode
);
2809 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
2810 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
2811 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2812 if (SecureBootEnable
== NULL
) {
2813 IfrNvData
->HideSecureBoot
= TRUE
;
2815 FreePool (SecureBootEnable
);
2816 IfrNvData
->HideSecureBoot
= FALSE
;
2818 Value
->b
= IfrNvData
->HideSecureBoot
;
2820 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
2822 // Force the platform back to Standard Mode once user leave the setup screen.
2824 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2825 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
2826 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2827 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
2829 if (SecureBootMode
!= NULL
) {
2830 FreePool (SecureBootMode
);
2834 if (!EFI_ERROR (Status
)) {
2835 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2836 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2838 FreePool (IfrNvData
);
2844 This function publish the SecureBoot configuration Form.
2846 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2848 @retval EFI_SUCCESS HII Form is installed successfully.
2849 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2850 @retval Others Other errors as indicated.
2854 InstallSecureBootConfigForm (
2855 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2859 EFI_HII_HANDLE HiiHandle
;
2860 EFI_HANDLE DriverHandle
;
2861 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2863 DriverHandle
= NULL
;
2864 ConfigAccess
= &PrivateData
->ConfigAccess
;
2865 Status
= gBS
->InstallMultipleProtocolInterfaces (
2867 &gEfiDevicePathProtocolGuid
,
2868 &mSecureBootHiiVendorDevicePath
,
2869 &gEfiHiiConfigAccessProtocolGuid
,
2873 if (EFI_ERROR (Status
)) {
2877 PrivateData
->DriverHandle
= DriverHandle
;
2880 // Publish the HII package list
2882 HiiHandle
= HiiAddPackages (
2883 &gSecureBootConfigFormSetGuid
,
2885 SecureBootConfigDxeStrings
,
2886 SecureBootConfigBin
,
2889 if (HiiHandle
== NULL
) {
2890 gBS
->UninstallMultipleProtocolInterfaces (
2892 &gEfiDevicePathProtocolGuid
,
2893 &mSecureBootHiiVendorDevicePath
,
2894 &gEfiHiiConfigAccessProtocolGuid
,
2898 return EFI_OUT_OF_RESOURCES
;
2901 PrivateData
->HiiHandle
= HiiHandle
;
2903 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
2904 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
2906 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
2907 UninstallSecureBootConfigForm (PrivateData
);
2908 return EFI_OUT_OF_RESOURCES
;
2911 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
2912 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2914 InitializeListHead (&FsOptionMenu
.Head
);
2915 InitializeListHead (&DirectoryMenu
.Head
);
2918 // Init OpCode Handle and Allocate space for creation of Buffer
2920 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2921 if (mStartOpCodeHandle
== NULL
) {
2922 UninstallSecureBootConfigForm (PrivateData
);
2923 return EFI_OUT_OF_RESOURCES
;
2926 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2927 if (mEndOpCodeHandle
== NULL
) {
2928 UninstallSecureBootConfigForm (PrivateData
);
2929 return EFI_OUT_OF_RESOURCES
;
2933 // Create Hii Extend Label OpCode as the start opcode
2935 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2939 sizeof (EFI_IFR_GUID_LABEL
)
2941 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2944 // Create Hii Extend Label OpCode as the end opcode
2946 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2950 sizeof (EFI_IFR_GUID_LABEL
)
2952 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2953 mEndLabel
->Number
= LABEL_END
;
2959 This function removes SecureBoot configuration Form.
2961 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2965 UninstallSecureBootConfigForm (
2966 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2970 // Uninstall HII package list
2972 if (PrivateData
->HiiHandle
!= NULL
) {
2973 HiiRemovePackages (PrivateData
->HiiHandle
);
2974 PrivateData
->HiiHandle
= NULL
;
2978 // Uninstall HII Config Access Protocol
2980 if (PrivateData
->DriverHandle
!= NULL
) {
2981 gBS
->UninstallMultipleProtocolInterfaces (
2982 PrivateData
->DriverHandle
,
2983 &gEfiDevicePathProtocolGuid
,
2984 &mSecureBootHiiVendorDevicePath
,
2985 &gEfiHiiConfigAccessProtocolGuid
,
2986 &PrivateData
->ConfigAccess
,
2989 PrivateData
->DriverHandle
= NULL
;
2992 if (PrivateData
->SignatureGUID
!= NULL
) {
2993 FreePool (PrivateData
->SignatureGUID
);
2996 if (PrivateData
->MenuEntry
!= NULL
) {
2997 FreePool (PrivateData
->MenuEntry
);
3000 if (PrivateData
->FileContext
!= NULL
) {
3001 FreePool (PrivateData
->FileContext
);
3004 FreePool (PrivateData
);
3006 FreeMenu (&DirectoryMenu
);
3007 FreeMenu (&FsOptionMenu
);
3009 if (mStartOpCodeHandle
!= NULL
) {
3010 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
3013 if (mEndOpCodeHandle
!= NULL
) {
3014 HiiFreeOpCodeHandle (mEndOpCodeHandle
);