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 <UefiSecureBoot.h>
12 #include <Protocol/HiiPopup.h>
13 #include <Library/BaseCryptLib.h>
14 #include <Library/SecureBootVariableLib.h>
15 #include <Library/SecureBootVariableProvisionLib.h>
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
)(END_DEVICE_PATH_LENGTH
),
45 (UINT8
)((END_DEVICE_PATH_LENGTH
) >> 8)
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
;
136 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
155 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
156 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
165 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
166 The function reads file content but won't open/close given FileHandle.
168 @param[in] FileHandle The FileHandle to be checked
170 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
171 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
175 IsAuthentication2Format (
176 IN EFI_FILE_HANDLE FileHandle
180 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
181 BOOLEAN IsAuth2Format
;
183 IsAuth2Format
= FALSE
;
186 // Read the whole file content
188 Status
= ReadFileContent (
190 (VOID
**)&mImageBase
,
194 if (EFI_ERROR (Status
)) {
198 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
199 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
203 if (CompareGuid (&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
204 IsAuth2Format
= TRUE
;
209 // Do not close File. simply check file content
211 if (mImageBase
!= NULL
) {
212 FreePool (mImageBase
);
216 return IsAuth2Format
;
220 Set Secure Boot option into variable space.
222 @param[in] VarValue The option of Secure Boot.
224 @retval EFI_SUCCESS The operation is finished successfully.
225 @retval Others Other errors as indicated.
229 SaveSecureBootVariable (
235 Status
= gRT
->SetVariable (
236 EFI_SECURE_BOOT_ENABLE_NAME
,
237 &gEfiSecureBootEnableDisableGuid
,
238 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
246 This code checks if the encode type and key strength of X.509
247 certificate is qualified.
249 @param[in] X509FileContext FileContext of X.509 certificate storing
251 @param[out] Error Error type checked in the certificate.
253 @return EFI_SUCCESS The certificate checked successfully.
254 @return EFI_INVALID_PARAMETER The parameter is invalid.
255 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
259 CheckX509Certificate (
260 IN SECUREBOOT_FILE_CONTEXT
*X509FileContext
,
261 OUT ENROLL_KEY_ERROR
*Error
272 if (X509FileContext
->FileName
== NULL
) {
273 *Error
= Unsupported_Type
;
274 return EFI_INVALID_PARAMETER
;
283 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
285 NameLength
= StrLen (X509FileContext
->FileName
);
286 if (NameLength
<= 4) {
287 DEBUG ((DEBUG_ERROR
, "Wrong X509 NameLength\n"));
288 *Error
= Unsupported_Type
;
289 return EFI_INVALID_PARAMETER
;
292 FilePostFix
= X509FileContext
->FileName
+ NameLength
- 4;
293 if (!IsDerEncodeCertificate (FilePostFix
)) {
294 DEBUG ((DEBUG_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix
));
295 *Error
= Unsupported_Type
;
296 return EFI_INVALID_PARAMETER
;
299 DEBUG ((DEBUG_INFO
, "FileName= %s\n", X509FileContext
->FileName
));
300 DEBUG ((DEBUG_INFO
, "FilePostFix = %s\n", FilePostFix
));
303 // Read the certificate file content
305 Status
= ReadFileContent (X509FileContext
->FHandle
, (VOID
**)&X509Data
, &X509DataSize
, 0);
306 if (EFI_ERROR (Status
)) {
307 DEBUG ((DEBUG_ERROR
, "Error occured while reading the file.\n"));
312 // Parse the public key context.
314 if (RsaGetPublicKeyFromX509 (X509Data
, X509DataSize
, &X509PubKey
) == FALSE
) {
315 DEBUG ((DEBUG_ERROR
, "Error occured while parsing the pubkey from certificate.\n"));
316 Status
= EFI_INVALID_PARAMETER
;
317 *Error
= Unsupported_Type
;
322 // Parse Module size of public key using interface provided by CryptoPkg, which is
323 // actually the size of public key.
325 if (X509PubKey
!= NULL
) {
326 RsaGetKey (X509PubKey
, RsaKeyN
, NULL
, &PubKeyModSize
);
327 if (PubKeyModSize
< CER_PUBKEY_MIN_SIZE
) {
328 DEBUG ((DEBUG_ERROR
, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
329 Status
= EFI_INVALID_PARAMETER
;
330 *Error
= Unqualified_Key
;
333 RsaFree (X509PubKey
);
337 if (X509Data
!= NULL
) {
345 Generate the PK signature list from the X509 Certificate storing file (.cer)
347 @param[in] X509File FileHandle of X509 Certificate storing file.
348 @param[out] PkCert Point to the data buffer to store the signature list.
350 @return EFI_UNSUPPORTED Unsupported Key Length.
351 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
355 CreatePkX509SignatureList (
356 IN EFI_FILE_HANDLE X509File
,
357 OUT EFI_SIGNATURE_LIST
**PkCert
363 EFI_SIGNATURE_DATA
*PkCertData
;
369 Status
= ReadFileContent (X509File
, (VOID
**)&X509Data
, &X509DataSize
, 0);
370 if (EFI_ERROR (Status
)) {
374 ASSERT (X509Data
!= NULL
);
377 // Allocate space for PK certificate list and initialize it.
378 // Create PK database entry with SignatureHeaderSize equals 0.
380 *PkCert
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (
381 sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1
384 if (*PkCert
== NULL
) {
385 Status
= EFI_OUT_OF_RESOURCES
;
389 (*PkCert
)->SignatureListSize
= (UINT32
)(sizeof (EFI_SIGNATURE_LIST
)
390 + sizeof (EFI_SIGNATURE_DATA
) - 1
392 (*PkCert
)->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
393 (*PkCert
)->SignatureHeaderSize
= 0;
394 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
395 PkCertData
= (EFI_SIGNATURE_DATA
*)((UINTN
)(*PkCert
)
396 + sizeof (EFI_SIGNATURE_LIST
)
397 + (*PkCert
)->SignatureHeaderSize
);
398 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
400 // Fill the PK database with PKpub data from X509 certificate file.
402 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
406 if (X509Data
!= NULL
) {
410 if (EFI_ERROR (Status
) && (*PkCert
!= NULL
)) {
419 Enroll new PK into the System without original PK's authentication.
421 The SignatureOwner GUID will be the same with PK's vendorguid.
423 @param[in] PrivateData The module's private data.
425 @retval EFI_SUCCESS New PK enrolled successfully.
426 @retval EFI_INVALID_PARAMETER The parameter is invalid.
427 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
432 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
438 EFI_SIGNATURE_LIST
*PkCert
;
442 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
443 if (EFI_ERROR (Status
)) {
448 // Prase the selected PK file and generate PK certificate list.
450 Status
= CreatePkX509SignatureList (
451 Private
->FileContext
->FHandle
,
454 if (EFI_ERROR (Status
)) {
458 ASSERT (PkCert
!= NULL
);
461 // Set Platform Key variable.
463 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
464 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
465 DataSize
= PkCert
->SignatureListSize
;
466 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**)&PkCert
);
467 if (EFI_ERROR (Status
)) {
468 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
472 Status
= gRT
->SetVariable (
473 EFI_PLATFORM_KEY_NAME
,
474 &gEfiGlobalVariableGuid
,
479 if (EFI_ERROR (Status
)) {
480 if (Status
== EFI_OUT_OF_RESOURCES
) {
481 DEBUG ((DEBUG_ERROR
, "Enroll PK failed with out of resource.\n"));
489 if (PkCert
!= NULL
) {
493 CloseEnrolledFile (Private
->FileContext
);
499 Enroll a new KEK item from public key storing file (*.pbk).
501 @param[in] PrivateData The module's private data.
503 @retval EFI_SUCCESS New KEK enrolled successfully.
504 @retval EFI_INVALID_PARAMETER The parameter is invalid.
505 @retval EFI_UNSUPPORTED Unsupported command.
506 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
511 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
517 EFI_SIGNATURE_LIST
*KekSigList
;
520 CPL_KEY_INFO
*KeyInfo
;
521 EFI_SIGNATURE_DATA
*KEKSigData
;
522 UINTN KekSigListSize
;
537 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
538 // First, We have to parse out public key data from the pbk key file.
540 Status
= ReadFileContent (
541 Private
->FileContext
->FHandle
,
546 if (EFI_ERROR (Status
)) {
550 ASSERT (KeyBlob
!= NULL
);
551 KeyInfo
= (CPL_KEY_INFO
*)KeyBlob
;
552 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
553 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
554 Status
= EFI_UNSUPPORTED
;
559 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
561 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
562 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
563 if (KeyBuffer
== NULL
) {
564 Status
= EFI_OUT_OF_RESOURCES
;
569 (UINTN
*)(KeyBlob
+ sizeof (CPL_KEY_INFO
)),
570 KeyLenInBytes
/ sizeof (UINTN
),
574 CopyMem (KeyBlob
+ sizeof (CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
577 // Form an new EFI_SIGNATURE_LIST.
579 KekSigListSize
= sizeof (EFI_SIGNATURE_LIST
)
580 + sizeof (EFI_SIGNATURE_DATA
) - 1
581 + WIN_CERT_UEFI_RSA2048_SIZE
;
583 KekSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (KekSigListSize
);
584 if (KekSigList
== NULL
) {
585 Status
= EFI_OUT_OF_RESOURCES
;
589 KekSigList
->SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
)
590 + sizeof (EFI_SIGNATURE_DATA
) - 1
591 + WIN_CERT_UEFI_RSA2048_SIZE
;
592 KekSigList
->SignatureHeaderSize
= 0;
593 KekSigList
->SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
594 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
596 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
597 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
599 KEKSigData
->SignatureData
,
600 KeyBlob
+ sizeof (CPL_KEY_INFO
),
601 WIN_CERT_UEFI_RSA2048_SIZE
605 // Check if KEK entry has been already existed.
606 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
607 // new KEK to original variable.
609 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
610 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
611 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**)&KekSigList
);
612 if (EFI_ERROR (Status
)) {
613 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
617 Status
= gRT
->GetVariable (
618 EFI_KEY_EXCHANGE_KEY_NAME
,
619 &gEfiGlobalVariableGuid
,
624 if (Status
== EFI_BUFFER_TOO_SMALL
) {
625 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
626 } else if (Status
!= EFI_NOT_FOUND
) {
631 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
633 Status
= gRT
->SetVariable (
634 EFI_KEY_EXCHANGE_KEY_NAME
,
635 &gEfiGlobalVariableGuid
,
640 if (EFI_ERROR (Status
)) {
646 CloseEnrolledFile (Private
->FileContext
);
648 if (Private
->SignatureGUID
!= NULL
) {
649 FreePool (Private
->SignatureGUID
);
650 Private
->SignatureGUID
= NULL
;
653 if (KeyBlob
!= NULL
) {
657 if (KeyBuffer
!= NULL
) {
658 FreePool (KeyBuffer
);
661 if (KekSigList
!= NULL
) {
662 FreePool (KekSigList
);
669 Enroll a new KEK item from X509 certificate file.
671 @param[in] PrivateData The module's private data.
673 @retval EFI_SUCCESS New X509 is enrolled successfully.
674 @retval EFI_INVALID_PARAMETER The parameter is invalid.
675 @retval EFI_UNSUPPORTED Unsupported command.
676 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
681 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
687 EFI_SIGNATURE_DATA
*KEKSigData
;
688 EFI_SIGNATURE_LIST
*KekSigList
;
690 UINTN KekSigListSize
;
700 Status
= ReadFileContent (
701 Private
->FileContext
->FHandle
,
706 if (EFI_ERROR (Status
)) {
710 ASSERT (X509Data
!= NULL
);
712 KekSigListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
713 KekSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (KekSigListSize
);
714 if (KekSigList
== NULL
) {
715 Status
= EFI_OUT_OF_RESOURCES
;
720 // Fill Certificate Database parameters.
722 KekSigList
->SignatureListSize
= (UINT32
)KekSigListSize
;
723 KekSigList
->SignatureHeaderSize
= 0;
724 KekSigList
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
725 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
727 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
728 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
729 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
732 // Check if KEK been already existed.
733 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
734 // new kek to original variable
736 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
737 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
738 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**)&KekSigList
);
739 if (EFI_ERROR (Status
)) {
740 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
744 Status
= gRT
->GetVariable (
745 EFI_KEY_EXCHANGE_KEY_NAME
,
746 &gEfiGlobalVariableGuid
,
751 if (Status
== EFI_BUFFER_TOO_SMALL
) {
752 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
753 } else if (Status
!= EFI_NOT_FOUND
) {
757 Status
= gRT
->SetVariable (
758 EFI_KEY_EXCHANGE_KEY_NAME
,
759 &gEfiGlobalVariableGuid
,
764 if (EFI_ERROR (Status
)) {
770 CloseEnrolledFile (Private
->FileContext
);
772 if (Private
->SignatureGUID
!= NULL
) {
773 FreePool (Private
->SignatureGUID
);
774 Private
->SignatureGUID
= NULL
;
777 if (KekSigList
!= NULL
) {
778 FreePool (KekSigList
);
785 Enroll new KEK into the System without PK's authentication.
786 The SignatureOwner GUID will be Private->SignatureGUID.
788 @param[in] PrivateData The module's private data.
790 @retval EFI_SUCCESS New KEK enrolled successful.
791 @retval EFI_INVALID_PARAMETER The parameter is invalid.
792 @retval others Fail to enroll KEK data.
796 EnrollKeyExchangeKey (
797 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
804 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
805 return EFI_INVALID_PARAMETER
;
808 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
809 if (EFI_ERROR (Status
)) {
814 // Parse the file's postfix. Supports DER-encoded X509 certificate,
815 // and .pbk as RSA public key file.
817 NameLength
= StrLen (Private
->FileContext
->FileName
);
818 if (NameLength
<= 4) {
819 return EFI_INVALID_PARAMETER
;
822 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
823 if (IsDerEncodeCertificate (FilePostFix
)) {
824 return EnrollX509ToKek (Private
);
825 } else if (CompareMem (FilePostFix
, L
".pbk", 4) == 0) {
826 return EnrollRsa2048ToKek (Private
);
829 // File type is wrong, simply close it
831 CloseEnrolledFile (Private
->FileContext
);
833 return EFI_INVALID_PARAMETER
;
838 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
839 KEK's authentication.
841 @param[in] PrivateData The module's private data.
842 @param[in] VariableName Variable name of signature database, must be
843 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
845 @retval EFI_SUCCESS New X509 is enrolled successfully.
846 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
851 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
852 IN CHAR16
*VariableName
858 EFI_SIGNATURE_LIST
*SigDBCert
;
859 EFI_SIGNATURE_DATA
*SigDBCertData
;
870 SigDBCertData
= NULL
;
873 Status
= ReadFileContent (
874 Private
->FileContext
->FHandle
,
879 if (EFI_ERROR (Status
)) {
883 ASSERT (X509Data
!= NULL
);
885 SigDBSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
887 Data
= AllocateZeroPool (SigDBSize
);
889 Status
= EFI_OUT_OF_RESOURCES
;
894 // Fill Certificate Database parameters.
896 SigDBCert
= (EFI_SIGNATURE_LIST
*)Data
;
897 SigDBCert
->SignatureListSize
= (UINT32
)SigDBSize
;
898 SigDBCert
->SignatureHeaderSize
= 0;
899 SigDBCert
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
900 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
902 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
903 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
904 CopyMem ((UINT8
*)(SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
907 // Check if signature database entry has been already existed.
908 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
909 // new signature data to original variable
911 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
912 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
913 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**)&Data
);
914 if (EFI_ERROR (Status
)) {
915 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
919 Status
= gRT
->GetVariable (
921 &gEfiImageSecurityDatabaseGuid
,
926 if (Status
== EFI_BUFFER_TOO_SMALL
) {
927 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
928 } else if (Status
!= EFI_NOT_FOUND
) {
932 Status
= gRT
->SetVariable (
934 &gEfiImageSecurityDatabaseGuid
,
939 if (EFI_ERROR (Status
)) {
945 CloseEnrolledFile (Private
->FileContext
);
947 if (Private
->SignatureGUID
!= NULL
) {
948 FreePool (Private
->SignatureGUID
);
949 Private
->SignatureGUID
= NULL
;
956 if (X509Data
!= NULL
) {
964 Check whether signature is in specified database.
966 @param[in] VariableName Name of database variable that is searched in.
967 @param[in] Signature Pointer to signature that is searched for.
968 @param[in] SignatureSize Size of Signature.
970 @return TRUE Found the signature in the variable database.
971 @return FALSE Not found the signature in the variable database.
975 IsSignatureFoundInDatabase (
976 IN CHAR16
*VariableName
,
978 IN UINTN SignatureSize
982 EFI_SIGNATURE_LIST
*CertList
;
983 EFI_SIGNATURE_DATA
*Cert
;
991 // Read signature database variable.
996 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
997 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1001 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1006 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1007 if (EFI_ERROR (Status
)) {
1012 // Enumerate all signature data in SigDB to check if signature exists for executable.
1014 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
1015 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1016 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1017 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1018 if ((CertList
->SignatureSize
== sizeof (EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1019 for (Index
= 0; Index
< CertCount
; Index
++) {
1020 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1022 // Find the signature in database.
1028 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
1036 DataSize
-= CertList
->SignatureListSize
;
1037 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
1049 Calculate the hash of a certificate data with the specified hash algorithm.
1051 @param[in] CertData The certificate data to be hashed.
1052 @param[in] CertSize The certificate size in bytes.
1053 @param[in] HashAlg The specified hash algorithm.
1054 @param[out] CertHash The output digest of the certificate
1056 @retval TRUE Successfully got the hash of the CertData.
1057 @retval FALSE Failed to get the hash of CertData.
1077 if (HashAlg
>= HASHALG_MAX
) {
1082 // Retrieve the TBSCertificate for Hash Calculation.
1084 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1089 // 1. Initialize context of hash.
1091 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1092 HashCtx
= AllocatePool (CtxSize
);
1093 ASSERT (HashCtx
!= NULL
);
1096 // 2. Initialize a hash context.
1098 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1104 // 3. Calculate the hash.
1106 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1112 // 4. Get the hash result.
1114 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1115 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1118 if (HashCtx
!= NULL
) {
1126 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1128 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1129 @param[in] CertSize Size of X.509 Certificate.
1131 @return TRUE Found the certificate hash in the forbidden database.
1132 @return FALSE Certificate hash is Not found in the forbidden database.
1136 IsCertHashFoundInDbx (
1137 IN UINT8
*Certificate
,
1143 EFI_SIGNATURE_LIST
*DbxList
;
1144 EFI_SIGNATURE_DATA
*CertHash
;
1145 UINTN CertHashCount
;
1148 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1150 UINTN SiglistHeaderSize
;
1155 HashAlg
= HASHALG_MAX
;
1159 // Read signature database variable.
1162 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1163 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1167 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1172 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1173 if (EFI_ERROR (Status
)) {
1178 // Check whether the certificate hash exists in the forbidden database.
1180 DbxList
= (EFI_SIGNATURE_LIST
*)Data
;
1181 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1183 // Determine Hash Algorithm of Certificate in the forbidden database.
1185 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1186 HashAlg
= HASHALG_SHA256
;
1187 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1188 HashAlg
= HASHALG_SHA384
;
1189 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1190 HashAlg
= HASHALG_SHA512
;
1192 DataSize
-= DbxList
->SignatureListSize
;
1193 DbxList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)DbxList
+ DbxList
->SignatureListSize
);
1198 // Calculate the hash value of current db certificate for comparision.
1200 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1204 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1205 CertHash
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DbxList
+ SiglistHeaderSize
);
1206 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1207 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1209 // Iterate each Signature Data Node within this CertList for verify.
1211 DbxCertHash
= CertHash
->SignatureData
;
1212 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1214 // Hash of Certificate is found in forbidden database.
1220 CertHash
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertHash
+ DbxList
->SignatureSize
);
1223 DataSize
-= DbxList
->SignatureListSize
;
1224 DbxList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)DbxList
+ DbxList
->SignatureListSize
);
1236 Check whether the signature list exists in given variable data.
1238 It searches the signature list for the certificate hash by CertType.
1239 If the signature list is found, get the offset of Database for the
1240 next hash of a certificate.
1242 @param[in] Database Variable data to save signature list.
1243 @param[in] DatabaseSize Variable size.
1244 @param[in] SignatureType The type of the signature.
1245 @param[out] Offset The offset to save a new hash of certificate.
1247 @return TRUE The signature list is found in the forbidden database.
1248 @return FALSE The signature list is not found in the forbidden database.
1251 GetSignaturelistOffset (
1252 IN EFI_SIGNATURE_LIST
*Database
,
1253 IN UINTN DatabaseSize
,
1254 IN EFI_GUID
*SignatureType
,
1258 EFI_SIGNATURE_LIST
*SigList
;
1261 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1267 SiglistSize
= DatabaseSize
;
1268 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1269 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1270 *Offset
= DatabaseSize
- SiglistSize
;
1274 SiglistSize
-= SigList
->SignatureListSize
;
1275 SigList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)SigList
+ SigList
->SignatureListSize
);
1283 Enroll a new X509 certificate hash into Signature Database (dbx) without
1284 KEK's authentication.
1286 @param[in] PrivateData The module's private data.
1287 @param[in] HashAlg The hash algorithm to enroll the certificate.
1288 @param[in] RevocationDate The revocation date of the certificate.
1289 @param[in] RevocationTime The revocation time of the certificate.
1290 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1292 @retval EFI_SUCCESS New X509 is enrolled successfully.
1293 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1294 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1298 EnrollX509HashtoSigDB (
1299 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1301 IN EFI_HII_DATE
*RevocationDate
,
1302 IN EFI_HII_TIME
*RevocationTime
,
1303 IN BOOLEAN AlwaysRevocation
1309 EFI_SIGNATURE_LIST
*SignatureList
;
1310 UINTN SignatureListSize
;
1316 EFI_SIGNATURE_DATA
*SignatureData
;
1317 UINTN SignatureSize
;
1318 EFI_GUID SignatureType
;
1320 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1321 UINT16
*FilePostFix
;
1328 SignatureData
= NULL
;
1329 SignatureList
= NULL
;
1333 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1334 return EFI_INVALID_PARAMETER
;
1337 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1338 if (EFI_ERROR (Status
)) {
1343 // Parse the file's postfix.
1345 NameLength
= StrLen (Private
->FileContext
->FileName
);
1346 if (NameLength
<= 4) {
1347 return EFI_INVALID_PARAMETER
;
1350 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1351 if (!IsDerEncodeCertificate (FilePostFix
)) {
1353 // Only supports DER-encoded X509 certificate.
1355 return EFI_INVALID_PARAMETER
;
1359 // Get the certificate from file and calculate its hash.
1361 Status
= ReadFileContent (
1362 Private
->FileContext
->FHandle
,
1367 if (EFI_ERROR (Status
)) {
1371 ASSERT (X509Data
!= NULL
);
1373 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1378 // Get the variable for enrollment.
1381 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1382 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1383 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1385 return EFI_OUT_OF_RESOURCES
;
1388 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1389 if (EFI_ERROR (Status
)) {
1395 // Allocate memory for Signature and fill the Signature
1397 SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1398 SignatureData
= (EFI_SIGNATURE_DATA
*)AllocateZeroPool (SignatureSize
);
1399 if (SignatureData
== NULL
) {
1400 return EFI_OUT_OF_RESOURCES
;
1403 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1404 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1409 if (!AlwaysRevocation
) {
1410 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1411 Time
->Year
= RevocationDate
->Year
;
1412 Time
->Month
= RevocationDate
->Month
;
1413 Time
->Day
= RevocationDate
->Day
;
1414 Time
->Hour
= RevocationTime
->Hour
;
1415 Time
->Minute
= RevocationTime
->Minute
;
1416 Time
->Second
= RevocationTime
->Second
;
1420 // Determine the GUID for certificate hash.
1423 case HASHALG_SHA256
:
1424 SignatureType
= gEfiCertX509Sha256Guid
;
1426 case HASHALG_SHA384
:
1427 SignatureType
= gEfiCertX509Sha384Guid
;
1429 case HASHALG_SHA512
:
1430 SignatureType
= gEfiCertX509Sha512Guid
;
1437 // Add signature into the new variable data buffer
1439 if (GetSignaturelistOffset ((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1441 // Add the signature to the found signaturelist.
1443 DbSize
= DataSize
+ SignatureSize
;
1444 NewData
= AllocateZeroPool (DbSize
);
1445 if (NewData
== NULL
) {
1446 Status
= EFI_OUT_OF_RESOURCES
;
1450 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1451 SignatureListSize
= (UINTN
)ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1452 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1454 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1455 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1457 Offset
+= SignatureListSize
;
1458 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1459 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1466 // Create a new signaturelist, and add the signature into the signaturelist.
1468 DbSize
= DataSize
+ sizeof (EFI_SIGNATURE_LIST
) + SignatureSize
;
1469 NewData
= AllocateZeroPool (DbSize
);
1470 if (NewData
== NULL
) {
1471 Status
= EFI_OUT_OF_RESOURCES
;
1476 // Fill Certificate Database parameters.
1478 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ DataSize
);
1479 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + SignatureSize
;
1480 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
, (UINT32
)SignatureListSize
);
1481 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureSize
, (UINT32
)SignatureSize
);
1482 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1483 CopyMem ((UINT8
*)SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1484 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1485 CopyMem (NewData
, Data
, DataSize
);
1493 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**)&Data
);
1494 if (EFI_ERROR (Status
)) {
1498 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1499 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1500 Status
= gRT
->SetVariable (
1501 EFI_IMAGE_SECURITY_DATABASE1
,
1502 &gEfiImageSecurityDatabaseGuid
,
1507 if (EFI_ERROR (Status
)) {
1513 CloseEnrolledFile (Private
->FileContext
);
1515 if (Private
->SignatureGUID
!= NULL
) {
1516 FreePool (Private
->SignatureGUID
);
1517 Private
->SignatureGUID
= NULL
;
1524 if (SignatureData
!= NULL
) {
1525 FreePool (SignatureData
);
1528 if (X509Data
!= NULL
) {
1529 FreePool (X509Data
);
1536 Check whether a certificate from a file exists in dbx.
1538 @param[in] PrivateData The module's private data.
1539 @param[in] VariableName Variable name of signature database, must be
1540 EFI_IMAGE_SECURITY_DATABASE1.
1542 @retval TRUE The X509 certificate is found in dbx successfully.
1543 @retval FALSE The X509 certificate is not found in dbx.
1547 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1548 IN CHAR16
*VariableName
1557 // Read the certificate from file
1561 Status
= ReadFileContent (
1562 Private
->FileContext
->FHandle
,
1567 if (EFI_ERROR (Status
)) {
1572 // Check the raw certificate.
1575 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1581 // Check the hash of certificate.
1583 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1589 if (X509Data
!= NULL
) {
1590 FreePool (X509Data
);
1597 Reads contents of a PE/COFF image in memory buffer.
1599 Caution: This function may receive untrusted input.
1600 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1601 read is within the image buffer.
1603 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1604 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1605 @param ReadSize On input, the size in bytes of the requested read operation.
1606 On output, the number of bytes actually read.
1607 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1609 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1613 SecureBootConfigImageRead (
1614 IN VOID
*FileHandle
,
1615 IN UINTN FileOffset
,
1616 IN OUT UINTN
*ReadSize
,
1622 if ((FileHandle
== NULL
) || (ReadSize
== NULL
) || (Buffer
== NULL
)) {
1623 return EFI_INVALID_PARAMETER
;
1626 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1627 return EFI_INVALID_PARAMETER
;
1630 EndPosition
= FileOffset
+ *ReadSize
;
1631 if (EndPosition
> mImageSize
) {
1632 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1635 if (FileOffset
>= mImageSize
) {
1639 CopyMem (Buffer
, (UINT8
*)((UINTN
)FileHandle
+ FileOffset
), *ReadSize
);
1645 Load PE/COFF image information into internal buffer and check its validity.
1647 @retval EFI_SUCCESS Successful
1648 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1649 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1657 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1658 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1659 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1660 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1666 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1667 ImageContext
.Handle
= (VOID
*)mImageBase
;
1668 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)SecureBootConfigImageRead
;
1671 // Get information about the image being loaded
1673 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1674 if (EFI_ERROR (Status
)) {
1676 // The information can't be got from the invalid PeImage
1678 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1683 // Read the Dos header
1685 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1686 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1688 // DOS image header is present,
1689 // So read the PE header after the DOS image header
1691 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1693 mPeCoffHeaderOffset
= 0;
1697 // Read PE header and check the signature validity and machine compatibility
1699 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*)(mImageBase
+ mPeCoffHeaderOffset
);
1700 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1701 return EFI_UNSUPPORTED
;
1704 mNtHeader
.Pe32
= NtHeader32
;
1707 // Check the architecture field of PE header and get the Certificate Data Directory data
1708 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1710 if ( (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1711 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1712 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
))
1715 // 32-bits Architecture
1717 mImageType
= ImageType_IA32
;
1718 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*)&(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1719 } else if ( (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1720 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1721 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
))
1724 // 64-bits Architecture
1726 mImageType
= ImageType_X64
;
1727 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*)(mImageBase
+ mPeCoffHeaderOffset
);
1728 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*)&(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1730 return EFI_UNSUPPORTED
;
1737 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1738 PE/COFF Specification 8.0 Appendix A
1740 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1741 the function LoadPeImage ().
1743 @param[in] HashAlg Hash algorithm type.
1745 @retval TRUE Successfully hash image.
1746 @retval FALSE Fail in hash image.
1755 EFI_IMAGE_SECTION_HEADER
*Section
;
1760 UINTN SumOfBytesHashed
;
1761 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1766 SectionHeader
= NULL
;
1769 if (HashAlg
!= HASHALG_SHA256
) {
1774 // Initialize context of hash.
1776 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1778 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1779 mCertType
= gEfiCertSha256Guid
;
1781 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1783 HashCtx
= AllocatePool (CtxSize
);
1784 ASSERT (HashCtx
!= NULL
);
1786 // 1. Load the image header into memory.
1788 // 2. Initialize a SHA hash context.
1789 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1795 // Measuring PE/COFF Image Header;
1796 // But CheckSum field and SECURITY data directory (certificate) are excluded
1800 // 3. Calculate the distance from the base of the image header to the image checksum address.
1801 // 4. Hash the image header from its base to beginning of the image checksum.
1803 HashBase
= mImageBase
;
1804 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1808 HashSize
= (UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
)HashBase
;
1811 // Use PE32+ offset.
1813 HashSize
= (UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
)HashBase
;
1816 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1822 // 5. Skip over the image checksum (it occupies a single ULONG).
1823 // 6. Get the address of the beginning of the Cert Directory.
1824 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1826 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1830 HashBase
= (UINT8
*)&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1831 HashSize
= (UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
)HashBase
;
1834 // Use PE32+ offset.
1836 HashBase
= (UINT8
*)&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1837 HashSize
= (UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
)HashBase
;
1840 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1846 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1847 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1849 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1853 HashBase
= (UINT8
*)&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1854 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
)mImageBase
);
1857 // Use PE32+ offset.
1859 HashBase
= (UINT8
*)&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1860 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
)mImageBase
);
1863 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1869 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1871 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1875 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1880 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1884 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1885 // structures in the image. The 'NumberOfSections' field of the image
1886 // header indicates how big the table should be. Do not include any
1887 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1889 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1890 ASSERT (SectionHeader
!= NULL
);
1892 // 12. Using the 'PointerToRawData' in the referenced section headers as
1893 // a key, arrange the elements in the table in ascending order. In other
1894 // words, sort the section headers according to the disk-file offset of
1897 Section
= (EFI_IMAGE_SECTION_HEADER
*)(
1899 mPeCoffHeaderOffset
+
1901 sizeof (EFI_IMAGE_FILE_HEADER
) +
1902 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1904 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1906 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1907 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1911 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1916 // 13. Walk through the sorted table, bring the corresponding section
1917 // into memory, and hash the entire section (using the 'SizeOfRawData'
1918 // field in the section header to determine the amount of data to hash).
1919 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1920 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1922 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1923 Section
= &SectionHeader
[Index
];
1924 if (Section
->SizeOfRawData
== 0) {
1928 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1929 HashSize
= (UINTN
)Section
->SizeOfRawData
;
1931 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1936 SumOfBytesHashed
+= HashSize
;
1940 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1941 // data in the file that needs to be added to the hash. This data begins
1942 // at file offset SUM_OF_BYTES_HASHED and its length is:
1943 // FileSize - (CertDirectory->Size)
1945 if (mImageSize
> SumOfBytesHashed
) {
1946 HashBase
= mImageBase
+ SumOfBytesHashed
;
1947 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1953 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1957 // Use PE32+ offset.
1961 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1965 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1971 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, mImageDigest
);
1974 if (HashCtx
!= NULL
) {
1978 if (SectionHeader
!= NULL
) {
1979 FreePool (SectionHeader
);
1986 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
1987 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1990 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1991 @retval EFI_SUCCESS Hash successfully.
2000 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2002 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*)(mImageBase
+ mSecDataDir
->Offset
);
2004 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2006 // Check the Hash algorithm in PE/COFF Authenticode.
2007 // According to PKCS#7 Definition:
2008 // SignedData ::= SEQUENCE {
2010 // digestAlgorithms DigestAlgorithmIdentifiers,
2011 // contentInfo ContentInfo,
2013 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2014 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2015 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2017 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2019 // Only support two bytes of Long Form of Length Encoding.
2025 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2030 if (Index
== HASHALG_MAX
) {
2031 return EFI_UNSUPPORTED
;
2035 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2037 if (!HashPeImage (Index
)) {
2038 return EFI_UNSUPPORTED
;
2045 Enroll a new signature of executable into Signature Database.
2047 @param[in] PrivateData The module's private data.
2048 @param[in] VariableName Variable name of signature database, must be
2049 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2050 or EFI_IMAGE_SECURITY_DATABASE2.
2052 @retval EFI_SUCCESS New signature is enrolled successfully.
2053 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2054 @retval EFI_UNSUPPORTED Unsupported command.
2055 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2059 EnrollAuthentication2Descriptor (
2060 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2061 IN CHAR16
*VariableName
2072 // DBT only support DER-X509 Cert Enrollment
2074 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2075 return EFI_UNSUPPORTED
;
2079 // Read the whole file content
2081 Status
= ReadFileContent (
2082 Private
->FileContext
->FHandle
,
2083 (VOID
**)&mImageBase
,
2087 if (EFI_ERROR (Status
)) {
2091 ASSERT (mImageBase
!= NULL
);
2093 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2094 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2097 // Check if SigDB variable has been already existed.
2098 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2099 // new signature data to original variable
2102 Status
= gRT
->GetVariable (
2104 &gEfiImageSecurityDatabaseGuid
,
2109 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2110 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2111 } else if (Status
!= EFI_NOT_FOUND
) {
2116 // Directly set AUTHENTICATION_2 data to SetVariable
2118 Status
= gRT
->SetVariable (
2120 &gEfiImageSecurityDatabaseGuid
,
2126 DEBUG ((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2130 CloseEnrolledFile (Private
->FileContext
);
2136 if (mImageBase
!= NULL
) {
2137 FreePool (mImageBase
);
2145 Enroll a new signature of executable into Signature Database.
2147 @param[in] PrivateData The module's private data.
2148 @param[in] VariableName Variable name of signature database, must be
2149 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2150 or EFI_IMAGE_SECURITY_DATABASE2.
2152 @retval EFI_SUCCESS New signature is enrolled successfully.
2153 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2154 @retval EFI_UNSUPPORTED Unsupported command.
2155 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2159 EnrollImageSignatureToSigDB (
2160 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2161 IN CHAR16
*VariableName
2165 EFI_SIGNATURE_LIST
*SigDBCert
;
2166 EFI_SIGNATURE_DATA
*SigDBCertData
;
2171 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2174 GuidCertData
= NULL
;
2176 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2177 return EFI_UNSUPPORTED
;
2181 // Form the SigDB certificate list.
2182 // Format the data item into EFI_SIGNATURE_LIST type.
2184 // We need to parse signature data of executable from specified signed executable file.
2185 // In current implementation, we simply trust the pass-in signed executable file.
2186 // In reality, it's OS's responsibility to verify the signed executable file.
2190 // Read the whole file content
2192 Status
= ReadFileContent (
2193 Private
->FileContext
->FHandle
,
2194 (VOID
**)&mImageBase
,
2198 if (EFI_ERROR (Status
)) {
2202 ASSERT (mImageBase
!= NULL
);
2204 Status
= LoadPeImage ();
2205 if (EFI_ERROR (Status
)) {
2209 if (mSecDataDir
->SizeOfCert
== 0) {
2210 if (!HashPeImage (HASHALG_SHA256
)) {
2211 Status
= EFI_SECURITY_VIOLATION
;
2216 // Read the certificate data
2218 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2220 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2221 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*)mCertificate
;
2222 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof (EFI_GUID
)) != 0) {
2223 Status
= EFI_ABORTED
;
2227 if (!HashPeImage (HASHALG_SHA256
)) {
2228 Status
= EFI_ABORTED
;
2231 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2232 Status
= HashPeImageByType ();
2233 if (EFI_ERROR (Status
)) {
2237 Status
= EFI_ABORTED
;
2243 // Create a new SigDB entry.
2245 SigDBSize
= sizeof (EFI_SIGNATURE_LIST
)
2246 + sizeof (EFI_SIGNATURE_DATA
) - 1
2247 + (UINT32
)mImageDigestSize
;
2249 Data
= (UINT8
*)AllocateZeroPool (SigDBSize
);
2251 Status
= EFI_OUT_OF_RESOURCES
;
2256 // Adjust the Certificate Database parameters.
2258 SigDBCert
= (EFI_SIGNATURE_LIST
*)Data
;
2259 SigDBCert
->SignatureListSize
= (UINT32
)SigDBSize
;
2260 SigDBCert
->SignatureHeaderSize
= 0;
2261 SigDBCert
->SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + (UINT32
)mImageDigestSize
;
2262 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2264 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
2265 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2266 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2268 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2269 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2270 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**)&Data
);
2271 if (EFI_ERROR (Status
)) {
2272 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2277 // Check if SigDB variable has been already existed.
2278 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2279 // new signature data to original variable
2282 Status
= gRT
->GetVariable (
2284 &gEfiImageSecurityDatabaseGuid
,
2289 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2290 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2291 } else if (Status
!= EFI_NOT_FOUND
) {
2296 // Enroll the variable.
2298 Status
= gRT
->SetVariable (
2300 &gEfiImageSecurityDatabaseGuid
,
2305 if (EFI_ERROR (Status
)) {
2311 CloseEnrolledFile (Private
->FileContext
);
2313 if (Private
->SignatureGUID
!= NULL
) {
2314 FreePool (Private
->SignatureGUID
);
2315 Private
->SignatureGUID
= NULL
;
2322 if (mImageBase
!= NULL
) {
2323 FreePool (mImageBase
);
2331 Enroll signature into DB/DBX/DBT without KEK's authentication.
2332 The SignatureOwner GUID will be Private->SignatureGUID.
2334 @param[in] PrivateData The module's private data.
2335 @param[in] VariableName Variable name of signature database, must be
2336 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2338 @retval EFI_SUCCESS New signature enrolled successfully.
2339 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2340 @retval others Fail to enroll signature data.
2344 EnrollSignatureDatabase (
2345 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2346 IN CHAR16
*VariableName
2349 UINT16
*FilePostFix
;
2353 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2354 return EFI_INVALID_PARAMETER
;
2357 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2358 if (EFI_ERROR (Status
)) {
2363 // Parse the file's postfix.
2365 NameLength
= StrLen (Private
->FileContext
->FileName
);
2366 if (NameLength
<= 4) {
2367 return EFI_INVALID_PARAMETER
;
2370 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2371 if (IsDerEncodeCertificate (FilePostFix
)) {
2373 // Supports DER-encoded X509 certificate.
2375 return EnrollX509toSigDB (Private
, VariableName
);
2376 } else if (IsAuthentication2Format (Private
->FileContext
->FHandle
)) {
2377 return EnrollAuthentication2Descriptor (Private
, VariableName
);
2379 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2384 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2385 by GUID in the page for user to select and delete as needed.
2387 @param[in] PrivateData Module's private data.
2388 @param[in] VariableName The variable name of the vendor's signature database.
2389 @param[in] VendorGuid A unique identifier for the vendor.
2390 @param[in] LabelNumber Label number to insert opcodes.
2391 @param[in] FormId Form ID of current page.
2392 @param[in] QuestionIdBase Base question id of the signature list.
2394 @retval EFI_SUCCESS Success to update the signature list page
2395 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2400 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2401 IN CHAR16
*VariableName
,
2402 IN EFI_GUID
*VendorGuid
,
2403 IN UINT16 LabelNumber
,
2404 IN EFI_FORM_ID FormId
,
2405 IN EFI_QUESTION_ID QuestionIdBase
2412 VOID
*StartOpCodeHandle
;
2413 VOID
*EndOpCodeHandle
;
2414 EFI_IFR_GUID_LABEL
*StartLabel
;
2415 EFI_IFR_GUID_LABEL
*EndLabel
;
2418 EFI_SIGNATURE_LIST
*CertList
;
2419 EFI_SIGNATURE_DATA
*Cert
;
2420 UINT32 ItemDataSize
;
2422 EFI_STRING_ID GuidID
;
2429 StartOpCodeHandle
= NULL
;
2430 EndOpCodeHandle
= NULL
;
2433 // Initialize the container for dynamic opcodes.
2435 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2436 if (StartOpCodeHandle
== NULL
) {
2437 Status
= EFI_OUT_OF_RESOURCES
;
2441 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2442 if (EndOpCodeHandle
== NULL
) {
2443 Status
= EFI_OUT_OF_RESOURCES
;
2448 // Create Hii Extend Label OpCode.
2450 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
2454 sizeof (EFI_IFR_GUID_LABEL
)
2456 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2457 StartLabel
->Number
= LabelNumber
;
2459 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
2463 sizeof (EFI_IFR_GUID_LABEL
)
2465 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2466 EndLabel
->Number
= LABEL_END
;
2472 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2473 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2477 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2479 Status
= EFI_OUT_OF_RESOURCES
;
2483 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2484 if (EFI_ERROR (Status
)) {
2488 GuidStr
= AllocateZeroPool (100);
2489 if (GuidStr
== NULL
) {
2490 Status
= EFI_OUT_OF_RESOURCES
;
2495 // Enumerate all KEK pub data.
2497 ItemDataSize
= (UINT32
)DataSize
;
2498 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2501 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2502 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2503 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2504 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2505 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2506 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2507 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2508 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2509 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2510 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2511 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2512 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2513 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2514 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2515 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2518 // The signature type is not supported in current implementation.
2520 ItemDataSize
-= CertList
->SignatureListSize
;
2521 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2525 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2526 for (Index
= 0; Index
< CertCount
; Index
++) {
2527 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
2528 + sizeof (EFI_SIGNATURE_LIST
)
2529 + CertList
->SignatureHeaderSize
2530 + Index
* CertList
->SignatureSize
);
2532 // Display GUID and help
2534 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2535 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2536 HiiCreateCheckBoxOpCode (
2538 (EFI_QUESTION_ID
)(QuestionIdBase
+ GuidIndex
++),
2543 EFI_IFR_FLAG_CALLBACK
,
2549 ItemDataSize
-= CertList
->SignatureListSize
;
2550 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2555 PrivateData
->HiiHandle
,
2556 &gSecureBootConfigFormSetGuid
,
2562 if (StartOpCodeHandle
!= NULL
) {
2563 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2566 if (EndOpCodeHandle
!= NULL
) {
2567 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2574 if (GuidStr
!= NULL
) {
2582 Delete a KEK entry from KEK database.
2584 @param[in] PrivateData Module's private data.
2585 @param[in] QuestionId Question id of the KEK item to delete.
2587 @retval EFI_SUCCESS Delete kek item successfully.
2588 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2592 DeleteKeyExchangeKey (
2593 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2594 IN EFI_QUESTION_ID QuestionId
2603 EFI_SIGNATURE_LIST
*CertList
;
2604 EFI_SIGNATURE_LIST
*NewCertList
;
2605 EFI_SIGNATURE_DATA
*Cert
;
2608 BOOLEAN IsKEKItemFound
;
2610 UINTN DeleteKekIndex
;
2618 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2620 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2621 if (EFI_ERROR (Status
)) {
2626 // Get original KEK variable.
2629 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2630 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2634 OldData
= (UINT8
*)AllocateZeroPool (DataSize
);
2635 if (OldData
== NULL
) {
2636 Status
= EFI_OUT_OF_RESOURCES
;
2640 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2641 if (EFI_ERROR (Status
)) {
2646 // Allocate space for new variable.
2648 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2650 Status
= EFI_OUT_OF_RESOURCES
;
2655 // Enumerate all KEK pub data and erasing the target item.
2657 IsKEKItemFound
= FALSE
;
2658 KekDataSize
= (UINT32
)DataSize
;
2659 CertList
= (EFI_SIGNATURE_LIST
*)OldData
;
2662 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2663 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2664 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
))
2666 CopyMem (Data
+ Offset
, CertList
, (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2667 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2668 Offset
+= (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2669 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2670 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2671 for (Index
= 0; Index
< CertCount
; Index
++) {
2672 if (GuidIndex
== DeleteKekIndex
) {
2674 // Find it! Skip it!
2676 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2677 IsKEKItemFound
= TRUE
;
2680 // This item doesn't match. Copy it to the Data buffer.
2682 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2683 Offset
+= CertList
->SignatureSize
;
2687 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
2691 // This List doesn't match. Copy it to the Data buffer.
2693 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2694 Offset
+= CertList
->SignatureListSize
;
2697 KekDataSize
-= CertList
->SignatureListSize
;
2698 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2701 if (!IsKEKItemFound
) {
2703 // Doesn't find the Kek Item!
2705 Status
= EFI_NOT_FOUND
;
2710 // Delete the Signature header if there is no signature in the list.
2712 KekDataSize
= Offset
;
2713 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2715 ZeroMem (OldData
, KekDataSize
);
2716 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2717 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2718 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2719 if (CertCount
!= 0) {
2720 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2721 Offset
+= CertList
->SignatureListSize
;
2724 KekDataSize
-= CertList
->SignatureListSize
;
2725 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2729 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2730 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2731 if (EFI_ERROR (Status
)) {
2732 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2737 Status
= gRT
->SetVariable (
2738 EFI_KEY_EXCHANGE_KEY_NAME
,
2739 &gEfiGlobalVariableGuid
,
2744 if (EFI_ERROR (Status
)) {
2745 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2754 if (OldData
!= NULL
) {
2758 return UpdateDeletePage (
2760 EFI_KEY_EXCHANGE_KEY_NAME
,
2761 &gEfiGlobalVariableGuid
,
2763 FORMID_DELETE_KEK_FORM
,
2764 OPTION_DEL_KEK_QUESTION_ID
2769 Delete a signature entry from signature database.
2771 @param[in] PrivateData Module's private data.
2772 @param[in] VariableName The variable name of the vendor's signature database.
2773 @param[in] VendorGuid A unique identifier for the vendor.
2774 @param[in] LabelNumber Label number to insert opcodes.
2775 @param[in] FormId Form ID of current page.
2776 @param[in] QuestionIdBase Base question id of the signature list.
2777 @param[in] DeleteIndex Signature index to delete.
2779 @retval EFI_SUCCESS Delete signature successfully.
2780 @retval EFI_NOT_FOUND Can't find the signature item,
2781 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2785 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2786 IN CHAR16
*VariableName
,
2787 IN EFI_GUID
*VendorGuid
,
2788 IN UINT16 LabelNumber
,
2789 IN EFI_FORM_ID FormId
,
2790 IN EFI_QUESTION_ID QuestionIdBase
,
2791 IN UINTN DeleteIndex
2800 EFI_SIGNATURE_LIST
*CertList
;
2801 EFI_SIGNATURE_LIST
*NewCertList
;
2802 EFI_SIGNATURE_DATA
*Cert
;
2805 BOOLEAN IsItemFound
;
2806 UINT32 ItemDataSize
;
2815 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2816 if (EFI_ERROR (Status
)) {
2821 // Get original signature list data.
2824 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2825 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2829 OldData
= (UINT8
*)AllocateZeroPool (DataSize
);
2830 if (OldData
== NULL
) {
2831 Status
= EFI_OUT_OF_RESOURCES
;
2835 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2836 if (EFI_ERROR (Status
)) {
2841 // Allocate space for new variable.
2843 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2845 Status
= EFI_OUT_OF_RESOURCES
;
2850 // Enumerate all signature data and erasing the target item.
2852 IsItemFound
= FALSE
;
2853 ItemDataSize
= (UINT32
)DataSize
;
2854 CertList
= (EFI_SIGNATURE_LIST
*)OldData
;
2857 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2858 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2859 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2860 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2861 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2862 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2863 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2864 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2868 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2870 CopyMem (Data
+ Offset
, CertList
, (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2871 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2872 Offset
+= (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2873 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2874 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2875 for (Index
= 0; Index
< CertCount
; Index
++) {
2876 if (GuidIndex
== DeleteIndex
) {
2878 // Find it! Skip it!
2880 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2884 // This item doesn't match. Copy it to the Data buffer.
2886 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2887 Offset
+= CertList
->SignatureSize
;
2891 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
2895 // This List doesn't match. Just copy it to the Data buffer.
2897 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2898 Offset
+= CertList
->SignatureListSize
;
2901 ItemDataSize
-= CertList
->SignatureListSize
;
2902 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2907 // Doesn't find the signature Item!
2909 Status
= EFI_NOT_FOUND
;
2914 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2916 ItemDataSize
= Offset
;
2917 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2919 ZeroMem (OldData
, ItemDataSize
);
2920 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2921 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2922 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2923 if (CertCount
!= 0) {
2924 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2925 Offset
+= CertList
->SignatureListSize
;
2928 ItemDataSize
-= CertList
->SignatureListSize
;
2929 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2933 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2934 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2935 if (EFI_ERROR (Status
)) {
2936 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2941 Status
= gRT
->SetVariable (
2948 if (EFI_ERROR (Status
)) {
2949 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2958 if (OldData
!= NULL
) {
2962 return UpdateDeletePage (
2973 This function to delete signature list or data, according by DelType.
2975 @param[in] PrivateData Module's private data.
2976 @param[in] DelType Indicate delete signature list or data.
2977 @param[in] CheckedCount Indicate how many signature data have
2978 been checked in current signature list.
2980 @retval EFI_SUCCESS Success to update the signature list page
2981 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2985 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2986 IN SIGNATURE_DELETE_TYPE DelType
,
2987 IN UINT32 CheckedCount
2991 EFI_SIGNATURE_LIST
*ListWalker
;
2992 EFI_SIGNATURE_LIST
*NewCertList
;
2993 EFI_SIGNATURE_DATA
*DataWalker
;
2994 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
2995 UINT32 VariableAttr
;
2996 UINTN VariableDataSize
;
2997 UINTN RemainingSize
;
3001 UINT8
*VariableData
;
3002 UINT8
*NewVariableData
;
3004 Status
= EFI_SUCCESS
;
3006 VariableDataSize
= 0;
3009 VariableData
= NULL
;
3010 NewVariableData
= NULL
;
3012 if (PrivateData
->VariableName
== Variable_DB
) {
3013 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3014 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3015 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3016 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3017 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3022 Status
= gRT
->GetVariable (
3024 &gEfiImageSecurityDatabaseGuid
,
3029 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
3033 VariableData
= AllocateZeroPool (VariableDataSize
);
3034 if (VariableData
== NULL
) {
3035 Status
= EFI_OUT_OF_RESOURCES
;
3039 Status
= gRT
->GetVariable (
3041 &gEfiImageSecurityDatabaseGuid
,
3046 if (EFI_ERROR (Status
)) {
3050 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3051 if (EFI_ERROR (Status
)) {
3055 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3056 if (NewVariableData
== NULL
) {
3057 Status
= EFI_OUT_OF_RESOURCES
;
3061 RemainingSize
= VariableDataSize
;
3062 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3063 if (DelType
== Delete_Signature_List_All
) {
3064 VariableDataSize
= 0;
3067 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3069 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3070 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3071 Offset
+= ListWalker
->SignatureListSize
;
3073 RemainingSize
-= ListWalker
->SignatureListSize
;
3074 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3079 // Handle the target EFI_SIGNATURE_LIST.
3080 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3081 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3083 if ((CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
)) && (DelType
== Delete_Signature_Data
)) {
3084 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3088 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3089 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3091 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3092 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS (ListWalker
); Index
= Index
+ 1) {
3093 if (PrivateData
->CheckArray
[Index
]) {
3095 // Delete checked signature data, and update the size of whole signature list.
3097 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3100 // Remain the unchecked signature data.
3102 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3103 Offset
+= ListWalker
->SignatureSize
;
3106 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3110 RemainingSize
-= ListWalker
->SignatureListSize
;
3111 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3114 // Copy remaining data, maybe 0.
3116 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3117 Offset
+= RemainingSize
;
3119 VariableDataSize
= Offset
;
3122 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3123 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3124 if (EFI_ERROR (Status
)) {
3125 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3130 Status
= gRT
->SetVariable (
3132 &gEfiImageSecurityDatabaseGuid
,
3137 if (EFI_ERROR (Status
)) {
3138 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3143 SECUREBOOT_FREE_NON_NULL (VariableData
);
3144 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3151 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3152 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3154 @param[in] PrivateData Module's private data.
3156 @return EFI_SUCCESS Update secure boot strings successfully.
3157 @return other Fail to update secure boot strings.
3161 UpdateSecureBootString (
3162 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3170 // Get current secure boot state.
3172 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3173 if (SecureBoot
== NULL
) {
3174 return EFI_NOT_FOUND
;
3177 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3178 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3180 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3183 FreePool (SecureBoot
);
3189 This function extracts configuration from variable.
3191 @param[in] Private Point to SecureBoot configuration driver private data.
3192 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3196 SecureBootExtractConfigFromVariable (
3197 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3198 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3201 UINT8
*SecureBootEnable
;
3203 UINT8
*SecureBootMode
;
3206 SecureBootEnable
= NULL
;
3208 SecureBootMode
= NULL
;
3211 // Initialize the Date and Time using system time.
3213 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3214 ConfigData
->AlwaysRevocation
= TRUE
;
3215 gRT
->GetTime (&CurrTime
, NULL
);
3216 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3217 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3218 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3219 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3220 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3221 ConfigData
->RevocationTime
.Second
= 0;
3222 if (Private
->FileContext
->FHandle
!= NULL
) {
3223 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3225 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3229 // If it is Physical Presence User, set the PhysicalPresent to true.
3231 if (UserPhysicalPresent ()) {
3232 ConfigData
->PhysicalPresent
= TRUE
;
3234 ConfigData
->PhysicalPresent
= FALSE
;
3238 // If there is no PK then the Delete Pk button will be gray.
3240 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3241 if ((SetupMode
== NULL
) || ((*SetupMode
) == SETUP_MODE
)) {
3242 ConfigData
->HasPk
= FALSE
;
3244 ConfigData
->HasPk
= TRUE
;
3248 // Check SecureBootEnable & Pk status, fix the inconsistency.
3249 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3252 ConfigData
->AttemptSecureBoot
= FALSE
;
3253 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3256 // Fix Pk and SecureBootEnable inconsistency
3258 if ((SetupMode
!= NULL
) && ((*SetupMode
) == USER_MODE
)) {
3259 ConfigData
->HideSecureBoot
= FALSE
;
3260 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3261 ConfigData
->AttemptSecureBoot
= TRUE
;
3264 ConfigData
->HideSecureBoot
= TRUE
;
3268 // Get the SecureBootMode from CustomMode variable.
3270 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3271 if (SecureBootMode
== NULL
) {
3272 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3274 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3277 if (SecureBootEnable
!= NULL
) {
3278 FreePool (SecureBootEnable
);
3281 if (SetupMode
!= NULL
) {
3282 FreePool (SetupMode
);
3285 if (SecureBootMode
!= NULL
) {
3286 FreePool (SecureBootMode
);
3291 This function allows a caller to extract the current configuration for one
3292 or more named elements from the target driver.
3294 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3295 @param[in] Request A null-terminated Unicode string in
3296 <ConfigRequest> format.
3297 @param[out] Progress On return, points to a character in the Request
3298 string. Points to the string's null terminator if
3299 request was successful. Points to the most recent
3300 '&' before the first failing name/value pair (or
3301 the beginning of the string if the failure is in
3302 the first name/value pair) if the request was not
3304 @param[out] Results A null-terminated Unicode string in
3305 <ConfigAltResp> format which has all values filled
3306 in for the names in the Request string. String to
3307 be allocated by the called function.
3309 @retval EFI_SUCCESS The Results is filled with the requested values.
3310 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3311 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3312 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3318 SecureBootExtractConfig (
3319 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3320 IN CONST EFI_STRING Request
,
3321 OUT EFI_STRING
*Progress
,
3322 OUT EFI_STRING
*Results
3328 SECUREBOOT_CONFIGURATION Configuration
;
3329 EFI_STRING ConfigRequest
;
3330 EFI_STRING ConfigRequestHdr
;
3331 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3332 BOOLEAN AllocatedRequest
;
3334 if ((Progress
== NULL
) || (Results
== NULL
)) {
3335 return EFI_INVALID_PARAMETER
;
3338 AllocatedRequest
= FALSE
;
3339 ConfigRequestHdr
= NULL
;
3340 ConfigRequest
= NULL
;
3343 ZeroMem (&Configuration
, sizeof (Configuration
));
3344 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3345 *Progress
= Request
;
3347 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3348 return EFI_NOT_FOUND
;
3351 ZeroMem (&Configuration
, sizeof (SECUREBOOT_CONFIGURATION
));
3354 // Get Configuration from Variable.
3356 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3358 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3359 ConfigRequest
= Request
;
3360 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3362 // Request is set to NULL or OFFSET is NULL, construct full request string.
3364 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3365 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3367 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3368 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3369 ConfigRequest
= AllocateZeroPool (Size
);
3370 ASSERT (ConfigRequest
!= NULL
);
3371 AllocatedRequest
= TRUE
;
3372 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3373 FreePool (ConfigRequestHdr
);
3374 ConfigRequestHdr
= NULL
;
3377 Status
= gHiiConfigRouting
->BlockToConfig (
3380 (UINT8
*)&Configuration
,
3387 // Free the allocated config request string.
3389 if (AllocatedRequest
) {
3390 FreePool (ConfigRequest
);
3394 // Set Progress string to the original request string.
3396 if (Request
== NULL
) {
3398 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3399 *Progress
= Request
+ StrLen (Request
);
3406 This function processes the results of changes in configuration.
3408 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3409 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3411 @param[out] Progress A pointer to a string filled in with the offset of
3412 the most recent '&' before the first failing
3413 name/value pair (or the beginning of the string if
3414 the failure is in the first name/value pair) or
3415 the terminating NULL if all was successful.
3417 @retval EFI_SUCCESS The Results is processed successfully.
3418 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3419 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3425 SecureBootRouteConfig (
3426 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3427 IN CONST EFI_STRING Configuration
,
3428 OUT EFI_STRING
*Progress
3431 SECUREBOOT_CONFIGURATION IfrNvData
;
3433 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3436 if ((Configuration
== NULL
) || (Progress
== NULL
)) {
3437 return EFI_INVALID_PARAMETER
;
3440 *Progress
= Configuration
;
3441 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3442 return EFI_NOT_FOUND
;
3445 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3448 // Get Configuration from Variable.
3450 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3453 // Map the Configuration to the configuration block.
3455 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3456 Status
= gHiiConfigRouting
->ConfigToBlock (
3459 (UINT8
*)&IfrNvData
,
3463 if (EFI_ERROR (Status
)) {
3468 // Store Buffer Storage back to EFI variable if needed
3470 if (!IfrNvData
.HideSecureBoot
) {
3471 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3472 if (EFI_ERROR (Status
)) {
3477 *Progress
= Configuration
+ StrLen (Configuration
);
3482 This function to load signature list, the update the menu page.
3484 @param[in] PrivateData Module's private data.
3485 @param[in] LabelId Label number to insert opcodes.
3486 @param[in] FormId Form ID of current page.
3487 @param[in] QuestionIdBase Base question id of the signature list.
3489 @retval EFI_SUCCESS Success to update the signature list page
3490 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3494 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3496 IN EFI_FORM_ID FormId
,
3497 IN EFI_QUESTION_ID QuestionIdBase
3501 EFI_STRING_ID ListType
;
3502 EFI_STRING FormatNameString
;
3503 EFI_STRING FormatHelpString
;
3504 EFI_STRING FormatTypeString
;
3505 EFI_SIGNATURE_LIST
*ListWalker
;
3506 EFI_IFR_GUID_LABEL
*StartLabel
;
3507 EFI_IFR_GUID_LABEL
*EndLabel
;
3508 EFI_IFR_GUID_LABEL
*StartGoto
;
3509 EFI_IFR_GUID_LABEL
*EndGoto
;
3510 EFI_FORM_ID DstFormId
;
3511 VOID
*StartOpCodeHandle
;
3512 VOID
*EndOpCodeHandle
;
3513 VOID
*StartGotoHandle
;
3514 VOID
*EndGotoHandle
;
3516 UINTN RemainingSize
;
3518 UINT8
*VariableData
;
3519 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3520 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3521 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3523 Status
= EFI_SUCCESS
;
3524 FormatNameString
= NULL
;
3525 FormatHelpString
= NULL
;
3526 StartOpCodeHandle
= NULL
;
3527 EndOpCodeHandle
= NULL
;
3528 StartGotoHandle
= NULL
;
3529 EndGotoHandle
= NULL
;
3531 VariableData
= NULL
;
3534 // Initialize the container for dynamic opcodes.
3536 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3537 if (StartOpCodeHandle
== NULL
) {
3538 Status
= EFI_OUT_OF_RESOURCES
;
3542 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3543 if (EndOpCodeHandle
== NULL
) {
3544 Status
= EFI_OUT_OF_RESOURCES
;
3548 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3549 if (StartGotoHandle
== NULL
) {
3550 Status
= EFI_OUT_OF_RESOURCES
;
3554 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3555 if (EndGotoHandle
== NULL
) {
3556 Status
= EFI_OUT_OF_RESOURCES
;
3561 // Create Hii Extend Label OpCode.
3563 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3567 sizeof (EFI_IFR_GUID_LABEL
)
3569 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3570 StartLabel
->Number
= LabelId
;
3572 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3576 sizeof (EFI_IFR_GUID_LABEL
)
3578 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3579 EndLabel
->Number
= LABEL_END
;
3581 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3585 sizeof (EFI_IFR_GUID_LABEL
)
3587 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3588 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3590 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3594 sizeof (EFI_IFR_GUID_LABEL
)
3596 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3597 EndGoto
->Number
= LABEL_END
;
3599 if (PrivateData
->VariableName
== Variable_DB
) {
3600 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3601 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3602 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3603 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3604 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3605 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3606 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3607 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3612 HiiCreateGotoOpCode (
3615 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3616 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3617 EFI_IFR_FLAG_CALLBACK
,
3618 KEY_SECURE_BOOT_DELETE_ALL_LIST
3622 // Read Variable, the variable name save in the PrivateData->VariableName.
3625 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3626 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
3630 VariableData
= AllocateZeroPool (DataSize
);
3631 if (VariableData
== NULL
) {
3632 Status
= EFI_OUT_OF_RESOURCES
;
3636 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3637 if (EFI_ERROR (Status
)) {
3641 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3642 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3643 if ((FormatNameString
== NULL
) || (FormatHelpString
== NULL
)) {
3647 RemainingSize
= DataSize
;
3648 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3649 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3650 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3651 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3652 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3653 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3654 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3655 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3656 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3657 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3658 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3659 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3660 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3661 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3662 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3663 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3665 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3668 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3669 if (FormatTypeString
== NULL
) {
3673 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3674 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3676 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3679 sizeof (HelpBuffer
),
3682 SIGNATURE_DATA_COUNTS (ListWalker
)
3684 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3685 FormatTypeString
= NULL
;
3687 HiiCreateGotoOpCode (
3689 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3690 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3691 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3692 EFI_IFR_FLAG_CALLBACK
,
3693 QuestionIdBase
+ Index
++
3696 RemainingSize
-= ListWalker
->SignatureListSize
;
3697 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3702 PrivateData
->HiiHandle
,
3703 &gSecureBootConfigFormSetGuid
,
3710 PrivateData
->HiiHandle
,
3711 &gSecureBootConfigFormSetGuid
,
3717 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3718 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3719 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3720 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3722 SECUREBOOT_FREE_NON_NULL (VariableData
);
3723 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3724 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3726 PrivateData
->ListCount
= Index
;
3732 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3733 The buffer is callee allocated and should be freed by the caller.
3735 @param[in] ListEntry The pointer point to the signature list.
3736 @param[in] DataEntry The signature data we are processing.
3737 @param[out] BufferToReturn Buffer to save the hash value.
3739 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3740 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3741 @retval EFI_SUCCESS Operation success.
3745 IN EFI_SIGNATURE_LIST
*ListEntry
,
3746 IN EFI_SIGNATURE_DATA
*DataEntry
,
3747 OUT CHAR16
**BufferToReturn
3758 // Assume that, display 8 bytes in one line.
3762 if ((ListEntry
== NULL
) || (DataEntry
== NULL
) || (BufferToReturn
== NULL
)) {
3763 return EFI_INVALID_PARAMETER
;
3766 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3767 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3770 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3772 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof (CHAR16
));
3774 *BufferToReturn
= AllocateZeroPool (TotalSize
);
3775 if (*BufferToReturn
== NULL
) {
3776 return EFI_OUT_OF_RESOURCES
;
3779 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3780 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3781 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"\n");
3784 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3787 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"\n");
3793 Function to get the common name from the X509 format certificate.
3794 The buffer is callee allocated and should be freed by the caller.
3796 @param[in] ListEntry The pointer point to the signature list.
3797 @param[in] DataEntry The signature data we are processing.
3798 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3800 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3801 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3802 @retval EFI_SUCCESS Operation success.
3803 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3806 GetCommonNameFromX509 (
3807 IN EFI_SIGNATURE_LIST
*ListEntry
,
3808 IN EFI_SIGNATURE_DATA
*DataEntry
,
3809 OUT CHAR16
**BufferToReturn
3816 Status
= EFI_SUCCESS
;
3819 CNBuffer
= AllocateZeroPool (256);
3820 if (CNBuffer
== NULL
) {
3821 Status
= EFI_OUT_OF_RESOURCES
;
3827 (UINT8
*)DataEntry
+ sizeof (EFI_GUID
),
3828 ListEntry
->SignatureSize
- sizeof (EFI_GUID
),
3833 *BufferToReturn
= AllocateZeroPool (256 * sizeof (CHAR16
));
3834 if (*BufferToReturn
== NULL
) {
3835 Status
= EFI_OUT_OF_RESOURCES
;
3839 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3842 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3848 Format the help info for the signature data, each help info contain 3 parts.
3850 2. Content, depends on the type of the signature list.
3853 @param[in] PrivateData Module's private data.
3854 @param[in] ListEntry Point to the signature list.
3855 @param[in] DataEntry Point to the signature data we are processing.
3856 @param[out] StringId Save the string id of help info.
3858 @retval EFI_SUCCESS Operation success.
3859 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3863 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3864 IN EFI_SIGNATURE_LIST
*ListEntry
,
3865 IN EFI_SIGNATURE_DATA
*DataEntry
,
3866 OUT EFI_STRING_ID
*StringId
3871 EFI_STRING_ID ListTypeId
;
3872 EFI_STRING FormatHelpString
;
3873 EFI_STRING FormatTypeString
;
3875 UINTN HelpInfoIndex
;
3877 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3878 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3880 CHAR16
*HelpInfoString
;
3883 Status
= EFI_SUCCESS
;
3885 FormatTypeString
= NULL
;
3888 HelpInfoString
= NULL
;
3891 if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3892 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3893 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3895 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
3896 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3897 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3899 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
3900 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3902 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
3903 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3905 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3906 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3908 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3909 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3910 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3912 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3913 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3914 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3916 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3918 Status
= EFI_UNSUPPORTED
;
3922 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
3923 if (FormatTypeString
== NULL
) {
3928 HelpInfoString
= AllocateZeroPool (TotalSize
);
3929 if (HelpInfoString
== NULL
) {
3930 Status
= EFI_OUT_OF_RESOURCES
;
3935 // Format GUID part.
3937 ZeroMem (GuidString
, sizeof (GuidString
));
3938 GuidToString (&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
3939 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
3940 if (FormatHelpString
== NULL
) {
3944 HelpInfoIndex
+= UnicodeSPrint (
3945 &HelpInfoString
[HelpInfoIndex
],
3946 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3950 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3951 FormatHelpString
= NULL
;
3954 // Format content part, it depends on the type of signature list, hash value or CN.
3957 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
3958 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
3961 // Format hash value for each signature data entry.
3963 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
3964 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
3967 if (FormatHelpString
== NULL
) {
3971 HelpInfoIndex
+= UnicodeSPrint (
3972 &HelpInfoString
[HelpInfoIndex
],
3973 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3979 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3980 FormatHelpString
= NULL
;
3983 // Format revocation time part.
3986 ZeroMem (TimeString
, sizeof (TimeString
));
3989 sizeof (TimeString
),
3990 L
"%d-%d-%d %d:%d:%d",
3998 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
3999 if (FormatHelpString
== NULL
) {
4004 &HelpInfoString
[HelpInfoIndex
],
4005 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4009 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4010 FormatHelpString
= NULL
;
4013 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
4015 SECUREBOOT_FREE_NON_NULL (DataString
);
4016 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
4018 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
4024 This function to load signature data under the signature list.
4026 @param[in] PrivateData Module's private data.
4027 @param[in] LabelId Label number to insert opcodes.
4028 @param[in] FormId Form ID of current page.
4029 @param[in] QuestionIdBase Base question id of the signature list.
4030 @param[in] ListIndex Indicate to load which signature list.
4032 @retval EFI_SUCCESS Success to update the signature list page
4033 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4037 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4039 IN EFI_FORM_ID FormId
,
4040 IN EFI_QUESTION_ID QuestionIdBase
,
4045 EFI_SIGNATURE_LIST
*ListWalker
;
4046 EFI_SIGNATURE_DATA
*DataWalker
;
4047 EFI_IFR_GUID_LABEL
*StartLabel
;
4048 EFI_IFR_GUID_LABEL
*EndLabel
;
4049 EFI_STRING_ID HelpStringId
;
4050 EFI_STRING FormatNameString
;
4051 VOID
*StartOpCodeHandle
;
4052 VOID
*EndOpCodeHandle
;
4054 UINTN RemainingSize
;
4056 UINT8
*VariableData
;
4057 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4058 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4060 Status
= EFI_SUCCESS
;
4061 FormatNameString
= NULL
;
4062 StartOpCodeHandle
= NULL
;
4063 EndOpCodeHandle
= NULL
;
4065 VariableData
= NULL
;
4068 // Initialize the container for dynamic opcodes.
4070 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4071 if (StartOpCodeHandle
== NULL
) {
4072 Status
= EFI_OUT_OF_RESOURCES
;
4076 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4077 if (EndOpCodeHandle
== NULL
) {
4078 Status
= EFI_OUT_OF_RESOURCES
;
4083 // Create Hii Extend Label OpCode.
4085 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4089 sizeof (EFI_IFR_GUID_LABEL
)
4091 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4092 StartLabel
->Number
= LabelId
;
4094 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4098 sizeof (EFI_IFR_GUID_LABEL
)
4100 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4101 EndLabel
->Number
= LABEL_END
;
4103 if (PrivateData
->VariableName
== Variable_DB
) {
4104 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4105 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4106 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4107 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4108 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4114 // Read Variable, the variable name save in the PrivateData->VariableName.
4117 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4118 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
4122 VariableData
= AllocateZeroPool (DataSize
);
4123 if (VariableData
== NULL
) {
4124 Status
= EFI_OUT_OF_RESOURCES
;
4128 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4129 if (EFI_ERROR (Status
)) {
4133 RemainingSize
= DataSize
;
4134 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4137 // Skip signature list.
4139 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4140 RemainingSize
-= ListWalker
->SignatureListSize
;
4141 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4144 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4145 if (FormatNameString
== NULL
) {
4149 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4150 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS (ListWalker
); Index
= Index
+ 1) {
4152 // Format name buffer.
4154 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4155 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4158 // Format help info buffer.
4160 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4161 if (EFI_ERROR (Status
)) {
4165 HiiCreateCheckBoxOpCode (
4167 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4170 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4172 EFI_IFR_FLAG_CALLBACK
,
4177 ZeroMem (NameBuffer
, 100);
4178 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4182 // Allocate a buffer to record which signature data will be checked.
4183 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4185 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4188 PrivateData
->HiiHandle
,
4189 &gSecureBootConfigFormSetGuid
,
4195 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4196 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4198 SECUREBOOT_FREE_NON_NULL (VariableData
);
4199 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4205 This function reinitializes Secure Boot variables with default values.
4207 @retval EFI_SUCCESS Success to update the signature list page
4208 @retval others Fail to delete or enroll signature data.
4219 Status
= EFI_SUCCESS
;
4221 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4222 if (EFI_ERROR (Status
)) {
4226 // Clear all the keys and databases
4227 Status
= DeleteDb ();
4228 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4229 DEBUG ((DEBUG_ERROR
, "Fail to clear DB: %r\n", Status
));
4233 Status
= DeleteDbx ();
4234 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4235 DEBUG ((DEBUG_ERROR
, "Fail to clear DBX: %r\n", Status
));
4239 Status
= DeleteDbt ();
4240 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4241 DEBUG ((DEBUG_ERROR
, "Fail to clear DBT: %r\n", Status
));
4245 Status
= DeleteKEK ();
4246 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4247 DEBUG ((DEBUG_ERROR
, "Fail to clear KEK: %r\n", Status
));
4251 Status
= DeletePlatformKey ();
4252 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4253 DEBUG ((DEBUG_ERROR
, "Fail to clear PK: %r\n", Status
));
4257 // After PK clear, Setup Mode shall be enabled
4258 Status
= GetSetupMode (&SetupMode
);
4259 if (EFI_ERROR (Status
)) {
4262 "Cannot get SetupMode variable: %r\n",
4268 if (SetupMode
== USER_MODE
) {
4269 DEBUG ((DEBUG_INFO
, "Skipped - USER_MODE\n"));
4273 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4274 if (EFI_ERROR (Status
)) {
4277 "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n",
4283 // Enroll all the keys from default variables
4284 Status
= EnrollDbFromDefault ();
4285 if (EFI_ERROR (Status
)) {
4286 DEBUG ((DEBUG_ERROR
, "Cannot enroll db: %r\n", Status
));
4290 Status
= EnrollDbxFromDefault ();
4291 if (EFI_ERROR (Status
)) {
4292 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbx: %r\n", Status
));
4295 Status
= EnrollDbtFromDefault ();
4296 if (EFI_ERROR (Status
)) {
4297 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbt: %r\n", Status
));
4300 Status
= EnrollKEKFromDefault ();
4301 if (EFI_ERROR (Status
)) {
4302 DEBUG ((DEBUG_ERROR
, "Cannot enroll KEK: %r\n", Status
));
4306 Status
= EnrollPKFromDefault ();
4307 if (EFI_ERROR (Status
)) {
4308 DEBUG ((DEBUG_ERROR
, "Cannot enroll PK: %r\n", Status
));
4312 Status
= SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
4313 if (EFI_ERROR (Status
)) {
4316 "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
4317 "Please do it manually, otherwise system can be easily compromised\n"
4332 if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
) != EFI_SUCCESS
) {
4333 DEBUG ((DEBUG_ERROR
, "Cannot set mode to Secure: %r\n", Status
));
4340 This function is called to provide results data to the driver.
4342 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4343 @param[in] Action Specifies the type of action taken by the browser.
4344 @param[in] QuestionId A unique value which is sent to the original
4345 exporting driver so that it can identify the type
4347 @param[in] Type The type of value for the question.
4348 @param[in] Value A pointer to the data being sent to the original
4350 @param[out] ActionRequest On return, points to the action requested by the
4353 @retval EFI_SUCCESS The callback successfully handled the action.
4354 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4355 variable and its data.
4356 @retval EFI_DEVICE_ERROR The variable could not be saved.
4357 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4363 SecureBootCallback (
4364 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4365 IN EFI_BROWSER_ACTION Action
,
4366 IN EFI_QUESTION_ID QuestionId
,
4368 IN EFI_IFR_TYPE_VALUE
*Value
,
4369 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4374 RETURN_STATUS RStatus
;
4375 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4377 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4379 UINT8
*SecureBootEnable
;
4381 UINT8
*SecureBootMode
;
4383 CHAR16 PromptString
[100];
4384 EFI_DEVICE_PATH_PROTOCOL
*File
;
4386 UINT16
*FilePostFix
;
4387 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4388 BOOLEAN GetBrowserDataResult
;
4389 ENROLL_KEY_ERROR EnrollKeyErrorCode
;
4390 EFI_HII_POPUP_PROTOCOL
*HiiPopup
;
4391 EFI_HII_POPUP_SELECTION UserSelection
;
4393 Status
= EFI_SUCCESS
;
4394 SecureBootEnable
= NULL
;
4395 SecureBootMode
= NULL
;
4398 EnrollKeyErrorCode
= None_Error
;
4400 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4401 return EFI_INVALID_PARAMETER
;
4404 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4406 gSecureBootPrivateData
= Private
;
4409 // Retrieve uncommitted data from Browser
4411 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4412 IfrNvData
= AllocateZeroPool (BufferSize
);
4413 if (IfrNvData
== NULL
) {
4414 return EFI_OUT_OF_RESOURCES
;
4417 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*)IfrNvData
);
4419 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4420 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4422 // Update secure boot strings when opening this form
4424 Status
= UpdateSecureBootString (Private
);
4425 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4426 mIsEnterSecureBootForm
= TRUE
;
4429 // When entering SecureBoot OPTION Form
4430 // always close opened file & free resource
4432 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4433 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4434 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4435 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4436 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
))
4438 CloseEnrolledFile (Private
->FileContext
);
4439 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4441 // Update ListCount field in varstore
4442 // Button "Delete All Signature List" is
4443 // enable when ListCount is greater than 0.
4445 IfrNvData
->ListCount
= Private
->ListCount
;
4452 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4453 Status
= EFI_UNSUPPORTED
;
4454 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4455 if (mIsEnterSecureBootForm
) {
4456 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4457 Status
= EFI_SUCCESS
;
4464 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4465 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4466 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4467 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
))
4469 Status
= EFI_UNSUPPORTED
;
4473 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4474 switch (QuestionId
) {
4475 case KEY_SECURE_BOOT_ENABLE
:
4476 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4477 if (NULL
!= SecureBootEnable
) {
4478 FreePool (SecureBootEnable
);
4479 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4481 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4483 L
"Only Physical Presence User could disable secure boot!",
4486 Status
= EFI_UNSUPPORTED
;
4489 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4491 L
"Configuration changed, please reset the platform to take effect!",
4499 case KEY_SECURE_BOOT_KEK_OPTION
:
4500 case KEY_SECURE_BOOT_DB_OPTION
:
4501 case KEY_SECURE_BOOT_DBX_OPTION
:
4502 case KEY_SECURE_BOOT_DBT_OPTION
:
4503 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4505 // Clear Signature GUID.
4507 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4508 if (Private
->SignatureGUID
== NULL
) {
4509 Private
->SignatureGUID
= (EFI_GUID
*)AllocateZeroPool (sizeof (EFI_GUID
));
4510 if (Private
->SignatureGUID
== NULL
) {
4511 return EFI_OUT_OF_RESOURCES
;
4516 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4518 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4520 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4521 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4522 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4523 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4524 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4525 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4527 LabelId
= FORMID_ENROLL_KEK_FORM
;
4531 // Refresh selected file.
4533 CleanUpPage (LabelId
, Private
);
4535 case KEY_SECURE_BOOT_PK_OPTION
:
4536 LabelId
= FORMID_ENROLL_PK_FORM
;
4538 // Refresh selected file.
4540 CleanUpPage (LabelId
, Private
);
4543 case FORMID_ENROLL_PK_FORM
:
4544 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4547 case FORMID_ENROLL_KEK_FORM
:
4548 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4551 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4552 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4555 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4556 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4558 if (Private
->FileContext
->FHandle
!= NULL
) {
4560 // Parse the file's postfix.
4562 NameLength
= StrLen (Private
->FileContext
->FileName
);
4563 if (NameLength
<= 4) {
4567 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4569 if (IsDerEncodeCertificate (FilePostFix
)) {
4571 // Supports DER-encoded X509 certificate.
4573 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4574 } else if (IsAuthentication2Format (Private
->FileContext
->FHandle
)) {
4575 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4577 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4580 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4583 // Clean up Certificate Format if File type is not X509 DER
4585 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4586 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4589 DEBUG ((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4594 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4595 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4598 case KEY_SECURE_BOOT_DELETE_PK
:
4601 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4603 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4604 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4607 if ((Key
.UnicodeChar
== 'y') || (Key
.UnicodeChar
== 'Y')) {
4608 Status
= DeletePlatformKey ();
4609 if (EFI_ERROR (Status
)) {
4611 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4613 L
"Only Physical Presence User could delete PK in custom mode!",
4622 case KEY_DELETE_KEK
:
4625 EFI_KEY_EXCHANGE_KEY_NAME
,
4626 &gEfiGlobalVariableGuid
,
4628 FORMID_DELETE_KEK_FORM
,
4629 OPTION_DEL_KEK_QUESTION_ID
4633 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4636 EFI_IMAGE_SECURITY_DATABASE
,
4637 &gEfiImageSecurityDatabaseGuid
,
4639 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4640 OPTION_DEL_DB_QUESTION_ID
4645 // From DBX option to the level-1 form, display signature list.
4647 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4648 Private
->VariableName
= Variable_DBX
;
4651 LABEL_SIGNATURE_LIST_START
,
4652 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4653 OPTION_SIGNATURE_LIST_QUESTION_ID
4658 // Delete all signature list and reload.
4660 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4662 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4664 L
"Press 'Y' to delete signature list.",
4665 L
"Press other key to cancel and exit.",
4669 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4670 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4675 LABEL_SIGNATURE_LIST_START
,
4676 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4677 OPTION_SIGNATURE_LIST_QUESTION_ID
4682 // Delete one signature list and reload.
4684 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4686 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4688 L
"Press 'Y' to delete signature data.",
4689 L
"Press other key to cancel and exit.",
4693 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4694 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4699 LABEL_SIGNATURE_LIST_START
,
4700 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4701 OPTION_SIGNATURE_LIST_QUESTION_ID
4706 // Delete checked signature data and reload.
4708 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4710 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4712 L
"Press 'Y' to delete signature data.",
4713 L
"Press other key to cancel and exit.",
4717 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4718 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4723 LABEL_SIGNATURE_LIST_START
,
4724 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4725 OPTION_SIGNATURE_LIST_QUESTION_ID
4729 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4732 EFI_IMAGE_SECURITY_DATABASE2
,
4733 &gEfiImageSecurityDatabaseGuid
,
4735 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4736 OPTION_DEL_DBT_QUESTION_ID
4741 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4742 Status
= EnrollKeyExchangeKey (Private
);
4743 if (EFI_ERROR (Status
)) {
4745 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4747 L
"ERROR: Unsupported file type!",
4748 L
"Only supports DER-encoded X509 certificate",
4755 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4756 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4757 if (EFI_ERROR (Status
)) {
4759 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4761 L
"ERROR: Unsupported file type!",
4762 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4769 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4770 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4772 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4774 L
"Enrollment failed! Same certificate had already been in the dbx!",
4779 // Cert already exists in DBX. Close opened file before exit.
4781 CloseEnrolledFile (Private
->FileContext
);
4785 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4786 Status
= EnrollX509HashtoSigDB (
4788 IfrNvData
->CertificateFormat
,
4789 &IfrNvData
->RevocationDate
,
4790 &IfrNvData
->RevocationTime
,
4791 IfrNvData
->AlwaysRevocation
4793 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4795 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4798 if (EFI_ERROR (Status
)) {
4800 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4802 L
"ERROR: Unsupported file type!",
4803 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4810 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4811 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4812 if (EFI_ERROR (Status
)) {
4814 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4816 L
"ERROR: Unsupported file type!",
4817 L
"Only supports DER-encoded X509 certificate.",
4823 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4825 // Check the suffix, encode type and the key strength of PK certificate.
4827 Status
= CheckX509Certificate (Private
->FileContext
, &EnrollKeyErrorCode
);
4828 if (EFI_ERROR (Status
)) {
4829 if ((EnrollKeyErrorCode
!= None_Error
) && (EnrollKeyErrorCode
< Enroll_Error_Max
)) {
4831 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4833 mX509EnrollPromptTitle
[EnrollKeyErrorCode
],
4834 mX509EnrollPromptString
[EnrollKeyErrorCode
],
4840 Status
= EnrollPlatformKey (Private
);
4843 if (EFI_ERROR (Status
)) {
4846 sizeof (PromptString
),
4847 L
"Error status: %x.",
4851 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4853 L
"ERROR: Enrollment failed!",
4861 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4862 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4864 DeleteKeyExchangeKey (Private
, QuestionId
);
4865 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4866 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4870 EFI_IMAGE_SECURITY_DATABASE
,
4871 &gEfiImageSecurityDatabaseGuid
,
4873 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4874 OPTION_DEL_DB_QUESTION_ID
,
4875 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4877 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4878 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4882 LABEL_SIGNATURE_DATA_START
,
4883 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4884 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4885 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4887 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4888 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4889 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4891 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4892 IfrNvData
->CheckedDataCount
--;
4893 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4895 IfrNvData
->CheckedDataCount
++;
4896 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4898 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4899 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4903 EFI_IMAGE_SECURITY_DATABASE2
,
4904 &gEfiImageSecurityDatabaseGuid
,
4906 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4907 OPTION_DEL_DBT_QUESTION_ID
,
4908 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4914 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4915 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4916 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4917 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4918 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4919 CloseEnrolledFile (Private
->FileContext
);
4921 if (Private
->SignatureGUID
!= NULL
) {
4922 FreePool (Private
->SignatureGUID
);
4923 Private
->SignatureGUID
= NULL
;
4928 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4929 switch (QuestionId
) {
4930 case KEY_SECURE_BOOT_ENABLE
:
4931 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4933 case KEY_SECURE_BOOT_MODE
:
4934 mIsEnterSecureBootForm
= FALSE
;
4936 case KEY_SECURE_BOOT_KEK_GUID
:
4937 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4938 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4939 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4940 ASSERT (Private
->SignatureGUID
!= NULL
);
4941 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4942 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4943 Status
= EFI_INVALID_PARAMETER
;
4947 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4949 case KEY_SECURE_BOOT_DELETE_PK
:
4950 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4951 if ((SetupMode
== NULL
) || ((*SetupMode
) == SETUP_MODE
)) {
4952 IfrNvData
->DeletePk
= TRUE
;
4953 IfrNvData
->HasPk
= FALSE
;
4954 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4956 IfrNvData
->DeletePk
= FALSE
;
4957 IfrNvData
->HasPk
= TRUE
;
4958 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4961 if (SetupMode
!= NULL
) {
4962 FreePool (SetupMode
);
4966 case KEY_SECURE_BOOT_RESET_TO_DEFAULT
:
4968 Status
= gBS
->LocateProtocol (&gEfiHiiPopupProtocolGuid
, NULL
, (VOID
**)&HiiPopup
);
4969 if (EFI_ERROR (Status
)) {
4973 Status
= HiiPopup
->CreatePopup (
4975 EfiHiiPopupStyleInfo
,
4976 EfiHiiPopupTypeYesNo
,
4978 STRING_TOKEN (STR_RESET_TO_DEFAULTS_POPUP
),
4981 if (UserSelection
== EfiHiiPopupSelectionYes
) {
4982 Status
= KeyEnrollReset ();
4986 // Update secure boot strings after key reset
4988 if (Status
== EFI_SUCCESS
) {
4989 Status
= UpdateSecureBootString (Private
);
4990 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4996 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4997 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4998 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
5000 IfrNvData
->HideSecureBoot
= TRUE
;
5003 IfrNvData
->HideSecureBoot
= FALSE
;
5006 Value
->b
= IfrNvData
->HideSecureBoot
;
5008 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
5010 // Force the platform back to Standard Mode once user leave the setup screen.
5012 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
5013 if ((NULL
!= SecureBootMode
) && (*SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
)) {
5014 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
5015 SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
5018 if (SecureBootMode
!= NULL
) {
5019 FreePool (SecureBootMode
);
5022 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
5024 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
5026 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
5027 IfrNvData
->CheckedDataCount
= 0;
5033 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
5034 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
5035 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*)IfrNvData
, NULL
);
5038 FreePool (IfrNvData
);
5049 This function publish the SecureBoot configuration Form.
5051 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5053 @retval EFI_SUCCESS HII Form is installed successfully.
5054 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
5055 @retval Others Other errors as indicated.
5059 InstallSecureBootConfigForm (
5060 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5064 EFI_HII_HANDLE HiiHandle
;
5065 EFI_HANDLE DriverHandle
;
5066 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5068 DriverHandle
= NULL
;
5069 ConfigAccess
= &PrivateData
->ConfigAccess
;
5070 Status
= gBS
->InstallMultipleProtocolInterfaces (
5072 &gEfiDevicePathProtocolGuid
,
5073 &mSecureBootHiiVendorDevicePath
,
5074 &gEfiHiiConfigAccessProtocolGuid
,
5078 if (EFI_ERROR (Status
)) {
5082 PrivateData
->DriverHandle
= DriverHandle
;
5085 // Publish the HII package list
5087 HiiHandle
= HiiAddPackages (
5088 &gSecureBootConfigFormSetGuid
,
5090 SecureBootConfigDxeStrings
,
5091 SecureBootConfigBin
,
5094 if (HiiHandle
== NULL
) {
5095 gBS
->UninstallMultipleProtocolInterfaces (
5097 &gEfiDevicePathProtocolGuid
,
5098 &mSecureBootHiiVendorDevicePath
,
5099 &gEfiHiiConfigAccessProtocolGuid
,
5103 return EFI_OUT_OF_RESOURCES
;
5106 PrivateData
->HiiHandle
= HiiHandle
;
5108 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
5110 if (PrivateData
->FileContext
== NULL
) {
5111 UninstallSecureBootConfigForm (PrivateData
);
5112 return EFI_OUT_OF_RESOURCES
;
5116 // Init OpCode Handle and Allocate space for creation of Buffer
5118 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
5119 if (mStartOpCodeHandle
== NULL
) {
5120 UninstallSecureBootConfigForm (PrivateData
);
5121 return EFI_OUT_OF_RESOURCES
;
5124 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
5125 if (mEndOpCodeHandle
== NULL
) {
5126 UninstallSecureBootConfigForm (PrivateData
);
5127 return EFI_OUT_OF_RESOURCES
;
5131 // Create Hii Extend Label OpCode as the start opcode
5133 mStartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
5137 sizeof (EFI_IFR_GUID_LABEL
)
5139 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5142 // Create Hii Extend Label OpCode as the end opcode
5144 mEndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
5148 sizeof (EFI_IFR_GUID_LABEL
)
5150 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5151 mEndLabel
->Number
= LABEL_END
;
5157 This function removes SecureBoot configuration Form.
5159 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5163 UninstallSecureBootConfigForm (
5164 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5168 // Uninstall HII package list
5170 if (PrivateData
->HiiHandle
!= NULL
) {
5171 HiiRemovePackages (PrivateData
->HiiHandle
);
5172 PrivateData
->HiiHandle
= NULL
;
5176 // Uninstall HII Config Access Protocol
5178 if (PrivateData
->DriverHandle
!= NULL
) {
5179 gBS
->UninstallMultipleProtocolInterfaces (
5180 PrivateData
->DriverHandle
,
5181 &gEfiDevicePathProtocolGuid
,
5182 &mSecureBootHiiVendorDevicePath
,
5183 &gEfiHiiConfigAccessProtocolGuid
,
5184 &PrivateData
->ConfigAccess
,
5187 PrivateData
->DriverHandle
= NULL
;
5190 if (PrivateData
->SignatureGUID
!= NULL
) {
5191 FreePool (PrivateData
->SignatureGUID
);
5194 if (PrivateData
->FileContext
!= NULL
) {
5195 FreePool (PrivateData
->FileContext
);
5198 FreePool (PrivateData
);
5200 if (mStartOpCodeHandle
!= NULL
) {
5201 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5204 if (mEndOpCodeHandle
!= NULL
) {
5205 HiiFreeOpCodeHandle (mEndOpCodeHandle
);