2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "SecureBootConfigImpl.h"
11 #include <UefiSecureBoot.h>
12 #include <Protocol/HiiPopup.h>
13 #include <Protocol/RealTimeClock.h>
14 #include <Library/BaseCryptLib.h>
15 #include <Library/SecureBootVariableLib.h>
16 #include <Library/SecureBootVariableProvisionLib.h>
18 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
20 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
21 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
23 SecureBootExtractConfig
,
24 SecureBootRouteConfig
,
29 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
35 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
)),
36 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
39 SECUREBOOT_CONFIG_FORM_SET_GUID
43 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
45 (UINT8
)(END_DEVICE_PATH_LENGTH
),
46 (UINT8
)((END_DEVICE_PATH_LENGTH
) >> 8)
51 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
54 // OID ASN.1 Value for Hash Algorithms
56 UINT8 mHashOidValue
[] = {
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
65 HASH_TABLE mHash
[] = {
66 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
67 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
68 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
69 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
73 // Variable Definitions
75 UINT32 mPeCoffHeaderOffset
= 0;
76 WIN_CERTIFICATE
*mCertificate
= NULL
;
77 IMAGE_TYPE mImageType
;
78 UINT8
*mImageBase
= NULL
;
80 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
81 UINTN mImageDigestSize
;
83 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
84 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
87 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
89 CHAR16
*mDerEncodedSuffix
[] = {
95 CHAR16
*mSupportX509Suffix
= L
"*.cer/der/crt";
98 // Prompt strings during certificate enrollment.
100 CHAR16
*mX509EnrollPromptTitle
[] = {
102 L
"ERROR: Unsupported file type!",
103 L
"ERROR: Unsupported certificate!",
106 CHAR16
*mX509EnrollPromptString
[] = {
108 L
"Only DER encoded certificate file (*.cer/der/crt) is supported.",
109 L
"Public key length should be equal to or greater than 2048 bits.",
113 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
116 This code cleans up enrolled file by closing file & free related resources attached to
119 @param[in] FileContext FileContext cached in SecureBootConfig driver
124 IN SECUREBOOT_FILE_CONTEXT
*FileContext
127 if (FileContext
->FHandle
!= NULL
) {
128 CloseFile (FileContext
->FHandle
);
129 FileContext
->FHandle
= NULL
;
132 if (FileContext
->FileName
!= NULL
) {
133 FreePool (FileContext
->FileName
);
134 FileContext
->FileName
= NULL
;
137 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
141 Helper function to populate an EFI_TIME instance.
143 @param[in] Time FileContext cached in SecureBootConfig driver
156 return EFI_INVALID_PARAMETER
;
159 Status
= gBS
->LocateProtocol (&gEfiRealTimeClockArchProtocolGuid
, NULL
, &TestPointer
);
160 if (EFI_ERROR (Status
)) {
164 ZeroMem (Time
, sizeof (EFI_TIME
));
165 Status
= gRT
->GetTime (Time
, NULL
);
166 if (EFI_ERROR (Status
)) {
169 "%a(), GetTime() failed, status = '%r'\n",
177 Time
->Nanosecond
= 0;
186 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
188 @param[in] FileSuffix The suffix of the input certificate file
190 @retval TRUE It's a DER-encoded certificate.
191 @retval FALSE It's NOT a DER-encoded certificate.
195 IsDerEncodeCertificate (
196 IN CONST CHAR16
*FileSuffix
201 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
202 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
211 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
212 The function reads file content but won't open/close given FileHandle.
214 @param[in] FileHandle The FileHandle to be checked
216 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
217 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
221 IsAuthentication2Format (
222 IN EFI_FILE_HANDLE FileHandle
226 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
227 BOOLEAN IsAuth2Format
;
229 IsAuth2Format
= FALSE
;
232 // Read the whole file content
234 Status
= ReadFileContent (
236 (VOID
**)&mImageBase
,
240 if (EFI_ERROR (Status
)) {
244 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
245 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
249 if (CompareGuid (&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
250 IsAuth2Format
= TRUE
;
255 // Do not close File. simply check file content
257 if (mImageBase
!= NULL
) {
258 FreePool (mImageBase
);
262 return IsAuth2Format
;
266 Set Secure Boot option into variable space.
268 @param[in] VarValue The option of Secure Boot.
270 @retval EFI_SUCCESS The operation is finished successfully.
271 @retval Others Other errors as indicated.
275 SaveSecureBootVariable (
281 Status
= gRT
->SetVariable (
282 EFI_SECURE_BOOT_ENABLE_NAME
,
283 &gEfiSecureBootEnableDisableGuid
,
284 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
292 This code checks if the encode type and key strength of X.509
293 certificate is qualified.
295 @param[in] X509FileContext FileContext of X.509 certificate storing
297 @param[out] Error Error type checked in the certificate.
299 @return EFI_SUCCESS The certificate checked successfully.
300 @return EFI_INVALID_PARAMETER The parameter is invalid.
301 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
305 CheckX509Certificate (
306 IN SECUREBOOT_FILE_CONTEXT
*X509FileContext
,
307 OUT ENROLL_KEY_ERROR
*Error
318 if (X509FileContext
->FileName
== NULL
) {
319 *Error
= Unsupported_Type
;
320 return EFI_INVALID_PARAMETER
;
329 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
331 NameLength
= StrLen (X509FileContext
->FileName
);
332 if (NameLength
<= 4) {
333 DEBUG ((DEBUG_ERROR
, "Wrong X509 NameLength\n"));
334 *Error
= Unsupported_Type
;
335 return EFI_INVALID_PARAMETER
;
338 FilePostFix
= X509FileContext
->FileName
+ NameLength
- 4;
339 if (!IsDerEncodeCertificate (FilePostFix
)) {
340 DEBUG ((DEBUG_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix
));
341 *Error
= Unsupported_Type
;
342 return EFI_INVALID_PARAMETER
;
345 DEBUG ((DEBUG_INFO
, "FileName= %s\n", X509FileContext
->FileName
));
346 DEBUG ((DEBUG_INFO
, "FilePostFix = %s\n", FilePostFix
));
349 // Read the certificate file content
351 Status
= ReadFileContent (X509FileContext
->FHandle
, (VOID
**)&X509Data
, &X509DataSize
, 0);
352 if (EFI_ERROR (Status
)) {
353 DEBUG ((DEBUG_ERROR
, "Error occured while reading the file.\n"));
358 // Parse the public key context.
360 if (RsaGetPublicKeyFromX509 (X509Data
, X509DataSize
, &X509PubKey
) == FALSE
) {
361 DEBUG ((DEBUG_ERROR
, "Error occured while parsing the pubkey from certificate.\n"));
362 Status
= EFI_INVALID_PARAMETER
;
363 *Error
= Unsupported_Type
;
368 // Parse Module size of public key using interface provided by CryptoPkg, which is
369 // actually the size of public key.
371 if (X509PubKey
!= NULL
) {
372 RsaGetKey (X509PubKey
, RsaKeyN
, NULL
, &PubKeyModSize
);
373 if (PubKeyModSize
< CER_PUBKEY_MIN_SIZE
) {
374 DEBUG ((DEBUG_ERROR
, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
375 Status
= EFI_INVALID_PARAMETER
;
376 *Error
= Unqualified_Key
;
379 RsaFree (X509PubKey
);
383 if (X509Data
!= NULL
) {
391 Generate the PK signature list from the X509 Certificate storing file (.cer)
393 @param[in] X509File FileHandle of X509 Certificate storing file.
394 @param[out] PkCert Point to the data buffer to store the signature list.
396 @return EFI_UNSUPPORTED Unsupported Key Length.
397 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
401 CreatePkX509SignatureList (
402 IN EFI_FILE_HANDLE X509File
,
403 OUT EFI_SIGNATURE_LIST
**PkCert
409 EFI_SIGNATURE_DATA
*PkCertData
;
415 Status
= ReadFileContent (X509File
, (VOID
**)&X509Data
, &X509DataSize
, 0);
416 if (EFI_ERROR (Status
)) {
420 ASSERT (X509Data
!= NULL
);
423 // Allocate space for PK certificate list and initialize it.
424 // Create PK database entry with SignatureHeaderSize equals 0.
426 *PkCert
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (
427 sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1
430 if (*PkCert
== NULL
) {
431 Status
= EFI_OUT_OF_RESOURCES
;
435 (*PkCert
)->SignatureListSize
= (UINT32
)(sizeof (EFI_SIGNATURE_LIST
)
436 + sizeof (EFI_SIGNATURE_DATA
) - 1
438 (*PkCert
)->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
439 (*PkCert
)->SignatureHeaderSize
= 0;
440 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
441 PkCertData
= (EFI_SIGNATURE_DATA
*)((UINTN
)(*PkCert
)
442 + sizeof (EFI_SIGNATURE_LIST
)
443 + (*PkCert
)->SignatureHeaderSize
);
444 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
446 // Fill the PK database with PKpub data from X509 certificate file.
448 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
452 if (X509Data
!= NULL
) {
456 if (EFI_ERROR (Status
) && (*PkCert
!= NULL
)) {
465 Enroll new PK into the System without original PK's authentication.
467 The SignatureOwner GUID will be the same with PK's vendorguid.
469 @param[in] PrivateData The module's private data.
471 @retval EFI_SUCCESS New PK enrolled successfully.
472 @retval EFI_INVALID_PARAMETER The parameter is invalid.
473 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
478 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
484 EFI_SIGNATURE_LIST
*PkCert
;
489 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
490 if (EFI_ERROR (Status
)) {
495 // Prase the selected PK file and generate PK certificate list.
497 Status
= CreatePkX509SignatureList (
498 Private
->FileContext
->FHandle
,
501 if (EFI_ERROR (Status
)) {
505 ASSERT (PkCert
!= NULL
);
508 // Set Platform Key variable.
510 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
511 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
512 DataSize
= PkCert
->SignatureListSize
;
513 Status
= GetCurrentTime (&Time
);
514 if (EFI_ERROR (Status
)) {
515 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
519 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**)&PkCert
, &Time
);
520 if (EFI_ERROR (Status
)) {
521 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
525 Status
= gRT
->SetVariable (
526 EFI_PLATFORM_KEY_NAME
,
527 &gEfiGlobalVariableGuid
,
532 if (EFI_ERROR (Status
)) {
533 if (Status
== EFI_OUT_OF_RESOURCES
) {
534 DEBUG ((DEBUG_ERROR
, "Enroll PK failed with out of resource.\n"));
542 if (PkCert
!= NULL
) {
546 CloseEnrolledFile (Private
->FileContext
);
552 Enroll a new KEK item from public key storing file (*.pbk).
554 @param[in] PrivateData The module's private data.
556 @retval EFI_SUCCESS New KEK enrolled successfully.
557 @retval EFI_INVALID_PARAMETER The parameter is invalid.
558 @retval EFI_UNSUPPORTED Unsupported command.
559 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
564 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
570 EFI_SIGNATURE_LIST
*KekSigList
;
573 CPL_KEY_INFO
*KeyInfo
;
574 EFI_SIGNATURE_DATA
*KEKSigData
;
575 UINTN KekSigListSize
;
591 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
592 // First, We have to parse out public key data from the pbk key file.
594 Status
= ReadFileContent (
595 Private
->FileContext
->FHandle
,
600 if (EFI_ERROR (Status
)) {
604 ASSERT (KeyBlob
!= NULL
);
605 KeyInfo
= (CPL_KEY_INFO
*)KeyBlob
;
606 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
607 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
608 Status
= EFI_UNSUPPORTED
;
613 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
615 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
616 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
617 if (KeyBuffer
== NULL
) {
618 Status
= EFI_OUT_OF_RESOURCES
;
623 (UINTN
*)(KeyBlob
+ sizeof (CPL_KEY_INFO
)),
624 KeyLenInBytes
/ sizeof (UINTN
),
628 CopyMem (KeyBlob
+ sizeof (CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
631 // Form an new EFI_SIGNATURE_LIST.
633 KekSigListSize
= sizeof (EFI_SIGNATURE_LIST
)
634 + sizeof (EFI_SIGNATURE_DATA
) - 1
635 + WIN_CERT_UEFI_RSA2048_SIZE
;
637 KekSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (KekSigListSize
);
638 if (KekSigList
== NULL
) {
639 Status
= EFI_OUT_OF_RESOURCES
;
643 KekSigList
->SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
)
644 + sizeof (EFI_SIGNATURE_DATA
) - 1
645 + WIN_CERT_UEFI_RSA2048_SIZE
;
646 KekSigList
->SignatureHeaderSize
= 0;
647 KekSigList
->SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
648 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
650 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
651 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
653 KEKSigData
->SignatureData
,
654 KeyBlob
+ sizeof (CPL_KEY_INFO
),
655 WIN_CERT_UEFI_RSA2048_SIZE
659 // Check if KEK entry has been already existed.
660 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
661 // new KEK to original variable.
663 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
664 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
665 Status
= GetCurrentTime (&Time
);
666 if (EFI_ERROR (Status
)) {
667 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
671 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**)&KekSigList
, &Time
);
672 if (EFI_ERROR (Status
)) {
673 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
677 Status
= gRT
->GetVariable (
678 EFI_KEY_EXCHANGE_KEY_NAME
,
679 &gEfiGlobalVariableGuid
,
684 if (Status
== EFI_BUFFER_TOO_SMALL
) {
685 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
686 } else if (Status
!= EFI_NOT_FOUND
) {
691 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
693 Status
= gRT
->SetVariable (
694 EFI_KEY_EXCHANGE_KEY_NAME
,
695 &gEfiGlobalVariableGuid
,
700 if (EFI_ERROR (Status
)) {
706 CloseEnrolledFile (Private
->FileContext
);
708 if (Private
->SignatureGUID
!= NULL
) {
709 FreePool (Private
->SignatureGUID
);
710 Private
->SignatureGUID
= NULL
;
713 if (KeyBlob
!= NULL
) {
717 if (KeyBuffer
!= NULL
) {
718 FreePool (KeyBuffer
);
721 if (KekSigList
!= NULL
) {
722 FreePool (KekSigList
);
729 Enroll a new KEK item from X509 certificate file.
731 @param[in] PrivateData The module's private data.
733 @retval EFI_SUCCESS New X509 is enrolled successfully.
734 @retval EFI_INVALID_PARAMETER The parameter is invalid.
735 @retval EFI_UNSUPPORTED Unsupported command.
736 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
741 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
747 EFI_SIGNATURE_DATA
*KEKSigData
;
748 EFI_SIGNATURE_LIST
*KekSigList
;
750 UINTN KekSigListSize
;
761 Status
= ReadFileContent (
762 Private
->FileContext
->FHandle
,
767 if (EFI_ERROR (Status
)) {
771 ASSERT (X509Data
!= NULL
);
773 KekSigListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
774 KekSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (KekSigListSize
);
775 if (KekSigList
== NULL
) {
776 Status
= EFI_OUT_OF_RESOURCES
;
781 // Fill Certificate Database parameters.
783 KekSigList
->SignatureListSize
= (UINT32
)KekSigListSize
;
784 KekSigList
->SignatureHeaderSize
= 0;
785 KekSigList
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
786 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
788 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
789 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
790 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
793 // Check if KEK been already existed.
794 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
795 // new kek to original variable
797 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
798 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
799 Status
= GetCurrentTime (&Time
);
800 if (EFI_ERROR (Status
)) {
801 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
805 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**)&KekSigList
, &Time
);
806 if (EFI_ERROR (Status
)) {
807 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
811 Status
= gRT
->GetVariable (
812 EFI_KEY_EXCHANGE_KEY_NAME
,
813 &gEfiGlobalVariableGuid
,
818 if (Status
== EFI_BUFFER_TOO_SMALL
) {
819 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
820 } else if (Status
!= EFI_NOT_FOUND
) {
824 Status
= gRT
->SetVariable (
825 EFI_KEY_EXCHANGE_KEY_NAME
,
826 &gEfiGlobalVariableGuid
,
831 if (EFI_ERROR (Status
)) {
837 CloseEnrolledFile (Private
->FileContext
);
839 if (Private
->SignatureGUID
!= NULL
) {
840 FreePool (Private
->SignatureGUID
);
841 Private
->SignatureGUID
= NULL
;
844 if (KekSigList
!= NULL
) {
845 FreePool (KekSigList
);
852 Enroll new KEK into the System without PK's authentication.
853 The SignatureOwner GUID will be Private->SignatureGUID.
855 @param[in] PrivateData The module's private data.
857 @retval EFI_SUCCESS New KEK enrolled successful.
858 @retval EFI_INVALID_PARAMETER The parameter is invalid.
859 @retval others Fail to enroll KEK data.
863 EnrollKeyExchangeKey (
864 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
871 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
872 return EFI_INVALID_PARAMETER
;
875 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
876 if (EFI_ERROR (Status
)) {
881 // Parse the file's postfix. Supports DER-encoded X509 certificate,
882 // and .pbk as RSA public key file.
884 NameLength
= StrLen (Private
->FileContext
->FileName
);
885 if (NameLength
<= 4) {
886 return EFI_INVALID_PARAMETER
;
889 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
890 if (IsDerEncodeCertificate (FilePostFix
)) {
891 return EnrollX509ToKek (Private
);
892 } else if (CompareMem (FilePostFix
, L
".pbk", 4) == 0) {
893 return EnrollRsa2048ToKek (Private
);
896 // File type is wrong, simply close it
898 CloseEnrolledFile (Private
->FileContext
);
900 return EFI_INVALID_PARAMETER
;
905 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
906 KEK's authentication.
908 @param[in] PrivateData The module's private data.
909 @param[in] VariableName Variable name of signature database, must be
910 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
912 @retval EFI_SUCCESS New X509 is enrolled successfully.
913 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
918 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
919 IN CHAR16
*VariableName
925 EFI_SIGNATURE_LIST
*SigDBCert
;
926 EFI_SIGNATURE_DATA
*SigDBCertData
;
938 SigDBCertData
= NULL
;
941 Status
= ReadFileContent (
942 Private
->FileContext
->FHandle
,
947 if (EFI_ERROR (Status
)) {
951 ASSERT (X509Data
!= NULL
);
953 SigDBSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
955 Data
= AllocateZeroPool (SigDBSize
);
957 Status
= EFI_OUT_OF_RESOURCES
;
962 // Fill Certificate Database parameters.
964 SigDBCert
= (EFI_SIGNATURE_LIST
*)Data
;
965 SigDBCert
->SignatureListSize
= (UINT32
)SigDBSize
;
966 SigDBCert
->SignatureHeaderSize
= 0;
967 SigDBCert
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
968 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
970 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
971 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
972 CopyMem ((UINT8
*)(SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
975 // Check if signature database entry has been already existed.
976 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
977 // new signature data to original variable
979 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
980 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
981 Status
= GetCurrentTime (&Time
);
982 if (EFI_ERROR (Status
)) {
983 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
987 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**)&Data
, &Time
);
988 if (EFI_ERROR (Status
)) {
989 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
993 Status
= gRT
->GetVariable (
995 &gEfiImageSecurityDatabaseGuid
,
1000 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1001 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1002 } else if (Status
!= EFI_NOT_FOUND
) {
1006 Status
= gRT
->SetVariable (
1008 &gEfiImageSecurityDatabaseGuid
,
1013 if (EFI_ERROR (Status
)) {
1019 CloseEnrolledFile (Private
->FileContext
);
1021 if (Private
->SignatureGUID
!= NULL
) {
1022 FreePool (Private
->SignatureGUID
);
1023 Private
->SignatureGUID
= NULL
;
1030 if (X509Data
!= NULL
) {
1031 FreePool (X509Data
);
1038 Check whether signature is in specified database.
1040 @param[in] VariableName Name of database variable that is searched in.
1041 @param[in] Signature Pointer to signature that is searched for.
1042 @param[in] SignatureSize Size of Signature.
1044 @return TRUE Found the signature in the variable database.
1045 @return FALSE Not found the signature in the variable database.
1049 IsSignatureFoundInDatabase (
1050 IN CHAR16
*VariableName
,
1051 IN UINT8
*Signature
,
1052 IN UINTN SignatureSize
1056 EFI_SIGNATURE_LIST
*CertList
;
1057 EFI_SIGNATURE_DATA
*Cert
;
1065 // Read signature database variable.
1070 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1071 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1075 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1080 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1081 if (EFI_ERROR (Status
)) {
1086 // Enumerate all signature data in SigDB to check if signature exists for executable.
1088 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
1089 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1090 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1091 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1092 if ((CertList
->SignatureSize
== sizeof (EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1093 for (Index
= 0; Index
< CertCount
; Index
++) {
1094 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1096 // Find the signature in database.
1102 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
1110 DataSize
-= CertList
->SignatureListSize
;
1111 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
1123 Calculate the hash of a certificate data with the specified hash algorithm.
1125 @param[in] CertData The certificate data to be hashed.
1126 @param[in] CertSize The certificate size in bytes.
1127 @param[in] HashAlg The specified hash algorithm.
1128 @param[out] CertHash The output digest of the certificate
1130 @retval TRUE Successfully got the hash of the CertData.
1131 @retval FALSE Failed to get the hash of CertData.
1151 if (HashAlg
>= HASHALG_MAX
) {
1156 // Retrieve the TBSCertificate for Hash Calculation.
1158 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1163 // 1. Initialize context of hash.
1165 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1166 HashCtx
= AllocatePool (CtxSize
);
1167 ASSERT (HashCtx
!= NULL
);
1170 // 2. Initialize a hash context.
1172 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1178 // 3. Calculate the hash.
1180 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1186 // 4. Get the hash result.
1188 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1189 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1192 if (HashCtx
!= NULL
) {
1200 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1202 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1203 @param[in] CertSize Size of X.509 Certificate.
1205 @return TRUE Found the certificate hash in the forbidden database.
1206 @return FALSE Certificate hash is Not found in the forbidden database.
1210 IsCertHashFoundInDbx (
1211 IN UINT8
*Certificate
,
1217 EFI_SIGNATURE_LIST
*DbxList
;
1218 EFI_SIGNATURE_DATA
*CertHash
;
1219 UINTN CertHashCount
;
1222 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1224 UINTN SiglistHeaderSize
;
1229 HashAlg
= HASHALG_MAX
;
1233 // Read signature database variable.
1236 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1237 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1241 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1246 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1247 if (EFI_ERROR (Status
)) {
1252 // Check whether the certificate hash exists in the forbidden database.
1254 DbxList
= (EFI_SIGNATURE_LIST
*)Data
;
1255 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1257 // Determine Hash Algorithm of Certificate in the forbidden database.
1259 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1260 HashAlg
= HASHALG_SHA256
;
1261 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1262 HashAlg
= HASHALG_SHA384
;
1263 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1264 HashAlg
= HASHALG_SHA512
;
1266 DataSize
-= DbxList
->SignatureListSize
;
1267 DbxList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)DbxList
+ DbxList
->SignatureListSize
);
1272 // Calculate the hash value of current db certificate for comparision.
1274 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1278 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1279 CertHash
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DbxList
+ SiglistHeaderSize
);
1280 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1281 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1283 // Iterate each Signature Data Node within this CertList for verify.
1285 DbxCertHash
= CertHash
->SignatureData
;
1286 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1288 // Hash of Certificate is found in forbidden database.
1294 CertHash
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertHash
+ DbxList
->SignatureSize
);
1297 DataSize
-= DbxList
->SignatureListSize
;
1298 DbxList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)DbxList
+ DbxList
->SignatureListSize
);
1310 Check whether the signature list exists in given variable data.
1312 It searches the signature list for the certificate hash by CertType.
1313 If the signature list is found, get the offset of Database for the
1314 next hash of a certificate.
1316 @param[in] Database Variable data to save signature list.
1317 @param[in] DatabaseSize Variable size.
1318 @param[in] SignatureType The type of the signature.
1319 @param[out] Offset The offset to save a new hash of certificate.
1321 @return TRUE The signature list is found in the forbidden database.
1322 @return FALSE The signature list is not found in the forbidden database.
1325 GetSignaturelistOffset (
1326 IN EFI_SIGNATURE_LIST
*Database
,
1327 IN UINTN DatabaseSize
,
1328 IN EFI_GUID
*SignatureType
,
1332 EFI_SIGNATURE_LIST
*SigList
;
1335 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1341 SiglistSize
= DatabaseSize
;
1342 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1343 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1344 *Offset
= DatabaseSize
- SiglistSize
;
1348 SiglistSize
-= SigList
->SignatureListSize
;
1349 SigList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)SigList
+ SigList
->SignatureListSize
);
1357 Enroll a new X509 certificate hash into Signature Database (dbx) without
1358 KEK's authentication.
1360 @param[in] PrivateData The module's private data.
1361 @param[in] HashAlg The hash algorithm to enroll the certificate.
1362 @param[in] RevocationDate The revocation date of the certificate.
1363 @param[in] RevocationTime The revocation time of the certificate.
1364 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1366 @retval EFI_SUCCESS New X509 is enrolled successfully.
1367 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1368 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1372 EnrollX509HashtoSigDB (
1373 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1375 IN EFI_HII_DATE
*RevocationDate
,
1376 IN EFI_HII_TIME
*RevocationTime
,
1377 IN BOOLEAN AlwaysRevocation
1383 EFI_SIGNATURE_LIST
*SignatureList
;
1384 UINTN SignatureListSize
;
1390 EFI_SIGNATURE_DATA
*SignatureData
;
1391 UINTN SignatureSize
;
1392 EFI_GUID SignatureType
;
1394 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1395 UINT16
*FilePostFix
;
1403 SignatureData
= NULL
;
1404 SignatureList
= NULL
;
1408 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1409 return EFI_INVALID_PARAMETER
;
1412 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1413 if (EFI_ERROR (Status
)) {
1418 // Parse the file's postfix.
1420 NameLength
= StrLen (Private
->FileContext
->FileName
);
1421 if (NameLength
<= 4) {
1422 return EFI_INVALID_PARAMETER
;
1425 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1426 if (!IsDerEncodeCertificate (FilePostFix
)) {
1428 // Only supports DER-encoded X509 certificate.
1430 return EFI_INVALID_PARAMETER
;
1434 // Get the certificate from file and calculate its hash.
1436 Status
= ReadFileContent (
1437 Private
->FileContext
->FHandle
,
1442 if (EFI_ERROR (Status
)) {
1446 ASSERT (X509Data
!= NULL
);
1448 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1453 // Get the variable for enrollment.
1456 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1457 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1458 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
1460 return EFI_OUT_OF_RESOURCES
;
1463 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1464 if (EFI_ERROR (Status
)) {
1470 // Allocate memory for Signature and fill the Signature
1472 SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1473 SignatureData
= (EFI_SIGNATURE_DATA
*)AllocateZeroPool (SignatureSize
);
1474 if (SignatureData
== NULL
) {
1475 return EFI_OUT_OF_RESOURCES
;
1478 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1479 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1484 if (!AlwaysRevocation
) {
1485 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1486 Time
->Year
= RevocationDate
->Year
;
1487 Time
->Month
= RevocationDate
->Month
;
1488 Time
->Day
= RevocationDate
->Day
;
1489 Time
->Hour
= RevocationTime
->Hour
;
1490 Time
->Minute
= RevocationTime
->Minute
;
1491 Time
->Second
= RevocationTime
->Second
;
1495 // Determine the GUID for certificate hash.
1498 case HASHALG_SHA256
:
1499 SignatureType
= gEfiCertX509Sha256Guid
;
1501 case HASHALG_SHA384
:
1502 SignatureType
= gEfiCertX509Sha384Guid
;
1504 case HASHALG_SHA512
:
1505 SignatureType
= gEfiCertX509Sha512Guid
;
1512 // Add signature into the new variable data buffer
1514 if (GetSignaturelistOffset ((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1516 // Add the signature to the found signaturelist.
1518 DbSize
= DataSize
+ SignatureSize
;
1519 NewData
= AllocateZeroPool (DbSize
);
1520 if (NewData
== NULL
) {
1521 Status
= EFI_OUT_OF_RESOURCES
;
1525 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1526 SignatureListSize
= (UINTN
)ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1527 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1529 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1530 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1532 Offset
+= SignatureListSize
;
1533 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1534 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1541 // Create a new signaturelist, and add the signature into the signaturelist.
1543 DbSize
= DataSize
+ sizeof (EFI_SIGNATURE_LIST
) + SignatureSize
;
1544 NewData
= AllocateZeroPool (DbSize
);
1545 if (NewData
== NULL
) {
1546 Status
= EFI_OUT_OF_RESOURCES
;
1551 // Fill Certificate Database parameters.
1553 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ DataSize
);
1554 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + SignatureSize
;
1555 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
, (UINT32
)SignatureListSize
);
1556 WriteUnaligned32 ((UINT32
*)&SignatureList
->SignatureSize
, (UINT32
)SignatureSize
);
1557 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1558 CopyMem ((UINT8
*)SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1559 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1560 CopyMem (NewData
, Data
, DataSize
);
1568 Status
= GetCurrentTime (&NewTime
);
1569 if (EFI_ERROR (Status
)) {
1570 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
1574 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**)&Data
, &NewTime
);
1575 if (EFI_ERROR (Status
)) {
1579 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1580 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1581 Status
= gRT
->SetVariable (
1582 EFI_IMAGE_SECURITY_DATABASE1
,
1583 &gEfiImageSecurityDatabaseGuid
,
1588 if (EFI_ERROR (Status
)) {
1594 CloseEnrolledFile (Private
->FileContext
);
1596 if (Private
->SignatureGUID
!= NULL
) {
1597 FreePool (Private
->SignatureGUID
);
1598 Private
->SignatureGUID
= NULL
;
1605 if (SignatureData
!= NULL
) {
1606 FreePool (SignatureData
);
1609 if (X509Data
!= NULL
) {
1610 FreePool (X509Data
);
1617 Check whether a certificate from a file exists in dbx.
1619 @param[in] PrivateData The module's private data.
1620 @param[in] VariableName Variable name of signature database, must be
1621 EFI_IMAGE_SECURITY_DATABASE1.
1623 @retval TRUE The X509 certificate is found in dbx successfully.
1624 @retval FALSE The X509 certificate is not found in dbx.
1628 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1629 IN CHAR16
*VariableName
1638 // Read the certificate from file
1642 Status
= ReadFileContent (
1643 Private
->FileContext
->FHandle
,
1648 if (EFI_ERROR (Status
)) {
1653 // Check the raw certificate.
1656 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1662 // Check the hash of certificate.
1664 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1670 if (X509Data
!= NULL
) {
1671 FreePool (X509Data
);
1678 Reads contents of a PE/COFF image in memory buffer.
1680 Caution: This function may receive untrusted input.
1681 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1682 read is within the image buffer.
1684 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1685 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1686 @param ReadSize On input, the size in bytes of the requested read operation.
1687 On output, the number of bytes actually read.
1688 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1690 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1694 SecureBootConfigImageRead (
1695 IN VOID
*FileHandle
,
1696 IN UINTN FileOffset
,
1697 IN OUT UINTN
*ReadSize
,
1703 if ((FileHandle
== NULL
) || (ReadSize
== NULL
) || (Buffer
== NULL
)) {
1704 return EFI_INVALID_PARAMETER
;
1707 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1708 return EFI_INVALID_PARAMETER
;
1711 EndPosition
= FileOffset
+ *ReadSize
;
1712 if (EndPosition
> mImageSize
) {
1713 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1716 if (FileOffset
>= mImageSize
) {
1720 CopyMem (Buffer
, (UINT8
*)((UINTN
)FileHandle
+ FileOffset
), *ReadSize
);
1726 Load PE/COFF image information into internal buffer and check its validity.
1728 @retval EFI_SUCCESS Successful
1729 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1730 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1738 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1739 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1740 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1741 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1747 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1748 ImageContext
.Handle
= (VOID
*)mImageBase
;
1749 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)SecureBootConfigImageRead
;
1752 // Get information about the image being loaded
1754 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1755 if (EFI_ERROR (Status
)) {
1757 // The information can't be got from the invalid PeImage
1759 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1764 // Read the Dos header
1766 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1767 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1769 // DOS image header is present,
1770 // So read the PE header after the DOS image header
1772 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1774 mPeCoffHeaderOffset
= 0;
1778 // Read PE header and check the signature validity and machine compatibility
1780 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*)(mImageBase
+ mPeCoffHeaderOffset
);
1781 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1782 return EFI_UNSUPPORTED
;
1785 mNtHeader
.Pe32
= NtHeader32
;
1788 // Check the architecture field of PE header and get the Certificate Data Directory data
1789 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1791 if ( (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1792 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1793 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
))
1796 // 32-bits Architecture
1798 mImageType
= ImageType_IA32
;
1799 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*)&(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1800 } else if ( (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1801 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1802 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
))
1805 // 64-bits Architecture
1807 mImageType
= ImageType_X64
;
1808 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*)(mImageBase
+ mPeCoffHeaderOffset
);
1809 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*)&(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1811 return EFI_UNSUPPORTED
;
1818 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1819 PE/COFF Specification 8.0 Appendix A
1821 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1822 the function LoadPeImage ().
1824 @param[in] HashAlg Hash algorithm type.
1826 @retval TRUE Successfully hash image.
1827 @retval FALSE Fail in hash image.
1836 EFI_IMAGE_SECTION_HEADER
*Section
;
1841 UINTN SumOfBytesHashed
;
1842 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1847 SectionHeader
= NULL
;
1850 if (HashAlg
!= HASHALG_SHA256
) {
1855 // Initialize context of hash.
1857 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1859 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1860 mCertType
= gEfiCertSha256Guid
;
1862 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1864 HashCtx
= AllocatePool (CtxSize
);
1865 ASSERT (HashCtx
!= NULL
);
1867 // 1. Load the image header into memory.
1869 // 2. Initialize a SHA hash context.
1870 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1876 // Measuring PE/COFF Image Header;
1877 // But CheckSum field and SECURITY data directory (certificate) are excluded
1881 // 3. Calculate the distance from the base of the image header to the image checksum address.
1882 // 4. Hash the image header from its base to beginning of the image checksum.
1884 HashBase
= mImageBase
;
1885 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1889 HashSize
= (UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
)HashBase
;
1892 // Use PE32+ offset.
1894 HashSize
= (UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
)HashBase
;
1897 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1903 // 5. Skip over the image checksum (it occupies a single ULONG).
1904 // 6. Get the address of the beginning of the Cert Directory.
1905 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1907 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1911 HashBase
= (UINT8
*)&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1912 HashSize
= (UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
)HashBase
;
1915 // Use PE32+ offset.
1917 HashBase
= (UINT8
*)&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1918 HashSize
= (UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
)HashBase
;
1921 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1927 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1928 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1930 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1934 HashBase
= (UINT8
*)&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1935 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
)(&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
)mImageBase
);
1938 // Use PE32+ offset.
1940 HashBase
= (UINT8
*)&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1941 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
)(&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
)mImageBase
);
1944 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
1950 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1952 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1956 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1961 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1965 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1966 // structures in the image. The 'NumberOfSections' field of the image
1967 // header indicates how big the table should be. Do not include any
1968 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1970 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1971 ASSERT (SectionHeader
!= NULL
);
1973 // 12. Using the 'PointerToRawData' in the referenced section headers as
1974 // a key, arrange the elements in the table in ascending order. In other
1975 // words, sort the section headers according to the disk-file offset of
1978 Section
= (EFI_IMAGE_SECTION_HEADER
*)(
1980 mPeCoffHeaderOffset
+
1982 sizeof (EFI_IMAGE_FILE_HEADER
) +
1983 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1985 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1987 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1988 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1992 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1997 // 13. Walk through the sorted table, bring the corresponding section
1998 // into memory, and hash the entire section (using the 'SizeOfRawData'
1999 // field in the section header to determine the amount of data to hash).
2000 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2001 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
2003 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
2004 Section
= &SectionHeader
[Index
];
2005 if (Section
->SizeOfRawData
== 0) {
2009 HashBase
= mImageBase
+ Section
->PointerToRawData
;
2010 HashSize
= (UINTN
)Section
->SizeOfRawData
;
2012 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
2017 SumOfBytesHashed
+= HashSize
;
2021 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2022 // data in the file that needs to be added to the hash. This data begins
2023 // at file offset SUM_OF_BYTES_HASHED and its length is:
2024 // FileSize - (CertDirectory->Size)
2026 if (mImageSize
> SumOfBytesHashed
) {
2027 HashBase
= mImageBase
+ SumOfBytesHashed
;
2028 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2034 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2038 // Use PE32+ offset.
2042 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2046 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, HashBase
, HashSize
);
2052 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, mImageDigest
);
2055 if (HashCtx
!= NULL
) {
2059 if (SectionHeader
!= NULL
) {
2060 FreePool (SectionHeader
);
2067 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2068 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2071 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2072 @retval EFI_SUCCESS Hash successfully.
2081 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2083 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*)(mImageBase
+ mSecDataDir
->Offset
);
2085 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2087 // Check the Hash algorithm in PE/COFF Authenticode.
2088 // According to PKCS#7 Definition:
2089 // SignedData ::= SEQUENCE {
2091 // digestAlgorithms DigestAlgorithmIdentifiers,
2092 // contentInfo ContentInfo,
2094 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2095 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2096 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2098 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2100 // Only support two bytes of Long Form of Length Encoding.
2106 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2111 if (Index
== HASHALG_MAX
) {
2112 return EFI_UNSUPPORTED
;
2116 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2118 if (!HashPeImage (Index
)) {
2119 return EFI_UNSUPPORTED
;
2126 Enroll a new signature of executable into Signature Database.
2128 @param[in] PrivateData The module's private data.
2129 @param[in] VariableName Variable name of signature database, must be
2130 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2131 or EFI_IMAGE_SECURITY_DATABASE2.
2133 @retval EFI_SUCCESS New signature is enrolled successfully.
2134 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2135 @retval EFI_UNSUPPORTED Unsupported command.
2136 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2140 EnrollAuthentication2Descriptor (
2141 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2142 IN CHAR16
*VariableName
2153 // DBT only support DER-X509 Cert Enrollment
2155 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2156 return EFI_UNSUPPORTED
;
2160 // Read the whole file content
2162 Status
= ReadFileContent (
2163 Private
->FileContext
->FHandle
,
2164 (VOID
**)&mImageBase
,
2168 if (EFI_ERROR (Status
)) {
2172 ASSERT (mImageBase
!= NULL
);
2174 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2175 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2178 // Check if SigDB variable has been already existed.
2179 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2180 // new signature data to original variable
2183 Status
= gRT
->GetVariable (
2185 &gEfiImageSecurityDatabaseGuid
,
2190 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2191 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2192 } else if (Status
!= EFI_NOT_FOUND
) {
2197 // Directly set AUTHENTICATION_2 data to SetVariable
2199 Status
= gRT
->SetVariable (
2201 &gEfiImageSecurityDatabaseGuid
,
2207 DEBUG ((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2211 CloseEnrolledFile (Private
->FileContext
);
2217 if (mImageBase
!= NULL
) {
2218 FreePool (mImageBase
);
2226 Enroll a new signature of executable into Signature Database.
2228 @param[in] PrivateData The module's private data.
2229 @param[in] VariableName Variable name of signature database, must be
2230 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2231 or EFI_IMAGE_SECURITY_DATABASE2.
2233 @retval EFI_SUCCESS New signature is enrolled successfully.
2234 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2235 @retval EFI_UNSUPPORTED Unsupported command.
2236 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2240 EnrollImageSignatureToSigDB (
2241 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2242 IN CHAR16
*VariableName
2246 EFI_SIGNATURE_LIST
*SigDBCert
;
2247 EFI_SIGNATURE_DATA
*SigDBCertData
;
2252 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2256 GuidCertData
= NULL
;
2258 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2259 return EFI_UNSUPPORTED
;
2263 // Form the SigDB certificate list.
2264 // Format the data item into EFI_SIGNATURE_LIST type.
2266 // We need to parse signature data of executable from specified signed executable file.
2267 // In current implementation, we simply trust the pass-in signed executable file.
2268 // In reality, it's OS's responsibility to verify the signed executable file.
2272 // Read the whole file content
2274 Status
= ReadFileContent (
2275 Private
->FileContext
->FHandle
,
2276 (VOID
**)&mImageBase
,
2280 if (EFI_ERROR (Status
)) {
2284 ASSERT (mImageBase
!= NULL
);
2286 Status
= LoadPeImage ();
2287 if (EFI_ERROR (Status
)) {
2291 if (mSecDataDir
->SizeOfCert
== 0) {
2292 if (!HashPeImage (HASHALG_SHA256
)) {
2293 Status
= EFI_SECURITY_VIOLATION
;
2298 // Read the certificate data
2300 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2302 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2303 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*)mCertificate
;
2304 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof (EFI_GUID
)) != 0) {
2305 Status
= EFI_ABORTED
;
2309 if (!HashPeImage (HASHALG_SHA256
)) {
2310 Status
= EFI_ABORTED
;
2313 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2314 Status
= HashPeImageByType ();
2315 if (EFI_ERROR (Status
)) {
2319 Status
= EFI_ABORTED
;
2325 // Create a new SigDB entry.
2327 SigDBSize
= sizeof (EFI_SIGNATURE_LIST
)
2328 + sizeof (EFI_SIGNATURE_DATA
) - 1
2329 + (UINT32
)mImageDigestSize
;
2331 Data
= (UINT8
*)AllocateZeroPool (SigDBSize
);
2333 Status
= EFI_OUT_OF_RESOURCES
;
2338 // Adjust the Certificate Database parameters.
2340 SigDBCert
= (EFI_SIGNATURE_LIST
*)Data
;
2341 SigDBCert
->SignatureListSize
= (UINT32
)SigDBSize
;
2342 SigDBCert
->SignatureHeaderSize
= 0;
2343 SigDBCert
->SignatureSize
= sizeof (EFI_SIGNATURE_DATA
) - 1 + (UINT32
)mImageDigestSize
;
2344 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2346 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
2347 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2348 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2350 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2351 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2352 Status
= GetCurrentTime (&Time
);
2353 if (EFI_ERROR (Status
)) {
2354 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
2358 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**)&Data
, &Time
);
2359 if (EFI_ERROR (Status
)) {
2360 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2365 // Check if SigDB variable has been already existed.
2366 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2367 // new signature data to original variable
2370 Status
= gRT
->GetVariable (
2372 &gEfiImageSecurityDatabaseGuid
,
2377 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2378 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2379 } else if (Status
!= EFI_NOT_FOUND
) {
2384 // Enroll the variable.
2386 Status
= gRT
->SetVariable (
2388 &gEfiImageSecurityDatabaseGuid
,
2393 if (EFI_ERROR (Status
)) {
2399 CloseEnrolledFile (Private
->FileContext
);
2401 if (Private
->SignatureGUID
!= NULL
) {
2402 FreePool (Private
->SignatureGUID
);
2403 Private
->SignatureGUID
= NULL
;
2410 if (mImageBase
!= NULL
) {
2411 FreePool (mImageBase
);
2419 Enroll signature into DB/DBX/DBT without KEK's authentication.
2420 The SignatureOwner GUID will be Private->SignatureGUID.
2422 @param[in] PrivateData The module's private data.
2423 @param[in] VariableName Variable name of signature database, must be
2424 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2426 @retval EFI_SUCCESS New signature enrolled successfully.
2427 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2428 @retval others Fail to enroll signature data.
2432 EnrollSignatureDatabase (
2433 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2434 IN CHAR16
*VariableName
2437 UINT16
*FilePostFix
;
2441 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2442 return EFI_INVALID_PARAMETER
;
2445 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2446 if (EFI_ERROR (Status
)) {
2451 // Parse the file's postfix.
2453 NameLength
= StrLen (Private
->FileContext
->FileName
);
2454 if (NameLength
<= 4) {
2455 return EFI_INVALID_PARAMETER
;
2458 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2459 if (IsDerEncodeCertificate (FilePostFix
)) {
2461 // Supports DER-encoded X509 certificate.
2463 return EnrollX509toSigDB (Private
, VariableName
);
2464 } else if (IsAuthentication2Format (Private
->FileContext
->FHandle
)) {
2465 return EnrollAuthentication2Descriptor (Private
, VariableName
);
2467 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2472 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2473 by GUID in the page for user to select and delete as needed.
2475 @param[in] PrivateData Module's private data.
2476 @param[in] VariableName The variable name of the vendor's signature database.
2477 @param[in] VendorGuid A unique identifier for the vendor.
2478 @param[in] LabelNumber Label number to insert opcodes.
2479 @param[in] FormId Form ID of current page.
2480 @param[in] QuestionIdBase Base question id of the signature list.
2482 @retval EFI_SUCCESS Success to update the signature list page
2483 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2488 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2489 IN CHAR16
*VariableName
,
2490 IN EFI_GUID
*VendorGuid
,
2491 IN UINT16 LabelNumber
,
2492 IN EFI_FORM_ID FormId
,
2493 IN EFI_QUESTION_ID QuestionIdBase
2500 VOID
*StartOpCodeHandle
;
2501 VOID
*EndOpCodeHandle
;
2502 EFI_IFR_GUID_LABEL
*StartLabel
;
2503 EFI_IFR_GUID_LABEL
*EndLabel
;
2506 EFI_SIGNATURE_LIST
*CertList
;
2507 EFI_SIGNATURE_DATA
*Cert
;
2508 UINT32 ItemDataSize
;
2510 EFI_STRING_ID GuidID
;
2517 StartOpCodeHandle
= NULL
;
2518 EndOpCodeHandle
= NULL
;
2521 // Initialize the container for dynamic opcodes.
2523 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2524 if (StartOpCodeHandle
== NULL
) {
2525 Status
= EFI_OUT_OF_RESOURCES
;
2529 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2530 if (EndOpCodeHandle
== NULL
) {
2531 Status
= EFI_OUT_OF_RESOURCES
;
2536 // Create Hii Extend Label OpCode.
2538 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
2542 sizeof (EFI_IFR_GUID_LABEL
)
2544 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2545 StartLabel
->Number
= LabelNumber
;
2547 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
2551 sizeof (EFI_IFR_GUID_LABEL
)
2553 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2554 EndLabel
->Number
= LABEL_END
;
2560 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2561 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2565 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2567 Status
= EFI_OUT_OF_RESOURCES
;
2571 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2572 if (EFI_ERROR (Status
)) {
2576 GuidStr
= AllocateZeroPool (100);
2577 if (GuidStr
== NULL
) {
2578 Status
= EFI_OUT_OF_RESOURCES
;
2583 // Enumerate all KEK pub data.
2585 ItemDataSize
= (UINT32
)DataSize
;
2586 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2589 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2590 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2591 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2592 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2593 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2594 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2595 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2596 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2597 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2598 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2599 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2600 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2601 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2602 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2603 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2606 // The signature type is not supported in current implementation.
2608 ItemDataSize
-= CertList
->SignatureListSize
;
2609 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2613 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2614 for (Index
= 0; Index
< CertCount
; Index
++) {
2615 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
2616 + sizeof (EFI_SIGNATURE_LIST
)
2617 + CertList
->SignatureHeaderSize
2618 + Index
* CertList
->SignatureSize
);
2620 // Display GUID and help
2622 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2623 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2624 HiiCreateCheckBoxOpCode (
2626 (EFI_QUESTION_ID
)(QuestionIdBase
+ GuidIndex
++),
2631 EFI_IFR_FLAG_CALLBACK
,
2637 ItemDataSize
-= CertList
->SignatureListSize
;
2638 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2643 PrivateData
->HiiHandle
,
2644 &gSecureBootConfigFormSetGuid
,
2650 if (StartOpCodeHandle
!= NULL
) {
2651 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2654 if (EndOpCodeHandle
!= NULL
) {
2655 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2662 if (GuidStr
!= NULL
) {
2670 Delete a KEK entry from KEK database.
2672 @param[in] PrivateData Module's private data.
2673 @param[in] QuestionId Question id of the KEK item to delete.
2675 @retval EFI_SUCCESS Delete kek item successfully.
2676 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2680 DeleteKeyExchangeKey (
2681 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2682 IN EFI_QUESTION_ID QuestionId
2691 EFI_SIGNATURE_LIST
*CertList
;
2692 EFI_SIGNATURE_LIST
*NewCertList
;
2693 EFI_SIGNATURE_DATA
*Cert
;
2696 BOOLEAN IsKEKItemFound
;
2698 UINTN DeleteKekIndex
;
2707 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2709 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2710 if (EFI_ERROR (Status
)) {
2715 // Get original KEK variable.
2718 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2719 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2723 OldData
= (UINT8
*)AllocateZeroPool (DataSize
);
2724 if (OldData
== NULL
) {
2725 Status
= EFI_OUT_OF_RESOURCES
;
2729 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2730 if (EFI_ERROR (Status
)) {
2735 // Allocate space for new variable.
2737 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2739 Status
= EFI_OUT_OF_RESOURCES
;
2744 // Enumerate all KEK pub data and erasing the target item.
2746 IsKEKItemFound
= FALSE
;
2747 KekDataSize
= (UINT32
)DataSize
;
2748 CertList
= (EFI_SIGNATURE_LIST
*)OldData
;
2751 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2752 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2753 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
))
2755 CopyMem (Data
+ Offset
, CertList
, (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2756 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2757 Offset
+= (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2758 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2759 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2760 for (Index
= 0; Index
< CertCount
; Index
++) {
2761 if (GuidIndex
== DeleteKekIndex
) {
2763 // Find it! Skip it!
2765 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2766 IsKEKItemFound
= TRUE
;
2769 // This item doesn't match. Copy it to the Data buffer.
2771 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2772 Offset
+= CertList
->SignatureSize
;
2776 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
2780 // This List doesn't match. Copy it to the Data buffer.
2782 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2783 Offset
+= CertList
->SignatureListSize
;
2786 KekDataSize
-= CertList
->SignatureListSize
;
2787 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2790 if (!IsKEKItemFound
) {
2792 // Doesn't find the Kek Item!
2794 Status
= EFI_NOT_FOUND
;
2799 // Delete the Signature header if there is no signature in the list.
2801 KekDataSize
= Offset
;
2802 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
2804 ZeroMem (OldData
, KekDataSize
);
2805 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2806 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2807 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2808 if (CertCount
!= 0) {
2809 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2810 Offset
+= CertList
->SignatureListSize
;
2813 KekDataSize
-= CertList
->SignatureListSize
;
2814 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
2818 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2819 Status
= GetCurrentTime (&Time
);
2820 if (EFI_ERROR (Status
)) {
2821 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
2825 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
, &Time
);
2826 if (EFI_ERROR (Status
)) {
2827 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
2832 Status
= gRT
->SetVariable (
2833 EFI_KEY_EXCHANGE_KEY_NAME
,
2834 &gEfiGlobalVariableGuid
,
2839 if (EFI_ERROR (Status
)) {
2840 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2849 if (OldData
!= NULL
) {
2853 return UpdateDeletePage (
2855 EFI_KEY_EXCHANGE_KEY_NAME
,
2856 &gEfiGlobalVariableGuid
,
2858 FORMID_DELETE_KEK_FORM
,
2859 OPTION_DEL_KEK_QUESTION_ID
2864 Delete a signature entry from signature database.
2866 @param[in] PrivateData Module's private data.
2867 @param[in] VariableName The variable name of the vendor's signature database.
2868 @param[in] VendorGuid A unique identifier for the vendor.
2869 @param[in] LabelNumber Label number to insert opcodes.
2870 @param[in] FormId Form ID of current page.
2871 @param[in] QuestionIdBase Base question id of the signature list.
2872 @param[in] DeleteIndex Signature index to delete.
2874 @retval EFI_SUCCESS Delete signature successfully.
2875 @retval EFI_NOT_FOUND Can't find the signature item,
2876 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2880 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2881 IN CHAR16
*VariableName
,
2882 IN EFI_GUID
*VendorGuid
,
2883 IN UINT16 LabelNumber
,
2884 IN EFI_FORM_ID FormId
,
2885 IN EFI_QUESTION_ID QuestionIdBase
,
2886 IN UINTN DeleteIndex
2895 EFI_SIGNATURE_LIST
*CertList
;
2896 EFI_SIGNATURE_LIST
*NewCertList
;
2897 EFI_SIGNATURE_DATA
*Cert
;
2900 BOOLEAN IsItemFound
;
2901 UINT32 ItemDataSize
;
2911 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2912 if (EFI_ERROR (Status
)) {
2917 // Get original signature list data.
2920 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2921 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
2925 OldData
= (UINT8
*)AllocateZeroPool (DataSize
);
2926 if (OldData
== NULL
) {
2927 Status
= EFI_OUT_OF_RESOURCES
;
2931 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2932 if (EFI_ERROR (Status
)) {
2937 // Allocate space for new variable.
2939 Data
= (UINT8
*)AllocateZeroPool (DataSize
);
2941 Status
= EFI_OUT_OF_RESOURCES
;
2946 // Enumerate all signature data and erasing the target item.
2948 IsItemFound
= FALSE
;
2949 ItemDataSize
= (UINT32
)DataSize
;
2950 CertList
= (EFI_SIGNATURE_LIST
*)OldData
;
2953 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2954 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2955 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2956 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2957 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2958 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2959 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2960 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2964 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2966 CopyMem (Data
+ Offset
, CertList
, (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2967 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2968 Offset
+= (sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2969 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2970 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2971 for (Index
= 0; Index
< CertCount
; Index
++) {
2972 if (GuidIndex
== DeleteIndex
) {
2974 // Find it! Skip it!
2976 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2980 // This item doesn't match. Copy it to the Data buffer.
2982 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2983 Offset
+= CertList
->SignatureSize
;
2987 Cert
= (EFI_SIGNATURE_DATA
*)((UINT8
*)Cert
+ CertList
->SignatureSize
);
2991 // This List doesn't match. Just copy it to the Data buffer.
2993 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2994 Offset
+= CertList
->SignatureListSize
;
2997 ItemDataSize
-= CertList
->SignatureListSize
;
2998 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
3003 // Doesn't find the signature Item!
3005 Status
= EFI_NOT_FOUND
;
3010 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
3012 ItemDataSize
= Offset
;
3013 CertList
= (EFI_SIGNATURE_LIST
*)Data
;
3015 ZeroMem (OldData
, ItemDataSize
);
3016 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
3017 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
3018 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
3019 if (CertCount
!= 0) {
3020 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
3021 Offset
+= CertList
->SignatureListSize
;
3024 ItemDataSize
-= CertList
->SignatureListSize
;
3025 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*)CertList
+ CertList
->SignatureListSize
);
3029 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3030 Status
= GetCurrentTime (&Time
);
3031 if (EFI_ERROR (Status
)) {
3032 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
3036 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
, &Time
);
3037 if (EFI_ERROR (Status
)) {
3038 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3043 Status
= gRT
->SetVariable (
3050 if (EFI_ERROR (Status
)) {
3051 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
3060 if (OldData
!= NULL
) {
3064 return UpdateDeletePage (
3075 This function to delete signature list or data, according by DelType.
3077 @param[in] PrivateData Module's private data.
3078 @param[in] DelType Indicate delete signature list or data.
3079 @param[in] CheckedCount Indicate how many signature data have
3080 been checked in current signature list.
3082 @retval EFI_SUCCESS Success to update the signature list page
3083 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3087 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3088 IN SIGNATURE_DELETE_TYPE DelType
,
3089 IN UINT32 CheckedCount
3093 EFI_SIGNATURE_LIST
*ListWalker
;
3094 EFI_SIGNATURE_LIST
*NewCertList
;
3095 EFI_SIGNATURE_DATA
*DataWalker
;
3096 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3097 UINT32 VariableAttr
;
3098 UINTN VariableDataSize
;
3099 UINTN RemainingSize
;
3103 UINT8
*VariableData
;
3104 UINT8
*NewVariableData
;
3107 Status
= EFI_SUCCESS
;
3109 VariableDataSize
= 0;
3112 VariableData
= NULL
;
3113 NewVariableData
= NULL
;
3115 if (PrivateData
->VariableName
== Variable_DB
) {
3116 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3117 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3118 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3119 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3120 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3125 Status
= gRT
->GetVariable (
3127 &gEfiImageSecurityDatabaseGuid
,
3132 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
3136 VariableData
= AllocateZeroPool (VariableDataSize
);
3137 if (VariableData
== NULL
) {
3138 Status
= EFI_OUT_OF_RESOURCES
;
3142 Status
= gRT
->GetVariable (
3144 &gEfiImageSecurityDatabaseGuid
,
3149 if (EFI_ERROR (Status
)) {
3153 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3154 if (EFI_ERROR (Status
)) {
3158 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3159 if (NewVariableData
== NULL
) {
3160 Status
= EFI_OUT_OF_RESOURCES
;
3164 RemainingSize
= VariableDataSize
;
3165 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3166 if (DelType
== Delete_Signature_List_All
) {
3167 VariableDataSize
= 0;
3170 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3172 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3173 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3174 Offset
+= ListWalker
->SignatureListSize
;
3176 RemainingSize
-= ListWalker
->SignatureListSize
;
3177 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3182 // Handle the target EFI_SIGNATURE_LIST.
3183 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3184 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3186 if ((CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
)) && (DelType
== Delete_Signature_Data
)) {
3187 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3191 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3192 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3194 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3195 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS (ListWalker
); Index
= Index
+ 1) {
3196 if (PrivateData
->CheckArray
[Index
]) {
3198 // Delete checked signature data, and update the size of whole signature list.
3200 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3203 // Remain the unchecked signature data.
3205 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3206 Offset
+= ListWalker
->SignatureSize
;
3209 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3213 RemainingSize
-= ListWalker
->SignatureListSize
;
3214 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3217 // Copy remaining data, maybe 0.
3219 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3220 Offset
+= RemainingSize
;
3222 VariableDataSize
= Offset
;
3225 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3226 Status
= GetCurrentTime (&Time
);
3227 if (EFI_ERROR (Status
)) {
3228 DEBUG ((DEBUG_ERROR
, "Fail to fetch valid time data: %r", Status
));
3232 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
, &Time
);
3233 if (EFI_ERROR (Status
)) {
3234 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3239 Status
= gRT
->SetVariable (
3241 &gEfiImageSecurityDatabaseGuid
,
3246 if (EFI_ERROR (Status
)) {
3247 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3252 SECUREBOOT_FREE_NON_NULL (VariableData
);
3253 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3260 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3261 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3263 @param[in] PrivateData Module's private data.
3265 @return EFI_SUCCESS Update secure boot strings successfully.
3266 @return other Fail to update secure boot strings.
3270 UpdateSecureBootString (
3271 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3279 // Get current secure boot state.
3281 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3282 if (SecureBoot
== NULL
) {
3283 return EFI_NOT_FOUND
;
3286 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3287 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3289 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3292 FreePool (SecureBoot
);
3298 This function extracts configuration from variable.
3300 @param[in] Private Point to SecureBoot configuration driver private data.
3301 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3305 SecureBootExtractConfigFromVariable (
3306 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3307 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3310 UINT8
*SecureBootEnable
;
3312 UINT8
*SecureBootMode
;
3315 SecureBootEnable
= NULL
;
3317 SecureBootMode
= NULL
;
3320 // Initialize the Date and Time using system time.
3322 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3323 ConfigData
->AlwaysRevocation
= TRUE
;
3324 gRT
->GetTime (&CurrTime
, NULL
);
3325 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3326 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3327 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3328 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3329 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3330 ConfigData
->RevocationTime
.Second
= 0;
3331 if (Private
->FileContext
->FHandle
!= NULL
) {
3332 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3334 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3338 // If it is Physical Presence User, set the PhysicalPresent to true.
3340 if (UserPhysicalPresent ()) {
3341 ConfigData
->PhysicalPresent
= TRUE
;
3343 ConfigData
->PhysicalPresent
= FALSE
;
3347 // If there is no PK then the Delete Pk button will be gray.
3349 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3350 if ((SetupMode
== NULL
) || ((*SetupMode
) == SETUP_MODE
)) {
3351 ConfigData
->HasPk
= FALSE
;
3353 ConfigData
->HasPk
= TRUE
;
3357 // Check SecureBootEnable & Pk status, fix the inconsistency.
3358 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3361 ConfigData
->AttemptSecureBoot
= FALSE
;
3362 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3365 // Fix Pk and SecureBootEnable inconsistency
3367 if ((SetupMode
!= NULL
) && ((*SetupMode
) == USER_MODE
)) {
3368 ConfigData
->HideSecureBoot
= FALSE
;
3369 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3370 ConfigData
->AttemptSecureBoot
= TRUE
;
3373 ConfigData
->HideSecureBoot
= TRUE
;
3377 // Get the SecureBootMode from CustomMode variable.
3379 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3380 if (SecureBootMode
== NULL
) {
3381 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3383 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3386 if (SecureBootEnable
!= NULL
) {
3387 FreePool (SecureBootEnable
);
3390 if (SetupMode
!= NULL
) {
3391 FreePool (SetupMode
);
3394 if (SecureBootMode
!= NULL
) {
3395 FreePool (SecureBootMode
);
3400 This function allows a caller to extract the current configuration for one
3401 or more named elements from the target driver.
3403 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3404 @param[in] Request A null-terminated Unicode string in
3405 <ConfigRequest> format.
3406 @param[out] Progress On return, points to a character in the Request
3407 string. Points to the string's null terminator if
3408 request was successful. Points to the most recent
3409 '&' before the first failing name/value pair (or
3410 the beginning of the string if the failure is in
3411 the first name/value pair) if the request was not
3413 @param[out] Results A null-terminated Unicode string in
3414 <ConfigAltResp> format which has all values filled
3415 in for the names in the Request string. String to
3416 be allocated by the called function.
3418 @retval EFI_SUCCESS The Results is filled with the requested values.
3419 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3420 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3421 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3427 SecureBootExtractConfig (
3428 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3429 IN CONST EFI_STRING Request
,
3430 OUT EFI_STRING
*Progress
,
3431 OUT EFI_STRING
*Results
3437 SECUREBOOT_CONFIGURATION Configuration
;
3438 EFI_STRING ConfigRequest
;
3439 EFI_STRING ConfigRequestHdr
;
3440 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3441 BOOLEAN AllocatedRequest
;
3443 if ((Progress
== NULL
) || (Results
== NULL
)) {
3444 return EFI_INVALID_PARAMETER
;
3447 AllocatedRequest
= FALSE
;
3448 ConfigRequestHdr
= NULL
;
3449 ConfigRequest
= NULL
;
3452 ZeroMem (&Configuration
, sizeof (Configuration
));
3453 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3454 *Progress
= Request
;
3456 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3457 return EFI_NOT_FOUND
;
3460 ZeroMem (&Configuration
, sizeof (SECUREBOOT_CONFIGURATION
));
3463 // Get Configuration from Variable.
3465 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3467 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3468 ConfigRequest
= Request
;
3469 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3471 // Request is set to NULL or OFFSET is NULL, construct full request string.
3473 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3474 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3476 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3477 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3478 ConfigRequest
= AllocateZeroPool (Size
);
3479 ASSERT (ConfigRequest
!= NULL
);
3480 AllocatedRequest
= TRUE
;
3481 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3482 FreePool (ConfigRequestHdr
);
3483 ConfigRequestHdr
= NULL
;
3486 Status
= gHiiConfigRouting
->BlockToConfig (
3489 (UINT8
*)&Configuration
,
3496 // Free the allocated config request string.
3498 if (AllocatedRequest
) {
3499 FreePool (ConfigRequest
);
3503 // Set Progress string to the original request string.
3505 if (Request
== NULL
) {
3507 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3508 *Progress
= Request
+ StrLen (Request
);
3515 This function processes the results of changes in configuration.
3517 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3518 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3520 @param[out] Progress A pointer to a string filled in with the offset of
3521 the most recent '&' before the first failing
3522 name/value pair (or the beginning of the string if
3523 the failure is in the first name/value pair) or
3524 the terminating NULL if all was successful.
3526 @retval EFI_SUCCESS The Results is processed successfully.
3527 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3528 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3534 SecureBootRouteConfig (
3535 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3536 IN CONST EFI_STRING Configuration
,
3537 OUT EFI_STRING
*Progress
3540 SECUREBOOT_CONFIGURATION IfrNvData
;
3542 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3545 if ((Configuration
== NULL
) || (Progress
== NULL
)) {
3546 return EFI_INVALID_PARAMETER
;
3549 *Progress
= Configuration
;
3550 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3551 return EFI_NOT_FOUND
;
3554 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3557 // Get Configuration from Variable.
3559 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3562 // Map the Configuration to the configuration block.
3564 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3565 Status
= gHiiConfigRouting
->ConfigToBlock (
3568 (UINT8
*)&IfrNvData
,
3572 if (EFI_ERROR (Status
)) {
3577 // Store Buffer Storage back to EFI variable if needed
3579 if (!IfrNvData
.HideSecureBoot
) {
3580 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3581 if (EFI_ERROR (Status
)) {
3586 *Progress
= Configuration
+ StrLen (Configuration
);
3591 This function to load signature list, the update the menu page.
3593 @param[in] PrivateData Module's private data.
3594 @param[in] LabelId Label number to insert opcodes.
3595 @param[in] FormId Form ID of current page.
3596 @param[in] QuestionIdBase Base question id of the signature list.
3598 @retval EFI_SUCCESS Success to update the signature list page
3599 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3603 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3605 IN EFI_FORM_ID FormId
,
3606 IN EFI_QUESTION_ID QuestionIdBase
3610 EFI_STRING_ID ListType
;
3611 EFI_STRING FormatNameString
;
3612 EFI_STRING FormatHelpString
;
3613 EFI_STRING FormatTypeString
;
3614 EFI_SIGNATURE_LIST
*ListWalker
;
3615 EFI_IFR_GUID_LABEL
*StartLabel
;
3616 EFI_IFR_GUID_LABEL
*EndLabel
;
3617 EFI_IFR_GUID_LABEL
*StartGoto
;
3618 EFI_IFR_GUID_LABEL
*EndGoto
;
3619 EFI_FORM_ID DstFormId
;
3620 VOID
*StartOpCodeHandle
;
3621 VOID
*EndOpCodeHandle
;
3622 VOID
*StartGotoHandle
;
3623 VOID
*EndGotoHandle
;
3625 UINTN RemainingSize
;
3627 UINT8
*VariableData
;
3628 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3629 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3630 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3632 Status
= EFI_SUCCESS
;
3633 FormatNameString
= NULL
;
3634 FormatHelpString
= NULL
;
3635 StartOpCodeHandle
= NULL
;
3636 EndOpCodeHandle
= NULL
;
3637 StartGotoHandle
= NULL
;
3638 EndGotoHandle
= NULL
;
3640 VariableData
= NULL
;
3643 // Initialize the container for dynamic opcodes.
3645 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3646 if (StartOpCodeHandle
== NULL
) {
3647 Status
= EFI_OUT_OF_RESOURCES
;
3651 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3652 if (EndOpCodeHandle
== NULL
) {
3653 Status
= EFI_OUT_OF_RESOURCES
;
3657 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3658 if (StartGotoHandle
== NULL
) {
3659 Status
= EFI_OUT_OF_RESOURCES
;
3663 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3664 if (EndGotoHandle
== NULL
) {
3665 Status
= EFI_OUT_OF_RESOURCES
;
3670 // Create Hii Extend Label OpCode.
3672 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3676 sizeof (EFI_IFR_GUID_LABEL
)
3678 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3679 StartLabel
->Number
= LabelId
;
3681 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3685 sizeof (EFI_IFR_GUID_LABEL
)
3687 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3688 EndLabel
->Number
= LABEL_END
;
3690 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3694 sizeof (EFI_IFR_GUID_LABEL
)
3696 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3697 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3699 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3703 sizeof (EFI_IFR_GUID_LABEL
)
3705 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3706 EndGoto
->Number
= LABEL_END
;
3708 if (PrivateData
->VariableName
== Variable_DB
) {
3709 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3710 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3711 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3712 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3713 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3714 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3715 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3716 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3721 HiiCreateGotoOpCode (
3724 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3725 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3726 EFI_IFR_FLAG_CALLBACK
,
3727 KEY_SECURE_BOOT_DELETE_ALL_LIST
3731 // Read Variable, the variable name save in the PrivateData->VariableName.
3734 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3735 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
3739 VariableData
= AllocateZeroPool (DataSize
);
3740 if (VariableData
== NULL
) {
3741 Status
= EFI_OUT_OF_RESOURCES
;
3745 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3746 if (EFI_ERROR (Status
)) {
3750 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3751 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3752 if ((FormatNameString
== NULL
) || (FormatHelpString
== NULL
)) {
3756 RemainingSize
= DataSize
;
3757 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3758 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3759 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3760 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3761 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3762 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3763 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3764 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3765 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3766 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3767 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3768 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3769 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3770 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3771 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3772 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3774 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3777 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3778 if (FormatTypeString
== NULL
) {
3782 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3783 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3785 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3788 sizeof (HelpBuffer
),
3791 SIGNATURE_DATA_COUNTS (ListWalker
)
3793 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3794 FormatTypeString
= NULL
;
3796 HiiCreateGotoOpCode (
3798 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3799 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3800 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3801 EFI_IFR_FLAG_CALLBACK
,
3802 QuestionIdBase
+ Index
++
3805 RemainingSize
-= ListWalker
->SignatureListSize
;
3806 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3811 PrivateData
->HiiHandle
,
3812 &gSecureBootConfigFormSetGuid
,
3819 PrivateData
->HiiHandle
,
3820 &gSecureBootConfigFormSetGuid
,
3826 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3827 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3828 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3829 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3831 SECUREBOOT_FREE_NON_NULL (VariableData
);
3832 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3833 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3835 PrivateData
->ListCount
= Index
;
3841 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3842 The buffer is callee allocated and should be freed by the caller.
3844 @param[in] ListEntry The pointer point to the signature list.
3845 @param[in] DataEntry The signature data we are processing.
3846 @param[out] BufferToReturn Buffer to save the hash value.
3848 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3849 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3850 @retval EFI_SUCCESS Operation success.
3854 IN EFI_SIGNATURE_LIST
*ListEntry
,
3855 IN EFI_SIGNATURE_DATA
*DataEntry
,
3856 OUT CHAR16
**BufferToReturn
3867 // Assume that, display 8 bytes in one line.
3871 if ((ListEntry
== NULL
) || (DataEntry
== NULL
) || (BufferToReturn
== NULL
)) {
3872 return EFI_INVALID_PARAMETER
;
3875 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
3876 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3879 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3881 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof (CHAR16
));
3883 *BufferToReturn
= AllocateZeroPool (TotalSize
);
3884 if (*BufferToReturn
== NULL
) {
3885 return EFI_OUT_OF_RESOURCES
;
3888 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3889 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3890 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"\n");
3893 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3896 BufferIndex
+= UnicodeSPrint (&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof (CHAR16
) * BufferIndex
, L
"\n");
3902 Function to get the common name from the X509 format certificate.
3903 The buffer is callee allocated and should be freed by the caller.
3905 @param[in] ListEntry The pointer point to the signature list.
3906 @param[in] DataEntry The signature data we are processing.
3907 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3909 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3910 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3911 @retval EFI_SUCCESS Operation success.
3912 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3915 GetCommonNameFromX509 (
3916 IN EFI_SIGNATURE_LIST
*ListEntry
,
3917 IN EFI_SIGNATURE_DATA
*DataEntry
,
3918 OUT CHAR16
**BufferToReturn
3925 Status
= EFI_SUCCESS
;
3928 CNBuffer
= AllocateZeroPool (256);
3929 if (CNBuffer
== NULL
) {
3930 Status
= EFI_OUT_OF_RESOURCES
;
3936 (UINT8
*)DataEntry
+ sizeof (EFI_GUID
),
3937 ListEntry
->SignatureSize
- sizeof (EFI_GUID
),
3942 *BufferToReturn
= AllocateZeroPool (256 * sizeof (CHAR16
));
3943 if (*BufferToReturn
== NULL
) {
3944 Status
= EFI_OUT_OF_RESOURCES
;
3948 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3951 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3957 Format the help info for the signature data, each help info contain 3 parts.
3959 2. Content, depends on the type of the signature list.
3962 @param[in] PrivateData Module's private data.
3963 @param[in] ListEntry Point to the signature list.
3964 @param[in] DataEntry Point to the signature data we are processing.
3965 @param[out] StringId Save the string id of help info.
3967 @retval EFI_SUCCESS Operation success.
3968 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3972 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3973 IN EFI_SIGNATURE_LIST
*ListEntry
,
3974 IN EFI_SIGNATURE_DATA
*DataEntry
,
3975 OUT EFI_STRING_ID
*StringId
3980 EFI_STRING_ID ListTypeId
;
3981 EFI_STRING FormatHelpString
;
3982 EFI_STRING FormatTypeString
;
3984 UINTN HelpInfoIndex
;
3986 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3987 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3989 CHAR16
*HelpInfoString
;
3992 Status
= EFI_SUCCESS
;
3994 FormatTypeString
= NULL
;
3997 HelpInfoString
= NULL
;
4000 if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
4001 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
4002 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
4004 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
4005 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509
);
4006 DataSize
= ListEntry
->SignatureSize
- sizeof (EFI_GUID
);
4008 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
4009 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
4011 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
4012 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
4014 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
4015 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
4017 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
4018 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
4019 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
4021 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
4022 } else if (CompareGuid (&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
4023 ListTypeId
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
4025 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
4027 Status
= EFI_UNSUPPORTED
;
4031 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
4032 if (FormatTypeString
== NULL
) {
4037 HelpInfoString
= AllocateZeroPool (TotalSize
);
4038 if (HelpInfoString
== NULL
) {
4039 Status
= EFI_OUT_OF_RESOURCES
;
4044 // Format GUID part.
4046 ZeroMem (GuidString
, sizeof (GuidString
));
4047 GuidToString (&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
4048 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
4049 if (FormatHelpString
== NULL
) {
4053 HelpInfoIndex
+= UnicodeSPrint (
4054 &HelpInfoString
[HelpInfoIndex
],
4055 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4059 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4060 FormatHelpString
= NULL
;
4063 // Format content part, it depends on the type of signature list, hash value or CN.
4066 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
4067 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
4070 // Format hash value for each signature data entry.
4072 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
4073 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
4076 if (FormatHelpString
== NULL
) {
4080 HelpInfoIndex
+= UnicodeSPrint (
4081 &HelpInfoString
[HelpInfoIndex
],
4082 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4088 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4089 FormatHelpString
= NULL
;
4092 // Format revocation time part.
4095 ZeroMem (TimeString
, sizeof (TimeString
));
4098 sizeof (TimeString
),
4099 L
"%d-%d-%d %d:%d:%d",
4107 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
4108 if (FormatHelpString
== NULL
) {
4113 &HelpInfoString
[HelpInfoIndex
],
4114 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4118 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4119 FormatHelpString
= NULL
;
4122 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
4124 SECUREBOOT_FREE_NON_NULL (DataString
);
4125 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
4127 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
4133 This function to load signature data under the signature list.
4135 @param[in] PrivateData Module's private data.
4136 @param[in] LabelId Label number to insert opcodes.
4137 @param[in] FormId Form ID of current page.
4138 @param[in] QuestionIdBase Base question id of the signature list.
4139 @param[in] ListIndex Indicate to load which signature list.
4141 @retval EFI_SUCCESS Success to update the signature list page
4142 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4146 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4148 IN EFI_FORM_ID FormId
,
4149 IN EFI_QUESTION_ID QuestionIdBase
,
4154 EFI_SIGNATURE_LIST
*ListWalker
;
4155 EFI_SIGNATURE_DATA
*DataWalker
;
4156 EFI_IFR_GUID_LABEL
*StartLabel
;
4157 EFI_IFR_GUID_LABEL
*EndLabel
;
4158 EFI_STRING_ID HelpStringId
;
4159 EFI_STRING FormatNameString
;
4160 VOID
*StartOpCodeHandle
;
4161 VOID
*EndOpCodeHandle
;
4163 UINTN RemainingSize
;
4165 UINT8
*VariableData
;
4166 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4167 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4169 Status
= EFI_SUCCESS
;
4170 FormatNameString
= NULL
;
4171 StartOpCodeHandle
= NULL
;
4172 EndOpCodeHandle
= NULL
;
4174 VariableData
= NULL
;
4177 // Initialize the container for dynamic opcodes.
4179 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4180 if (StartOpCodeHandle
== NULL
) {
4181 Status
= EFI_OUT_OF_RESOURCES
;
4185 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4186 if (EndOpCodeHandle
== NULL
) {
4187 Status
= EFI_OUT_OF_RESOURCES
;
4192 // Create Hii Extend Label OpCode.
4194 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4198 sizeof (EFI_IFR_GUID_LABEL
)
4200 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4201 StartLabel
->Number
= LabelId
;
4203 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4207 sizeof (EFI_IFR_GUID_LABEL
)
4209 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4210 EndLabel
->Number
= LABEL_END
;
4212 if (PrivateData
->VariableName
== Variable_DB
) {
4213 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4214 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4215 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4216 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4217 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4223 // Read Variable, the variable name save in the PrivateData->VariableName.
4226 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4227 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
4231 VariableData
= AllocateZeroPool (DataSize
);
4232 if (VariableData
== NULL
) {
4233 Status
= EFI_OUT_OF_RESOURCES
;
4237 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4238 if (EFI_ERROR (Status
)) {
4242 RemainingSize
= DataSize
;
4243 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4246 // Skip signature list.
4248 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4249 RemainingSize
-= ListWalker
->SignatureListSize
;
4250 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4253 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4254 if (FormatNameString
== NULL
) {
4258 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4259 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS (ListWalker
); Index
= Index
+ 1) {
4261 // Format name buffer.
4263 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4264 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4267 // Format help info buffer.
4269 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4270 if (EFI_ERROR (Status
)) {
4274 HiiCreateCheckBoxOpCode (
4276 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4279 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4281 EFI_IFR_FLAG_CALLBACK
,
4286 ZeroMem (NameBuffer
, 100);
4287 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4291 // Allocate a buffer to record which signature data will be checked.
4292 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4294 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4297 PrivateData
->HiiHandle
,
4298 &gSecureBootConfigFormSetGuid
,
4304 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4305 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4307 SECUREBOOT_FREE_NON_NULL (VariableData
);
4308 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4314 This function reinitializes Secure Boot variables with default values.
4316 @retval EFI_SUCCESS Success to update the signature list page
4317 @retval others Fail to delete or enroll signature data.
4328 Status
= EFI_SUCCESS
;
4330 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4331 if (EFI_ERROR (Status
)) {
4335 // Clear all the keys and databases
4336 Status
= DeleteDb ();
4337 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4338 DEBUG ((DEBUG_ERROR
, "Fail to clear DB: %r\n", Status
));
4342 Status
= DeleteDbx ();
4343 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4344 DEBUG ((DEBUG_ERROR
, "Fail to clear DBX: %r\n", Status
));
4348 Status
= DeleteDbt ();
4349 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4350 DEBUG ((DEBUG_ERROR
, "Fail to clear DBT: %r\n", Status
));
4354 Status
= DeleteKEK ();
4355 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4356 DEBUG ((DEBUG_ERROR
, "Fail to clear KEK: %r\n", Status
));
4360 Status
= DeletePlatformKey ();
4361 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
4362 DEBUG ((DEBUG_ERROR
, "Fail to clear PK: %r\n", Status
));
4366 // After PK clear, Setup Mode shall be enabled
4367 Status
= GetSetupMode (&SetupMode
);
4368 if (EFI_ERROR (Status
)) {
4371 "Cannot get SetupMode variable: %r\n",
4377 if (SetupMode
== USER_MODE
) {
4378 DEBUG ((DEBUG_INFO
, "Skipped - USER_MODE\n"));
4382 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
4383 if (EFI_ERROR (Status
)) {
4386 "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n",
4392 // Enroll all the keys from default variables
4393 Status
= EnrollDbFromDefault ();
4394 if (EFI_ERROR (Status
)) {
4395 DEBUG ((DEBUG_ERROR
, "Cannot enroll db: %r\n", Status
));
4399 Status
= EnrollDbxFromDefault ();
4400 if (EFI_ERROR (Status
)) {
4401 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbx: %r\n", Status
));
4404 Status
= EnrollDbtFromDefault ();
4405 if (EFI_ERROR (Status
)) {
4406 DEBUG ((DEBUG_ERROR
, "Cannot enroll dbt: %r\n", Status
));
4409 Status
= EnrollKEKFromDefault ();
4410 if (EFI_ERROR (Status
)) {
4411 DEBUG ((DEBUG_ERROR
, "Cannot enroll KEK: %r\n", Status
));
4415 Status
= EnrollPKFromDefault ();
4416 if (EFI_ERROR (Status
)) {
4417 DEBUG ((DEBUG_ERROR
, "Cannot enroll PK: %r\n", Status
));
4421 Status
= SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
4422 if (EFI_ERROR (Status
)) {
4425 "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
4426 "Please do it manually, otherwise system can be easily compromised\n"
4441 if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
) != EFI_SUCCESS
) {
4442 DEBUG ((DEBUG_ERROR
, "Cannot set mode to Secure: %r\n", Status
));
4449 This function is called to provide results data to the driver.
4451 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4452 @param[in] Action Specifies the type of action taken by the browser.
4453 @param[in] QuestionId A unique value which is sent to the original
4454 exporting driver so that it can identify the type
4456 @param[in] Type The type of value for the question.
4457 @param[in] Value A pointer to the data being sent to the original
4459 @param[out] ActionRequest On return, points to the action requested by the
4462 @retval EFI_SUCCESS The callback successfully handled the action.
4463 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4464 variable and its data.
4465 @retval EFI_DEVICE_ERROR The variable could not be saved.
4466 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4472 SecureBootCallback (
4473 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4474 IN EFI_BROWSER_ACTION Action
,
4475 IN EFI_QUESTION_ID QuestionId
,
4477 IN EFI_IFR_TYPE_VALUE
*Value
,
4478 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4483 RETURN_STATUS RStatus
;
4484 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4486 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4488 UINT8
*SecureBootEnable
;
4490 UINT8
*SecureBootMode
;
4492 CHAR16 PromptString
[100];
4493 EFI_DEVICE_PATH_PROTOCOL
*File
;
4495 UINT16
*FilePostFix
;
4496 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4497 BOOLEAN GetBrowserDataResult
;
4498 ENROLL_KEY_ERROR EnrollKeyErrorCode
;
4499 EFI_HII_POPUP_PROTOCOL
*HiiPopup
;
4500 EFI_HII_POPUP_SELECTION UserSelection
;
4502 Status
= EFI_SUCCESS
;
4503 SecureBootEnable
= NULL
;
4504 SecureBootMode
= NULL
;
4507 EnrollKeyErrorCode
= None_Error
;
4509 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4510 return EFI_INVALID_PARAMETER
;
4513 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4515 gSecureBootPrivateData
= Private
;
4518 // Retrieve uncommitted data from Browser
4520 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4521 IfrNvData
= AllocateZeroPool (BufferSize
);
4522 if (IfrNvData
== NULL
) {
4523 return EFI_OUT_OF_RESOURCES
;
4526 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*)IfrNvData
);
4528 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4529 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4531 // Update secure boot strings when opening this form
4533 Status
= UpdateSecureBootString (Private
);
4534 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4535 mIsEnterSecureBootForm
= TRUE
;
4538 // When entering SecureBoot OPTION Form
4539 // always close opened file & free resource
4541 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4542 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4543 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4544 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4545 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
))
4547 CloseEnrolledFile (Private
->FileContext
);
4548 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4550 // Update ListCount field in varstore
4551 // Button "Delete All Signature List" is
4552 // enable when ListCount is greater than 0.
4554 IfrNvData
->ListCount
= Private
->ListCount
;
4561 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4562 Status
= EFI_UNSUPPORTED
;
4563 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4564 if (mIsEnterSecureBootForm
) {
4565 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4566 Status
= EFI_SUCCESS
;
4573 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4574 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4575 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4576 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
))
4578 Status
= EFI_UNSUPPORTED
;
4582 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4583 switch (QuestionId
) {
4584 case KEY_SECURE_BOOT_ENABLE
:
4585 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4586 if (NULL
!= SecureBootEnable
) {
4587 FreePool (SecureBootEnable
);
4588 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4590 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4592 L
"Only Physical Presence User could disable secure boot!",
4595 Status
= EFI_UNSUPPORTED
;
4598 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4600 L
"Configuration changed, please reset the platform to take effect!",
4608 case KEY_SECURE_BOOT_KEK_OPTION
:
4609 case KEY_SECURE_BOOT_DB_OPTION
:
4610 case KEY_SECURE_BOOT_DBX_OPTION
:
4611 case KEY_SECURE_BOOT_DBT_OPTION
:
4612 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4614 // Clear Signature GUID.
4616 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4617 if (Private
->SignatureGUID
== NULL
) {
4618 Private
->SignatureGUID
= (EFI_GUID
*)AllocateZeroPool (sizeof (EFI_GUID
));
4619 if (Private
->SignatureGUID
== NULL
) {
4620 return EFI_OUT_OF_RESOURCES
;
4625 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4627 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4629 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4630 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4631 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4632 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4633 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4634 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4636 LabelId
= FORMID_ENROLL_KEK_FORM
;
4640 // Refresh selected file.
4642 CleanUpPage (LabelId
, Private
);
4644 case KEY_SECURE_BOOT_PK_OPTION
:
4645 LabelId
= FORMID_ENROLL_PK_FORM
;
4647 // Refresh selected file.
4649 CleanUpPage (LabelId
, Private
);
4652 case FORMID_ENROLL_PK_FORM
:
4653 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4656 case FORMID_ENROLL_KEK_FORM
:
4657 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4660 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4661 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4664 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4665 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4667 if (Private
->FileContext
->FHandle
!= NULL
) {
4669 // Parse the file's postfix.
4671 NameLength
= StrLen (Private
->FileContext
->FileName
);
4672 if (NameLength
<= 4) {
4676 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4678 if (IsDerEncodeCertificate (FilePostFix
)) {
4680 // Supports DER-encoded X509 certificate.
4682 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4683 } else if (IsAuthentication2Format (Private
->FileContext
->FHandle
)) {
4684 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4686 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4689 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4692 // Clean up Certificate Format if File type is not X509 DER
4694 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4695 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4698 DEBUG ((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4703 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4704 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4707 case KEY_SECURE_BOOT_DELETE_PK
:
4710 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4712 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4713 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4716 if ((Key
.UnicodeChar
== 'y') || (Key
.UnicodeChar
== 'Y')) {
4717 Status
= DeletePlatformKey ();
4718 if (EFI_ERROR (Status
)) {
4720 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4722 L
"Only Physical Presence User could delete PK in custom mode!",
4731 case KEY_DELETE_KEK
:
4734 EFI_KEY_EXCHANGE_KEY_NAME
,
4735 &gEfiGlobalVariableGuid
,
4737 FORMID_DELETE_KEK_FORM
,
4738 OPTION_DEL_KEK_QUESTION_ID
4742 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4745 EFI_IMAGE_SECURITY_DATABASE
,
4746 &gEfiImageSecurityDatabaseGuid
,
4748 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4749 OPTION_DEL_DB_QUESTION_ID
4754 // From DBX option to the level-1 form, display signature list.
4756 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4757 Private
->VariableName
= Variable_DBX
;
4760 LABEL_SIGNATURE_LIST_START
,
4761 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4762 OPTION_SIGNATURE_LIST_QUESTION_ID
4767 // Delete all signature list and reload.
4769 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4771 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4773 L
"Press 'Y' to delete signature list.",
4774 L
"Press other key to cancel and exit.",
4778 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4779 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4784 LABEL_SIGNATURE_LIST_START
,
4785 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4786 OPTION_SIGNATURE_LIST_QUESTION_ID
4791 // Delete one signature list and reload.
4793 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4795 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4797 L
"Press 'Y' to delete signature data.",
4798 L
"Press other key to cancel and exit.",
4802 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4803 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4808 LABEL_SIGNATURE_LIST_START
,
4809 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4810 OPTION_SIGNATURE_LIST_QUESTION_ID
4815 // Delete checked signature data and reload.
4817 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4819 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4821 L
"Press 'Y' to delete signature data.",
4822 L
"Press other key to cancel and exit.",
4826 if ((Key
.UnicodeChar
== L
'Y') || (Key
.UnicodeChar
== L
'y')) {
4827 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4832 LABEL_SIGNATURE_LIST_START
,
4833 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4834 OPTION_SIGNATURE_LIST_QUESTION_ID
4838 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4841 EFI_IMAGE_SECURITY_DATABASE2
,
4842 &gEfiImageSecurityDatabaseGuid
,
4844 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4845 OPTION_DEL_DBT_QUESTION_ID
4850 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4851 Status
= EnrollKeyExchangeKey (Private
);
4852 if (EFI_ERROR (Status
)) {
4854 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4856 L
"ERROR: Unsupported file type!",
4857 L
"Only supports DER-encoded X509 certificate",
4864 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4865 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4866 if (EFI_ERROR (Status
)) {
4868 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4870 L
"ERROR: Unsupported file type!",
4871 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4878 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4879 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4881 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4883 L
"Enrollment failed! Same certificate had already been in the dbx!",
4888 // Cert already exists in DBX. Close opened file before exit.
4890 CloseEnrolledFile (Private
->FileContext
);
4894 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4895 Status
= EnrollX509HashtoSigDB (
4897 IfrNvData
->CertificateFormat
,
4898 &IfrNvData
->RevocationDate
,
4899 &IfrNvData
->RevocationTime
,
4900 IfrNvData
->AlwaysRevocation
4902 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4904 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4907 if (EFI_ERROR (Status
)) {
4909 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4911 L
"ERROR: Unsupported file type!",
4912 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4919 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4920 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4921 if (EFI_ERROR (Status
)) {
4923 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4925 L
"ERROR: Unsupported file type!",
4926 L
"Only supports DER-encoded X509 certificate.",
4932 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4934 // Check the suffix, encode type and the key strength of PK certificate.
4936 Status
= CheckX509Certificate (Private
->FileContext
, &EnrollKeyErrorCode
);
4937 if (EFI_ERROR (Status
)) {
4938 if ((EnrollKeyErrorCode
!= None_Error
) && (EnrollKeyErrorCode
< Enroll_Error_Max
)) {
4940 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4942 mX509EnrollPromptTitle
[EnrollKeyErrorCode
],
4943 mX509EnrollPromptString
[EnrollKeyErrorCode
],
4949 Status
= EnrollPlatformKey (Private
);
4952 if (EFI_ERROR (Status
)) {
4955 sizeof (PromptString
),
4956 L
"Error status: %x.",
4960 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4962 L
"ERROR: Enrollment failed!",
4970 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4971 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4973 DeleteKeyExchangeKey (Private
, QuestionId
);
4974 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4975 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4979 EFI_IMAGE_SECURITY_DATABASE
,
4980 &gEfiImageSecurityDatabaseGuid
,
4982 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4983 OPTION_DEL_DB_QUESTION_ID
,
4984 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4986 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4987 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
4991 LABEL_SIGNATURE_DATA_START
,
4992 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4993 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4994 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4996 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4997 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4998 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
5000 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
5001 IfrNvData
->CheckedDataCount
--;
5002 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
5004 IfrNvData
->CheckedDataCount
++;
5005 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
5007 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
5008 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
)))
5012 EFI_IMAGE_SECURITY_DATABASE2
,
5013 &gEfiImageSecurityDatabaseGuid
,
5015 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
5016 OPTION_DEL_DBT_QUESTION_ID
,
5017 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
5023 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
5024 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
5025 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
5026 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
5027 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
5028 CloseEnrolledFile (Private
->FileContext
);
5030 if (Private
->SignatureGUID
!= NULL
) {
5031 FreePool (Private
->SignatureGUID
);
5032 Private
->SignatureGUID
= NULL
;
5037 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
5038 switch (QuestionId
) {
5039 case KEY_SECURE_BOOT_ENABLE
:
5040 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
5042 case KEY_SECURE_BOOT_MODE
:
5043 mIsEnterSecureBootForm
= FALSE
;
5045 case KEY_SECURE_BOOT_KEK_GUID
:
5046 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
5047 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
5048 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
5049 ASSERT (Private
->SignatureGUID
!= NULL
);
5050 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
5051 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
5052 Status
= EFI_INVALID_PARAMETER
;
5056 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
5058 case KEY_SECURE_BOOT_DELETE_PK
:
5059 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
5060 if ((SetupMode
== NULL
) || ((*SetupMode
) == SETUP_MODE
)) {
5061 IfrNvData
->DeletePk
= TRUE
;
5062 IfrNvData
->HasPk
= FALSE
;
5063 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
5065 IfrNvData
->DeletePk
= FALSE
;
5066 IfrNvData
->HasPk
= TRUE
;
5067 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
5070 if (SetupMode
!= NULL
) {
5071 FreePool (SetupMode
);
5075 case KEY_SECURE_BOOT_RESET_TO_DEFAULT
:
5077 Status
= gBS
->LocateProtocol (&gEfiHiiPopupProtocolGuid
, NULL
, (VOID
**)&HiiPopup
);
5078 if (EFI_ERROR (Status
)) {
5082 Status
= HiiPopup
->CreatePopup (
5084 EfiHiiPopupStyleInfo
,
5085 EfiHiiPopupTypeYesNo
,
5087 STRING_TOKEN (STR_RESET_TO_DEFAULTS_POPUP
),
5090 if (UserSelection
== EfiHiiPopupSelectionYes
) {
5091 Status
= KeyEnrollReset ();
5095 // Update secure boot strings after key reset
5097 if (Status
== EFI_SUCCESS
) {
5098 Status
= UpdateSecureBootString (Private
);
5099 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
5105 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
5106 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
5107 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
5109 IfrNvData
->HideSecureBoot
= TRUE
;
5112 IfrNvData
->HideSecureBoot
= FALSE
;
5115 Value
->b
= IfrNvData
->HideSecureBoot
;
5117 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
5119 // Force the platform back to Standard Mode once user leave the setup screen.
5121 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
5122 if ((NULL
!= SecureBootMode
) && (*SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
)) {
5123 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
5124 SetSecureBootMode (STANDARD_SECURE_BOOT_MODE
);
5127 if (SecureBootMode
!= NULL
) {
5128 FreePool (SecureBootMode
);
5131 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
5133 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
5135 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
5136 IfrNvData
->CheckedDataCount
= 0;
5142 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
5143 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
5144 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*)IfrNvData
, NULL
);
5147 FreePool (IfrNvData
);
5158 This function publish the SecureBoot configuration Form.
5160 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5162 @retval EFI_SUCCESS HII Form is installed successfully.
5163 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
5164 @retval Others Other errors as indicated.
5168 InstallSecureBootConfigForm (
5169 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5173 EFI_HII_HANDLE HiiHandle
;
5174 EFI_HANDLE DriverHandle
;
5175 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5177 DriverHandle
= NULL
;
5178 ConfigAccess
= &PrivateData
->ConfigAccess
;
5179 Status
= gBS
->InstallMultipleProtocolInterfaces (
5181 &gEfiDevicePathProtocolGuid
,
5182 &mSecureBootHiiVendorDevicePath
,
5183 &gEfiHiiConfigAccessProtocolGuid
,
5187 if (EFI_ERROR (Status
)) {
5191 PrivateData
->DriverHandle
= DriverHandle
;
5194 // Publish the HII package list
5196 HiiHandle
= HiiAddPackages (
5197 &gSecureBootConfigFormSetGuid
,
5199 SecureBootConfigDxeStrings
,
5200 SecureBootConfigBin
,
5203 if (HiiHandle
== NULL
) {
5204 gBS
->UninstallMultipleProtocolInterfaces (
5206 &gEfiDevicePathProtocolGuid
,
5207 &mSecureBootHiiVendorDevicePath
,
5208 &gEfiHiiConfigAccessProtocolGuid
,
5212 return EFI_OUT_OF_RESOURCES
;
5215 PrivateData
->HiiHandle
= HiiHandle
;
5217 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
5219 if (PrivateData
->FileContext
== NULL
) {
5220 UninstallSecureBootConfigForm (PrivateData
);
5221 return EFI_OUT_OF_RESOURCES
;
5225 // Init OpCode Handle and Allocate space for creation of Buffer
5227 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
5228 if (mStartOpCodeHandle
== NULL
) {
5229 UninstallSecureBootConfigForm (PrivateData
);
5230 return EFI_OUT_OF_RESOURCES
;
5233 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
5234 if (mEndOpCodeHandle
== NULL
) {
5235 UninstallSecureBootConfigForm (PrivateData
);
5236 return EFI_OUT_OF_RESOURCES
;
5240 // Create Hii Extend Label OpCode as the start opcode
5242 mStartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
5246 sizeof (EFI_IFR_GUID_LABEL
)
5248 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5251 // Create Hii Extend Label OpCode as the end opcode
5253 mEndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
5257 sizeof (EFI_IFR_GUID_LABEL
)
5259 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5260 mEndLabel
->Number
= LABEL_END
;
5266 This function removes SecureBoot configuration Form.
5268 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5272 UninstallSecureBootConfigForm (
5273 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5277 // Uninstall HII package list
5279 if (PrivateData
->HiiHandle
!= NULL
) {
5280 HiiRemovePackages (PrivateData
->HiiHandle
);
5281 PrivateData
->HiiHandle
= NULL
;
5285 // Uninstall HII Config Access Protocol
5287 if (PrivateData
->DriverHandle
!= NULL
) {
5288 gBS
->UninstallMultipleProtocolInterfaces (
5289 PrivateData
->DriverHandle
,
5290 &gEfiDevicePathProtocolGuid
,
5291 &mSecureBootHiiVendorDevicePath
,
5292 &gEfiHiiConfigAccessProtocolGuid
,
5293 &PrivateData
->ConfigAccess
,
5296 PrivateData
->DriverHandle
= NULL
;
5299 if (PrivateData
->SignatureGUID
!= NULL
) {
5300 FreePool (PrivateData
->SignatureGUID
);
5303 if (PrivateData
->FileContext
!= NULL
) {
5304 FreePool (PrivateData
->FileContext
);
5307 FreePool (PrivateData
);
5309 if (mStartOpCodeHandle
!= NULL
) {
5310 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5313 if (mEndOpCodeHandle
!= NULL
) {
5314 HiiFreeOpCodeHandle (mEndOpCodeHandle
);