2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "SecureBootConfigImpl.h"
11 #include <Protocol/HiiPopup.h>
12 #include <Library/BaseCryptLib.h>
13 #include <Library/SecureBootVariableLib.h>
14 #include <Library/SecureBootVariableProvisionLib.h>
16 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
18 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
19 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
21 SecureBootExtractConfig
,
22 SecureBootRouteConfig
,
27 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
33 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
)),
34 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
37 SECUREBOOT_CONFIG_FORM_SET_GUID
41 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 (UINT8
)(END_DEVICE_PATH_LENGTH
),
44 (UINT8
)((END_DEVICE_PATH_LENGTH
) >> 8)
49 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
52 // OID ASN.1 Value for Hash Algorithms
54 UINT8 mHashOidValue
[] = {
55 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
56 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
63 HASH_TABLE mHash
[] = {
64 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
65 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
66 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
67 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
71 // Variable Definitions
73 UINT32 mPeCoffHeaderOffset
= 0;
74 WIN_CERTIFICATE
*mCertificate
= NULL
;
75 IMAGE_TYPE mImageType
;
76 UINT8
*mImageBase
= NULL
;
78 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
79 UINTN mImageDigestSize
;
81 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
82 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
85 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
87 CHAR16
*mDerEncodedSuffix
[] = {
93 CHAR16
*mSupportX509Suffix
= L
"*.cer/der/crt";
96 // Prompt strings during certificate enrollment.
98 CHAR16
*mX509EnrollPromptTitle
[] = {
100 L
"ERROR: Unsupported file type!",
101 L
"ERROR: Unsupported certificate!",
104 CHAR16
*mX509EnrollPromptString
[] = {
106 L
"Only DER encoded certificate file (*.cer/der/crt) is supported.",
107 L
"Public key length should be equal to or greater than 2048 bits.",
111 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
114 This code cleans up enrolled file by closing file & free related resources attached to
117 @param[in] FileContext FileContext cached in SecureBootConfig driver
122 IN SECUREBOOT_FILE_CONTEXT
*FileContext
125 if (FileContext
->FHandle
!= NULL
) {
126 CloseFile (FileContext
->FHandle
);
127 FileContext
->FHandle
= NULL
;
130 if (FileContext
->FileName
!= NULL
) {
131 FreePool (FileContext
->FileName
);
132 FileContext
->FileName
= NULL
;
135 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
139 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
141 @param[in] FileSuffix The suffix of the input certificate file
143 @retval TRUE It's a DER-encoded certificate.
144 @retval FALSE It's NOT a DER-encoded certificate.
148 IsDerEncodeCertificate (
149 IN CONST CHAR16
*FileSuffix
154 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
155 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
164 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
165 The function reads file content but won't open/close given FileHandle.
167 @param[in] FileHandle The FileHandle to be checked
169 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
170 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
174 IsAuthentication2Format (
175 IN EFI_FILE_HANDLE FileHandle
179 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
180 BOOLEAN IsAuth2Format
;
182 IsAuth2Format
= FALSE
;
185 // Read the whole file content
187 Status
= ReadFileContent (
189 (VOID
**)&mImageBase
,
193 if (EFI_ERROR (Status
)) {
197 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
198 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
202 if (CompareGuid (&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
203 IsAuth2Format
= TRUE
;
208 // Do not close File. simply check file content
210 if (mImageBase
!= NULL
) {
211 FreePool (mImageBase
);
215 return IsAuth2Format
;
219 Set Secure Boot option into variable space.
221 @param[in] VarValue The option of Secure Boot.
223 @retval EFI_SUCCESS The operation is finished successfully.
224 @retval Others Other errors as indicated.
228 SaveSecureBootVariable (
234 Status
= gRT
->SetVariable (
235 EFI_SECURE_BOOT_ENABLE_NAME
,
236 &gEfiSecureBootEnableDisableGuid
,
237 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
245 This code checks if the encode type and key strength of X.509
246 certificate is qualified.
248 @param[in] X509FileContext FileContext of X.509 certificate storing
250 @param[out] Error Error type checked in the certificate.
252 @return EFI_SUCCESS The certificate checked successfully.
253 @return EFI_INVALID_PARAMETER The parameter is invalid.
254 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
258 CheckX509Certificate (
259 IN SECUREBOOT_FILE_CONTEXT
*X509FileContext
,
260 OUT ENROLL_KEY_ERROR
*Error
271 if (X509FileContext
->FileName
== NULL
) {
272 *Error
= Unsupported_Type
;
273 return EFI_INVALID_PARAMETER
;
282 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
284 NameLength
= StrLen (X509FileContext
->FileName
);
285 if (NameLength
<= 4) {
286 DEBUG ((DEBUG_ERROR
, "Wrong X509 NameLength\n"));
287 *Error
= Unsupported_Type
;
288 return EFI_INVALID_PARAMETER
;
291 FilePostFix
= X509FileContext
->FileName
+ NameLength
- 4;
292 if (!IsDerEncodeCertificate (FilePostFix
)) {
293 DEBUG ((DEBUG_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix
));
294 *Error
= Unsupported_Type
;
295 return EFI_INVALID_PARAMETER
;
298 DEBUG ((DEBUG_INFO
, "FileName= %s\n", X509FileContext
->FileName
));
299 DEBUG ((DEBUG_INFO
, "FilePostFix = %s\n", FilePostFix
));
302 // Read the certificate file content
304 Status
= ReadFileContent (X509FileContext
->FHandle
, (VOID
**)&X509Data
, &X509DataSize
, 0);
305 if (EFI_ERROR (Status
)) {
306 DEBUG ((DEBUG_ERROR
, "Error occured while reading the file.\n"));
311 // Parse the public key context.
313 if (RsaGetPublicKeyFromX509 (X509Data
, X509DataSize
, &X509PubKey
) == FALSE
) {
314 DEBUG ((DEBUG_ERROR
, "Error occured while parsing the pubkey from certificate.\n"));
315 Status
= EFI_INVALID_PARAMETER
;
316 *Error
= Unsupported_Type
;
321 // Parse Module size of public key using interface provided by CryptoPkg, which is
322 // actually the size of public key.
324 if (X509PubKey
!= NULL
) {
325 RsaGetKey (X509PubKey
, RsaKeyN
, NULL
, &PubKeyModSize
);
326 if (PubKeyModSize
< CER_PUBKEY_MIN_SIZE
) {
327 DEBUG ((DEBUG_ERROR
, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
328 Status
= EFI_INVALID_PARAMETER
;
329 *Error
= Unqualified_Key
;
332 RsaFree (X509PubKey
);
336 if (X509Data
!= NULL
) {
344 Generate the PK signature list from the X509 Certificate storing file (.cer)
346 @param[in] X509File FileHandle of X509 Certificate storing file.
347 @param[out] PkCert Point to the data buffer to store the signature list.
349 @return EFI_UNSUPPORTED Unsupported Key Length.
350 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
354 CreatePkX509SignatureList (
355 IN EFI_FILE_HANDLE X509File
,
356 OUT EFI_SIGNATURE_LIST
**PkCert
362 EFI_SIGNATURE_DATA
*PkCertData
;
368 Status
= ReadFileContent (X509File
, (VOID
**)&X509Data
, &X509DataSize
, 0);
369 if (EFI_ERROR (Status
)) {
373 ASSERT (X509Data
!= NULL
);
376 // Allocate space for PK certificate list and initialize it.
377 // Create PK database entry with SignatureHeaderSize equals 0.
379 *PkCert
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (
380 sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1
383 if (*PkCert
== NULL
) {
384 Status
= EFI_OUT_OF_RESOURCES
;
388 (*PkCert
)->SignatureListSize
= (UINT32
)(sizeof (EFI_SIGNATURE_LIST
)
389 + sizeof (EFI_SIGNATURE_DATA
) - 1
391 (*PkCert
)->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
392 (*PkCert
)->SignatureHeaderSize
= 0;
393 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
394 PkCertData
= (EFI_SIGNATURE_DATA
*)((UINTN
)(*PkCert
)
395 + sizeof (EFI_SIGNATURE_LIST
)
396 + (*PkCert
)->SignatureHeaderSize
);
397 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
399 // Fill the PK database with PKpub data from X509 certificate file.
401 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
405 if (X509Data
!= NULL
) {
409 if (EFI_ERROR (Status
) && (*PkCert
!= NULL
)) {
418 Enroll new PK into the System without original PK's authentication.
420 The SignatureOwner GUID will be the same with PK's vendorguid.
422 @param[in] PrivateData The module's private data.
424 @retval EFI_SUCCESS New PK enrolled successfully.
425 @retval EFI_INVALID_PARAMETER The parameter is invalid.
426 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
431 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
437 EFI_SIGNATURE_LIST
*PkCert
;
441 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
442 if (EFI_ERROR (Status
)) {
447 // Prase the selected PK file and generate PK certificate list.
449 Status
= CreatePkX509SignatureList (
450 Private
->FileContext
->FHandle
,
453 if (EFI_ERROR (Status
)) {
457 ASSERT (PkCert
!= NULL
);
460 // Set Platform Key variable.
462 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
463 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
464 DataSize
= PkCert
->SignatureListSize
;
465 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**)&PkCert
);
466 if (EFI_ERROR (Status
)) {
467 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
471 Status
= gRT
->SetVariable (
472 EFI_PLATFORM_KEY_NAME
,
473 &gEfiGlobalVariableGuid
,
478 if (EFI_ERROR (Status
)) {
479 if (Status
== EFI_OUT_OF_RESOURCES
) {
480 DEBUG ((DEBUG_ERROR
, "Enroll PK failed with out of resource.\n"));
488 if (PkCert
!= NULL
) {
492 CloseEnrolledFile (Private
->FileContext
);
498 Enroll a new KEK item from public key storing file (*.pbk).
500 @param[in] PrivateData The module's private data.
502 @retval EFI_SUCCESS New KEK enrolled successfully.
503 @retval EFI_INVALID_PARAMETER The parameter is invalid.
504 @retval EFI_UNSUPPORTED Unsupported command.
505 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
510 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
516 EFI_SIGNATURE_LIST
*KekSigList
;
519 CPL_KEY_INFO
*KeyInfo
;
520 EFI_SIGNATURE_DATA
*KEKSigData
;
521 UINTN KekSigListSize
;
536 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
537 // First, We have to parse out public key data from the pbk key file.
539 Status
= ReadFileContent (
540 Private
->FileContext
->FHandle
,
545 if (EFI_ERROR (Status
)) {
549 ASSERT (KeyBlob
!= NULL
);
550 KeyInfo
= (CPL_KEY_INFO
*)KeyBlob
;
551 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
552 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
553 Status
= EFI_UNSUPPORTED
;
558 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
560 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
561 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
562 if (KeyBuffer
== NULL
) {
563 Status
= EFI_OUT_OF_RESOURCES
;
568 (UINTN
*)(KeyBlob
+ sizeof (CPL_KEY_INFO
)),
569 KeyLenInBytes
/ sizeof (UINTN
),
573 CopyMem (KeyBlob
+ sizeof (CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
576 // Form an new EFI_SIGNATURE_LIST.
578 KekSigListSize
= sizeof (EFI_SIGNATURE_LIST
)
579 + sizeof (EFI_SIGNATURE_DATA
) - 1
580 + WIN_CERT_UEFI_RSA2048_SIZE
;
582 KekSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (KekSigListSize
);
583 if (KekSigList
== NULL
) {
584 Status
= EFI_OUT_OF_RESOURCES
;
588 KekSigList
->SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
)
589 + sizeof (EFI_SIGNATURE_DATA
) - 1
590 + WIN_CERT_UEFI_RSA2048_SIZE
;
591 KekSigList
->SignatureHeaderSize
= 0;
592 KekSigList
->SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
593 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
595 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
596 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
598 KEKSigData
->SignatureData
,
599 KeyBlob
+ sizeof (CPL_KEY_INFO
),
600 WIN_CERT_UEFI_RSA2048_SIZE
604 // Check if KEK entry has been already existed.
605 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
606 // new KEK to original variable.
608 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
609 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
610 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**)&KekSigList
);
611 if (EFI_ERROR (Status
)) {
612 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
616 Status
= gRT
->GetVariable (
617 EFI_KEY_EXCHANGE_KEY_NAME
,
618 &gEfiGlobalVariableGuid
,
623 if (Status
== EFI_BUFFER_TOO_SMALL
) {
624 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
625 } else if (Status
!= EFI_NOT_FOUND
) {
630 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
632 Status
= gRT
->SetVariable (
633 EFI_KEY_EXCHANGE_KEY_NAME
,
634 &gEfiGlobalVariableGuid
,
639 if (EFI_ERROR (Status
)) {
645 CloseEnrolledFile (Private
->FileContext
);
647 if (Private
->SignatureGUID
!= NULL
) {
648 FreePool (Private
->SignatureGUID
);
649 Private
->SignatureGUID
= NULL
;
652 if (KeyBlob
!= NULL
) {
656 if (KeyBuffer
!= NULL
) {
657 FreePool (KeyBuffer
);
660 if (KekSigList
!= NULL
) {
661 FreePool (KekSigList
);
668 Enroll a new KEK item from X509 certificate file.
670 @param[in] PrivateData The module's private data.
672 @retval EFI_SUCCESS New X509 is enrolled successfully.
673 @retval EFI_INVALID_PARAMETER The parameter is invalid.
674 @retval EFI_UNSUPPORTED Unsupported command.
675 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
680 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
686 EFI_SIGNATURE_DATA
*KEKSigData
;
687 EFI_SIGNATURE_LIST
*KekSigList
;
689 UINTN KekSigListSize
;
699 Status
= ReadFileContent (
700 Private
->FileContext
->FHandle
,
705 if (EFI_ERROR (Status
)) {
709 ASSERT (X509Data
!= NULL
);
711 KekSigListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
712 KekSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (KekSigListSize
);
713 if (KekSigList
== NULL
) {
714 Status
= EFI_OUT_OF_RESOURCES
;
719 // Fill Certificate Database parameters.
721 KekSigList
->SignatureListSize
= (UINT32
)KekSigListSize
;
722 KekSigList
->SignatureHeaderSize
= 0;
723 KekSigList
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
724 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
726 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
727 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
728 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
731 // Check if KEK been already existed.
732 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
733 // new kek to original variable
735 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
736 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
737 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**)&KekSigList
);
738 if (EFI_ERROR (Status
)) {
739 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
743 Status
= gRT
->GetVariable (
744 EFI_KEY_EXCHANGE_KEY_NAME
,
745 &gEfiGlobalVariableGuid
,
750 if (Status
== EFI_BUFFER_TOO_SMALL
) {
751 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
752 } else if (Status
!= EFI_NOT_FOUND
) {
756 Status
= gRT
->SetVariable (
757 EFI_KEY_EXCHANGE_KEY_NAME
,
758 &gEfiGlobalVariableGuid
,
763 if (EFI_ERROR (Status
)) {
769 CloseEnrolledFile (Private
->FileContext
);
771 if (Private
->SignatureGUID
!= NULL
) {
772 FreePool (Private
->SignatureGUID
);
773 Private
->SignatureGUID
= NULL
;
776 if (KekSigList
!= NULL
) {
777 FreePool (KekSigList
);
784 Enroll new KEK into the System without PK's authentication.
785 The SignatureOwner GUID will be Private->SignatureGUID.
787 @param[in] PrivateData The module's private data.
789 @retval EFI_SUCCESS New KEK enrolled successful.
790 @retval EFI_INVALID_PARAMETER The parameter is invalid.
791 @retval others Fail to enroll KEK data.
795 EnrollKeyExchangeKey (
796 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
803 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
804 return EFI_INVALID_PARAMETER
;
807 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
808 if (EFI_ERROR (Status
)) {
813 // Parse the file's postfix. Supports DER-encoded X509 certificate,
814 // and .pbk as RSA public key file.
816 NameLength
= StrLen (Private
->FileContext
->FileName
);
817 if (NameLength
<= 4) {
818 return EFI_INVALID_PARAMETER
;
821 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
822 if (IsDerEncodeCertificate (FilePostFix
)) {
823 return EnrollX509ToKek (Private
);
824 } else if (CompareMem (FilePostFix
, L
".pbk", 4) == 0) {
825 return EnrollRsa2048ToKek (Private
);
828 // File type is wrong, simply close it
830 CloseEnrolledFile (Private
->FileContext
);
832 return EFI_INVALID_PARAMETER
;
837 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
838 KEK's authentication.
840 @param[in] PrivateData The module's private data.
841 @param[in] VariableName Variable name of signature database, must be
842 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
844 @retval EFI_SUCCESS New X509 is enrolled successfully.
845 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
850 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
851 IN CHAR16
*VariableName
857 EFI_SIGNATURE_LIST
*SigDBCert
;
858 EFI_SIGNATURE_DATA
*SigDBCertData
;
869 SigDBCertData
= NULL
;
872 Status
= ReadFileContent (
873 Private
->FileContext
->FHandle
,
878 if (EFI_ERROR (Status
)) {
882 ASSERT (X509Data
!= NULL
);
884 SigDBSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
886 Data
= AllocateZeroPool (SigDBSize
);
888 Status
= EFI_OUT_OF_RESOURCES
;
893 // Fill Certificate Database parameters.
895 SigDBCert
= (EFI_SIGNATURE_LIST
*)Data
;
896 SigDBCert
->SignatureListSize
= (UINT32
)SigDBSize
;
897 SigDBCert
->SignatureHeaderSize
= 0;
898 SigDBCert
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
899 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
901 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
902 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
903 CopyMem ((UINT8
*)(SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
906 // Check if signature database entry has been already existed.
907 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
908 // new signature data to original variable
910 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
911 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
912 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**)&Data
);
913 if (EFI_ERROR (Status
)) {
914 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
918 Status
= gRT
->GetVariable (
920 &gEfiImageSecurityDatabaseGuid
,
925 if (Status
== EFI_BUFFER_TOO_SMALL
) {
926 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
927 } else if (Status
!= EFI_NOT_FOUND
) {
931 Status
= gRT
->SetVariable (
933 &gEfiImageSecurityDatabaseGuid
,
938 if (EFI_ERROR (Status
)) {
944 CloseEnrolledFile (Private
->FileContext
);
946 if (Private
->SignatureGUID
!= NULL
) {
947 FreePool (Private
->SignatureGUID
);
948 Private
->SignatureGUID
= NULL
;
955 if (X509Data
!= NULL
) {
963 Check whether signature is in specified database.
965 @param[in] VariableName Name of database variable that is searched in.
966 @param[in] Signature Pointer to signature that is searched for.
967 @param[in] SignatureSize Size of Signature.
969 @return TRUE Found the signature in the variable database.
970 @return FALSE Not found the signature in the variable database.
974 IsSignatureFoundInDatabase (
975 IN CHAR16
*VariableName
,
977 IN UINTN SignatureSize
981 EFI_SIGNATURE_LIST
*CertList
;
982 EFI_SIGNATURE_DATA
*Cert
;
990 // Read signature database variable.
995 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
996 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1000 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1005 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1006 if (EFI_ERROR (Status
)) {
1011 // Enumerate all signature data in SigDB to check if signature exists for executable.
1013 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
1014 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1015 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1016 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1017 if ((CertList
->SignatureSize
== sizeof (EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1018 for (Index
= 0; Index
< CertCount
; Index
++) {
1019 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1021 // Find the signature in database.
1027 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
1035 DataSize
-= CertList
->SignatureListSize
;
1036 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
1048 Calculate the hash of a certificate data with the specified hash algorithm.
1050 @param[in] CertData The certificate data to be hashed.
1051 @param[in] CertSize The certificate size in bytes.
1052 @param[in] HashAlg The specified hash algorithm.
1053 @param[out] CertHash The output digest of the certificate
1055 @retval TRUE Successfully got the hash of the CertData.
1056 @retval FALSE Failed to get the hash of CertData.
1076 if (HashAlg
>= HASHALG_MAX
) {
1081 // Retrieve the TBSCertificate for Hash Calculation.
1083 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1088 // 1. Initialize context of hash.
1090 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1091 HashCtx
= AllocatePool (CtxSize
);
1092 ASSERT (HashCtx
!= NULL
);
1095 // 2. Initialize a hash context.
1097 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1103 // 3. Calculate the hash.
1105 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1111 // 4. Get the hash result.
1113 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1114 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1117 if (HashCtx
!= NULL
) {
1125 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1127 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1128 @param[in] CertSize Size of X.509 Certificate.
1130 @return TRUE Found the certificate hash in the forbidden database.
1131 @return FALSE Certificate hash is Not found in the forbidden database.
1135 IsCertHashFoundInDbx (
1136 IN UINT8
*Certificate
,
1142 EFI_SIGNATURE_LIST
*DbxList
;
1143 EFI_SIGNATURE_DATA
*CertHash
;
1144 UINTN CertHashCount
;
1147 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1149 UINTN SiglistHeaderSize
;
1154 HashAlg
= HASHALG_MAX
;
1158 // Read signature database variable.
1161 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1162 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1166 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1171 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1172 if (EFI_ERROR (Status
)) {
1177 // Check whether the certificate hash exists in the forbidden database.
1179 DbxList
= (EFI_SIGNATURE_LIST
*)Data
;
1180 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1182 // Determine Hash Algorithm of Certificate in the forbidden database.
1184 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1185 HashAlg
= HASHALG_SHA256
;
1186 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1187 HashAlg
= HASHALG_SHA384
;
1188 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1189 HashAlg
= HASHALG_SHA512
;
1191 DataSize
-= DbxList
->SignatureListSize
;
1192 DbxList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)DbxList
+ DbxList
->SignatureListSize
);
1197 // Calculate the hash value of current db certificate for comparision.
1199 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1203 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1204 CertHash
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DbxList
+ SiglistHeaderSize
);
1205 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1206 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1208 // Iterate each Signature Data Node within this CertList for verify.
1210 DbxCertHash
= CertHash
->SignatureData
;
1211 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1213 // Hash of Certificate is found in forbidden database.
1219 CertHash
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertHash
+ DbxList
->SignatureSize
);
1222 DataSize
-= DbxList
->SignatureListSize
;
1223 DbxList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)DbxList
+ DbxList
->SignatureListSize
);
1235 Check whether the signature list exists in given variable data.
1237 It searches the signature list for the certificate hash by CertType.
1238 If the signature list is found, get the offset of Database for the
1239 next hash of a certificate.
1241 @param[in] Database Variable data to save signature list.
1242 @param[in] DatabaseSize Variable size.
1243 @param[in] SignatureType The type of the signature.
1244 @param[out] Offset The offset to save a new hash of certificate.
1246 @return TRUE The signature list is found in the forbidden database.
1247 @return FALSE The signature list is not found in the forbidden database.
1250 GetSignaturelistOffset (
1251 IN EFI_SIGNATURE_LIST
*Database
,
1252 IN UINTN DatabaseSize
,
1253 IN EFI_GUID
*SignatureType
,
1257 EFI_SIGNATURE_LIST
*SigList
;
1260 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1266 SiglistSize
= DatabaseSize
;
1267 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1268 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1269 *Offset
= DatabaseSize
- SiglistSize
;
1273 SiglistSize
-= SigList
->SignatureListSize
;
1274 SigList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)SigList
+ SigList
->SignatureListSize
);
1282 Enroll a new X509 certificate hash into Signature Database (dbx) without
1283 KEK's authentication.
1285 @param[in] PrivateData The module's private data.
1286 @param[in] HashAlg The hash algorithm to enroll the certificate.
1287 @param[in] RevocationDate The revocation date of the certificate.
1288 @param[in] RevocationTime The revocation time of the certificate.
1289 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1291 @retval EFI_SUCCESS New X509 is enrolled successfully.
1292 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1293 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1297 EnrollX509HashtoSigDB (
1298 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1300 IN EFI_HII_DATE
*RevocationDate
,
1301 IN EFI_HII_TIME
*RevocationTime
,
1302 IN BOOLEAN AlwaysRevocation
1308 EFI_SIGNATURE_LIST
*SignatureList
;
1309 UINTN SignatureListSize
;
1315 EFI_SIGNATURE_DATA
*SignatureData
;
1316 UINTN SignatureSize
;
1317 EFI_GUID SignatureType
;
1319 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1320 UINT16
*FilePostFix
;
1327 SignatureData
= NULL
;
1328 SignatureList
= NULL
;
1332 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1333 return EFI_INVALID_PARAMETER
;
1336 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1337 if (EFI_ERROR (Status
)) {
1342 // Parse the file's postfix.
1344 NameLength
= StrLen (Private
->FileContext
->FileName
);
1345 if (NameLength
<= 4) {
1346 return EFI_INVALID_PARAMETER
;
1349 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1350 if (!IsDerEncodeCertificate (FilePostFix
)) {
1352 // Only supports DER-encoded X509 certificate.
1354 return EFI_INVALID_PARAMETER
;
1358 // Get the certificate from file and calculate its hash.
1360 Status
= ReadFileContent (
1361 Private
->FileContext
->FHandle
,
1366 if (EFI_ERROR (Status
)) {
1370 ASSERT (X509Data
!= NULL
);
1372 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1377 // Get the variable for enrollment.
1380 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1381 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1382 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1384 return EFI_OUT_OF_RESOURCES
;
1387 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1388 if (EFI_ERROR (Status
)) {
1394 // Allocate memory for Signature and fill the Signature
1396 SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1397 SignatureData
= (EFI_SIGNATURE_DATA
*)AllocateZeroPool (SignatureSize
);
1398 if (SignatureData
== NULL
) {
1399 return EFI_OUT_OF_RESOURCES
;
1402 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1403 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1408 if (!AlwaysRevocation
) {
1409 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1410 Time
->Year
= RevocationDate
->Year
;
1411 Time
->Month
= RevocationDate
->Month
;
1412 Time
->Day
= RevocationDate
->Day
;
1413 Time
->Hour
= RevocationTime
->Hour
;
1414 Time
->Minute
= RevocationTime
->Minute
;
1415 Time
->Second
= RevocationTime
->Second
;
1419 // Determine the GUID for certificate hash.
1422 case HASHALG_SHA256
:
1423 SignatureType
= gEfiCertX509Sha256Guid
;
1425 case HASHALG_SHA384
:
1426 SignatureType
= gEfiCertX509Sha384Guid
;
1428 case HASHALG_SHA512
:
1429 SignatureType
= gEfiCertX509Sha512Guid
;
1436 // Add signature into the new variable data buffer
1438 if (GetSignaturelistOffset ((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1440 // Add the signature to the found signaturelist.
1442 DbSize
= DataSize
+ SignatureSize
;
1443 NewData
= AllocateZeroPool (DbSize
);
1444 if (NewData
== NULL
) {
1445 Status
= EFI_OUT_OF_RESOURCES
;
1449 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1450 SignatureListSize
= (UINTN
)ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1451 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1453 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1454 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1456 Offset
+= SignatureListSize
;
1457 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1458 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1465 // Create a new signaturelist, and add the signature into the signaturelist.
1467 DbSize
= DataSize
+ sizeof (EFI_SIGNATURE_LIST
) + SignatureSize
;
1468 NewData
= AllocateZeroPool (DbSize
);
1469 if (NewData
== NULL
) {
1470 Status
= EFI_OUT_OF_RESOURCES
;
1475 // Fill Certificate Database parameters.
1477 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ DataSize
);
1478 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + SignatureSize
;
1479 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
, (UINT32
)SignatureListSize
);
1480 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureSize
, (UINT32
)SignatureSize
);
1481 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1482 CopyMem ((UINT8
*)SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1483 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1484 CopyMem (NewData
, Data
, DataSize
);
1492 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**)&Data
);
1493 if (EFI_ERROR (Status
)) {
1497 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1498 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1499 Status
= gRT
->SetVariable (
1500 EFI_IMAGE_SECURITY_DATABASE1
,
1501 &gEfiImageSecurityDatabaseGuid
,
1506 if (EFI_ERROR (Status
)) {
1512 CloseEnrolledFile (Private
->FileContext
);
1514 if (Private
->SignatureGUID
!= NULL
) {
1515 FreePool (Private
->SignatureGUID
);
1516 Private
->SignatureGUID
= NULL
;
1523 if (SignatureData
!= NULL
) {
1524 FreePool (SignatureData
);
1527 if (X509Data
!= NULL
) {
1528 FreePool (X509Data
);
1535 Check whether a certificate from a file exists in dbx.
1537 @param[in] PrivateData The module's private data.
1538 @param[in] VariableName Variable name of signature database, must be
1539 EFI_IMAGE_SECURITY_DATABASE1.
1541 @retval TRUE The X509 certificate is found in dbx successfully.
1542 @retval FALSE The X509 certificate is not found in dbx.
1546 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1547 IN CHAR16
*VariableName
1556 // Read the certificate from file
1560 Status
= ReadFileContent (
1561 Private
->FileContext
->FHandle
,
1566 if (EFI_ERROR (Status
)) {
1571 // Check the raw certificate.
1574 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1580 // Check the hash of certificate.
1582 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1588 if (X509Data
!= NULL
) {
1589 FreePool (X509Data
);
1596 Reads contents of a PE/COFF image in memory buffer.
1598 Caution: This function may receive untrusted input.
1599 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1600 read is within the image buffer.
1602 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1603 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1604 @param ReadSize On input, the size in bytes of the requested read operation.
1605 On output, the number of bytes actually read.
1606 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1608 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1612 SecureBootConfigImageRead (
1613 IN VOID
*FileHandle
,
1614 IN UINTN FileOffset
,
1615 IN OUT UINTN
*ReadSize
,
1621 if ((FileHandle
== NULL
) || (ReadSize
== NULL
) || (Buffer
== NULL
)) {
1622 return EFI_INVALID_PARAMETER
;
1625 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1626 return EFI_INVALID_PARAMETER
;
1629 EndPosition
= FileOffset
+ *ReadSize
;
1630 if (EndPosition
> mImageSize
) {
1631 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1634 if (FileOffset
>= mImageSize
) {
1638 CopyMem (Buffer
, (UINT8
*)((UINTN
)FileHandle
+ FileOffset
), *ReadSize
);
1644 Load PE/COFF image information into internal buffer and check its validity.
1646 @retval EFI_SUCCESS Successful
1647 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1648 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1656 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1657 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1658 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1659 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1665 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1666 ImageContext
.Handle
= (VOID
*)mImageBase
;
1667 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)SecureBootConfigImageRead
;
1670 // Get information about the image being loaded
1672 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1673 if (EFI_ERROR (Status
)) {
1675 // The information can't be got from the invalid PeImage
1677 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1682 // Read the Dos header
1684 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1685 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1687 // DOS image header is present,
1688 // So read the PE header after the DOS image header
1690 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1692 mPeCoffHeaderOffset
= 0;
1696 // Read PE header and check the signature validity and machine compatibility
1698 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*)(mImageBase
+ mPeCoffHeaderOffset
);
1699 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1700 return EFI_UNSUPPORTED
;
1703 mNtHeader
.Pe32
= NtHeader32
;
1706 // Check the architecture field of PE header and get the Certificate Data Directory data
1707 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1709 if ( (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1710 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1711 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
))
1714 // 32-bits Architecture
1716 mImageType
= ImageType_IA32
;
1717 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*)&(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1718 } else if ( (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1719 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1720 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
))
1723 // 64-bits Architecture
1725 mImageType
= ImageType_X64
;
1726 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*)(mImageBase
+ mPeCoffHeaderOffset
);
1727 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*)&(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1729 return EFI_UNSUPPORTED
;
1736 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1737 PE/COFF Specification 8.0 Appendix A
1739 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1740 the function LoadPeImage ().
1742 @param[in] HashAlg Hash algorithm type.
1744 @retval TRUE Successfully hash image.
1745 @retval FALSE Fail in hash image.
1754 EFI_IMAGE_SECTION_HEADER
*Section
;
1759 UINTN SumOfBytesHashed
;
1760 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1765 SectionHeader
= NULL
;
1768 if (HashAlg
!= HASHALG_SHA256
) {
1773 // Initialize context of hash.
1775 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1777 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1778 mCertType
= gEfiCertSha256Guid
;
1780 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1782 HashCtx
= AllocatePool (CtxSize
);
1783 ASSERT (HashCtx
!= NULL
);
1785 // 1. Load the image header into memory.
1787 // 2. Initialize a SHA hash context.
1788 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1794 // Measuring PE/COFF Image Header;
1795 // But CheckSum field and SECURITY data directory (certificate) are excluded
1799 // 3. Calculate the distance from the base of the image header to the image checksum address.
1800 // 4. Hash the image header from its base to beginning of the image checksum.
1802 HashBase
= mImageBase
;
1803 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1807 HashSize
= (UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
)HashBase
;
1810 // Use PE32+ offset.
1812 HashSize
= (UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
)HashBase
;
1815 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1821 // 5. Skip over the image checksum (it occupies a single ULONG).
1822 // 6. Get the address of the beginning of the Cert Directory.
1823 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1825 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1829 HashBase
= (UINT8
*)&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1830 HashSize
= (UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
)HashBase
;
1833 // Use PE32+ offset.
1835 HashBase
= (UINT8
*)&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1836 HashSize
= (UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
)HashBase
;
1839 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1845 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1846 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1848 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1852 HashBase
= (UINT8
*)&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1853 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
)mImageBase
);
1856 // Use PE32+ offset.
1858 HashBase
= (UINT8
*)&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1859 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
)mImageBase
);
1862 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1868 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1870 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1874 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1879 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1883 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1884 // structures in the image. The 'NumberOfSections' field of the image
1885 // header indicates how big the table should be. Do not include any
1886 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1888 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1889 ASSERT (SectionHeader
!= NULL
);
1891 // 12. Using the 'PointerToRawData' in the referenced section headers as
1892 // a key, arrange the elements in the table in ascending order. In other
1893 // words, sort the section headers according to the disk-file offset of
1896 Section
= (EFI_IMAGE_SECTION_HEADER
*)(
1898 mPeCoffHeaderOffset
+
1900 sizeof (EFI_IMAGE_FILE_HEADER
) +
1901 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1903 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1905 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1906 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1910 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1915 // 13. Walk through the sorted table, bring the corresponding section
1916 // into memory, and hash the entire section (using the 'SizeOfRawData'
1917 // field in the section header to determine the amount of data to hash).
1918 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1919 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1921 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1922 Section
= &SectionHeader
[Index
];
1923 if (Section
->SizeOfRawData
== 0) {
1927 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1928 HashSize
= (UINTN
)Section
->SizeOfRawData
;
1930 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1935 SumOfBytesHashed
+= HashSize
;
1939 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1940 // data in the file that needs to be added to the hash. This data begins
1941 // at file offset SUM_OF_BYTES_HASHED and its length is:
1942 // FileSize - (CertDirectory->Size)
1944 if (mImageSize
> SumOfBytesHashed
) {
1945 HashBase
= mImageBase
+ SumOfBytesHashed
;
1946 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1952 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1956 // Use PE32+ offset.
1960 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1964 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1970 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, mImageDigest
);
1973 if (HashCtx
!= NULL
) {
1977 if (SectionHeader
!= NULL
) {
1978 FreePool (SectionHeader
);
1985 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
1986 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1989 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1990 @retval EFI_SUCCESS Hash successfully.
1999 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2001 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*)(mImageBase
+ mSecDataDir
->Offset
);
2003 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2005 // Check the Hash algorithm in PE/COFF Authenticode.
2006 // According to PKCS#7 Definition:
2007 // SignedData ::= SEQUENCE {
2009 // digestAlgorithms DigestAlgorithmIdentifiers,
2010 // contentInfo ContentInfo,
2012 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2013 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2014 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2016 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2018 // Only support two bytes of Long Form of Length Encoding.
2024 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2029 if (Index
== HASHALG_MAX
) {
2030 return EFI_UNSUPPORTED
;
2034 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2036 if (!HashPeImage (Index
)) {
2037 return EFI_UNSUPPORTED
;
2044 Enroll a new signature of executable into Signature Database.
2046 @param[in] PrivateData The module's private data.
2047 @param[in] VariableName Variable name of signature database, must be
2048 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2049 or EFI_IMAGE_SECURITY_DATABASE2.
2051 @retval EFI_SUCCESS New signature is enrolled successfully.
2052 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2053 @retval EFI_UNSUPPORTED Unsupported command.
2054 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2058 EnrollAuthentication2Descriptor (
2059 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2060 IN CHAR16
*VariableName
2071 // DBT only support DER-X509 Cert Enrollment
2073 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2074 return EFI_UNSUPPORTED
;
2078 // Read the whole file content
2080 Status
= ReadFileContent (
2081 Private
->FileContext
->FHandle
,
2082 (VOID
**)&mImageBase
,
2086 if (EFI_ERROR (Status
)) {
2090 ASSERT (mImageBase
!= NULL
);
2092 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2093 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2096 // Check if SigDB variable has been already existed.
2097 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2098 // new signature data to original variable
2101 Status
= gRT
->GetVariable (
2103 &gEfiImageSecurityDatabaseGuid
,
2108 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2109 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2110 } else if (Status
!= EFI_NOT_FOUND
) {
2115 // Directly set AUTHENTICATION_2 data to SetVariable
2117 Status
= gRT
->SetVariable (
2119 &gEfiImageSecurityDatabaseGuid
,
2125 DEBUG ((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2129 CloseEnrolledFile (Private
->FileContext
);
2135 if (mImageBase
!= NULL
) {
2136 FreePool (mImageBase
);
2144 Enroll a new signature of executable into Signature Database.
2146 @param[in] PrivateData The module's private data.
2147 @param[in] VariableName Variable name of signature database, must be
2148 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2149 or EFI_IMAGE_SECURITY_DATABASE2.
2151 @retval EFI_SUCCESS New signature is enrolled successfully.
2152 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2153 @retval EFI_UNSUPPORTED Unsupported command.
2154 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2158 EnrollImageSignatureToSigDB (
2159 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2160 IN CHAR16
*VariableName
2164 EFI_SIGNATURE_LIST
*SigDBCert
;
2165 EFI_SIGNATURE_DATA
*SigDBCertData
;
2170 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2173 GuidCertData
= NULL
;
2175 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2176 return EFI_UNSUPPORTED
;
2180 // Form the SigDB certificate list.
2181 // Format the data item into EFI_SIGNATURE_LIST type.
2183 // We need to parse signature data of executable from specified signed executable file.
2184 // In current implementation, we simply trust the pass-in signed executable file.
2185 // In reality, it's OS's responsibility to verify the signed executable file.
2189 // Read the whole file content
2191 Status
= ReadFileContent (
2192 Private
->FileContext
->FHandle
,
2193 (VOID
**)&mImageBase
,
2197 if (EFI_ERROR (Status
)) {
2201 ASSERT (mImageBase
!= NULL
);
2203 Status
= LoadPeImage ();
2204 if (EFI_ERROR (Status
)) {
2208 if (mSecDataDir
->SizeOfCert
== 0) {
2209 if (!HashPeImage (HASHALG_SHA256
)) {
2210 Status
= EFI_SECURITY_VIOLATION
;
2215 // Read the certificate data
2217 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2219 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2220 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*)mCertificate
;
2221 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof (EFI_GUID
)) != 0) {
2222 Status
= EFI_ABORTED
;
2226 if (!HashPeImage (HASHALG_SHA256
)) {
2227 Status
= EFI_ABORTED
;
2230 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2231 Status
= HashPeImageByType ();
2232 if (EFI_ERROR (Status
)) {
2236 Status
= EFI_ABORTED
;
2242 // Create a new SigDB entry.
2244 SigDBSize
= sizeof (EFI_SIGNATURE_LIST
)
2245 + sizeof (EFI_SIGNATURE_DATA
) - 1
2246 + (UINT32
)mImageDigestSize
;
2248 Data
= (UINT8
*)AllocateZeroPool (SigDBSize
);
2250 Status
= EFI_OUT_OF_RESOURCES
;
2255 // Adjust the Certificate Database parameters.
2257 SigDBCert
= (EFI_SIGNATURE_LIST
*)Data
;
2258 SigDBCert
->SignatureListSize
= (UINT32
)SigDBSize
;
2259 SigDBCert
->SignatureHeaderSize
= 0;
2260 SigDBCert
->SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + (UINT32
)mImageDigestSize
;
2261 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2263 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
2264 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2265 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2267 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2268 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2269 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**)&Data
);
2270 if (EFI_ERROR (Status
)) {
2271 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2276 // Check if SigDB variable has been already existed.
2277 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2278 // new signature data to original variable
2281 Status
= gRT
->GetVariable (
2283 &gEfiImageSecurityDatabaseGuid
,
2288 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2289 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2290 } else if (Status
!= EFI_NOT_FOUND
) {
2295 // Enroll the variable.
2297 Status
= gRT
->SetVariable (
2299 &gEfiImageSecurityDatabaseGuid
,
2304 if (EFI_ERROR (Status
)) {
2310 CloseEnrolledFile (Private
->FileContext
);
2312 if (Private
->SignatureGUID
!= NULL
) {
2313 FreePool (Private
->SignatureGUID
);
2314 Private
->SignatureGUID
= NULL
;
2321 if (mImageBase
!= NULL
) {
2322 FreePool (mImageBase
);
2330 Enroll signature into DB/DBX/DBT without KEK's authentication.
2331 The SignatureOwner GUID will be Private->SignatureGUID.
2333 @param[in] PrivateData The module's private data.
2334 @param[in] VariableName Variable name of signature database, must be
2335 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2337 @retval EFI_SUCCESS New signature enrolled successfully.
2338 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2339 @retval others Fail to enroll signature data.
2343 EnrollSignatureDatabase (
2344 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2345 IN CHAR16
*VariableName
2348 UINT16
*FilePostFix
;
2352 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2353 return EFI_INVALID_PARAMETER
;
2356 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2357 if (EFI_ERROR (Status
)) {
2362 // Parse the file's postfix.
2364 NameLength
= StrLen (Private
->FileContext
->FileName
);
2365 if (NameLength
<= 4) {
2366 return EFI_INVALID_PARAMETER
;
2369 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2370 if (IsDerEncodeCertificate (FilePostFix
)) {
2372 // Supports DER-encoded X509 certificate.
2374 return EnrollX509toSigDB (Private
, VariableName
);
2375 } else if (IsAuthentication2Format (Private
->FileContext
->FHandle
)) {
2376 return EnrollAuthentication2Descriptor (Private
, VariableName
);
2378 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2383 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2384 by GUID in the page for user to select and delete as needed.
2386 @param[in] PrivateData Module's private data.
2387 @param[in] VariableName The variable name of the vendor's signature database.
2388 @param[in] VendorGuid A unique identifier for the vendor.
2389 @param[in] LabelNumber Label number to insert opcodes.
2390 @param[in] FormId Form ID of current page.
2391 @param[in] QuestionIdBase Base question id of the signature list.
2393 @retval EFI_SUCCESS Success to update the signature list page
2394 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2399 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2400 IN CHAR16
*VariableName
,
2401 IN EFI_GUID
*VendorGuid
,
2402 IN UINT16 LabelNumber
,
2403 IN EFI_FORM_ID FormId
,
2404 IN EFI_QUESTION_ID QuestionIdBase
2411 VOID
*StartOpCodeHandle
;
2412 VOID
*EndOpCodeHandle
;
2413 EFI_IFR_GUID_LABEL
*StartLabel
;
2414 EFI_IFR_GUID_LABEL
*EndLabel
;
2417 EFI_SIGNATURE_LIST
*CertList
;
2418 EFI_SIGNATURE_DATA
*Cert
;
2419 UINT32 ItemDataSize
;
2421 EFI_STRING_ID GuidID
;
2428 StartOpCodeHandle
= NULL
;
2429 EndOpCodeHandle
= NULL
;
2432 // Initialize the container for dynamic opcodes.
2434 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2435 if (StartOpCodeHandle
== NULL
) {
2436 Status
= EFI_OUT_OF_RESOURCES
;
2440 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2441 if (EndOpCodeHandle
== NULL
) {
2442 Status
= EFI_OUT_OF_RESOURCES
;
2447 // Create Hii Extend Label OpCode.
2449 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
2453 sizeof (EFI_IFR_GUID_LABEL
)
2455 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2456 StartLabel
->Number
= LabelNumber
;
2458 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
2462 sizeof (EFI_IFR_GUID_LABEL
)
2464 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2465 EndLabel
->Number
= LABEL_END
;
2471 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2472 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2476 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2478 Status
= EFI_OUT_OF_RESOURCES
;
2482 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2483 if (EFI_ERROR (Status
)) {
2487 GuidStr
= AllocateZeroPool (100);
2488 if (GuidStr
== NULL
) {
2489 Status
= EFI_OUT_OF_RESOURCES
;
2494 // Enumerate all KEK pub data.
2496 ItemDataSize
= (UINT32
)DataSize
;
2497 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2500 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2501 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2502 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2503 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2504 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2505 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2506 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2507 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2508 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2509 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2510 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2511 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2512 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2513 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2514 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2517 // The signature type is not supported in current implementation.
2519 ItemDataSize
-= CertList
->SignatureListSize
;
2520 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2524 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2525 for (Index
= 0; Index
< CertCount
; Index
++) {
2526 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
2527 + sizeof (EFI_SIGNATURE_LIST
)
2528 + CertList
->SignatureHeaderSize
2529 + Index
* CertList
->SignatureSize
);
2531 // Display GUID and help
2533 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2534 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2535 HiiCreateCheckBoxOpCode (
2537 (EFI_QUESTION_ID
)(QuestionIdBase
+ GuidIndex
++),
2542 EFI_IFR_FLAG_CALLBACK
,
2548 ItemDataSize
-= CertList
->SignatureListSize
;
2549 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2554 PrivateData
->HiiHandle
,
2555 &gSecureBootConfigFormSetGuid
,
2561 if (StartOpCodeHandle
!= NULL
) {
2562 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2565 if (EndOpCodeHandle
!= NULL
) {
2566 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2573 if (GuidStr
!= NULL
) {
2581 Delete a KEK entry from KEK database.
2583 @param[in] PrivateData Module's private data.
2584 @param[in] QuestionId Question id of the KEK item to delete.
2586 @retval EFI_SUCCESS Delete kek item successfully.
2587 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2591 DeleteKeyExchangeKey (
2592 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2593 IN EFI_QUESTION_ID QuestionId
2602 EFI_SIGNATURE_LIST
*CertList
;
2603 EFI_SIGNATURE_LIST
*NewCertList
;
2604 EFI_SIGNATURE_DATA
*Cert
;
2607 BOOLEAN IsKEKItemFound
;
2609 UINTN DeleteKekIndex
;
2617 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2619 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2620 if (EFI_ERROR (Status
)) {
2625 // Get original KEK variable.
2628 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2629 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2633 OldData
= (UINT8
*)AllocateZeroPool (DataSize
);
2634 if (OldData
== NULL
) {
2635 Status
= EFI_OUT_OF_RESOURCES
;
2639 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2640 if (EFI_ERROR (Status
)) {
2645 // Allocate space for new variable.
2647 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2649 Status
= EFI_OUT_OF_RESOURCES
;
2654 // Enumerate all KEK pub data and erasing the target item.
2656 IsKEKItemFound
= FALSE
;
2657 KekDataSize
= (UINT32
)DataSize
;
2658 CertList
= (EFI_SIGNATURE_LIST
*)OldData
;
2661 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2662 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2663 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
))
2665 CopyMem (Data
+ Offset
, CertList
, (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2666 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2667 Offset
+= (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2668 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2669 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2670 for (Index
= 0; Index
< CertCount
; Index
++) {
2671 if (GuidIndex
== DeleteKekIndex
) {
2673 // Find it! Skip it!
2675 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2676 IsKEKItemFound
= TRUE
;
2679 // This item doesn't match. Copy it to the Data buffer.
2681 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2682 Offset
+= CertList
->SignatureSize
;
2686 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
2690 // This List doesn't match. Copy it to the Data buffer.
2692 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2693 Offset
+= CertList
->SignatureListSize
;
2696 KekDataSize
-= CertList
->SignatureListSize
;
2697 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2700 if (!IsKEKItemFound
) {
2702 // Doesn't find the Kek Item!
2704 Status
= EFI_NOT_FOUND
;
2709 // Delete the Signature header if there is no signature in the list.
2711 KekDataSize
= Offset
;
2712 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2714 ZeroMem (OldData
, KekDataSize
);
2715 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2716 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2717 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2718 if (CertCount
!= 0) {
2719 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2720 Offset
+= CertList
->SignatureListSize
;
2723 KekDataSize
-= CertList
->SignatureListSize
;
2724 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2728 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2729 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2730 if (EFI_ERROR (Status
)) {
2731 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2736 Status
= gRT
->SetVariable (
2737 EFI_KEY_EXCHANGE_KEY_NAME
,
2738 &gEfiGlobalVariableGuid
,
2743 if (EFI_ERROR (Status
)) {
2744 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2753 if (OldData
!= NULL
) {
2757 return UpdateDeletePage (
2759 EFI_KEY_EXCHANGE_KEY_NAME
,
2760 &gEfiGlobalVariableGuid
,
2762 FORMID_DELETE_KEK_FORM
,
2763 OPTION_DEL_KEK_QUESTION_ID
2768 Delete a signature entry from signature database.
2770 @param[in] PrivateData Module's private data.
2771 @param[in] VariableName The variable name of the vendor's signature database.
2772 @param[in] VendorGuid A unique identifier for the vendor.
2773 @param[in] LabelNumber Label number to insert opcodes.
2774 @param[in] FormId Form ID of current page.
2775 @param[in] QuestionIdBase Base question id of the signature list.
2776 @param[in] DeleteIndex Signature index to delete.
2778 @retval EFI_SUCCESS Delete signature successfully.
2779 @retval EFI_NOT_FOUND Can't find the signature item,
2780 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2784 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2785 IN CHAR16
*VariableName
,
2786 IN EFI_GUID
*VendorGuid
,
2787 IN UINT16 LabelNumber
,
2788 IN EFI_FORM_ID FormId
,
2789 IN EFI_QUESTION_ID QuestionIdBase
,
2790 IN UINTN DeleteIndex
2799 EFI_SIGNATURE_LIST
*CertList
;
2800 EFI_SIGNATURE_LIST
*NewCertList
;
2801 EFI_SIGNATURE_DATA
*Cert
;
2804 BOOLEAN IsItemFound
;
2805 UINT32 ItemDataSize
;
2814 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2815 if (EFI_ERROR (Status
)) {
2820 // Get original signature list data.
2823 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2824 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2828 OldData
= (UINT8
*)AllocateZeroPool (DataSize
);
2829 if (OldData
== NULL
) {
2830 Status
= EFI_OUT_OF_RESOURCES
;
2834 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2835 if (EFI_ERROR (Status
)) {
2840 // Allocate space for new variable.
2842 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2844 Status
= EFI_OUT_OF_RESOURCES
;
2849 // Enumerate all signature data and erasing the target item.
2851 IsItemFound
= FALSE
;
2852 ItemDataSize
= (UINT32
)DataSize
;
2853 CertList
= (EFI_SIGNATURE_LIST
*)OldData
;
2856 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2857 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2858 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2859 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2860 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2861 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2862 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2863 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2867 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2869 CopyMem (Data
+ Offset
, CertList
, (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2870 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2871 Offset
+= (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2872 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2873 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2874 for (Index
= 0; Index
< CertCount
; Index
++) {
2875 if (GuidIndex
== DeleteIndex
) {
2877 // Find it! Skip it!
2879 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2883 // This item doesn't match. Copy it to the Data buffer.
2885 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2886 Offset
+= CertList
->SignatureSize
;
2890 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
2894 // This List doesn't match. Just copy it to the Data buffer.
2896 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2897 Offset
+= CertList
->SignatureListSize
;
2900 ItemDataSize
-= CertList
->SignatureListSize
;
2901 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2906 // Doesn't find the signature Item!
2908 Status
= EFI_NOT_FOUND
;
2913 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2915 ItemDataSize
= Offset
;
2916 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2918 ZeroMem (OldData
, ItemDataSize
);
2919 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2920 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2921 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2922 if (CertCount
!= 0) {
2923 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2924 Offset
+= CertList
->SignatureListSize
;
2927 ItemDataSize
-= CertList
->SignatureListSize
;
2928 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2932 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2933 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2934 if (EFI_ERROR (Status
)) {
2935 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2940 Status
= gRT
->SetVariable (
2947 if (EFI_ERROR (Status
)) {
2948 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2957 if (OldData
!= NULL
) {
2961 return UpdateDeletePage (
2972 This function to delete signature list or data, according by DelType.
2974 @param[in] PrivateData Module's private data.
2975 @param[in] DelType Indicate delete signature list or data.
2976 @param[in] CheckedCount Indicate how many signature data have
2977 been checked in current signature list.
2979 @retval EFI_SUCCESS Success to update the signature list page
2980 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2984 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2985 IN SIGNATURE_DELETE_TYPE DelType
,
2986 IN UINT32 CheckedCount
2990 EFI_SIGNATURE_LIST
*ListWalker
;
2991 EFI_SIGNATURE_LIST
*NewCertList
;
2992 EFI_SIGNATURE_DATA
*DataWalker
;
2993 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
2994 UINT32 VariableAttr
;
2995 UINTN VariableDataSize
;
2996 UINTN RemainingSize
;
3000 UINT8
*VariableData
;
3001 UINT8
*NewVariableData
;
3003 Status
= EFI_SUCCESS
;
3005 VariableDataSize
= 0;
3008 VariableData
= NULL
;
3009 NewVariableData
= NULL
;
3011 if (PrivateData
->VariableName
== Variable_DB
) {
3012 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3013 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3014 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3015 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3016 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3021 Status
= gRT
->GetVariable (
3023 &gEfiImageSecurityDatabaseGuid
,
3028 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
3032 VariableData
= AllocateZeroPool (VariableDataSize
);
3033 if (VariableData
== NULL
) {
3034 Status
= EFI_OUT_OF_RESOURCES
;
3038 Status
= gRT
->GetVariable (
3040 &gEfiImageSecurityDatabaseGuid
,
3045 if (EFI_ERROR (Status
)) {
3049 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3050 if (EFI_ERROR (Status
)) {
3054 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3055 if (NewVariableData
== NULL
) {
3056 Status
= EFI_OUT_OF_RESOURCES
;
3060 RemainingSize
= VariableDataSize
;
3061 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3062 if (DelType
== Delete_Signature_List_All
) {
3063 VariableDataSize
= 0;
3066 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3068 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3069 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3070 Offset
+= ListWalker
->SignatureListSize
;
3072 RemainingSize
-= ListWalker
->SignatureListSize
;
3073 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3078 // Handle the target EFI_SIGNATURE_LIST.
3079 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3080 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3082 if ((CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
)) && (DelType
== Delete_Signature_Data
)) {
3083 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3087 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3088 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3090 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3091 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS (ListWalker
); Index
= Index
+ 1) {
3092 if (PrivateData
->CheckArray
[Index
]) {
3094 // Delete checked signature data, and update the size of whole signature list.
3096 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3099 // Remain the unchecked signature data.
3101 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3102 Offset
+= ListWalker
->SignatureSize
;
3105 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3109 RemainingSize
-= ListWalker
->SignatureListSize
;
3110 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3113 // Copy remaining data, maybe 0.
3115 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3116 Offset
+= RemainingSize
;
3118 VariableDataSize
= Offset
;
3121 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3122 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3123 if (EFI_ERROR (Status
)) {
3124 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3129 Status
= gRT
->SetVariable (
3131 &gEfiImageSecurityDatabaseGuid
,
3136 if (EFI_ERROR (Status
)) {
3137 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3142 SECUREBOOT_FREE_NON_NULL (VariableData
);
3143 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3150 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3151 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3153 @param[in] PrivateData Module's private data.
3155 @return EFI_SUCCESS Update secure boot strings successfully.
3156 @return other Fail to update secure boot strings.
3160 UpdateSecureBootString (
3161 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3169 // Get current secure boot state.
3171 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3172 if (SecureBoot
== NULL
) {
3173 return EFI_NOT_FOUND
;
3176 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3177 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3179 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3182 FreePool (SecureBoot
);
3188 This function extracts configuration from variable.
3190 @param[in] Private Point to SecureBoot configuration driver private data.
3191 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3195 SecureBootExtractConfigFromVariable (
3196 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3197 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3200 UINT8
*SecureBootEnable
;
3202 UINT8
*SecureBootMode
;
3205 SecureBootEnable
= NULL
;
3207 SecureBootMode
= NULL
;
3210 // Initialize the Date and Time using system time.
3212 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3213 ConfigData
->AlwaysRevocation
= TRUE
;
3214 gRT
->GetTime (&CurrTime
, NULL
);
3215 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3216 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3217 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3218 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3219 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3220 ConfigData
->RevocationTime
.Second
= 0;
3221 if (Private
->FileContext
->FHandle
!= NULL
) {
3222 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3224 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3228 // If it is Physical Presence User, set the PhysicalPresent to true.
3230 if (UserPhysicalPresent ()) {
3231 ConfigData
->PhysicalPresent
= TRUE
;
3233 ConfigData
->PhysicalPresent
= FALSE
;
3237 // If there is no PK then the Delete Pk button will be gray.
3239 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3240 if ((SetupMode
== NULL
) || ((*SetupMode
) == SETUP_MODE
)) {
3241 ConfigData
->HasPk
= FALSE
;
3243 ConfigData
->HasPk
= TRUE
;
3247 // Check SecureBootEnable & Pk status, fix the inconsistency.
3248 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3251 ConfigData
->AttemptSecureBoot
= FALSE
;
3252 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3255 // Fix Pk and SecureBootEnable inconsistency
3257 if ((SetupMode
!= NULL
) && ((*SetupMode
) == USER_MODE
)) {
3258 ConfigData
->HideSecureBoot
= FALSE
;
3259 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3260 ConfigData
->AttemptSecureBoot
= TRUE
;
3263 ConfigData
->HideSecureBoot
= TRUE
;
3267 // Get the SecureBootMode from CustomMode variable.
3269 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3270 if (SecureBootMode
== NULL
) {
3271 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3273 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3276 if (SecureBootEnable
!= NULL
) {
3277 FreePool (SecureBootEnable
);
3280 if (SetupMode
!= NULL
) {
3281 FreePool (SetupMode
);
3284 if (SecureBootMode
!= NULL
) {
3285 FreePool (SecureBootMode
);
3290 This function allows a caller to extract the current configuration for one
3291 or more named elements from the target driver.
3293 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3294 @param[in] Request A null-terminated Unicode string in
3295 <ConfigRequest> format.
3296 @param[out] Progress On return, points to a character in the Request
3297 string. Points to the string's null terminator if
3298 request was successful. Points to the most recent
3299 '&' before the first failing name/value pair (or
3300 the beginning of the string if the failure is in
3301 the first name/value pair) if the request was not
3303 @param[out] Results A null-terminated Unicode string in
3304 <ConfigAltResp> format which has all values filled
3305 in for the names in the Request string. String to
3306 be allocated by the called function.
3308 @retval EFI_SUCCESS The Results is filled with the requested values.
3309 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3310 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3311 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3317 SecureBootExtractConfig (
3318 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3319 IN CONST EFI_STRING Request
,
3320 OUT EFI_STRING
*Progress
,
3321 OUT EFI_STRING
*Results
3327 SECUREBOOT_CONFIGURATION Configuration
;
3328 EFI_STRING ConfigRequest
;
3329 EFI_STRING ConfigRequestHdr
;
3330 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3331 BOOLEAN AllocatedRequest
;
3333 if ((Progress
== NULL
) || (Results
== NULL
)) {
3334 return EFI_INVALID_PARAMETER
;
3337 AllocatedRequest
= FALSE
;
3338 ConfigRequestHdr
= NULL
;
3339 ConfigRequest
= NULL
;
3342 ZeroMem (&Configuration
, sizeof (Configuration
));
3343 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3344 *Progress
= Request
;
3346 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3347 return EFI_NOT_FOUND
;
3350 ZeroMem (&Configuration
, sizeof (SECUREBOOT_CONFIGURATION
));
3353 // Get Configuration from Variable.
3355 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3357 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3358 ConfigRequest
= Request
;
3359 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3361 // Request is set to NULL or OFFSET is NULL, construct full request string.
3363 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3364 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3366 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3367 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3368 ConfigRequest
= AllocateZeroPool (Size
);
3369 ASSERT (ConfigRequest
!= NULL
);
3370 AllocatedRequest
= TRUE
;
3371 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3372 FreePool (ConfigRequestHdr
);
3373 ConfigRequestHdr
= NULL
;
3376 Status
= gHiiConfigRouting
->BlockToConfig (
3379 (UINT8
*)&Configuration
,
3386 // Free the allocated config request string.
3388 if (AllocatedRequest
) {
3389 FreePool (ConfigRequest
);
3393 // Set Progress string to the original request string.
3395 if (Request
== NULL
) {
3397 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3398 *Progress
= Request
+ StrLen (Request
);
3405 This function processes the results of changes in configuration.
3407 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3408 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3410 @param[out] Progress A pointer to a string filled in with the offset of
3411 the most recent '&' before the first failing
3412 name/value pair (or the beginning of the string if
3413 the failure is in the first name/value pair) or
3414 the terminating NULL if all was successful.
3416 @retval EFI_SUCCESS The Results is processed successfully.
3417 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3418 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3424 SecureBootRouteConfig (
3425 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3426 IN CONST EFI_STRING Configuration
,
3427 OUT EFI_STRING
*Progress
3430 SECUREBOOT_CONFIGURATION IfrNvData
;
3432 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3435 if ((Configuration
== NULL
) || (Progress
== NULL
)) {
3436 return EFI_INVALID_PARAMETER
;
3439 *Progress
= Configuration
;
3440 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3441 return EFI_NOT_FOUND
;
3444 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3447 // Get Configuration from Variable.
3449 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3452 // Map the Configuration to the configuration block.
3454 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3455 Status
= gHiiConfigRouting
->ConfigToBlock (
3458 (UINT8
*)&IfrNvData
,
3462 if (EFI_ERROR (Status
)) {
3467 // Store Buffer Storage back to EFI variable if needed
3469 if (!IfrNvData
.HideSecureBoot
) {
3470 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3471 if (EFI_ERROR (Status
)) {
3476 *Progress
= Configuration
+ StrLen (Configuration
);
3481 This function to load signature list, the update the menu page.
3483 @param[in] PrivateData Module's private data.
3484 @param[in] LabelId Label number to insert opcodes.
3485 @param[in] FormId Form ID of current page.
3486 @param[in] QuestionIdBase Base question id of the signature list.
3488 @retval EFI_SUCCESS Success to update the signature list page
3489 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3493 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3495 IN EFI_FORM_ID FormId
,
3496 IN EFI_QUESTION_ID QuestionIdBase
3500 EFI_STRING_ID ListType
;
3501 EFI_STRING FormatNameString
;
3502 EFI_STRING FormatHelpString
;
3503 EFI_STRING FormatTypeString
;
3504 EFI_SIGNATURE_LIST
*ListWalker
;
3505 EFI_IFR_GUID_LABEL
*StartLabel
;
3506 EFI_IFR_GUID_LABEL
*EndLabel
;
3507 EFI_IFR_GUID_LABEL
*StartGoto
;
3508 EFI_IFR_GUID_LABEL
*EndGoto
;
3509 EFI_FORM_ID DstFormId
;
3510 VOID
*StartOpCodeHandle
;
3511 VOID
*EndOpCodeHandle
;
3512 VOID
*StartGotoHandle
;
3513 VOID
*EndGotoHandle
;
3515 UINTN RemainingSize
;
3517 UINT8
*VariableData
;
3518 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3519 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3520 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3522 Status
= EFI_SUCCESS
;
3523 FormatNameString
= NULL
;
3524 FormatHelpString
= NULL
;
3525 StartOpCodeHandle
= NULL
;
3526 EndOpCodeHandle
= NULL
;
3527 StartGotoHandle
= NULL
;
3528 EndGotoHandle
= NULL
;
3530 VariableData
= NULL
;
3533 // Initialize the container for dynamic opcodes.
3535 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3536 if (StartOpCodeHandle
== NULL
) {
3537 Status
= EFI_OUT_OF_RESOURCES
;
3541 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3542 if (EndOpCodeHandle
== NULL
) {
3543 Status
= EFI_OUT_OF_RESOURCES
;
3547 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3548 if (StartGotoHandle
== NULL
) {
3549 Status
= EFI_OUT_OF_RESOURCES
;
3553 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3554 if (EndGotoHandle
== NULL
) {
3555 Status
= EFI_OUT_OF_RESOURCES
;
3560 // Create Hii Extend Label OpCode.
3562 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3566 sizeof (EFI_IFR_GUID_LABEL
)
3568 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3569 StartLabel
->Number
= LabelId
;
3571 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3575 sizeof (EFI_IFR_GUID_LABEL
)
3577 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3578 EndLabel
->Number
= LABEL_END
;
3580 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3584 sizeof (EFI_IFR_GUID_LABEL
)
3586 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3587 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3589 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3593 sizeof (EFI_IFR_GUID_LABEL
)
3595 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3596 EndGoto
->Number
= LABEL_END
;
3598 if (PrivateData
->VariableName
== Variable_DB
) {
3599 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3600 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3601 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3602 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3603 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3604 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3605 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3606 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3611 HiiCreateGotoOpCode (
3614 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3615 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3616 EFI_IFR_FLAG_CALLBACK
,
3617 KEY_SECURE_BOOT_DELETE_ALL_LIST
3621 // Read Variable, the variable name save in the PrivateData->VariableName.
3624 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3625 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
3629 VariableData
= AllocateZeroPool (DataSize
);
3630 if (VariableData
== NULL
) {
3631 Status
= EFI_OUT_OF_RESOURCES
;
3635 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3636 if (EFI_ERROR (Status
)) {
3640 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3641 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3642 if ((FormatNameString
== NULL
) || (FormatHelpString
== NULL
)) {
3646 RemainingSize
= DataSize
;
3647 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3648 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3649 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3650 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3651 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3652 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3653 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3654 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3655 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3656 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3657 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3658 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3659 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3660 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3661 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3662 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3664 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3667 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3668 if (FormatTypeString
== NULL
) {
3672 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3673 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3675 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3678 sizeof (HelpBuffer
),
3681 SIGNATURE_DATA_COUNTS (ListWalker
)
3683 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3684 FormatTypeString
= NULL
;
3686 HiiCreateGotoOpCode (
3688 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3689 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3690 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3691 EFI_IFR_FLAG_CALLBACK
,
3692 QuestionIdBase
+ Index
++
3695 RemainingSize
-= ListWalker
->SignatureListSize
;
3696 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3701 PrivateData
->HiiHandle
,
3702 &gSecureBootConfigFormSetGuid
,
3709 PrivateData
->HiiHandle
,
3710 &gSecureBootConfigFormSetGuid
,
3716 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3717 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3718 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3719 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3721 SECUREBOOT_FREE_NON_NULL (VariableData
);
3722 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3723 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3725 PrivateData
->ListCount
= Index
;
3731 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3732 The buffer is callee allocated and should be freed by the caller.
3734 @param[in] ListEntry The pointer point to the signature list.
3735 @param[in] DataEntry The signature data we are processing.
3736 @param[out] BufferToReturn Buffer to save the hash value.
3738 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3739 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3740 @retval EFI_SUCCESS Operation success.
3744 IN EFI_SIGNATURE_LIST
*ListEntry
,
3745 IN EFI_SIGNATURE_DATA
*DataEntry
,
3746 OUT CHAR16
**BufferToReturn
3757 // Assume that, display 8 bytes in one line.
3761 if ((ListEntry
== NULL
) || (DataEntry
== NULL
) || (BufferToReturn
== NULL
)) {
3762 return EFI_INVALID_PARAMETER
;
3765 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3766 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3769 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3771 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof (CHAR16
));
3773 *BufferToReturn
= AllocateZeroPool (TotalSize
);
3774 if (*BufferToReturn
== NULL
) {
3775 return EFI_OUT_OF_RESOURCES
;
3778 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3779 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3780 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"\n");
3783 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3786 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"\n");
3792 Function to get the common name from the X509 format certificate.
3793 The buffer is callee allocated and should be freed by the caller.
3795 @param[in] ListEntry The pointer point to the signature list.
3796 @param[in] DataEntry The signature data we are processing.
3797 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3799 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3800 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3801 @retval EFI_SUCCESS Operation success.
3802 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3805 GetCommonNameFromX509 (
3806 IN EFI_SIGNATURE_LIST
*ListEntry
,
3807 IN EFI_SIGNATURE_DATA
*DataEntry
,
3808 OUT CHAR16
**BufferToReturn
3815 Status
= EFI_SUCCESS
;
3818 CNBuffer
= AllocateZeroPool (256);
3819 if (CNBuffer
== NULL
) {
3820 Status
= EFI_OUT_OF_RESOURCES
;
3826 (UINT8
*)DataEntry
+ sizeof (EFI_GUID
),
3827 ListEntry
->SignatureSize
- sizeof (EFI_GUID
),
3832 *BufferToReturn
= AllocateZeroPool (256 * sizeof (CHAR16
));
3833 if (*BufferToReturn
== NULL
) {
3834 Status
= EFI_OUT_OF_RESOURCES
;
3838 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3841 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3847 Format the help info for the signature data, each help info contain 3 parts.
3849 2. Content, depends on the type of the signature list.
3852 @param[in] PrivateData Module's private data.
3853 @param[in] ListEntry Point to the signature list.
3854 @param[in] DataEntry Point to the signature data we are processing.
3855 @param[out] StringId Save the string id of help info.
3857 @retval EFI_SUCCESS Operation success.
3858 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3862 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3863 IN EFI_SIGNATURE_LIST
*ListEntry
,
3864 IN EFI_SIGNATURE_DATA
*DataEntry
,
3865 OUT EFI_STRING_ID
*StringId
3870 EFI_STRING_ID ListTypeId
;
3871 EFI_STRING FormatHelpString
;
3872 EFI_STRING FormatTypeString
;
3874 UINTN HelpInfoIndex
;
3876 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3877 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3879 CHAR16
*HelpInfoString
;
3882 Status
= EFI_SUCCESS
;
3884 FormatTypeString
= NULL
;
3887 HelpInfoString
= NULL
;
3890 if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3891 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3892 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3894 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
3895 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3896 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3898 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
3899 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3901 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
3902 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3904 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3905 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3907 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3908 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3909 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3911 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3912 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3913 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3915 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3917 Status
= EFI_UNSUPPORTED
;
3921 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
3922 if (FormatTypeString
== NULL
) {
3927 HelpInfoString
= AllocateZeroPool (TotalSize
);
3928 if (HelpInfoString
== NULL
) {
3929 Status
= EFI_OUT_OF_RESOURCES
;
3934 // Format GUID part.
3936 ZeroMem (GuidString
, sizeof (GuidString
));
3937 GuidToString (&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
3938 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
3939 if (FormatHelpString
== NULL
) {
3943 HelpInfoIndex
+= UnicodeSPrint (
3944 &HelpInfoString
[HelpInfoIndex
],
3945 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3949 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3950 FormatHelpString
= NULL
;
3953 // Format content part, it depends on the type of signature list, hash value or CN.
3956 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
3957 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
3960 // Format hash value for each signature data entry.
3962 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
3963 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
3966 if (FormatHelpString
== NULL
) {
3970 HelpInfoIndex
+= UnicodeSPrint (
3971 &HelpInfoString
[HelpInfoIndex
],
3972 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3978 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3979 FormatHelpString
= NULL
;
3982 // Format revocation time part.
3985 ZeroMem (TimeString
, sizeof (TimeString
));
3988 sizeof (TimeString
),
3989 L
"%d-%d-%d %d:%d:%d",
3997 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
3998 if (FormatHelpString
== NULL
) {
4003 &HelpInfoString
[HelpInfoIndex
],
4004 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4008 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4009 FormatHelpString
= NULL
;
4012 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
4014 SECUREBOOT_FREE_NON_NULL (DataString
);
4015 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
4017 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
4023 This function to load signature data under the signature list.
4025 @param[in] PrivateData Module's private data.
4026 @param[in] LabelId Label number to insert opcodes.
4027 @param[in] FormId Form ID of current page.
4028 @param[in] QuestionIdBase Base question id of the signature list.
4029 @param[in] ListIndex Indicate to load which signature list.
4031 @retval EFI_SUCCESS Success to update the signature list page
4032 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4036 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4038 IN EFI_FORM_ID FormId
,
4039 IN EFI_QUESTION_ID QuestionIdBase
,
4044 EFI_SIGNATURE_LIST
*ListWalker
;
4045 EFI_SIGNATURE_DATA
*DataWalker
;
4046 EFI_IFR_GUID_LABEL
*StartLabel
;
4047 EFI_IFR_GUID_LABEL
*EndLabel
;
4048 EFI_STRING_ID HelpStringId
;
4049 EFI_STRING FormatNameString
;
4050 VOID
*StartOpCodeHandle
;
4051 VOID
*EndOpCodeHandle
;
4053 UINTN RemainingSize
;
4055 UINT8
*VariableData
;
4056 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4057 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4059 Status
= EFI_SUCCESS
;
4060 FormatNameString
= NULL
;
4061 StartOpCodeHandle
= NULL
;
4062 EndOpCodeHandle
= NULL
;
4064 VariableData
= NULL
;
4067 // Initialize the container for dynamic opcodes.
4069 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4070 if (StartOpCodeHandle
== NULL
) {
4071 Status
= EFI_OUT_OF_RESOURCES
;
4075 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4076 if (EndOpCodeHandle
== NULL
) {
4077 Status
= EFI_OUT_OF_RESOURCES
;
4082 // Create Hii Extend Label OpCode.
4084 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4088 sizeof (EFI_IFR_GUID_LABEL
)
4090 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4091 StartLabel
->Number
= LabelId
;
4093 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4097 sizeof (EFI_IFR_GUID_LABEL
)
4099 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4100 EndLabel
->Number
= LABEL_END
;
4102 if (PrivateData
->VariableName
== Variable_DB
) {
4103 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4104 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4105 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4106 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4107 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4113 // Read Variable, the variable name save in the PrivateData->VariableName.
4116 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4117 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
4121 VariableData
= AllocateZeroPool (DataSize
);
4122 if (VariableData
== NULL
) {
4123 Status
= EFI_OUT_OF_RESOURCES
;
4127 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4128 if (EFI_ERROR (Status
)) {
4132 RemainingSize
= DataSize
;
4133 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4136 // Skip signature list.
4138 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4139 RemainingSize
-= ListWalker
->SignatureListSize
;
4140 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4143 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4144 if (FormatNameString
== NULL
) {
4148 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4149 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS (ListWalker
); Index
= Index
+ 1) {
4151 // Format name buffer.
4153 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4154 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4157 // Format help info buffer.
4159 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4160 if (EFI_ERROR (Status
)) {
4164 HiiCreateCheckBoxOpCode (
4166 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4169 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4171 EFI_IFR_FLAG_CALLBACK
,
4176 ZeroMem (NameBuffer
, 100);
4177 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4181 // Allocate a buffer to record which signature data will be checked.
4182 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4184 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4187 PrivateData
->HiiHandle
,
4188 &gSecureBootConfigFormSetGuid
,
4194 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4195 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4197 SECUREBOOT_FREE_NON_NULL (VariableData
);
4198 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4204 This function reinitializes Secure Boot variables with default values.
4206 @retval EFI_SUCCESS Success to update the signature list page
4207 @retval others Fail to delete or enroll signature data.
4218 Status
= EFI_SUCCESS
;
4220 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4221 if (EFI_ERROR (Status
)) {
4225 // Clear all the keys and databases
4226 Status
= DeleteDb ();
4227 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4228 DEBUG ((DEBUG_ERROR
, "Fail to clear DB: %r\n", Status
));
4232 Status
= DeleteDbx ();
4233 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4234 DEBUG ((DEBUG_ERROR
, "Fail to clear DBX: %r\n", Status
));
4238 Status
= DeleteDbt ();
4239 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4240 DEBUG ((DEBUG_ERROR
, "Fail to clear DBT: %r\n", Status
));
4244 Status
= DeleteKEK ();
4245 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4246 DEBUG ((DEBUG_ERROR
, "Fail to clear KEK: %r\n", Status
));
4250 Status
= DeletePlatformKey ();
4251 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4252 DEBUG ((DEBUG_ERROR
, "Fail to clear PK: %r\n", Status
));
4256 // After PK clear, Setup Mode shall be enabled
4257 Status
= GetSetupMode (&SetupMode
);
4258 if (EFI_ERROR (Status
)) {
4261 "Cannot get SetupMode variable: %r\n",
4267 if (SetupMode
== USER_MODE
) {
4268 DEBUG ((DEBUG_INFO
, "Skipped - USER_MODE\n"));
4272 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4273 if (EFI_ERROR (Status
)) {
4276 "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n",
4282 // Enroll all the keys from default variables
4283 Status
= EnrollDbFromDefault ();
4284 if (EFI_ERROR (Status
)) {
4285 DEBUG ((DEBUG_ERROR
, "Cannot enroll db: %r\n", Status
));
4289 Status
= EnrollDbxFromDefault ();
4290 if (EFI_ERROR (Status
)) {
4291 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbx: %r\n", Status
));
4294 Status
= EnrollDbtFromDefault ();
4295 if (EFI_ERROR (Status
)) {
4296 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbt: %r\n", Status
));
4299 Status
= EnrollKEKFromDefault ();
4300 if (EFI_ERROR (Status
)) {
4301 DEBUG ((DEBUG_ERROR
, "Cannot enroll KEK: %r\n", Status
));
4305 Status
= EnrollPKFromDefault ();
4306 if (EFI_ERROR (Status
)) {
4307 DEBUG ((DEBUG_ERROR
, "Cannot enroll PK: %r\n", Status
));
4311 Status
= SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
4312 if (EFI_ERROR (Status
)) {
4315 "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
4316 "Please do it manually, otherwise system can be easily compromised\n"
4331 if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
) != EFI_SUCCESS
) {
4332 DEBUG ((DEBUG_ERROR
, "Cannot set mode to Secure: %r\n", Status
));
4339 This function is called to provide results data to the driver.
4341 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4342 @param[in] Action Specifies the type of action taken by the browser.
4343 @param[in] QuestionId A unique value which is sent to the original
4344 exporting driver so that it can identify the type
4346 @param[in] Type The type of value for the question.
4347 @param[in] Value A pointer to the data being sent to the original
4349 @param[out] ActionRequest On return, points to the action requested by the
4352 @retval EFI_SUCCESS The callback successfully handled the action.
4353 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4354 variable and its data.
4355 @retval EFI_DEVICE_ERROR The variable could not be saved.
4356 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4362 SecureBootCallback (
4363 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4364 IN EFI_BROWSER_ACTION Action
,
4365 IN EFI_QUESTION_ID QuestionId
,
4367 IN EFI_IFR_TYPE_VALUE
*Value
,
4368 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4373 RETURN_STATUS RStatus
;
4374 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4376 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4378 UINT8
*SecureBootEnable
;
4380 UINT8
*SecureBootMode
;
4382 CHAR16 PromptString
[100];
4383 EFI_DEVICE_PATH_PROTOCOL
*File
;
4385 UINT16
*FilePostFix
;
4386 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4387 BOOLEAN GetBrowserDataResult
;
4388 ENROLL_KEY_ERROR EnrollKeyErrorCode
;
4389 EFI_HII_POPUP_PROTOCOL
*HiiPopup
;
4390 EFI_HII_POPUP_SELECTION UserSelection
;
4392 Status
= EFI_SUCCESS
;
4393 SecureBootEnable
= NULL
;
4394 SecureBootMode
= NULL
;
4397 EnrollKeyErrorCode
= None_Error
;
4399 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4400 return EFI_INVALID_PARAMETER
;
4403 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4405 gSecureBootPrivateData
= Private
;
4408 // Retrieve uncommitted data from Browser
4410 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4411 IfrNvData
= AllocateZeroPool (BufferSize
);
4412 if (IfrNvData
== NULL
) {
4413 return EFI_OUT_OF_RESOURCES
;
4416 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*)IfrNvData
);
4418 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4419 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4421 // Update secure boot strings when opening this form
4423 Status
= UpdateSecureBootString (Private
);
4424 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4425 mIsEnterSecureBootForm
= TRUE
;
4428 // When entering SecureBoot OPTION Form
4429 // always close opened file & free resource
4431 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4432 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4433 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4434 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4435 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
))
4437 CloseEnrolledFile (Private
->FileContext
);
4438 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4440 // Update ListCount field in varstore
4441 // Button "Delete All Signature List" is
4442 // enable when ListCount is greater than 0.
4444 IfrNvData
->ListCount
= Private
->ListCount
;
4451 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4452 Status
= EFI_UNSUPPORTED
;
4453 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4454 if (mIsEnterSecureBootForm
) {
4455 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4456 Status
= EFI_SUCCESS
;
4463 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4464 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4465 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4466 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
))
4468 Status
= EFI_UNSUPPORTED
;
4472 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4473 switch (QuestionId
) {
4474 case KEY_SECURE_BOOT_ENABLE
:
4475 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4476 if (NULL
!= SecureBootEnable
) {
4477 FreePool (SecureBootEnable
);
4478 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4480 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4482 L
"Only Physical Presence User could disable secure boot!",
4485 Status
= EFI_UNSUPPORTED
;
4488 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4490 L
"Configuration changed, please reset the platform to take effect!",
4498 case KEY_SECURE_BOOT_KEK_OPTION
:
4499 case KEY_SECURE_BOOT_DB_OPTION
:
4500 case KEY_SECURE_BOOT_DBX_OPTION
:
4501 case KEY_SECURE_BOOT_DBT_OPTION
:
4502 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4504 // Clear Signature GUID.
4506 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4507 if (Private
->SignatureGUID
== NULL
) {
4508 Private
->SignatureGUID
= (EFI_GUID
*)AllocateZeroPool (sizeof (EFI_GUID
));
4509 if (Private
->SignatureGUID
== NULL
) {
4510 return EFI_OUT_OF_RESOURCES
;
4515 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4517 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4519 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4520 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4521 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4522 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4523 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4524 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4526 LabelId
= FORMID_ENROLL_KEK_FORM
;
4530 // Refresh selected file.
4532 CleanUpPage (LabelId
, Private
);
4534 case KEY_SECURE_BOOT_PK_OPTION
:
4535 LabelId
= FORMID_ENROLL_PK_FORM
;
4537 // Refresh selected file.
4539 CleanUpPage (LabelId
, Private
);
4542 case FORMID_ENROLL_PK_FORM
:
4543 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4546 case FORMID_ENROLL_KEK_FORM
:
4547 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4550 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4551 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4554 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4555 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4557 if (Private
->FileContext
->FHandle
!= NULL
) {
4559 // Parse the file's postfix.
4561 NameLength
= StrLen (Private
->FileContext
->FileName
);
4562 if (NameLength
<= 4) {
4566 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4568 if (IsDerEncodeCertificate (FilePostFix
)) {
4570 // Supports DER-encoded X509 certificate.
4572 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4573 } else if (IsAuthentication2Format (Private
->FileContext
->FHandle
)) {
4574 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4576 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4579 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4582 // Clean up Certificate Format if File type is not X509 DER
4584 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4585 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4588 DEBUG ((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4593 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4594 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4597 case KEY_SECURE_BOOT_DELETE_PK
:
4600 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4602 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4603 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4606 if ((Key
.UnicodeChar
== 'y') || (Key
.UnicodeChar
== 'Y')) {
4607 Status
= DeletePlatformKey ();
4608 if (EFI_ERROR (Status
)) {
4610 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4612 L
"Only Physical Presence User could delete PK in custom mode!",
4621 case KEY_DELETE_KEK
:
4624 EFI_KEY_EXCHANGE_KEY_NAME
,
4625 &gEfiGlobalVariableGuid
,
4627 FORMID_DELETE_KEK_FORM
,
4628 OPTION_DEL_KEK_QUESTION_ID
4632 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4635 EFI_IMAGE_SECURITY_DATABASE
,
4636 &gEfiImageSecurityDatabaseGuid
,
4638 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4639 OPTION_DEL_DB_QUESTION_ID
4644 // From DBX option to the level-1 form, display signature list.
4646 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4647 Private
->VariableName
= Variable_DBX
;
4650 LABEL_SIGNATURE_LIST_START
,
4651 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4652 OPTION_SIGNATURE_LIST_QUESTION_ID
4657 // Delete all signature list and reload.
4659 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4661 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4663 L
"Press 'Y' to delete signature list.",
4664 L
"Press other key to cancel and exit.",
4668 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4669 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4674 LABEL_SIGNATURE_LIST_START
,
4675 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4676 OPTION_SIGNATURE_LIST_QUESTION_ID
4681 // Delete one signature list and reload.
4683 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4685 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4687 L
"Press 'Y' to delete signature data.",
4688 L
"Press other key to cancel and exit.",
4692 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4693 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4698 LABEL_SIGNATURE_LIST_START
,
4699 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4700 OPTION_SIGNATURE_LIST_QUESTION_ID
4705 // Delete checked signature data and reload.
4707 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4709 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4711 L
"Press 'Y' to delete signature data.",
4712 L
"Press other key to cancel and exit.",
4716 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4717 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4722 LABEL_SIGNATURE_LIST_START
,
4723 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4724 OPTION_SIGNATURE_LIST_QUESTION_ID
4728 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4731 EFI_IMAGE_SECURITY_DATABASE2
,
4732 &gEfiImageSecurityDatabaseGuid
,
4734 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4735 OPTION_DEL_DBT_QUESTION_ID
4740 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4741 Status
= EnrollKeyExchangeKey (Private
);
4742 if (EFI_ERROR (Status
)) {
4744 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4746 L
"ERROR: Unsupported file type!",
4747 L
"Only supports DER-encoded X509 certificate",
4754 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4755 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4756 if (EFI_ERROR (Status
)) {
4758 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4760 L
"ERROR: Unsupported file type!",
4761 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4768 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4769 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4771 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4773 L
"Enrollment failed! Same certificate had already been in the dbx!",
4778 // Cert already exists in DBX. Close opened file before exit.
4780 CloseEnrolledFile (Private
->FileContext
);
4784 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4785 Status
= EnrollX509HashtoSigDB (
4787 IfrNvData
->CertificateFormat
,
4788 &IfrNvData
->RevocationDate
,
4789 &IfrNvData
->RevocationTime
,
4790 IfrNvData
->AlwaysRevocation
4792 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4794 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4797 if (EFI_ERROR (Status
)) {
4799 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4801 L
"ERROR: Unsupported file type!",
4802 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4809 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4810 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4811 if (EFI_ERROR (Status
)) {
4813 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4815 L
"ERROR: Unsupported file type!",
4816 L
"Only supports DER-encoded X509 certificate.",
4822 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4824 // Check the suffix, encode type and the key strength of PK certificate.
4826 Status
= CheckX509Certificate (Private
->FileContext
, &EnrollKeyErrorCode
);
4827 if (EFI_ERROR (Status
)) {
4828 if ((EnrollKeyErrorCode
!= None_Error
) && (EnrollKeyErrorCode
< Enroll_Error_Max
)) {
4830 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4832 mX509EnrollPromptTitle
[EnrollKeyErrorCode
],
4833 mX509EnrollPromptString
[EnrollKeyErrorCode
],
4839 Status
= EnrollPlatformKey (Private
);
4842 if (EFI_ERROR (Status
)) {
4845 sizeof (PromptString
),
4846 L
"Error status: %x.",
4850 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4852 L
"ERROR: Enrollment failed!",
4860 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4861 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4863 DeleteKeyExchangeKey (Private
, QuestionId
);
4864 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4865 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4869 EFI_IMAGE_SECURITY_DATABASE
,
4870 &gEfiImageSecurityDatabaseGuid
,
4872 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4873 OPTION_DEL_DB_QUESTION_ID
,
4874 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4876 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4877 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4881 LABEL_SIGNATURE_DATA_START
,
4882 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4883 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4884 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4886 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4887 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4888 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4890 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4891 IfrNvData
->CheckedDataCount
--;
4892 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4894 IfrNvData
->CheckedDataCount
++;
4895 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4897 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4898 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4902 EFI_IMAGE_SECURITY_DATABASE2
,
4903 &gEfiImageSecurityDatabaseGuid
,
4905 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4906 OPTION_DEL_DBT_QUESTION_ID
,
4907 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4913 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4914 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4915 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4916 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4917 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4918 CloseEnrolledFile (Private
->FileContext
);
4920 if (Private
->SignatureGUID
!= NULL
) {
4921 FreePool (Private
->SignatureGUID
);
4922 Private
->SignatureGUID
= NULL
;
4927 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4928 switch (QuestionId
) {
4929 case KEY_SECURE_BOOT_ENABLE
:
4930 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4932 case KEY_SECURE_BOOT_MODE
:
4933 mIsEnterSecureBootForm
= FALSE
;
4935 case KEY_SECURE_BOOT_KEK_GUID
:
4936 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4937 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4938 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4939 ASSERT (Private
->SignatureGUID
!= NULL
);
4940 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4941 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4942 Status
= EFI_INVALID_PARAMETER
;
4946 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4948 case KEY_SECURE_BOOT_DELETE_PK
:
4949 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4950 if ((SetupMode
== NULL
) || ((*SetupMode
) == SETUP_MODE
)) {
4951 IfrNvData
->DeletePk
= TRUE
;
4952 IfrNvData
->HasPk
= FALSE
;
4953 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4955 IfrNvData
->DeletePk
= FALSE
;
4956 IfrNvData
->HasPk
= TRUE
;
4957 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4960 if (SetupMode
!= NULL
) {
4961 FreePool (SetupMode
);
4965 case KEY_SECURE_BOOT_RESET_TO_DEFAULT
:
4967 Status
= gBS
->LocateProtocol (&gEfiHiiPopupProtocolGuid
, NULL
, (VOID
**)&HiiPopup
);
4968 if (EFI_ERROR (Status
)) {
4972 Status
= HiiPopup
->CreatePopup (
4974 EfiHiiPopupStyleInfo
,
4975 EfiHiiPopupTypeYesNo
,
4977 STRING_TOKEN (STR_RESET_TO_DEFAULTS_POPUP
),
4980 if (UserSelection
== EfiHiiPopupSelectionYes
) {
4981 Status
= KeyEnrollReset ();
4985 // Update secure boot strings after key reset
4987 if (Status
== EFI_SUCCESS
) {
4988 Status
= UpdateSecureBootString (Private
);
4989 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4995 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4996 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4997 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
4999 IfrNvData
->HideSecureBoot
= TRUE
;
5002 IfrNvData
->HideSecureBoot
= FALSE
;
5005 Value
->b
= IfrNvData
->HideSecureBoot
;
5007 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
5009 // Force the platform back to Standard Mode once user leave the setup screen.
5011 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
5012 if ((NULL
!= SecureBootMode
) && (*SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
)) {
5013 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
5014 SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
5017 if (SecureBootMode
!= NULL
) {
5018 FreePool (SecureBootMode
);
5021 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
5023 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
5025 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
5026 IfrNvData
->CheckedDataCount
= 0;
5032 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
5033 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
5034 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*)IfrNvData
, NULL
);
5037 FreePool (IfrNvData
);
5048 This function publish the SecureBoot configuration Form.
5050 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5052 @retval EFI_SUCCESS HII Form is installed successfully.
5053 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
5054 @retval Others Other errors as indicated.
5058 InstallSecureBootConfigForm (
5059 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5063 EFI_HII_HANDLE HiiHandle
;
5064 EFI_HANDLE DriverHandle
;
5065 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5067 DriverHandle
= NULL
;
5068 ConfigAccess
= &PrivateData
->ConfigAccess
;
5069 Status
= gBS
->InstallMultipleProtocolInterfaces (
5071 &gEfiDevicePathProtocolGuid
,
5072 &mSecureBootHiiVendorDevicePath
,
5073 &gEfiHiiConfigAccessProtocolGuid
,
5077 if (EFI_ERROR (Status
)) {
5081 PrivateData
->DriverHandle
= DriverHandle
;
5084 // Publish the HII package list
5086 HiiHandle
= HiiAddPackages (
5087 &gSecureBootConfigFormSetGuid
,
5089 SecureBootConfigDxeStrings
,
5090 SecureBootConfigBin
,
5093 if (HiiHandle
== NULL
) {
5094 gBS
->UninstallMultipleProtocolInterfaces (
5096 &gEfiDevicePathProtocolGuid
,
5097 &mSecureBootHiiVendorDevicePath
,
5098 &gEfiHiiConfigAccessProtocolGuid
,
5102 return EFI_OUT_OF_RESOURCES
;
5105 PrivateData
->HiiHandle
= HiiHandle
;
5107 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
5109 if (PrivateData
->FileContext
== NULL
) {
5110 UninstallSecureBootConfigForm (PrivateData
);
5111 return EFI_OUT_OF_RESOURCES
;
5115 // Init OpCode Handle and Allocate space for creation of Buffer
5117 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
5118 if (mStartOpCodeHandle
== NULL
) {
5119 UninstallSecureBootConfigForm (PrivateData
);
5120 return EFI_OUT_OF_RESOURCES
;
5123 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
5124 if (mEndOpCodeHandle
== NULL
) {
5125 UninstallSecureBootConfigForm (PrivateData
);
5126 return EFI_OUT_OF_RESOURCES
;
5130 // Create Hii Extend Label OpCode as the start opcode
5132 mStartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
5136 sizeof (EFI_IFR_GUID_LABEL
)
5138 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5141 // Create Hii Extend Label OpCode as the end opcode
5143 mEndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
5147 sizeof (EFI_IFR_GUID_LABEL
)
5149 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5150 mEndLabel
->Number
= LABEL_END
;
5156 This function removes SecureBoot configuration Form.
5158 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5162 UninstallSecureBootConfigForm (
5163 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5167 // Uninstall HII package list
5169 if (PrivateData
->HiiHandle
!= NULL
) {
5170 HiiRemovePackages (PrivateData
->HiiHandle
);
5171 PrivateData
->HiiHandle
= NULL
;
5175 // Uninstall HII Config Access Protocol
5177 if (PrivateData
->DriverHandle
!= NULL
) {
5178 gBS
->UninstallMultipleProtocolInterfaces (
5179 PrivateData
->DriverHandle
,
5180 &gEfiDevicePathProtocolGuid
,
5181 &mSecureBootHiiVendorDevicePath
,
5182 &gEfiHiiConfigAccessProtocolGuid
,
5183 &PrivateData
->ConfigAccess
,
5186 PrivateData
->DriverHandle
= NULL
;
5189 if (PrivateData
->SignatureGUID
!= NULL
) {
5190 FreePool (PrivateData
->SignatureGUID
);
5193 if (PrivateData
->FileContext
!= NULL
) {
5194 FreePool (PrivateData
->FileContext
);
5197 FreePool (PrivateData
);
5199 if (mStartOpCodeHandle
!= NULL
) {
5200 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5203 if (mEndOpCodeHandle
!= NULL
) {
5204 HiiFreeOpCodeHandle (mEndOpCodeHandle
);