2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "SecureBootConfigImpl.h"
11 #include <Protocol/HiiPopup.h>
12 #include <Library/BaseCryptLib.h>
13 #include <Library/SecureBootVariableLib.h>
14 #include <Library/SecureBootVariableProvisionLib.h>
16 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
18 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
19 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
21 SecureBootExtractConfig
,
22 SecureBootRouteConfig
,
27 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
33 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
34 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
37 SECUREBOOT_CONFIG_FORM_SET_GUID
41 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 (UINT8
) (END_DEVICE_PATH_LENGTH
),
44 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
50 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
53 // OID ASN.1 Value for Hash Algorithms
55 UINT8 mHashOidValue
[] = {
56 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
57 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
64 HASH_TABLE mHash
[] = {
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, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
68 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
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 // Prompt strings during certificate enrollment.
99 CHAR16
* mX509EnrollPromptTitle
[] = {
101 L
"ERROR: Unsupported file type!",
102 L
"ERROR: Unsupported certificate!",
105 CHAR16
* mX509EnrollPromptString
[] = {
107 L
"Only DER encoded certificate file (*.cer/der/crt) is supported.",
108 L
"Public key length should be equal to or greater than 2048 bits.",
112 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
115 This code cleans up enrolled file by closing file & free related resources attached to
118 @param[in] FileContext FileContext cached in SecureBootConfig driver
123 IN SECUREBOOT_FILE_CONTEXT
*FileContext
126 if (FileContext
->FHandle
!= NULL
) {
127 CloseFile (FileContext
->FHandle
);
128 FileContext
->FHandle
= NULL
;
131 if (FileContext
->FileName
!= NULL
){
132 FreePool(FileContext
->FileName
);
133 FileContext
->FileName
= NULL
;
135 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
140 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
142 @param[in] FileSuffix The suffix of the input certificate file
144 @retval TRUE It's a DER-encoded certificate.
145 @retval FALSE It's NOT a DER-encoded certificate.
149 IsDerEncodeCertificate (
150 IN CONST CHAR16
*FileSuffix
154 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
155 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
163 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
164 The function reads file content but won't open/close given FileHandle.
166 @param[in] FileHandle The FileHandle to be checked
168 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
169 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
173 IsAuthentication2Format (
174 IN EFI_FILE_HANDLE FileHandle
178 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
179 BOOLEAN IsAuth2Format
;
181 IsAuth2Format
= FALSE
;
184 // Read the whole file content
186 Status
= ReadFileContent(
188 (VOID
**) &mImageBase
,
192 if (EFI_ERROR (Status
)) {
196 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
197 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
201 if (CompareGuid(&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
202 IsAuth2Format
= TRUE
;
207 // Do not close File. simply check file content
209 if (mImageBase
!= NULL
) {
210 FreePool (mImageBase
);
214 return IsAuth2Format
;
218 Set Secure Boot option into variable space.
220 @param[in] VarValue The option of Secure Boot.
222 @retval EFI_SUCCESS The operation is finished successfully.
223 @retval Others Other errors as indicated.
227 SaveSecureBootVariable (
233 Status
= gRT
->SetVariable (
234 EFI_SECURE_BOOT_ENABLE_NAME
,
235 &gEfiSecureBootEnableDisableGuid
,
236 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
244 This code checks if the encode type and key strength of X.509
245 certificate is qualified.
247 @param[in] X509FileContext FileContext of X.509 certificate storing
249 @param[out] Error Error type checked in the certificate.
251 @return EFI_SUCCESS The certificate checked successfully.
252 @return EFI_INVALID_PARAMETER The parameter is invalid.
253 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
257 CheckX509Certificate (
258 IN SECUREBOOT_FILE_CONTEXT
* X509FileContext
,
259 OUT ENROLL_KEY_ERROR
* Error
270 if (X509FileContext
->FileName
== NULL
) {
271 *Error
= Unsupported_Type
;
272 return EFI_INVALID_PARAMETER
;
281 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
283 NameLength
= StrLen (X509FileContext
->FileName
);
284 if (NameLength
<= 4) {
285 DEBUG ((DEBUG_ERROR
, "Wrong X509 NameLength\n"));
286 *Error
= Unsupported_Type
;
287 return EFI_INVALID_PARAMETER
;
289 FilePostFix
= X509FileContext
->FileName
+ NameLength
- 4;
290 if (!IsDerEncodeCertificate (FilePostFix
)) {
291 DEBUG ((DEBUG_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix
));
292 *Error
= Unsupported_Type
;
293 return EFI_INVALID_PARAMETER
;
295 DEBUG ((DEBUG_INFO
, "FileName= %s\n", X509FileContext
->FileName
));
296 DEBUG ((DEBUG_INFO
, "FilePostFix = %s\n", FilePostFix
));
299 // Read the certificate file content
301 Status
= ReadFileContent (X509FileContext
->FHandle
, (VOID
**) &X509Data
, &X509DataSize
, 0);
302 if (EFI_ERROR (Status
)) {
303 DEBUG ((DEBUG_ERROR
, "Error occured while reading the file.\n"));
308 // Parse the public key context.
310 if (RsaGetPublicKeyFromX509 (X509Data
, X509DataSize
, &X509PubKey
) == FALSE
) {
311 DEBUG ((DEBUG_ERROR
, "Error occured while parsing the pubkey from certificate.\n"));
312 Status
= EFI_INVALID_PARAMETER
;
313 *Error
= Unsupported_Type
;
318 // Parse Module size of public key using interface provided by CryptoPkg, which is
319 // actually the size of public key.
321 if (X509PubKey
!= NULL
) {
322 RsaGetKey (X509PubKey
, RsaKeyN
, NULL
, &PubKeyModSize
);
323 if (PubKeyModSize
< CER_PUBKEY_MIN_SIZE
) {
324 DEBUG ((DEBUG_ERROR
, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
325 Status
= EFI_INVALID_PARAMETER
;
326 *Error
= Unqualified_Key
;
328 RsaFree (X509PubKey
);
332 if (X509Data
!= NULL
) {
340 Generate the PK signature list from the X509 Certificate storing file (.cer)
342 @param[in] X509File FileHandle of X509 Certificate storing file.
343 @param[out] PkCert Point to the data buffer to store the signature list.
345 @return EFI_UNSUPPORTED Unsupported Key Length.
346 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
350 CreatePkX509SignatureList (
351 IN EFI_FILE_HANDLE X509File
,
352 OUT EFI_SIGNATURE_LIST
**PkCert
358 EFI_SIGNATURE_DATA
*PkCertData
;
364 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
365 if (EFI_ERROR (Status
)) {
368 ASSERT (X509Data
!= NULL
);
371 // Allocate space for PK certificate list and initialize it.
372 // Create PK database entry with SignatureHeaderSize equals 0.
374 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
375 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
378 if (*PkCert
== NULL
) {
379 Status
= EFI_OUT_OF_RESOURCES
;
383 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
384 + sizeof(EFI_SIGNATURE_DATA
) - 1
386 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
387 (*PkCert
)->SignatureHeaderSize
= 0;
388 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
389 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
390 + sizeof(EFI_SIGNATURE_LIST
)
391 + (*PkCert
)->SignatureHeaderSize
);
392 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
394 // Fill the PK database with PKpub data from X509 certificate file.
396 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
400 if (X509Data
!= NULL
) {
404 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
413 Enroll new PK into the System without original PK's authentication.
415 The SignatureOwner GUID will be the same with PK's vendorguid.
417 @param[in] PrivateData The module's private data.
419 @retval EFI_SUCCESS New PK enrolled successfully.
420 @retval EFI_INVALID_PARAMETER The parameter is invalid.
421 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
426 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
432 EFI_SIGNATURE_LIST
*PkCert
;
436 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
437 if (EFI_ERROR (Status
)) {
442 // Prase the selected PK file and generate PK certificate list.
444 Status
= CreatePkX509SignatureList (
445 Private
->FileContext
->FHandle
,
448 if (EFI_ERROR (Status
)) {
451 ASSERT (PkCert
!= NULL
);
454 // Set Platform Key variable.
456 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
457 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
458 DataSize
= PkCert
->SignatureListSize
;
459 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
460 if (EFI_ERROR (Status
)) {
461 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
465 Status
= gRT
->SetVariable(
466 EFI_PLATFORM_KEY_NAME
,
467 &gEfiGlobalVariableGuid
,
472 if (EFI_ERROR (Status
)) {
473 if (Status
== EFI_OUT_OF_RESOURCES
) {
474 DEBUG ((DEBUG_ERROR
, "Enroll PK failed with out of resource.\n"));
481 if (PkCert
!= NULL
) {
485 CloseEnrolledFile(Private
->FileContext
);
491 Enroll a new KEK item from public key storing file (*.pbk).
493 @param[in] PrivateData The module's private data.
495 @retval EFI_SUCCESS New KEK enrolled successfully.
496 @retval EFI_INVALID_PARAMETER The parameter is invalid.
497 @retval EFI_UNSUPPORTED Unsupported command.
498 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
503 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
509 EFI_SIGNATURE_LIST
*KekSigList
;
512 CPL_KEY_INFO
*KeyInfo
;
513 EFI_SIGNATURE_DATA
*KEKSigData
;
514 UINTN KekSigListSize
;
529 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
530 // First, We have to parse out public key data from the pbk key file.
532 Status
= ReadFileContent (
533 Private
->FileContext
->FHandle
,
538 if (EFI_ERROR (Status
)) {
541 ASSERT (KeyBlob
!= NULL
);
542 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
543 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
544 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
545 Status
= EFI_UNSUPPORTED
;
550 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
552 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
553 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
554 if (KeyBuffer
== NULL
) {
555 Status
= EFI_OUT_OF_RESOURCES
;
559 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
560 KeyLenInBytes
/ sizeof (UINTN
),
564 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
567 // Form an new EFI_SIGNATURE_LIST.
569 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
570 + sizeof(EFI_SIGNATURE_DATA
) - 1
571 + WIN_CERT_UEFI_RSA2048_SIZE
;
573 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
574 if (KekSigList
== NULL
) {
575 Status
= EFI_OUT_OF_RESOURCES
;
579 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
580 + sizeof(EFI_SIGNATURE_DATA
) - 1
581 + WIN_CERT_UEFI_RSA2048_SIZE
;
582 KekSigList
->SignatureHeaderSize
= 0;
583 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
584 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
586 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
587 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
589 KEKSigData
->SignatureData
,
590 KeyBlob
+ sizeof(CPL_KEY_INFO
),
591 WIN_CERT_UEFI_RSA2048_SIZE
595 // Check if KEK entry has been already existed.
596 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
597 // new KEK to original variable.
599 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
600 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
601 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
602 if (EFI_ERROR (Status
)) {
603 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
607 Status
= gRT
->GetVariable(
608 EFI_KEY_EXCHANGE_KEY_NAME
,
609 &gEfiGlobalVariableGuid
,
614 if (Status
== EFI_BUFFER_TOO_SMALL
) {
615 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
616 } else if (Status
!= EFI_NOT_FOUND
) {
621 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
623 Status
= gRT
->SetVariable(
624 EFI_KEY_EXCHANGE_KEY_NAME
,
625 &gEfiGlobalVariableGuid
,
630 if (EFI_ERROR (Status
)) {
636 CloseEnrolledFile(Private
->FileContext
);
638 if (Private
->SignatureGUID
!= NULL
) {
639 FreePool (Private
->SignatureGUID
);
640 Private
->SignatureGUID
= NULL
;
643 if (KeyBlob
!= NULL
) {
646 if (KeyBuffer
!= NULL
) {
647 FreePool (KeyBuffer
);
649 if (KekSigList
!= NULL
) {
650 FreePool (KekSigList
);
657 Enroll a new KEK item from X509 certificate file.
659 @param[in] PrivateData The module's private data.
661 @retval EFI_SUCCESS New X509 is enrolled successfully.
662 @retval EFI_INVALID_PARAMETER The parameter is invalid.
663 @retval EFI_UNSUPPORTED Unsupported command.
664 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
669 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
675 EFI_SIGNATURE_DATA
*KEKSigData
;
676 EFI_SIGNATURE_LIST
*KekSigList
;
678 UINTN KekSigListSize
;
688 Status
= ReadFileContent (
689 Private
->FileContext
->FHandle
,
694 if (EFI_ERROR (Status
)) {
697 ASSERT (X509Data
!= NULL
);
699 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
700 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
701 if (KekSigList
== NULL
) {
702 Status
= EFI_OUT_OF_RESOURCES
;
707 // Fill Certificate Database parameters.
709 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
710 KekSigList
->SignatureHeaderSize
= 0;
711 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
712 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
714 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
715 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
716 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
719 // Check if KEK been already existed.
720 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
721 // new kek to original variable
723 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
724 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
725 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
726 if (EFI_ERROR (Status
)) {
727 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
731 Status
= gRT
->GetVariable(
732 EFI_KEY_EXCHANGE_KEY_NAME
,
733 &gEfiGlobalVariableGuid
,
738 if (Status
== EFI_BUFFER_TOO_SMALL
) {
739 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
740 } else if (Status
!= EFI_NOT_FOUND
) {
744 Status
= gRT
->SetVariable(
745 EFI_KEY_EXCHANGE_KEY_NAME
,
746 &gEfiGlobalVariableGuid
,
751 if (EFI_ERROR (Status
)) {
757 CloseEnrolledFile(Private
->FileContext
);
759 if (Private
->SignatureGUID
!= NULL
) {
760 FreePool (Private
->SignatureGUID
);
761 Private
->SignatureGUID
= NULL
;
764 if (KekSigList
!= NULL
) {
765 FreePool (KekSigList
);
772 Enroll new KEK into the System without PK's authentication.
773 The SignatureOwner GUID will be Private->SignatureGUID.
775 @param[in] PrivateData The module's private data.
777 @retval EFI_SUCCESS New KEK enrolled successful.
778 @retval EFI_INVALID_PARAMETER The parameter is invalid.
779 @retval others Fail to enroll KEK data.
783 EnrollKeyExchangeKey (
784 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
791 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
792 return EFI_INVALID_PARAMETER
;
795 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
796 if (EFI_ERROR (Status
)) {
801 // Parse the file's postfix. Supports DER-encoded X509 certificate,
802 // and .pbk as RSA public key file.
804 NameLength
= StrLen (Private
->FileContext
->FileName
);
805 if (NameLength
<= 4) {
806 return EFI_INVALID_PARAMETER
;
808 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
809 if (IsDerEncodeCertificate(FilePostFix
)) {
810 return EnrollX509ToKek (Private
);
811 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
812 return EnrollRsa2048ToKek (Private
);
815 // File type is wrong, simply close it
817 CloseEnrolledFile(Private
->FileContext
);
819 return EFI_INVALID_PARAMETER
;
824 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
825 KEK's authentication.
827 @param[in] PrivateData The module's private data.
828 @param[in] VariableName Variable name of signature database, must be
829 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
831 @retval EFI_SUCCESS New X509 is enrolled successfully.
832 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
837 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
838 IN CHAR16
*VariableName
844 EFI_SIGNATURE_LIST
*SigDBCert
;
845 EFI_SIGNATURE_DATA
*SigDBCertData
;
856 SigDBCertData
= NULL
;
859 Status
= ReadFileContent (
860 Private
->FileContext
->FHandle
,
865 if (EFI_ERROR (Status
)) {
868 ASSERT (X509Data
!= NULL
);
870 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
872 Data
= AllocateZeroPool (SigDBSize
);
874 Status
= EFI_OUT_OF_RESOURCES
;
879 // Fill Certificate Database parameters.
881 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
882 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
883 SigDBCert
->SignatureHeaderSize
= 0;
884 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
885 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
887 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
888 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
889 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
892 // Check if signature database entry has been already existed.
893 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
894 // new signature data to original variable
896 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
897 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
898 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
899 if (EFI_ERROR (Status
)) {
900 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
904 Status
= gRT
->GetVariable(
906 &gEfiImageSecurityDatabaseGuid
,
911 if (Status
== EFI_BUFFER_TOO_SMALL
) {
912 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
913 } else if (Status
!= EFI_NOT_FOUND
) {
917 Status
= gRT
->SetVariable(
919 &gEfiImageSecurityDatabaseGuid
,
924 if (EFI_ERROR (Status
)) {
930 CloseEnrolledFile(Private
->FileContext
);
932 if (Private
->SignatureGUID
!= NULL
) {
933 FreePool (Private
->SignatureGUID
);
934 Private
->SignatureGUID
= NULL
;
941 if (X509Data
!= NULL
) {
949 Check whether signature is in specified database.
951 @param[in] VariableName Name of database variable that is searched in.
952 @param[in] Signature Pointer to signature that is searched for.
953 @param[in] SignatureSize Size of Signature.
955 @return TRUE Found the signature in the variable database.
956 @return FALSE Not found the signature in the variable database.
960 IsSignatureFoundInDatabase (
961 IN CHAR16
*VariableName
,
963 IN UINTN SignatureSize
967 EFI_SIGNATURE_LIST
*CertList
;
968 EFI_SIGNATURE_DATA
*Cert
;
976 // Read signature database variable.
981 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
982 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
986 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
991 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
992 if (EFI_ERROR (Status
)) {
997 // Enumerate all signature data in SigDB to check if signature exists for executable.
999 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1000 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1001 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1002 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1003 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1004 for (Index
= 0; Index
< CertCount
; Index
++) {
1005 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1007 // Find the signature in database.
1012 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1020 DataSize
-= CertList
->SignatureListSize
;
1021 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1033 Calculate the hash of a certificate data with the specified hash algorithm.
1035 @param[in] CertData The certificate data to be hashed.
1036 @param[in] CertSize The certificate size in bytes.
1037 @param[in] HashAlg The specified hash algorithm.
1038 @param[out] CertHash The output digest of the certificate
1040 @retval TRUE Successfully got the hash of the CertData.
1041 @retval FALSE Failed to get the hash of CertData.
1061 if (HashAlg
>= HASHALG_MAX
) {
1066 // Retrieve the TBSCertificate for Hash Calculation.
1068 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1073 // 1. Initialize context of hash.
1075 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1076 HashCtx
= AllocatePool (CtxSize
);
1077 ASSERT (HashCtx
!= NULL
);
1080 // 2. Initialize a hash context.
1082 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1088 // 3. Calculate the hash.
1090 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1096 // 4. Get the hash result.
1098 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1099 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1102 if (HashCtx
!= NULL
) {
1110 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1112 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1113 @param[in] CertSize Size of X.509 Certificate.
1115 @return TRUE Found the certificate hash in the forbidden database.
1116 @return FALSE Certificate hash is Not found in the forbidden database.
1120 IsCertHashFoundInDbx (
1121 IN UINT8
*Certificate
,
1127 EFI_SIGNATURE_LIST
*DbxList
;
1128 EFI_SIGNATURE_DATA
*CertHash
;
1129 UINTN CertHashCount
;
1132 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1134 UINTN SiglistHeaderSize
;
1139 HashAlg
= HASHALG_MAX
;
1143 // Read signature database variable.
1146 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1147 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1151 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1156 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1157 if (EFI_ERROR (Status
)) {
1162 // Check whether the certificate hash exists in the forbidden database.
1164 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1165 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1167 // Determine Hash Algorithm of Certificate in the forbidden database.
1169 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1170 HashAlg
= HASHALG_SHA256
;
1171 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1172 HashAlg
= HASHALG_SHA384
;
1173 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1174 HashAlg
= HASHALG_SHA512
;
1176 DataSize
-= DbxList
->SignatureListSize
;
1177 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1182 // Calculate the hash value of current db certificate for comparision.
1184 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1188 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1189 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1190 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1191 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1193 // Iterate each Signature Data Node within this CertList for verify.
1195 DbxCertHash
= CertHash
->SignatureData
;
1196 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1198 // Hash of Certificate is found in forbidden database.
1203 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1206 DataSize
-= DbxList
->SignatureListSize
;
1207 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1219 Check whether the signature list exists in given variable data.
1221 It searches the signature list for the certificate hash by CertType.
1222 If the signature list is found, get the offset of Database for the
1223 next hash of a certificate.
1225 @param[in] Database Variable data to save signature list.
1226 @param[in] DatabaseSize Variable size.
1227 @param[in] SignatureType The type of the signature.
1228 @param[out] Offset The offset to save a new hash of certificate.
1230 @return TRUE The signature list is found in the forbidden database.
1231 @return FALSE The signature list is not found in the forbidden database.
1234 GetSignaturelistOffset (
1235 IN EFI_SIGNATURE_LIST
*Database
,
1236 IN UINTN DatabaseSize
,
1237 IN EFI_GUID
*SignatureType
,
1241 EFI_SIGNATURE_LIST
*SigList
;
1244 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1250 SiglistSize
= DatabaseSize
;
1251 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1252 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1253 *Offset
= DatabaseSize
- SiglistSize
;
1256 SiglistSize
-= SigList
->SignatureListSize
;
1257 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1264 Enroll a new X509 certificate hash into Signature Database (dbx) without
1265 KEK's authentication.
1267 @param[in] PrivateData The module's private data.
1268 @param[in] HashAlg The hash algorithm to enroll the certificate.
1269 @param[in] RevocationDate The revocation date of the certificate.
1270 @param[in] RevocationTime The revocation time of the certificate.
1271 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1273 @retval EFI_SUCCESS New X509 is enrolled successfully.
1274 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1275 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1279 EnrollX509HashtoSigDB (
1280 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1282 IN EFI_HII_DATE
*RevocationDate
,
1283 IN EFI_HII_TIME
*RevocationTime
,
1284 IN BOOLEAN AlwaysRevocation
1290 EFI_SIGNATURE_LIST
*SignatureList
;
1291 UINTN SignatureListSize
;
1297 EFI_SIGNATURE_DATA
*SignatureData
;
1298 UINTN SignatureSize
;
1299 EFI_GUID SignatureType
;
1301 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1302 UINT16
* FilePostFix
;
1309 SignatureData
= NULL
;
1310 SignatureList
= NULL
;
1314 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1315 return EFI_INVALID_PARAMETER
;
1318 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1319 if (EFI_ERROR (Status
)) {
1324 // Parse the file's postfix.
1326 NameLength
= StrLen (Private
->FileContext
->FileName
);
1327 if (NameLength
<= 4) {
1328 return EFI_INVALID_PARAMETER
;
1330 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1331 if (!IsDerEncodeCertificate(FilePostFix
)) {
1333 // Only supports DER-encoded X509 certificate.
1335 return EFI_INVALID_PARAMETER
;
1339 // Get the certificate from file and calculate its hash.
1341 Status
= ReadFileContent (
1342 Private
->FileContext
->FHandle
,
1347 if (EFI_ERROR (Status
)) {
1350 ASSERT (X509Data
!= NULL
);
1352 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1357 // Get the variable for enrollment.
1360 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1361 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1362 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1364 return EFI_OUT_OF_RESOURCES
;
1367 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1368 if (EFI_ERROR (Status
)) {
1374 // Allocate memory for Signature and fill the Signature
1376 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1377 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1378 if (SignatureData
== NULL
) {
1379 return EFI_OUT_OF_RESOURCES
;
1381 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1382 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1387 if (!AlwaysRevocation
) {
1388 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1389 Time
->Year
= RevocationDate
->Year
;
1390 Time
->Month
= RevocationDate
->Month
;
1391 Time
->Day
= RevocationDate
->Day
;
1392 Time
->Hour
= RevocationTime
->Hour
;
1393 Time
->Minute
= RevocationTime
->Minute
;
1394 Time
->Second
= RevocationTime
->Second
;
1398 // Determine the GUID for certificate hash.
1401 case HASHALG_SHA256
:
1402 SignatureType
= gEfiCertX509Sha256Guid
;
1404 case HASHALG_SHA384
:
1405 SignatureType
= gEfiCertX509Sha384Guid
;
1407 case HASHALG_SHA512
:
1408 SignatureType
= gEfiCertX509Sha512Guid
;
1415 // Add signature into the new variable data buffer
1417 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1419 // Add the signature to the found signaturelist.
1421 DbSize
= DataSize
+ SignatureSize
;
1422 NewData
= AllocateZeroPool (DbSize
);
1423 if (NewData
== NULL
) {
1424 Status
= EFI_OUT_OF_RESOURCES
;
1428 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1429 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1430 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1432 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1433 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1435 Offset
+= SignatureListSize
;
1436 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1437 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1444 // Create a new signaturelist, and add the signature into the signaturelist.
1446 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1447 NewData
= AllocateZeroPool (DbSize
);
1448 if (NewData
== NULL
) {
1449 Status
= EFI_OUT_OF_RESOURCES
;
1453 // Fill Certificate Database parameters.
1455 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1456 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1457 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1458 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1459 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1460 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1461 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1462 CopyMem (NewData
, Data
, DataSize
);
1469 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1470 if (EFI_ERROR (Status
)) {
1474 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1475 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1476 Status
= gRT
->SetVariable(
1477 EFI_IMAGE_SECURITY_DATABASE1
,
1478 &gEfiImageSecurityDatabaseGuid
,
1483 if (EFI_ERROR (Status
)) {
1489 CloseEnrolledFile(Private
->FileContext
);
1491 if (Private
->SignatureGUID
!= NULL
) {
1492 FreePool (Private
->SignatureGUID
);
1493 Private
->SignatureGUID
= NULL
;
1500 if (SignatureData
!= NULL
) {
1501 FreePool (SignatureData
);
1504 if (X509Data
!= NULL
) {
1505 FreePool (X509Data
);
1512 Check whether a certificate from a file exists in dbx.
1514 @param[in] PrivateData The module's private data.
1515 @param[in] VariableName Variable name of signature database, must be
1516 EFI_IMAGE_SECURITY_DATABASE1.
1518 @retval TRUE The X509 certificate is found in dbx successfully.
1519 @retval FALSE The X509 certificate is not found in dbx.
1523 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1524 IN CHAR16
*VariableName
1533 // Read the certificate from file
1537 Status
= ReadFileContent (
1538 Private
->FileContext
->FHandle
,
1543 if (EFI_ERROR (Status
)) {
1548 // Check the raw certificate.
1551 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1557 // Check the hash of certificate.
1559 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1565 if (X509Data
!= NULL
) {
1566 FreePool (X509Data
);
1573 Reads contents of a PE/COFF image in memory buffer.
1575 Caution: This function may receive untrusted input.
1576 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1577 read is within the image buffer.
1579 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1580 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1581 @param ReadSize On input, the size in bytes of the requested read operation.
1582 On output, the number of bytes actually read.
1583 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1585 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1589 SecureBootConfigImageRead (
1590 IN VOID
*FileHandle
,
1591 IN UINTN FileOffset
,
1592 IN OUT UINTN
*ReadSize
,
1598 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1599 return EFI_INVALID_PARAMETER
;
1602 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1603 return EFI_INVALID_PARAMETER
;
1606 EndPosition
= FileOffset
+ *ReadSize
;
1607 if (EndPosition
> mImageSize
) {
1608 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1611 if (FileOffset
>= mImageSize
) {
1615 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1621 Load PE/COFF image information into internal buffer and check its validity.
1623 @retval EFI_SUCCESS Successful
1624 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1625 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1633 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1634 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1635 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1636 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1642 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1643 ImageContext
.Handle
= (VOID
*) mImageBase
;
1644 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1647 // Get information about the image being loaded
1649 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1650 if (EFI_ERROR (Status
)) {
1652 // The information can't be got from the invalid PeImage
1654 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1659 // Read the Dos header
1661 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1662 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1665 // DOS image header is present,
1666 // So read the PE header after the DOS image header
1668 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1672 mPeCoffHeaderOffset
= 0;
1676 // Read PE header and check the signature validity and machine compatibility
1678 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1679 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1681 return EFI_UNSUPPORTED
;
1684 mNtHeader
.Pe32
= NtHeader32
;
1687 // Check the architecture field of PE header and get the Certificate Data Directory data
1688 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1690 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1691 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1692 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1694 // 32-bits Architecture
1696 mImageType
= ImageType_IA32
;
1697 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1699 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1700 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1701 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1703 // 64-bits Architecture
1705 mImageType
= ImageType_X64
;
1706 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1707 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1709 return EFI_UNSUPPORTED
;
1716 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1717 PE/COFF Specification 8.0 Appendix A
1719 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1720 the function LoadPeImage ().
1722 @param[in] HashAlg Hash algorithm type.
1724 @retval TRUE Successfully hash image.
1725 @retval FALSE Fail in hash image.
1734 EFI_IMAGE_SECTION_HEADER
*Section
;
1739 UINTN SumOfBytesHashed
;
1740 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1745 SectionHeader
= NULL
;
1748 if (HashAlg
!= HASHALG_SHA256
) {
1753 // Initialize context of hash.
1755 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1757 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1758 mCertType
= gEfiCertSha256Guid
;
1760 CtxSize
= mHash
[HashAlg
].GetContextSize();
1762 HashCtx
= AllocatePool (CtxSize
);
1763 ASSERT (HashCtx
!= NULL
);
1765 // 1. Load the image header into memory.
1767 // 2. Initialize a SHA hash context.
1768 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1773 // Measuring PE/COFF Image Header;
1774 // But CheckSum field and SECURITY data directory (certificate) are excluded
1778 // 3. Calculate the distance from the base of the image header to the image checksum address.
1779 // 4. Hash the image header from its base to beginning of the image checksum.
1781 HashBase
= mImageBase
;
1782 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1786 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1789 // Use PE32+ offset.
1791 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1794 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1799 // 5. Skip over the image checksum (it occupies a single ULONG).
1800 // 6. Get the address of the beginning of the Cert Directory.
1801 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1803 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1807 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1808 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1811 // Use PE32+ offset.
1813 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1814 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1817 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1822 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1823 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1825 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1829 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1830 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1833 // Use PE32+ offset.
1835 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1836 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1839 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1844 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1846 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1850 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1855 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1859 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1860 // structures in the image. The 'NumberOfSections' field of the image
1861 // header indicates how big the table should be. Do not include any
1862 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1864 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1865 ASSERT (SectionHeader
!= NULL
);
1867 // 12. Using the 'PointerToRawData' in the referenced section headers as
1868 // a key, arrange the elements in the table in ascending order. In other
1869 // words, sort the section headers according to the disk-file offset of
1872 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1874 mPeCoffHeaderOffset
+
1876 sizeof (EFI_IMAGE_FILE_HEADER
) +
1877 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1879 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1881 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1882 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1885 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1890 // 13. Walk through the sorted table, bring the corresponding section
1891 // into memory, and hash the entire section (using the 'SizeOfRawData'
1892 // field in the section header to determine the amount of data to hash).
1893 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1894 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1896 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1897 Section
= &SectionHeader
[Index
];
1898 if (Section
->SizeOfRawData
== 0) {
1901 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1902 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1904 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1909 SumOfBytesHashed
+= HashSize
;
1913 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1914 // data in the file that needs to be added to the hash. This data begins
1915 // at file offset SUM_OF_BYTES_HASHED and its length is:
1916 // FileSize - (CertDirectory->Size)
1918 if (mImageSize
> SumOfBytesHashed
) {
1919 HashBase
= mImageBase
+ SumOfBytesHashed
;
1920 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1926 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1930 // Use PE32+ offset.
1934 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1938 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1944 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1947 if (HashCtx
!= NULL
) {
1950 if (SectionHeader
!= NULL
) {
1951 FreePool (SectionHeader
);
1957 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
1958 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1961 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1962 @retval EFI_SUCCESS Hash successfully.
1971 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1973 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1975 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1977 // Check the Hash algorithm in PE/COFF Authenticode.
1978 // According to PKCS#7 Definition:
1979 // SignedData ::= SEQUENCE {
1981 // digestAlgorithms DigestAlgorithmIdentifiers,
1982 // contentInfo ContentInfo,
1984 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1985 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1986 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1988 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1990 // Only support two bytes of Long Form of Length Encoding.
1996 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2001 if (Index
== HASHALG_MAX
) {
2002 return EFI_UNSUPPORTED
;
2006 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2008 if (!HashPeImage(Index
)) {
2009 return EFI_UNSUPPORTED
;
2016 Enroll a new signature of executable into Signature Database.
2018 @param[in] PrivateData The module's private data.
2019 @param[in] VariableName Variable name of signature database, must be
2020 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2021 or EFI_IMAGE_SECURITY_DATABASE2.
2023 @retval EFI_SUCCESS New signature is enrolled successfully.
2024 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2025 @retval EFI_UNSUPPORTED Unsupported command.
2026 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2030 EnrollAuthentication2Descriptor (
2031 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2032 IN CHAR16
*VariableName
2043 // DBT only support DER-X509 Cert Enrollment
2045 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2046 return EFI_UNSUPPORTED
;
2050 // Read the whole file content
2052 Status
= ReadFileContent(
2053 Private
->FileContext
->FHandle
,
2054 (VOID
**) &mImageBase
,
2058 if (EFI_ERROR (Status
)) {
2061 ASSERT (mImageBase
!= NULL
);
2063 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2064 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2067 // Check if SigDB variable has been already existed.
2068 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2069 // new signature data to original variable
2072 Status
= gRT
->GetVariable(
2074 &gEfiImageSecurityDatabaseGuid
,
2079 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2080 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2081 } else if (Status
!= EFI_NOT_FOUND
) {
2086 // Directly set AUTHENTICATION_2 data to SetVariable
2088 Status
= gRT
->SetVariable(
2090 &gEfiImageSecurityDatabaseGuid
,
2096 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2100 CloseEnrolledFile(Private
->FileContext
);
2106 if (mImageBase
!= NULL
) {
2107 FreePool (mImageBase
);
2117 Enroll a new signature of executable into Signature Database.
2119 @param[in] PrivateData The module's private data.
2120 @param[in] VariableName Variable name of signature database, must be
2121 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2122 or EFI_IMAGE_SECURITY_DATABASE2.
2124 @retval EFI_SUCCESS New signature is enrolled successfully.
2125 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2126 @retval EFI_UNSUPPORTED Unsupported command.
2127 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2131 EnrollImageSignatureToSigDB (
2132 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2133 IN CHAR16
*VariableName
2137 EFI_SIGNATURE_LIST
*SigDBCert
;
2138 EFI_SIGNATURE_DATA
*SigDBCertData
;
2143 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2146 GuidCertData
= NULL
;
2148 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2149 return EFI_UNSUPPORTED
;
2153 // Form the SigDB certificate list.
2154 // Format the data item into EFI_SIGNATURE_LIST type.
2156 // We need to parse signature data of executable from specified signed executable file.
2157 // In current implementation, we simply trust the pass-in signed executable file.
2158 // In reality, it's OS's responsibility to verify the signed executable file.
2162 // Read the whole file content
2164 Status
= ReadFileContent(
2165 Private
->FileContext
->FHandle
,
2166 (VOID
**) &mImageBase
,
2170 if (EFI_ERROR (Status
)) {
2173 ASSERT (mImageBase
!= NULL
);
2175 Status
= LoadPeImage ();
2176 if (EFI_ERROR (Status
)) {
2180 if (mSecDataDir
->SizeOfCert
== 0) {
2181 if (!HashPeImage (HASHALG_SHA256
)) {
2182 Status
= EFI_SECURITY_VIOLATION
;
2188 // Read the certificate data
2190 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2192 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2193 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2194 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2195 Status
= EFI_ABORTED
;
2199 if (!HashPeImage (HASHALG_SHA256
)) {
2200 Status
= EFI_ABORTED
;
2204 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2206 Status
= HashPeImageByType ();
2207 if (EFI_ERROR (Status
)) {
2211 Status
= EFI_ABORTED
;
2217 // Create a new SigDB entry.
2219 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2220 + sizeof(EFI_SIGNATURE_DATA
) - 1
2221 + (UINT32
) mImageDigestSize
;
2223 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2225 Status
= EFI_OUT_OF_RESOURCES
;
2230 // Adjust the Certificate Database parameters.
2232 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2233 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2234 SigDBCert
->SignatureHeaderSize
= 0;
2235 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2236 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2238 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2239 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2240 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2242 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2243 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2244 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2245 if (EFI_ERROR (Status
)) {
2246 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2251 // Check if SigDB variable has been already existed.
2252 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2253 // new signature data to original variable
2256 Status
= gRT
->GetVariable(
2258 &gEfiImageSecurityDatabaseGuid
,
2263 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2264 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2265 } else if (Status
!= EFI_NOT_FOUND
) {
2270 // Enroll the variable.
2272 Status
= gRT
->SetVariable(
2274 &gEfiImageSecurityDatabaseGuid
,
2279 if (EFI_ERROR (Status
)) {
2285 CloseEnrolledFile(Private
->FileContext
);
2287 if (Private
->SignatureGUID
!= NULL
) {
2288 FreePool (Private
->SignatureGUID
);
2289 Private
->SignatureGUID
= NULL
;
2296 if (mImageBase
!= NULL
) {
2297 FreePool (mImageBase
);
2305 Enroll signature into DB/DBX/DBT without KEK's authentication.
2306 The SignatureOwner GUID will be Private->SignatureGUID.
2308 @param[in] PrivateData The module's private data.
2309 @param[in] VariableName Variable name of signature database, must be
2310 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2312 @retval EFI_SUCCESS New signature enrolled successfully.
2313 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2314 @retval others Fail to enroll signature data.
2318 EnrollSignatureDatabase (
2319 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2320 IN CHAR16
*VariableName
2323 UINT16
* FilePostFix
;
2327 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2328 return EFI_INVALID_PARAMETER
;
2331 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2332 if (EFI_ERROR (Status
)) {
2337 // Parse the file's postfix.
2339 NameLength
= StrLen (Private
->FileContext
->FileName
);
2340 if (NameLength
<= 4) {
2341 return EFI_INVALID_PARAMETER
;
2343 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2344 if (IsDerEncodeCertificate (FilePostFix
)) {
2346 // Supports DER-encoded X509 certificate.
2348 return EnrollX509toSigDB (Private
, VariableName
);
2349 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2350 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2352 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2357 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2358 by GUID in the page for user to select and delete as needed.
2360 @param[in] PrivateData Module's private data.
2361 @param[in] VariableName The variable name of the vendor's signature database.
2362 @param[in] VendorGuid A unique identifier for the vendor.
2363 @param[in] LabelNumber Label number to insert opcodes.
2364 @param[in] FormId Form ID of current page.
2365 @param[in] QuestionIdBase Base question id of the signature list.
2367 @retval EFI_SUCCESS Success to update the signature list page
2368 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2373 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2374 IN CHAR16
*VariableName
,
2375 IN EFI_GUID
*VendorGuid
,
2376 IN UINT16 LabelNumber
,
2377 IN EFI_FORM_ID FormId
,
2378 IN EFI_QUESTION_ID QuestionIdBase
2385 VOID
*StartOpCodeHandle
;
2386 VOID
*EndOpCodeHandle
;
2387 EFI_IFR_GUID_LABEL
*StartLabel
;
2388 EFI_IFR_GUID_LABEL
*EndLabel
;
2391 EFI_SIGNATURE_LIST
*CertList
;
2392 EFI_SIGNATURE_DATA
*Cert
;
2393 UINT32 ItemDataSize
;
2395 EFI_STRING_ID GuidID
;
2402 StartOpCodeHandle
= NULL
;
2403 EndOpCodeHandle
= NULL
;
2406 // Initialize the container for dynamic opcodes.
2408 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2409 if (StartOpCodeHandle
== NULL
) {
2410 Status
= EFI_OUT_OF_RESOURCES
;
2414 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2415 if (EndOpCodeHandle
== NULL
) {
2416 Status
= EFI_OUT_OF_RESOURCES
;
2421 // Create Hii Extend Label OpCode.
2423 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2427 sizeof (EFI_IFR_GUID_LABEL
)
2429 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2430 StartLabel
->Number
= LabelNumber
;
2432 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2436 sizeof (EFI_IFR_GUID_LABEL
)
2438 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2439 EndLabel
->Number
= LABEL_END
;
2445 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2446 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2450 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2452 Status
= EFI_OUT_OF_RESOURCES
;
2456 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2457 if (EFI_ERROR (Status
)) {
2461 GuidStr
= AllocateZeroPool (100);
2462 if (GuidStr
== NULL
) {
2463 Status
= EFI_OUT_OF_RESOURCES
;
2468 // Enumerate all KEK pub data.
2470 ItemDataSize
= (UINT32
) DataSize
;
2471 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2474 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2476 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2477 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2478 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2479 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2480 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2481 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2482 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2483 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2484 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2485 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2486 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2487 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2488 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2489 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2492 // The signature type is not supported in current implementation.
2494 ItemDataSize
-= CertList
->SignatureListSize
;
2495 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2499 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2500 for (Index
= 0; Index
< CertCount
; Index
++) {
2501 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2502 + sizeof (EFI_SIGNATURE_LIST
)
2503 + CertList
->SignatureHeaderSize
2504 + Index
* CertList
->SignatureSize
);
2506 // Display GUID and help
2508 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2509 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2510 HiiCreateCheckBoxOpCode (
2512 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2517 EFI_IFR_FLAG_CALLBACK
,
2523 ItemDataSize
-= CertList
->SignatureListSize
;
2524 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2529 PrivateData
->HiiHandle
,
2530 &gSecureBootConfigFormSetGuid
,
2536 if (StartOpCodeHandle
!= NULL
) {
2537 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2540 if (EndOpCodeHandle
!= NULL
) {
2541 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2548 if (GuidStr
!= NULL
) {
2556 Delete a KEK entry from KEK database.
2558 @param[in] PrivateData Module's private data.
2559 @param[in] QuestionId Question id of the KEK item to delete.
2561 @retval EFI_SUCCESS Delete kek item successfully.
2562 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2566 DeleteKeyExchangeKey (
2567 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2568 IN EFI_QUESTION_ID QuestionId
2577 EFI_SIGNATURE_LIST
*CertList
;
2578 EFI_SIGNATURE_LIST
*NewCertList
;
2579 EFI_SIGNATURE_DATA
*Cert
;
2582 BOOLEAN IsKEKItemFound
;
2584 UINTN DeleteKekIndex
;
2592 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2594 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2595 if (EFI_ERROR (Status
)) {
2600 // Get original KEK variable.
2603 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2604 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2608 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2609 if (OldData
== NULL
) {
2610 Status
= EFI_OUT_OF_RESOURCES
;
2614 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2615 if (EFI_ERROR(Status
)) {
2620 // Allocate space for new variable.
2622 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2624 Status
= EFI_OUT_OF_RESOURCES
;
2629 // Enumerate all KEK pub data and erasing the target item.
2631 IsKEKItemFound
= FALSE
;
2632 KekDataSize
= (UINT32
) DataSize
;
2633 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2636 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2637 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2638 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2639 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2640 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2641 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2642 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2643 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2644 for (Index
= 0; Index
< CertCount
; Index
++) {
2645 if (GuidIndex
== DeleteKekIndex
) {
2647 // Find it! Skip it!
2649 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2650 IsKEKItemFound
= TRUE
;
2653 // This item doesn't match. Copy it to the Data buffer.
2655 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2656 Offset
+= CertList
->SignatureSize
;
2659 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2663 // This List doesn't match. Copy it to the Data buffer.
2665 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2666 Offset
+= CertList
->SignatureListSize
;
2669 KekDataSize
-= CertList
->SignatureListSize
;
2670 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2673 if (!IsKEKItemFound
) {
2675 // Doesn't find the Kek Item!
2677 Status
= EFI_NOT_FOUND
;
2682 // Delete the Signature header if there is no signature in the list.
2684 KekDataSize
= Offset
;
2685 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2687 ZeroMem (OldData
, KekDataSize
);
2688 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2689 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2690 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2691 if (CertCount
!= 0) {
2692 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2693 Offset
+= CertList
->SignatureListSize
;
2695 KekDataSize
-= CertList
->SignatureListSize
;
2696 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2700 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2701 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2702 if (EFI_ERROR (Status
)) {
2703 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2708 Status
= gRT
->SetVariable(
2709 EFI_KEY_EXCHANGE_KEY_NAME
,
2710 &gEfiGlobalVariableGuid
,
2715 if (EFI_ERROR (Status
)) {
2716 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2725 if (OldData
!= NULL
) {
2729 return UpdateDeletePage (
2731 EFI_KEY_EXCHANGE_KEY_NAME
,
2732 &gEfiGlobalVariableGuid
,
2734 FORMID_DELETE_KEK_FORM
,
2735 OPTION_DEL_KEK_QUESTION_ID
2740 Delete a signature entry from signature database.
2742 @param[in] PrivateData Module's private data.
2743 @param[in] VariableName The variable name of the vendor's signature database.
2744 @param[in] VendorGuid A unique identifier for the vendor.
2745 @param[in] LabelNumber Label number to insert opcodes.
2746 @param[in] FormId Form ID of current page.
2747 @param[in] QuestionIdBase Base question id of the signature list.
2748 @param[in] DeleteIndex Signature index to delete.
2750 @retval EFI_SUCCESS Delete signature successfully.
2751 @retval EFI_NOT_FOUND Can't find the signature item,
2752 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2756 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2757 IN CHAR16
*VariableName
,
2758 IN EFI_GUID
*VendorGuid
,
2759 IN UINT16 LabelNumber
,
2760 IN EFI_FORM_ID FormId
,
2761 IN EFI_QUESTION_ID QuestionIdBase
,
2762 IN UINTN DeleteIndex
2771 EFI_SIGNATURE_LIST
*CertList
;
2772 EFI_SIGNATURE_LIST
*NewCertList
;
2773 EFI_SIGNATURE_DATA
*Cert
;
2776 BOOLEAN IsItemFound
;
2777 UINT32 ItemDataSize
;
2786 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2787 if (EFI_ERROR (Status
)) {
2792 // Get original signature list data.
2795 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2796 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2800 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2801 if (OldData
== NULL
) {
2802 Status
= EFI_OUT_OF_RESOURCES
;
2806 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2807 if (EFI_ERROR(Status
)) {
2812 // Allocate space for new variable.
2814 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2816 Status
= EFI_OUT_OF_RESOURCES
;
2821 // Enumerate all signature data and erasing the target item.
2823 IsItemFound
= FALSE
;
2824 ItemDataSize
= (UINT32
) DataSize
;
2825 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2828 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2829 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2830 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2831 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2832 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2833 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2834 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2835 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2838 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2840 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2841 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2842 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2843 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2844 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2845 for (Index
= 0; Index
< CertCount
; Index
++) {
2846 if (GuidIndex
== DeleteIndex
) {
2848 // Find it! Skip it!
2850 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2854 // This item doesn't match. Copy it to the Data buffer.
2856 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2857 Offset
+= CertList
->SignatureSize
;
2860 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2864 // This List doesn't match. Just copy it to the Data buffer.
2866 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2867 Offset
+= CertList
->SignatureListSize
;
2870 ItemDataSize
-= CertList
->SignatureListSize
;
2871 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2876 // Doesn't find the signature Item!
2878 Status
= EFI_NOT_FOUND
;
2883 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2885 ItemDataSize
= Offset
;
2886 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2888 ZeroMem (OldData
, ItemDataSize
);
2889 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2890 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2891 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2892 if (CertCount
!= 0) {
2893 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2894 Offset
+= CertList
->SignatureListSize
;
2896 ItemDataSize
-= CertList
->SignatureListSize
;
2897 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2901 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2902 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2903 if (EFI_ERROR (Status
)) {
2904 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2909 Status
= gRT
->SetVariable(
2916 if (EFI_ERROR (Status
)) {
2917 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2926 if (OldData
!= NULL
) {
2930 return UpdateDeletePage (
2941 This function to delete signature list or data, according by DelType.
2943 @param[in] PrivateData Module's private data.
2944 @param[in] DelType Indicate delete signature list or data.
2945 @param[in] CheckedCount Indicate how many signature data have
2946 been checked in current signature list.
2948 @retval EFI_SUCCESS Success to update the signature list page
2949 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2953 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2954 IN SIGNATURE_DELETE_TYPE DelType
,
2955 IN UINT32 CheckedCount
2959 EFI_SIGNATURE_LIST
*ListWalker
;
2960 EFI_SIGNATURE_LIST
*NewCertList
;
2961 EFI_SIGNATURE_DATA
*DataWalker
;
2962 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
2963 UINT32 VariableAttr
;
2964 UINTN VariableDataSize
;
2965 UINTN RemainingSize
;
2969 UINT8
*VariableData
;
2970 UINT8
*NewVariableData
;
2972 Status
= EFI_SUCCESS
;
2974 VariableDataSize
= 0;
2977 VariableData
= NULL
;
2978 NewVariableData
= NULL
;
2980 if (PrivateData
->VariableName
== Variable_DB
) {
2981 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
2982 } else if (PrivateData
->VariableName
== Variable_DBX
) {
2983 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
2984 } else if (PrivateData
->VariableName
== Variable_DBT
) {
2985 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
2990 Status
= gRT
->GetVariable (
2992 &gEfiImageSecurityDatabaseGuid
,
2997 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3001 VariableData
= AllocateZeroPool (VariableDataSize
);
3002 if (VariableData
== NULL
) {
3003 Status
= EFI_OUT_OF_RESOURCES
;
3007 Status
= gRT
->GetVariable (
3009 &gEfiImageSecurityDatabaseGuid
,
3014 if (EFI_ERROR (Status
)) {
3018 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3019 if (EFI_ERROR (Status
)) {
3023 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3024 if (NewVariableData
== NULL
) {
3025 Status
= EFI_OUT_OF_RESOURCES
;
3029 RemainingSize
= VariableDataSize
;
3030 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3031 if (DelType
== Delete_Signature_List_All
) {
3032 VariableDataSize
= 0;
3035 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3037 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3038 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3039 Offset
+= ListWalker
->SignatureListSize
;
3041 RemainingSize
-= ListWalker
->SignatureListSize
;
3042 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3047 // Handle the target EFI_SIGNATURE_LIST.
3048 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3049 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3051 if (CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
) && DelType
== Delete_Signature_Data
) {
3052 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3056 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3057 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3059 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3060 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
3061 if (PrivateData
->CheckArray
[Index
]) {
3063 // Delete checked signature data, and update the size of whole signature list.
3065 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3068 // Remain the unchecked signature data.
3070 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3071 Offset
+= ListWalker
->SignatureSize
;
3073 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3077 RemainingSize
-= ListWalker
->SignatureListSize
;
3078 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3081 // Copy remaining data, maybe 0.
3083 CopyMem((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3084 Offset
+= RemainingSize
;
3086 VariableDataSize
= Offset
;
3089 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3090 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3091 if (EFI_ERROR (Status
)) {
3092 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3097 Status
= gRT
->SetVariable (
3099 &gEfiImageSecurityDatabaseGuid
,
3104 if (EFI_ERROR (Status
)) {
3105 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3110 SECUREBOOT_FREE_NON_NULL (VariableData
);
3111 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3118 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3119 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3121 @param[in] PrivateData Module's private data.
3123 @return EFI_SUCCESS Update secure boot strings successfully.
3124 @return other Fail to update secure boot strings.
3128 UpdateSecureBootString(
3129 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3137 // Get current secure boot state.
3139 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3140 if (SecureBoot
== NULL
) {
3141 return EFI_NOT_FOUND
;
3144 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3145 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3147 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3150 FreePool(SecureBoot
);
3156 This function extracts configuration from variable.
3158 @param[in] Private Point to SecureBoot configuration driver private data.
3159 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3163 SecureBootExtractConfigFromVariable (
3164 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3165 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3168 UINT8
*SecureBootEnable
;
3170 UINT8
*SecureBootMode
;
3173 SecureBootEnable
= NULL
;
3175 SecureBootMode
= NULL
;
3178 // Initialize the Date and Time using system time.
3180 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3181 ConfigData
->AlwaysRevocation
= TRUE
;
3182 gRT
->GetTime (&CurrTime
, NULL
);
3183 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3184 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3185 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3186 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3187 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3188 ConfigData
->RevocationTime
.Second
= 0;
3189 if (Private
->FileContext
->FHandle
!= NULL
) {
3190 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3192 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3196 // If it is Physical Presence User, set the PhysicalPresent to true.
3198 if (UserPhysicalPresent()) {
3199 ConfigData
->PhysicalPresent
= TRUE
;
3201 ConfigData
->PhysicalPresent
= FALSE
;
3205 // If there is no PK then the Delete Pk button will be gray.
3207 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3208 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3209 ConfigData
->HasPk
= FALSE
;
3211 ConfigData
->HasPk
= TRUE
;
3215 // Check SecureBootEnable & Pk status, fix the inconsistency.
3216 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3219 ConfigData
->AttemptSecureBoot
= FALSE
;
3220 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3223 // Fix Pk and SecureBootEnable inconsistency
3225 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3226 ConfigData
->HideSecureBoot
= FALSE
;
3227 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3228 ConfigData
->AttemptSecureBoot
= TRUE
;
3231 ConfigData
->HideSecureBoot
= TRUE
;
3235 // Get the SecureBootMode from CustomMode variable.
3237 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3238 if (SecureBootMode
== NULL
) {
3239 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3241 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3244 if (SecureBootEnable
!= NULL
) {
3245 FreePool (SecureBootEnable
);
3247 if (SetupMode
!= NULL
) {
3248 FreePool (SetupMode
);
3250 if (SecureBootMode
!= NULL
) {
3251 FreePool (SecureBootMode
);
3256 This function allows a caller to extract the current configuration for one
3257 or more named elements from the target driver.
3259 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3260 @param[in] Request A null-terminated Unicode string in
3261 <ConfigRequest> format.
3262 @param[out] Progress On return, points to a character in the Request
3263 string. Points to the string's null terminator if
3264 request was successful. Points to the most recent
3265 '&' before the first failing name/value pair (or
3266 the beginning of the string if the failure is in
3267 the first name/value pair) if the request was not
3269 @param[out] Results A null-terminated Unicode string in
3270 <ConfigAltResp> format which has all values filled
3271 in for the names in the Request string. String to
3272 be allocated by the called function.
3274 @retval EFI_SUCCESS The Results is filled with the requested values.
3275 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3276 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3277 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3283 SecureBootExtractConfig (
3284 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3285 IN CONST EFI_STRING Request
,
3286 OUT EFI_STRING
*Progress
,
3287 OUT EFI_STRING
*Results
3293 SECUREBOOT_CONFIGURATION Configuration
;
3294 EFI_STRING ConfigRequest
;
3295 EFI_STRING ConfigRequestHdr
;
3296 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3297 BOOLEAN AllocatedRequest
;
3299 if (Progress
== NULL
|| Results
== NULL
) {
3300 return EFI_INVALID_PARAMETER
;
3303 AllocatedRequest
= FALSE
;
3304 ConfigRequestHdr
= NULL
;
3305 ConfigRequest
= NULL
;
3308 ZeroMem (&Configuration
, sizeof (Configuration
));
3309 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3310 *Progress
= Request
;
3312 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3313 return EFI_NOT_FOUND
;
3316 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3319 // Get Configuration from Variable.
3321 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3323 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3324 ConfigRequest
= Request
;
3325 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3327 // Request is set to NULL or OFFSET is NULL, construct full request string.
3329 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3330 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3332 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3333 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3334 ConfigRequest
= AllocateZeroPool (Size
);
3335 ASSERT (ConfigRequest
!= NULL
);
3336 AllocatedRequest
= TRUE
;
3337 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3338 FreePool (ConfigRequestHdr
);
3339 ConfigRequestHdr
= NULL
;
3342 Status
= gHiiConfigRouting
->BlockToConfig (
3345 (UINT8
*) &Configuration
,
3352 // Free the allocated config request string.
3354 if (AllocatedRequest
) {
3355 FreePool (ConfigRequest
);
3359 // Set Progress string to the original request string.
3361 if (Request
== NULL
) {
3363 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3364 *Progress
= Request
+ StrLen (Request
);
3371 This function processes the results of changes in configuration.
3373 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3374 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3376 @param[out] Progress A pointer to a string filled in with the offset of
3377 the most recent '&' before the first failing
3378 name/value pair (or the beginning of the string if
3379 the failure is in the first name/value pair) or
3380 the terminating NULL if all was successful.
3382 @retval EFI_SUCCESS The Results is processed successfully.
3383 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3384 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3390 SecureBootRouteConfig (
3391 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3392 IN CONST EFI_STRING Configuration
,
3393 OUT EFI_STRING
*Progress
3396 SECUREBOOT_CONFIGURATION IfrNvData
;
3398 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3401 if (Configuration
== NULL
|| Progress
== NULL
) {
3402 return EFI_INVALID_PARAMETER
;
3405 *Progress
= Configuration
;
3406 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3407 return EFI_NOT_FOUND
;
3410 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3413 // Get Configuration from Variable.
3415 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3418 // Map the Configuration to the configuration block.
3420 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3421 Status
= gHiiConfigRouting
->ConfigToBlock (
3424 (UINT8
*)&IfrNvData
,
3428 if (EFI_ERROR (Status
)) {
3433 // Store Buffer Storage back to EFI variable if needed
3435 if (!IfrNvData
.HideSecureBoot
) {
3436 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3437 if (EFI_ERROR (Status
)) {
3442 *Progress
= Configuration
+ StrLen (Configuration
);
3447 This function to load signature list, the update the menu page.
3449 @param[in] PrivateData Module's private data.
3450 @param[in] LabelId Label number to insert opcodes.
3451 @param[in] FormId Form ID of current page.
3452 @param[in] QuestionIdBase Base question id of the signature list.
3454 @retval EFI_SUCCESS Success to update the signature list page
3455 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3459 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3461 IN EFI_FORM_ID FormId
,
3462 IN EFI_QUESTION_ID QuestionIdBase
3466 EFI_STRING_ID ListType
;
3467 EFI_STRING FormatNameString
;
3468 EFI_STRING FormatHelpString
;
3469 EFI_STRING FormatTypeString
;
3470 EFI_SIGNATURE_LIST
*ListWalker
;
3471 EFI_IFR_GUID_LABEL
*StartLabel
;
3472 EFI_IFR_GUID_LABEL
*EndLabel
;
3473 EFI_IFR_GUID_LABEL
*StartGoto
;
3474 EFI_IFR_GUID_LABEL
*EndGoto
;
3475 EFI_FORM_ID DstFormId
;
3476 VOID
*StartOpCodeHandle
;
3477 VOID
*EndOpCodeHandle
;
3478 VOID
*StartGotoHandle
;
3479 VOID
*EndGotoHandle
;
3481 UINTN RemainingSize
;
3483 UINT8
*VariableData
;
3484 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3485 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3486 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3488 Status
= EFI_SUCCESS
;
3489 FormatNameString
= NULL
;
3490 FormatHelpString
= NULL
;
3491 StartOpCodeHandle
= NULL
;
3492 EndOpCodeHandle
= NULL
;
3493 StartGotoHandle
= NULL
;
3494 EndGotoHandle
= NULL
;
3496 VariableData
= NULL
;
3499 // Initialize the container for dynamic opcodes.
3501 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3502 if (StartOpCodeHandle
== NULL
) {
3503 Status
= EFI_OUT_OF_RESOURCES
;
3507 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3508 if (EndOpCodeHandle
== NULL
) {
3509 Status
= EFI_OUT_OF_RESOURCES
;
3513 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3514 if (StartGotoHandle
== NULL
) {
3515 Status
= EFI_OUT_OF_RESOURCES
;
3519 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3520 if (EndGotoHandle
== NULL
) {
3521 Status
= EFI_OUT_OF_RESOURCES
;
3526 // Create Hii Extend Label OpCode.
3528 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3532 sizeof (EFI_IFR_GUID_LABEL
)
3534 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3535 StartLabel
->Number
= LabelId
;
3537 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3541 sizeof (EFI_IFR_GUID_LABEL
)
3543 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3544 EndLabel
->Number
= LABEL_END
;
3546 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3550 sizeof(EFI_IFR_GUID_LABEL
)
3552 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3553 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3555 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3559 sizeof(EFI_IFR_GUID_LABEL
)
3561 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3562 EndGoto
->Number
= LABEL_END
;
3564 if (PrivateData
->VariableName
== Variable_DB
) {
3565 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3566 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3567 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3568 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3569 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3570 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3571 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3572 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3577 HiiCreateGotoOpCode (
3580 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3581 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3582 EFI_IFR_FLAG_CALLBACK
,
3583 KEY_SECURE_BOOT_DELETE_ALL_LIST
3587 // Read Variable, the variable name save in the PrivateData->VariableName.
3590 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3591 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3595 VariableData
= AllocateZeroPool (DataSize
);
3596 if (VariableData
== NULL
) {
3597 Status
= EFI_OUT_OF_RESOURCES
;
3600 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3601 if (EFI_ERROR (Status
)) {
3605 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3606 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3607 if (FormatNameString
== NULL
|| FormatHelpString
== NULL
) {
3611 RemainingSize
= DataSize
;
3612 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3613 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3614 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3615 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3616 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3617 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3618 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3619 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3620 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3621 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3622 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3623 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3624 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3625 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3626 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3627 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3629 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3631 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3632 if (FormatTypeString
== NULL
) {
3636 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3637 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3639 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3640 UnicodeSPrint (HelpBuffer
,
3641 sizeof (HelpBuffer
),
3644 SIGNATURE_DATA_COUNTS (ListWalker
)
3646 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3647 FormatTypeString
= NULL
;
3649 HiiCreateGotoOpCode (
3651 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3652 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3653 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3654 EFI_IFR_FLAG_CALLBACK
,
3655 QuestionIdBase
+ Index
++
3658 RemainingSize
-= ListWalker
->SignatureListSize
;
3659 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3664 PrivateData
->HiiHandle
,
3665 &gSecureBootConfigFormSetGuid
,
3672 PrivateData
->HiiHandle
,
3673 &gSecureBootConfigFormSetGuid
,
3679 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3680 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3681 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3682 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3684 SECUREBOOT_FREE_NON_NULL (VariableData
);
3685 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3686 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3688 PrivateData
->ListCount
= Index
;
3694 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3695 The buffer is callee allocated and should be freed by the caller.
3697 @param[in] ListEntry The pointer point to the signature list.
3698 @param[in] DataEntry The signature data we are processing.
3699 @param[out] BufferToReturn Buffer to save the hash value.
3701 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3702 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3703 @retval EFI_SUCCESS Operation success.
3707 IN EFI_SIGNATURE_LIST
*ListEntry
,
3708 IN EFI_SIGNATURE_DATA
*DataEntry
,
3709 OUT CHAR16
**BufferToReturn
3720 // Assume that, display 8 bytes in one line.
3724 if (ListEntry
== NULL
|| DataEntry
== NULL
|| BufferToReturn
== NULL
) {
3725 return EFI_INVALID_PARAMETER
;
3728 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3729 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3732 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3734 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof(CHAR16
));
3736 *BufferToReturn
= AllocateZeroPool(TotalSize
);
3737 if (*BufferToReturn
== NULL
) {
3738 return EFI_OUT_OF_RESOURCES
;
3741 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3742 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3743 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3745 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3747 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3753 Function to get the common name from the X509 format certificate.
3754 The buffer is callee allocated and should be freed by the caller.
3756 @param[in] ListEntry The pointer point to the signature list.
3757 @param[in] DataEntry The signature data we are processing.
3758 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3760 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3761 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3762 @retval EFI_SUCCESS Operation success.
3763 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3766 GetCommonNameFromX509 (
3767 IN EFI_SIGNATURE_LIST
*ListEntry
,
3768 IN EFI_SIGNATURE_DATA
*DataEntry
,
3769 OUT CHAR16
**BufferToReturn
3776 Status
= EFI_SUCCESS
;
3779 CNBuffer
= AllocateZeroPool(256);
3780 if (CNBuffer
== NULL
) {
3781 Status
= EFI_OUT_OF_RESOURCES
;
3787 (UINT8
*)DataEntry
+ sizeof(EFI_GUID
),
3788 ListEntry
->SignatureSize
- sizeof(EFI_GUID
),
3793 *BufferToReturn
= AllocateZeroPool(256 * sizeof(CHAR16
));
3794 if (*BufferToReturn
== NULL
) {
3795 Status
= EFI_OUT_OF_RESOURCES
;
3799 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3802 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3808 Format the help info for the signature data, each help info contain 3 parts.
3810 2. Content, depends on the type of the signature list.
3813 @param[in] PrivateData Module's private data.
3814 @param[in] ListEntry Point to the signature list.
3815 @param[in] DataEntry Point to the signature data we are processing.
3816 @param[out] StringId Save the string id of help info.
3818 @retval EFI_SUCCESS Operation success.
3819 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3823 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3824 IN EFI_SIGNATURE_LIST
*ListEntry
,
3825 IN EFI_SIGNATURE_DATA
*DataEntry
,
3826 OUT EFI_STRING_ID
*StringId
3831 EFI_STRING_ID ListTypeId
;
3832 EFI_STRING FormatHelpString
;
3833 EFI_STRING FormatTypeString
;
3835 UINTN HelpInfoIndex
;
3837 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3838 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3840 CHAR16
*HelpInfoString
;
3843 Status
= EFI_SUCCESS
;
3845 FormatTypeString
= NULL
;
3848 HelpInfoString
= NULL
;
3851 if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3852 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256
);
3853 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3855 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
3856 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509
);
3857 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3859 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
3860 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA1
);
3862 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
3863 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA256
);
3865 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3866 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA256
);
3868 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3869 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3870 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA384
);
3872 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3873 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3874 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA512
);
3876 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3878 Status
= EFI_UNSUPPORTED
;
3882 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
3883 if (FormatTypeString
== NULL
) {
3888 HelpInfoString
= AllocateZeroPool (TotalSize
);
3889 if (HelpInfoString
== NULL
) {
3890 Status
= EFI_OUT_OF_RESOURCES
;
3895 // Format GUID part.
3897 ZeroMem (GuidString
, sizeof (GuidString
));
3898 GuidToString(&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
3899 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
3900 if (FormatHelpString
== NULL
) {
3903 HelpInfoIndex
+= UnicodeSPrint (
3904 &HelpInfoString
[HelpInfoIndex
],
3905 TotalSize
- sizeof(CHAR16
) * HelpInfoIndex
,
3909 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3910 FormatHelpString
= NULL
;
3913 // Format content part, it depends on the type of signature list, hash value or CN.
3916 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
3917 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
3920 // Format hash value for each signature data entry.
3922 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
3923 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
3925 if (FormatHelpString
== NULL
) {
3928 HelpInfoIndex
+= UnicodeSPrint (
3929 &HelpInfoString
[HelpInfoIndex
],
3930 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3936 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3937 FormatHelpString
= NULL
;
3940 // Format revocation time part.
3943 ZeroMem (TimeString
, sizeof (TimeString
));
3946 sizeof (TimeString
),
3947 L
"%d-%d-%d %d:%d:%d",
3955 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
3956 if (FormatHelpString
== NULL
) {
3960 &HelpInfoString
[HelpInfoIndex
],
3961 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3965 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3966 FormatHelpString
= NULL
;
3969 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
3971 SECUREBOOT_FREE_NON_NULL (DataString
);
3972 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
3974 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3980 This function to load signature data under the signature list.
3982 @param[in] PrivateData Module's private data.
3983 @param[in] LabelId Label number to insert opcodes.
3984 @param[in] FormId Form ID of current page.
3985 @param[in] QuestionIdBase Base question id of the signature list.
3986 @param[in] ListIndex Indicate to load which signature list.
3988 @retval EFI_SUCCESS Success to update the signature list page
3989 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3993 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3995 IN EFI_FORM_ID FormId
,
3996 IN EFI_QUESTION_ID QuestionIdBase
,
4001 EFI_SIGNATURE_LIST
*ListWalker
;
4002 EFI_SIGNATURE_DATA
*DataWalker
;
4003 EFI_IFR_GUID_LABEL
*StartLabel
;
4004 EFI_IFR_GUID_LABEL
*EndLabel
;
4005 EFI_STRING_ID HelpStringId
;
4006 EFI_STRING FormatNameString
;
4007 VOID
*StartOpCodeHandle
;
4008 VOID
*EndOpCodeHandle
;
4010 UINTN RemainingSize
;
4012 UINT8
*VariableData
;
4013 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4014 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4016 Status
= EFI_SUCCESS
;
4017 FormatNameString
= NULL
;
4018 StartOpCodeHandle
= NULL
;
4019 EndOpCodeHandle
= NULL
;
4021 VariableData
= NULL
;
4024 // Initialize the container for dynamic opcodes.
4026 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4027 if (StartOpCodeHandle
== NULL
) {
4028 Status
= EFI_OUT_OF_RESOURCES
;
4032 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4033 if (EndOpCodeHandle
== NULL
) {
4034 Status
= EFI_OUT_OF_RESOURCES
;
4039 // Create Hii Extend Label OpCode.
4041 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4045 sizeof (EFI_IFR_GUID_LABEL
)
4047 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4048 StartLabel
->Number
= LabelId
;
4050 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4054 sizeof (EFI_IFR_GUID_LABEL
)
4056 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4057 EndLabel
->Number
= LABEL_END
;
4059 if (PrivateData
->VariableName
== Variable_DB
) {
4060 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4061 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4062 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4063 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4064 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4070 // Read Variable, the variable name save in the PrivateData->VariableName.
4073 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4074 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
4078 VariableData
= AllocateZeroPool (DataSize
);
4079 if (VariableData
== NULL
) {
4080 Status
= EFI_OUT_OF_RESOURCES
;
4083 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4084 if (EFI_ERROR (Status
)) {
4088 RemainingSize
= DataSize
;
4089 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4092 // Skip signature list.
4094 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4095 RemainingSize
-= ListWalker
->SignatureListSize
;
4096 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4099 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4100 if (FormatNameString
== NULL
) {
4104 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4105 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
4107 // Format name buffer.
4109 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4110 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4113 // Format help info buffer.
4115 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4116 if (EFI_ERROR (Status
)) {
4120 HiiCreateCheckBoxOpCode (
4122 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4125 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4127 EFI_IFR_FLAG_CALLBACK
,
4132 ZeroMem(NameBuffer
, 100);
4133 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4137 // Allocate a buffer to record which signature data will be checked.
4138 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4140 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4143 PrivateData
->HiiHandle
,
4144 &gSecureBootConfigFormSetGuid
,
4150 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4151 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4153 SECUREBOOT_FREE_NON_NULL (VariableData
);
4154 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4160 This function reinitializes Secure Boot variables with default values.
4162 @retval EFI_SUCCESS Success to update the signature list page
4163 @retval others Fail to delete or enroll signature data.
4174 Status
= EFI_SUCCESS
;
4176 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4177 if (EFI_ERROR(Status
)) {
4181 // Clear all the keys and databases
4182 Status
= DeleteDb ();
4183 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4184 DEBUG ((DEBUG_ERROR
, "Fail to clear DB: %r\n", Status
));
4188 Status
= DeleteDbx ();
4189 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4190 DEBUG ((DEBUG_ERROR
, "Fail to clear DBX: %r\n", Status
));
4194 Status
= DeleteDbt ();
4195 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4196 DEBUG ((DEBUG_ERROR
, "Fail to clear DBT: %r\n", Status
));
4200 Status
= DeleteKEK ();
4201 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4202 DEBUG ((DEBUG_ERROR
, "Fail to clear KEK: %r\n", Status
));
4206 Status
= DeletePlatformKey ();
4207 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4208 DEBUG ((DEBUG_ERROR
, "Fail to clear PK: %r\n", Status
));
4212 // After PK clear, Setup Mode shall be enabled
4213 Status
= GetSetupMode (&SetupMode
);
4214 if (EFI_ERROR (Status
)) {
4215 DEBUG ((DEBUG_ERROR
, "Cannot get SetupMode variable: %r\n",
4220 if (SetupMode
== USER_MODE
) {
4221 DEBUG((DEBUG_INFO
, "Skipped - USER_MODE\n"));
4225 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4226 if (EFI_ERROR (Status
)) {
4227 DEBUG ((DEBUG_ERROR
, "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n",
4232 // Enroll all the keys from default variables
4233 Status
= EnrollDbFromDefault ();
4234 if (EFI_ERROR (Status
)) {
4235 DEBUG ((DEBUG_ERROR
, "Cannot enroll db: %r\n", Status
));
4239 Status
= EnrollDbxFromDefault ();
4240 if (EFI_ERROR (Status
)) {
4241 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbx: %r\n", Status
));
4244 Status
= EnrollDbtFromDefault ();
4245 if (EFI_ERROR (Status
)) {
4246 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbt: %r\n", Status
));
4249 Status
= EnrollKEKFromDefault ();
4250 if (EFI_ERROR (Status
)) {
4251 DEBUG ((DEBUG_ERROR
, "Cannot enroll KEK: %r\n", Status
));
4255 Status
= EnrollPKFromDefault ();
4256 if (EFI_ERROR (Status
)) {
4257 DEBUG ((DEBUG_ERROR
, "Cannot enroll PK: %r\n", Status
));
4261 Status
= SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
4262 if (EFI_ERROR (Status
)) {
4263 DEBUG ((DEBUG_ERROR
, "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
4264 "Please do it manually, otherwise system can be easily compromised\n"));
4278 if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
) != EFI_SUCCESS
) {
4279 DEBUG ((DEBUG_ERROR
, "Cannot set mode to Secure: %r\n", Status
));
4285 This function is called to provide results data to the driver.
4287 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4288 @param[in] Action Specifies the type of action taken by the browser.
4289 @param[in] QuestionId A unique value which is sent to the original
4290 exporting driver so that it can identify the type
4292 @param[in] Type The type of value for the question.
4293 @param[in] Value A pointer to the data being sent to the original
4295 @param[out] ActionRequest On return, points to the action requested by the
4298 @retval EFI_SUCCESS The callback successfully handled the action.
4299 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4300 variable and its data.
4301 @retval EFI_DEVICE_ERROR The variable could not be saved.
4302 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4308 SecureBootCallback (
4309 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4310 IN EFI_BROWSER_ACTION Action
,
4311 IN EFI_QUESTION_ID QuestionId
,
4313 IN EFI_IFR_TYPE_VALUE
*Value
,
4314 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4319 RETURN_STATUS RStatus
;
4320 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4322 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4324 UINT8
*SecureBootEnable
;
4326 UINT8
*SecureBootMode
;
4328 CHAR16 PromptString
[100];
4329 EFI_DEVICE_PATH_PROTOCOL
*File
;
4331 UINT16
*FilePostFix
;
4332 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4333 BOOLEAN GetBrowserDataResult
;
4334 ENROLL_KEY_ERROR EnrollKeyErrorCode
;
4335 EFI_HII_POPUP_PROTOCOL
*HiiPopup
;
4336 EFI_HII_POPUP_SELECTION UserSelection
;
4338 Status
= EFI_SUCCESS
;
4339 SecureBootEnable
= NULL
;
4340 SecureBootMode
= NULL
;
4343 EnrollKeyErrorCode
= None_Error
;
4345 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4346 return EFI_INVALID_PARAMETER
;
4349 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4351 gSecureBootPrivateData
= Private
;
4354 // Retrieve uncommitted data from Browser
4356 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4357 IfrNvData
= AllocateZeroPool (BufferSize
);
4358 if (IfrNvData
== NULL
) {
4359 return EFI_OUT_OF_RESOURCES
;
4362 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
4364 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4365 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4367 // Update secure boot strings when opening this form
4369 Status
= UpdateSecureBootString(Private
);
4370 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4371 mIsEnterSecureBootForm
= TRUE
;
4374 // When entering SecureBoot OPTION Form
4375 // always close opened file & free resource
4377 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4378 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4379 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4380 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4381 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
4382 CloseEnrolledFile(Private
->FileContext
);
4383 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4385 // Update ListCount field in varstore
4386 // Button "Delete All Signature List" is
4387 // enable when ListCount is greater than 0.
4389 IfrNvData
->ListCount
= Private
->ListCount
;
4395 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4396 Status
= EFI_UNSUPPORTED
;
4397 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4398 if (mIsEnterSecureBootForm
) {
4399 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4400 Status
= EFI_SUCCESS
;
4406 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4407 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4408 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4409 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
4410 Status
= EFI_UNSUPPORTED
;
4414 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4416 switch (QuestionId
) {
4417 case KEY_SECURE_BOOT_ENABLE
:
4418 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4419 if (NULL
!= SecureBootEnable
) {
4420 FreePool (SecureBootEnable
);
4421 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4423 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4425 L
"Only Physical Presence User could disable secure boot!",
4428 Status
= EFI_UNSUPPORTED
;
4431 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4433 L
"Configuration changed, please reset the platform to take effect!",
4440 case KEY_SECURE_BOOT_KEK_OPTION
:
4441 case KEY_SECURE_BOOT_DB_OPTION
:
4442 case KEY_SECURE_BOOT_DBX_OPTION
:
4443 case KEY_SECURE_BOOT_DBT_OPTION
:
4444 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4446 // Clear Signature GUID.
4448 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4449 if (Private
->SignatureGUID
== NULL
) {
4450 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
4451 if (Private
->SignatureGUID
== NULL
) {
4452 return EFI_OUT_OF_RESOURCES
;
4457 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4459 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4461 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4462 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4463 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4464 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4465 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4466 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4468 LabelId
= FORMID_ENROLL_KEK_FORM
;
4472 // Refresh selected file.
4474 CleanUpPage (LabelId
, Private
);
4476 case KEY_SECURE_BOOT_PK_OPTION
:
4477 LabelId
= FORMID_ENROLL_PK_FORM
;
4479 // Refresh selected file.
4481 CleanUpPage (LabelId
, Private
);
4484 case FORMID_ENROLL_PK_FORM
:
4485 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4488 case FORMID_ENROLL_KEK_FORM
:
4489 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4492 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4493 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4496 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4497 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4499 if (Private
->FileContext
->FHandle
!= NULL
) {
4501 // Parse the file's postfix.
4503 NameLength
= StrLen (Private
->FileContext
->FileName
);
4504 if (NameLength
<= 4) {
4507 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4509 if (IsDerEncodeCertificate (FilePostFix
)) {
4511 // Supports DER-encoded X509 certificate.
4513 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4514 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
4515 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4517 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4519 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4522 // Clean up Certificate Format if File type is not X509 DER
4524 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4525 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4527 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4532 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4533 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4536 case KEY_SECURE_BOOT_DELETE_PK
:
4539 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4541 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4542 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4545 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
4546 Status
= DeletePlatformKey ();
4547 if (EFI_ERROR (Status
)) {
4549 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4551 L
"Only Physical Presence User could delete PK in custom mode!",
4559 case KEY_DELETE_KEK
:
4562 EFI_KEY_EXCHANGE_KEY_NAME
,
4563 &gEfiGlobalVariableGuid
,
4565 FORMID_DELETE_KEK_FORM
,
4566 OPTION_DEL_KEK_QUESTION_ID
4570 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4573 EFI_IMAGE_SECURITY_DATABASE
,
4574 &gEfiImageSecurityDatabaseGuid
,
4576 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4577 OPTION_DEL_DB_QUESTION_ID
4582 // From DBX option to the level-1 form, display signature list.
4584 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4585 Private
->VariableName
= Variable_DBX
;
4588 LABEL_SIGNATURE_LIST_START
,
4589 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4590 OPTION_SIGNATURE_LIST_QUESTION_ID
4595 // Delete all signature list and reload.
4597 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4599 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4601 L
"Press 'Y' to delete signature list.",
4602 L
"Press other key to cancel and exit.",
4606 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4607 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4612 LABEL_SIGNATURE_LIST_START
,
4613 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4614 OPTION_SIGNATURE_LIST_QUESTION_ID
4619 // Delete one signature list and reload.
4621 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4623 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4625 L
"Press 'Y' to delete signature data.",
4626 L
"Press other key to cancel and exit.",
4630 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4631 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4636 LABEL_SIGNATURE_LIST_START
,
4637 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4638 OPTION_SIGNATURE_LIST_QUESTION_ID
4643 // Delete checked signature data and reload.
4645 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4647 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4649 L
"Press 'Y' to delete signature data.",
4650 L
"Press other key to cancel and exit.",
4654 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4655 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4660 LABEL_SIGNATURE_LIST_START
,
4661 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4662 OPTION_SIGNATURE_LIST_QUESTION_ID
4666 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4669 EFI_IMAGE_SECURITY_DATABASE2
,
4670 &gEfiImageSecurityDatabaseGuid
,
4672 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4673 OPTION_DEL_DBT_QUESTION_ID
4678 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4679 Status
= EnrollKeyExchangeKey (Private
);
4680 if (EFI_ERROR (Status
)) {
4682 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4684 L
"ERROR: Unsupported file type!",
4685 L
"Only supports DER-encoded X509 certificate",
4691 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4692 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4693 if (EFI_ERROR (Status
)) {
4695 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4697 L
"ERROR: Unsupported file type!",
4698 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4704 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4705 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4707 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4709 L
"Enrollment failed! Same certificate had already been in the dbx!",
4714 // Cert already exists in DBX. Close opened file before exit.
4716 CloseEnrolledFile(Private
->FileContext
);
4720 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4721 Status
= EnrollX509HashtoSigDB (
4723 IfrNvData
->CertificateFormat
,
4724 &IfrNvData
->RevocationDate
,
4725 &IfrNvData
->RevocationTime
,
4726 IfrNvData
->AlwaysRevocation
4728 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4730 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4732 if (EFI_ERROR (Status
)) {
4734 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4736 L
"ERROR: Unsupported file type!",
4737 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4743 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4744 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4745 if (EFI_ERROR (Status
)) {
4747 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4749 L
"ERROR: Unsupported file type!",
4750 L
"Only supports DER-encoded X509 certificate.",
4755 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4757 // Check the suffix, encode type and the key strength of PK certificate.
4759 Status
= CheckX509Certificate (Private
->FileContext
, &EnrollKeyErrorCode
);
4760 if (EFI_ERROR (Status
)) {
4761 if (EnrollKeyErrorCode
!= None_Error
&& EnrollKeyErrorCode
< Enroll_Error_Max
) {
4763 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4765 mX509EnrollPromptTitle
[EnrollKeyErrorCode
],
4766 mX509EnrollPromptString
[EnrollKeyErrorCode
],
4772 Status
= EnrollPlatformKey (Private
);
4774 if (EFI_ERROR (Status
)) {
4777 sizeof (PromptString
),
4778 L
"Error status: %x.",
4782 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4784 L
"ERROR: Enrollment failed!",
4791 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4792 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4793 DeleteKeyExchangeKey (Private
, QuestionId
);
4794 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4795 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4798 EFI_IMAGE_SECURITY_DATABASE
,
4799 &gEfiImageSecurityDatabaseGuid
,
4801 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4802 OPTION_DEL_DB_QUESTION_ID
,
4803 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4805 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4806 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4809 LABEL_SIGNATURE_DATA_START
,
4810 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4811 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4812 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4814 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4815 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4816 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4817 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4818 IfrNvData
->CheckedDataCount
--;
4819 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4821 IfrNvData
->CheckedDataCount
++;
4822 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4824 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4825 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4828 EFI_IMAGE_SECURITY_DATABASE2
,
4829 &gEfiImageSecurityDatabaseGuid
,
4831 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4832 OPTION_DEL_DBT_QUESTION_ID
,
4833 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4838 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4839 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4840 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4841 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4842 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4843 CloseEnrolledFile(Private
->FileContext
);
4845 if (Private
->SignatureGUID
!= NULL
) {
4846 FreePool (Private
->SignatureGUID
);
4847 Private
->SignatureGUID
= NULL
;
4851 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4852 switch (QuestionId
) {
4853 case KEY_SECURE_BOOT_ENABLE
:
4854 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4856 case KEY_SECURE_BOOT_MODE
:
4857 mIsEnterSecureBootForm
= FALSE
;
4859 case KEY_SECURE_BOOT_KEK_GUID
:
4860 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4861 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4862 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4863 ASSERT (Private
->SignatureGUID
!= NULL
);
4864 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4865 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4866 Status
= EFI_INVALID_PARAMETER
;
4870 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4872 case KEY_SECURE_BOOT_DELETE_PK
:
4873 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4874 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
4875 IfrNvData
->DeletePk
= TRUE
;
4876 IfrNvData
->HasPk
= FALSE
;
4877 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4879 IfrNvData
->DeletePk
= FALSE
;
4880 IfrNvData
->HasPk
= TRUE
;
4881 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4883 if (SetupMode
!= NULL
) {
4884 FreePool (SetupMode
);
4887 case KEY_SECURE_BOOT_RESET_TO_DEFAULT
:
4889 Status
= gBS
->LocateProtocol (&gEfiHiiPopupProtocolGuid
, NULL
, (VOID
**) &HiiPopup
);
4890 if (EFI_ERROR (Status
)) {
4893 Status
= HiiPopup
->CreatePopup (
4895 EfiHiiPopupStyleInfo
,
4896 EfiHiiPopupTypeYesNo
,
4898 STRING_TOKEN (STR_RESET_TO_DEFAULTS_POPUP
),
4901 if (UserSelection
== EfiHiiPopupSelectionYes
) {
4902 Status
= KeyEnrollReset ();
4905 // Update secure boot strings after key reset
4907 if (Status
== EFI_SUCCESS
) {
4908 Status
= UpdateSecureBootString (Private
);
4909 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4915 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4916 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4917 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
4919 IfrNvData
->HideSecureBoot
= TRUE
;
4922 IfrNvData
->HideSecureBoot
= FALSE
;
4924 Value
->b
= IfrNvData
->HideSecureBoot
;
4926 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
4928 // Force the platform back to Standard Mode once user leave the setup screen.
4930 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
4931 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
4932 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
4933 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
4935 if (SecureBootMode
!= NULL
) {
4936 FreePool (SecureBootMode
);
4939 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
4941 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4943 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
4944 IfrNvData
->CheckedDataCount
= 0;
4950 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
4951 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4952 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
4955 FreePool (IfrNvData
);
4966 This function publish the SecureBoot configuration Form.
4968 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4970 @retval EFI_SUCCESS HII Form is installed successfully.
4971 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
4972 @retval Others Other errors as indicated.
4976 InstallSecureBootConfigForm (
4977 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4981 EFI_HII_HANDLE HiiHandle
;
4982 EFI_HANDLE DriverHandle
;
4983 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4985 DriverHandle
= NULL
;
4986 ConfigAccess
= &PrivateData
->ConfigAccess
;
4987 Status
= gBS
->InstallMultipleProtocolInterfaces (
4989 &gEfiDevicePathProtocolGuid
,
4990 &mSecureBootHiiVendorDevicePath
,
4991 &gEfiHiiConfigAccessProtocolGuid
,
4995 if (EFI_ERROR (Status
)) {
4999 PrivateData
->DriverHandle
= DriverHandle
;
5002 // Publish the HII package list
5004 HiiHandle
= HiiAddPackages (
5005 &gSecureBootConfigFormSetGuid
,
5007 SecureBootConfigDxeStrings
,
5008 SecureBootConfigBin
,
5011 if (HiiHandle
== NULL
) {
5012 gBS
->UninstallMultipleProtocolInterfaces (
5014 &gEfiDevicePathProtocolGuid
,
5015 &mSecureBootHiiVendorDevicePath
,
5016 &gEfiHiiConfigAccessProtocolGuid
,
5020 return EFI_OUT_OF_RESOURCES
;
5023 PrivateData
->HiiHandle
= HiiHandle
;
5025 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
5027 if (PrivateData
->FileContext
== NULL
) {
5028 UninstallSecureBootConfigForm (PrivateData
);
5029 return EFI_OUT_OF_RESOURCES
;
5033 // Init OpCode Handle and Allocate space for creation of Buffer
5035 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
5036 if (mStartOpCodeHandle
== NULL
) {
5037 UninstallSecureBootConfigForm (PrivateData
);
5038 return EFI_OUT_OF_RESOURCES
;
5041 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
5042 if (mEndOpCodeHandle
== NULL
) {
5043 UninstallSecureBootConfigForm (PrivateData
);
5044 return EFI_OUT_OF_RESOURCES
;
5048 // Create Hii Extend Label OpCode as the start opcode
5050 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
5054 sizeof (EFI_IFR_GUID_LABEL
)
5056 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5059 // Create Hii Extend Label OpCode as the end opcode
5061 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
5065 sizeof (EFI_IFR_GUID_LABEL
)
5067 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5068 mEndLabel
->Number
= LABEL_END
;
5074 This function removes SecureBoot configuration Form.
5076 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5080 UninstallSecureBootConfigForm (
5081 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5085 // Uninstall HII package list
5087 if (PrivateData
->HiiHandle
!= NULL
) {
5088 HiiRemovePackages (PrivateData
->HiiHandle
);
5089 PrivateData
->HiiHandle
= NULL
;
5093 // Uninstall HII Config Access Protocol
5095 if (PrivateData
->DriverHandle
!= NULL
) {
5096 gBS
->UninstallMultipleProtocolInterfaces (
5097 PrivateData
->DriverHandle
,
5098 &gEfiDevicePathProtocolGuid
,
5099 &mSecureBootHiiVendorDevicePath
,
5100 &gEfiHiiConfigAccessProtocolGuid
,
5101 &PrivateData
->ConfigAccess
,
5104 PrivateData
->DriverHandle
= NULL
;
5107 if (PrivateData
->SignatureGUID
!= NULL
) {
5108 FreePool (PrivateData
->SignatureGUID
);
5111 if (PrivateData
->FileContext
!= NULL
) {
5112 FreePool (PrivateData
->FileContext
);
5115 FreePool (PrivateData
);
5117 if (mStartOpCodeHandle
!= NULL
) {
5118 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5121 if (mEndOpCodeHandle
!= NULL
) {
5122 HiiFreeOpCodeHandle (mEndOpCodeHandle
);