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 <Library/BaseCryptLib.h>
13 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
15 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
16 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
18 SecureBootExtractConfig
,
19 SecureBootRouteConfig
,
24 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
30 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
31 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
34 SECUREBOOT_CONFIG_FORM_SET_GUID
38 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
40 (UINT8
) (END_DEVICE_PATH_LENGTH
),
41 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
47 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
50 // OID ASN.1 Value for Hash Algorithms
52 UINT8 mHashOidValue
[] = {
53 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
54 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
55 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
56 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
61 HASH_TABLE mHash
[] = {
62 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
63 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
64 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
65 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
69 // Variable Definitions
71 UINT32 mPeCoffHeaderOffset
= 0;
72 WIN_CERTIFICATE
*mCertificate
= NULL
;
73 IMAGE_TYPE mImageType
;
74 UINT8
*mImageBase
= NULL
;
76 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
77 UINTN mImageDigestSize
;
79 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
80 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
83 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
85 CHAR16
* mDerEncodedSuffix
[] = {
91 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
94 // Prompt strings during certificate enrollment.
96 CHAR16
* mX509EnrollPromptTitle
[] = {
98 L
"ERROR: Unsupported file type!",
99 L
"ERROR: Unsupported certificate!",
102 CHAR16
* mX509EnrollPromptString
[] = {
104 L
"Only DER encoded certificate file (*.cer/der/crt) is supported.",
105 L
"Public key length should be equal to or greater than 2048 bits.",
109 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
112 This code cleans up enrolled file by closing file & free related resources attached to
115 @param[in] FileContext FileContext cached in SecureBootConfig driver
120 IN SECUREBOOT_FILE_CONTEXT
*FileContext
123 if (FileContext
->FHandle
!= NULL
) {
124 CloseFile (FileContext
->FHandle
);
125 FileContext
->FHandle
= NULL
;
128 if (FileContext
->FileName
!= NULL
){
129 FreePool(FileContext
->FileName
);
130 FileContext
->FileName
= NULL
;
132 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
137 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
139 @param[in] FileSuffix The suffix of the input certificate file
141 @retval TRUE It's a DER-encoded certificate.
142 @retval FALSE It's NOT a DER-encoded certificate.
146 IsDerEncodeCertificate (
147 IN CONST CHAR16
*FileSuffix
151 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
152 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
160 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
161 The function reads file content but won't open/close given FileHandle.
163 @param[in] FileHandle The FileHandle to be checked
165 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
166 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
170 IsAuthentication2Format (
171 IN EFI_FILE_HANDLE FileHandle
175 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
176 BOOLEAN IsAuth2Format
;
178 IsAuth2Format
= FALSE
;
181 // Read the whole file content
183 Status
= ReadFileContent(
185 (VOID
**) &mImageBase
,
189 if (EFI_ERROR (Status
)) {
193 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
194 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
198 if (CompareGuid(&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
199 IsAuth2Format
= TRUE
;
204 // Do not close File. simply check file content
206 if (mImageBase
!= NULL
) {
207 FreePool (mImageBase
);
211 return IsAuth2Format
;
215 Set Secure Boot option into variable space.
217 @param[in] VarValue The option of Secure Boot.
219 @retval EFI_SUCCESS The operation is finished successfully.
220 @retval Others Other errors as indicated.
224 SaveSecureBootVariable (
230 Status
= gRT
->SetVariable (
231 EFI_SECURE_BOOT_ENABLE_NAME
,
232 &gEfiSecureBootEnableDisableGuid
,
233 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
241 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
242 descriptor with the input data. NO authentication is required in this function.
244 @param[in, out] DataSize On input, the size of Data buffer in bytes.
245 On output, the size of data returned in Data
247 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
248 pointer to NULL to wrap an empty payload.
249 On output, Pointer to the new payload date buffer allocated from pool,
250 it's caller's responsibility to free the memory when finish using it.
252 @retval EFI_SUCCESS Create time based payload successfully.
253 @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.
254 @retval EFI_INVALID_PARAMETER The parameter is invalid.
255 @retval Others Unexpected error happens.
259 CreateTimeBasedPayload (
260 IN OUT UINTN
*DataSize
,
268 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
269 UINTN DescriptorSize
;
272 if (Data
== NULL
|| DataSize
== NULL
) {
273 return EFI_INVALID_PARAMETER
;
277 // In Setup mode or Custom mode, the variable does not need to be signed but the
278 // parameters to the SetVariable() call still need to be prepared as authenticated
279 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
283 PayloadSize
= *DataSize
;
285 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
286 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
287 if (NewData
== NULL
) {
288 return EFI_OUT_OF_RESOURCES
;
291 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
292 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
295 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
297 ZeroMem (&Time
, sizeof (EFI_TIME
));
298 Status
= gRT
->GetTime (&Time
, NULL
);
299 if (EFI_ERROR (Status
)) {
308 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
310 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
311 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
312 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
313 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
315 if (Payload
!= NULL
) {
319 *DataSize
= DescriptorSize
+ PayloadSize
;
325 Internal helper function to delete a Variable given its name and GUID, NO authentication
328 @param[in] VariableName Name of the Variable.
329 @param[in] VendorGuid GUID of the Variable.
331 @retval EFI_SUCCESS Variable deleted successfully.
332 @retval Others The driver failed to start the device.
337 IN CHAR16
*VariableName
,
338 IN EFI_GUID
*VendorGuid
347 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
348 if (Variable
== NULL
) {
355 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
356 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
358 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
359 if (EFI_ERROR (Status
)) {
360 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
364 Status
= gRT
->SetVariable (
379 Set the platform secure boot mode into "Custom" or "Standard" mode.
381 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
382 CUSTOM_SECURE_BOOT_MODE.
384 @return EFI_SUCCESS The platform has switched to the special mode successfully.
385 @return other Fail to operate the secure boot mode.
390 IN UINT8 SecureBootMode
393 return gRT
->SetVariable (
394 EFI_CUSTOM_MODE_NAME
,
395 &gEfiCustomModeEnableGuid
,
396 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
403 This code checks if the encode type and key strength of X.509
404 certificate is qualified.
406 @param[in] X509FileContext FileContext of X.509 certificate storing
408 @param[out] Error Error type checked in the certificate.
410 @return EFI_SUCCESS The certificate checked successfully.
411 @return EFI_INVALID_PARAMETER The parameter is invalid.
412 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
416 CheckX509Certificate (
417 IN SECUREBOOT_FILE_CONTEXT
* X509FileContext
,
418 OUT ENROLL_KEY_ERROR
* Error
429 if (X509FileContext
->FileName
== NULL
) {
430 *Error
= Unsupported_Type
;
431 return EFI_INVALID_PARAMETER
;
440 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
442 NameLength
= StrLen (X509FileContext
->FileName
);
443 if (NameLength
<= 4) {
444 DEBUG ((DEBUG_ERROR
, "Wrong X509 NameLength\n"));
445 *Error
= Unsupported_Type
;
446 return EFI_INVALID_PARAMETER
;
448 FilePostFix
= X509FileContext
->FileName
+ NameLength
- 4;
449 if (!IsDerEncodeCertificate (FilePostFix
)) {
450 DEBUG ((DEBUG_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix
));
451 *Error
= Unsupported_Type
;
452 return EFI_INVALID_PARAMETER
;
454 DEBUG ((DEBUG_INFO
, "FileName= %s\n", X509FileContext
->FileName
));
455 DEBUG ((DEBUG_INFO
, "FilePostFix = %s\n", FilePostFix
));
458 // Read the certificate file content
460 Status
= ReadFileContent (X509FileContext
->FHandle
, (VOID
**) &X509Data
, &X509DataSize
, 0);
461 if (EFI_ERROR (Status
)) {
462 DEBUG ((DEBUG_ERROR
, "Error occured while reading the file.\n"));
467 // Parse the public key context.
469 if (RsaGetPublicKeyFromX509 (X509Data
, X509DataSize
, &X509PubKey
) == FALSE
) {
470 DEBUG ((DEBUG_ERROR
, "Error occured while parsing the pubkey from certificate.\n"));
471 Status
= EFI_INVALID_PARAMETER
;
472 *Error
= Unsupported_Type
;
477 // Parse Module size of public key using interface provided by CryptoPkg, which is
478 // actually the size of public key.
480 if (X509PubKey
!= NULL
) {
481 RsaGetKey (X509PubKey
, RsaKeyN
, NULL
, &PubKeyModSize
);
482 if (PubKeyModSize
< CER_PUBKEY_MIN_SIZE
) {
483 DEBUG ((DEBUG_ERROR
, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
484 Status
= EFI_INVALID_PARAMETER
;
485 *Error
= Unqualified_Key
;
487 RsaFree (X509PubKey
);
491 if (X509Data
!= NULL
) {
499 Generate the PK signature list from the X509 Certificate storing file (.cer)
501 @param[in] X509File FileHandle of X509 Certificate storing file.
502 @param[out] PkCert Point to the data buffer to store the signature list.
504 @return EFI_UNSUPPORTED Unsupported Key Length.
505 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
509 CreatePkX509SignatureList (
510 IN EFI_FILE_HANDLE X509File
,
511 OUT EFI_SIGNATURE_LIST
**PkCert
517 EFI_SIGNATURE_DATA
*PkCertData
;
523 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
524 if (EFI_ERROR (Status
)) {
527 ASSERT (X509Data
!= NULL
);
530 // Allocate space for PK certificate list and initialize it.
531 // Create PK database entry with SignatureHeaderSize equals 0.
533 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
534 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
537 if (*PkCert
== NULL
) {
538 Status
= EFI_OUT_OF_RESOURCES
;
542 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
543 + sizeof(EFI_SIGNATURE_DATA
) - 1
545 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
546 (*PkCert
)->SignatureHeaderSize
= 0;
547 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
548 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
549 + sizeof(EFI_SIGNATURE_LIST
)
550 + (*PkCert
)->SignatureHeaderSize
);
551 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
553 // Fill the PK database with PKpub data from X509 certificate file.
555 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
559 if (X509Data
!= NULL
) {
563 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
572 Enroll new PK into the System without original PK's authentication.
574 The SignatureOwner GUID will be the same with PK's vendorguid.
576 @param[in] PrivateData The module's private data.
578 @retval EFI_SUCCESS New PK enrolled successfully.
579 @retval EFI_INVALID_PARAMETER The parameter is invalid.
580 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
585 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
591 EFI_SIGNATURE_LIST
*PkCert
;
595 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
596 if (EFI_ERROR (Status
)) {
601 // Prase the selected PK file and generate PK certificate list.
603 Status
= CreatePkX509SignatureList (
604 Private
->FileContext
->FHandle
,
607 if (EFI_ERROR (Status
)) {
610 ASSERT (PkCert
!= NULL
);
613 // Set Platform Key variable.
615 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
616 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
617 DataSize
= PkCert
->SignatureListSize
;
618 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
619 if (EFI_ERROR (Status
)) {
620 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
624 Status
= gRT
->SetVariable(
625 EFI_PLATFORM_KEY_NAME
,
626 &gEfiGlobalVariableGuid
,
631 if (EFI_ERROR (Status
)) {
632 if (Status
== EFI_OUT_OF_RESOURCES
) {
633 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
640 if (PkCert
!= NULL
) {
644 CloseEnrolledFile(Private
->FileContext
);
650 Remove the PK variable.
652 @retval EFI_SUCCESS Delete PK successfully.
653 @retval Others Could not allow to delete PK.
663 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
664 if (EFI_ERROR (Status
)) {
668 Status
= DeleteVariable (
669 EFI_PLATFORM_KEY_NAME
,
670 &gEfiGlobalVariableGuid
676 Enroll a new KEK item from public key storing file (*.pbk).
678 @param[in] PrivateData The module's private data.
680 @retval EFI_SUCCESS New KEK enrolled successfully.
681 @retval EFI_INVALID_PARAMETER The parameter is invalid.
682 @retval EFI_UNSUPPORTED Unsupported command.
683 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
688 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
694 EFI_SIGNATURE_LIST
*KekSigList
;
697 CPL_KEY_INFO
*KeyInfo
;
698 EFI_SIGNATURE_DATA
*KEKSigData
;
699 UINTN KekSigListSize
;
714 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
715 // First, We have to parse out public key data from the pbk key file.
717 Status
= ReadFileContent (
718 Private
->FileContext
->FHandle
,
723 if (EFI_ERROR (Status
)) {
726 ASSERT (KeyBlob
!= NULL
);
727 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
728 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
729 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
730 Status
= EFI_UNSUPPORTED
;
735 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
737 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
738 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
739 if (KeyBuffer
== NULL
) {
740 Status
= EFI_OUT_OF_RESOURCES
;
744 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
745 KeyLenInBytes
/ sizeof (UINTN
),
749 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
752 // Form an new EFI_SIGNATURE_LIST.
754 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
755 + sizeof(EFI_SIGNATURE_DATA
) - 1
756 + WIN_CERT_UEFI_RSA2048_SIZE
;
758 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
759 if (KekSigList
== NULL
) {
760 Status
= EFI_OUT_OF_RESOURCES
;
764 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
765 + sizeof(EFI_SIGNATURE_DATA
) - 1
766 + WIN_CERT_UEFI_RSA2048_SIZE
;
767 KekSigList
->SignatureHeaderSize
= 0;
768 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
769 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
771 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
772 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
774 KEKSigData
->SignatureData
,
775 KeyBlob
+ sizeof(CPL_KEY_INFO
),
776 WIN_CERT_UEFI_RSA2048_SIZE
780 // Check if KEK entry has been already existed.
781 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
782 // new KEK to original variable.
784 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
785 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
786 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
787 if (EFI_ERROR (Status
)) {
788 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
792 Status
= gRT
->GetVariable(
793 EFI_KEY_EXCHANGE_KEY_NAME
,
794 &gEfiGlobalVariableGuid
,
799 if (Status
== EFI_BUFFER_TOO_SMALL
) {
800 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
801 } else if (Status
!= EFI_NOT_FOUND
) {
806 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
808 Status
= gRT
->SetVariable(
809 EFI_KEY_EXCHANGE_KEY_NAME
,
810 &gEfiGlobalVariableGuid
,
815 if (EFI_ERROR (Status
)) {
821 CloseEnrolledFile(Private
->FileContext
);
823 if (Private
->SignatureGUID
!= NULL
) {
824 FreePool (Private
->SignatureGUID
);
825 Private
->SignatureGUID
= NULL
;
828 if (KeyBlob
!= NULL
) {
831 if (KeyBuffer
!= NULL
) {
832 FreePool (KeyBuffer
);
834 if (KekSigList
!= NULL
) {
835 FreePool (KekSigList
);
842 Enroll a new KEK item from X509 certificate file.
844 @param[in] PrivateData The module's private data.
846 @retval EFI_SUCCESS New X509 is enrolled successfully.
847 @retval EFI_INVALID_PARAMETER The parameter is invalid.
848 @retval EFI_UNSUPPORTED Unsupported command.
849 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
854 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
860 EFI_SIGNATURE_DATA
*KEKSigData
;
861 EFI_SIGNATURE_LIST
*KekSigList
;
863 UINTN KekSigListSize
;
873 Status
= ReadFileContent (
874 Private
->FileContext
->FHandle
,
879 if (EFI_ERROR (Status
)) {
882 ASSERT (X509Data
!= NULL
);
884 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
885 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
886 if (KekSigList
== NULL
) {
887 Status
= EFI_OUT_OF_RESOURCES
;
892 // Fill Certificate Database parameters.
894 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
895 KekSigList
->SignatureHeaderSize
= 0;
896 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
897 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
899 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
900 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
901 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
904 // Check if KEK been already existed.
905 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
906 // new kek to original variable
908 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
909 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
910 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
911 if (EFI_ERROR (Status
)) {
912 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
916 Status
= gRT
->GetVariable(
917 EFI_KEY_EXCHANGE_KEY_NAME
,
918 &gEfiGlobalVariableGuid
,
923 if (Status
== EFI_BUFFER_TOO_SMALL
) {
924 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
925 } else if (Status
!= EFI_NOT_FOUND
) {
929 Status
= gRT
->SetVariable(
930 EFI_KEY_EXCHANGE_KEY_NAME
,
931 &gEfiGlobalVariableGuid
,
936 if (EFI_ERROR (Status
)) {
942 CloseEnrolledFile(Private
->FileContext
);
944 if (Private
->SignatureGUID
!= NULL
) {
945 FreePool (Private
->SignatureGUID
);
946 Private
->SignatureGUID
= NULL
;
949 if (KekSigList
!= NULL
) {
950 FreePool (KekSigList
);
957 Enroll new KEK into the System without PK's authentication.
958 The SignatureOwner GUID will be Private->SignatureGUID.
960 @param[in] PrivateData The module's private data.
962 @retval EFI_SUCCESS New KEK enrolled successful.
963 @retval EFI_INVALID_PARAMETER The parameter is invalid.
964 @retval others Fail to enroll KEK data.
968 EnrollKeyExchangeKey (
969 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
976 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
977 return EFI_INVALID_PARAMETER
;
980 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
981 if (EFI_ERROR (Status
)) {
986 // Parse the file's postfix. Supports DER-encoded X509 certificate,
987 // and .pbk as RSA public key file.
989 NameLength
= StrLen (Private
->FileContext
->FileName
);
990 if (NameLength
<= 4) {
991 return EFI_INVALID_PARAMETER
;
993 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
994 if (IsDerEncodeCertificate(FilePostFix
)) {
995 return EnrollX509ToKek (Private
);
996 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
997 return EnrollRsa2048ToKek (Private
);
1000 // File type is wrong, simply close it
1002 CloseEnrolledFile(Private
->FileContext
);
1004 return EFI_INVALID_PARAMETER
;
1009 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
1010 KEK's authentication.
1012 @param[in] PrivateData The module's private data.
1013 @param[in] VariableName Variable name of signature database, must be
1014 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1016 @retval EFI_SUCCESS New X509 is enrolled successfully.
1017 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1022 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1023 IN CHAR16
*VariableName
1029 EFI_SIGNATURE_LIST
*SigDBCert
;
1030 EFI_SIGNATURE_DATA
*SigDBCertData
;
1041 SigDBCertData
= NULL
;
1044 Status
= ReadFileContent (
1045 Private
->FileContext
->FHandle
,
1050 if (EFI_ERROR (Status
)) {
1053 ASSERT (X509Data
!= NULL
);
1055 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
1057 Data
= AllocateZeroPool (SigDBSize
);
1059 Status
= EFI_OUT_OF_RESOURCES
;
1064 // Fill Certificate Database parameters.
1066 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1067 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1068 SigDBCert
->SignatureHeaderSize
= 0;
1069 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
1070 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
1072 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
1073 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1074 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
1077 // Check if signature database entry has been already existed.
1078 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1079 // new signature data to original variable
1081 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1082 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1083 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
1084 if (EFI_ERROR (Status
)) {
1085 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1089 Status
= gRT
->GetVariable(
1091 &gEfiImageSecurityDatabaseGuid
,
1096 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1097 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1098 } else if (Status
!= EFI_NOT_FOUND
) {
1102 Status
= gRT
->SetVariable(
1104 &gEfiImageSecurityDatabaseGuid
,
1109 if (EFI_ERROR (Status
)) {
1115 CloseEnrolledFile(Private
->FileContext
);
1117 if (Private
->SignatureGUID
!= NULL
) {
1118 FreePool (Private
->SignatureGUID
);
1119 Private
->SignatureGUID
= NULL
;
1126 if (X509Data
!= NULL
) {
1127 FreePool (X509Data
);
1134 Check whether signature is in specified database.
1136 @param[in] VariableName Name of database variable that is searched in.
1137 @param[in] Signature Pointer to signature that is searched for.
1138 @param[in] SignatureSize Size of Signature.
1140 @return TRUE Found the signature in the variable database.
1141 @return FALSE Not found the signature in the variable database.
1145 IsSignatureFoundInDatabase (
1146 IN CHAR16
*VariableName
,
1147 IN UINT8
*Signature
,
1148 IN UINTN SignatureSize
1152 EFI_SIGNATURE_LIST
*CertList
;
1153 EFI_SIGNATURE_DATA
*Cert
;
1161 // Read signature database variable.
1166 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1167 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1171 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1176 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1177 if (EFI_ERROR (Status
)) {
1182 // Enumerate all signature data in SigDB to check if signature exists for executable.
1184 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1185 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1186 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1187 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1188 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1189 for (Index
= 0; Index
< CertCount
; Index
++) {
1190 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1192 // Find the signature in database.
1197 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1205 DataSize
-= CertList
->SignatureListSize
;
1206 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1218 Calculate the hash of a certificate data with the specified hash algorithm.
1220 @param[in] CertData The certificate data to be hashed.
1221 @param[in] CertSize The certificate size in bytes.
1222 @param[in] HashAlg The specified hash algorithm.
1223 @param[out] CertHash The output digest of the certificate
1225 @retval TRUE Successfully got the hash of the CertData.
1226 @retval FALSE Failed to get the hash of CertData.
1246 if (HashAlg
>= HASHALG_MAX
) {
1251 // Retrieve the TBSCertificate for Hash Calculation.
1253 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1258 // 1. Initialize context of hash.
1260 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1261 HashCtx
= AllocatePool (CtxSize
);
1262 ASSERT (HashCtx
!= NULL
);
1265 // 2. Initialize a hash context.
1267 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1273 // 3. Calculate the hash.
1275 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1281 // 4. Get the hash result.
1283 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1284 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1287 if (HashCtx
!= NULL
) {
1295 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1297 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1298 @param[in] CertSize Size of X.509 Certificate.
1300 @return TRUE Found the certificate hash in the forbidden database.
1301 @return FALSE Certificate hash is Not found in the forbidden database.
1305 IsCertHashFoundInDbx (
1306 IN UINT8
*Certificate
,
1312 EFI_SIGNATURE_LIST
*DbxList
;
1313 EFI_SIGNATURE_DATA
*CertHash
;
1314 UINTN CertHashCount
;
1317 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1319 UINTN SiglistHeaderSize
;
1324 HashAlg
= HASHALG_MAX
;
1328 // Read signature database variable.
1331 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1332 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1336 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1341 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1342 if (EFI_ERROR (Status
)) {
1347 // Check whether the certificate hash exists in the forbidden database.
1349 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1350 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1352 // Determine Hash Algorithm of Certificate in the forbidden database.
1354 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1355 HashAlg
= HASHALG_SHA256
;
1356 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1357 HashAlg
= HASHALG_SHA384
;
1358 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1359 HashAlg
= HASHALG_SHA512
;
1361 DataSize
-= DbxList
->SignatureListSize
;
1362 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1367 // Calculate the hash value of current db certificate for comparision.
1369 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1373 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1374 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1375 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1376 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1378 // Iterate each Signature Data Node within this CertList for verify.
1380 DbxCertHash
= CertHash
->SignatureData
;
1381 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1383 // Hash of Certificate is found in forbidden database.
1388 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1391 DataSize
-= DbxList
->SignatureListSize
;
1392 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1404 Check whether the signature list exists in given variable data.
1406 It searches the signature list for the certificate hash by CertType.
1407 If the signature list is found, get the offset of Database for the
1408 next hash of a certificate.
1410 @param[in] Database Variable data to save signature list.
1411 @param[in] DatabaseSize Variable size.
1412 @param[in] SignatureType The type of the signature.
1413 @param[out] Offset The offset to save a new hash of certificate.
1415 @return TRUE The signature list is found in the forbidden database.
1416 @return FALSE The signature list is not found in the forbidden database.
1419 GetSignaturelistOffset (
1420 IN EFI_SIGNATURE_LIST
*Database
,
1421 IN UINTN DatabaseSize
,
1422 IN EFI_GUID
*SignatureType
,
1426 EFI_SIGNATURE_LIST
*SigList
;
1429 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1435 SiglistSize
= DatabaseSize
;
1436 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1437 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1438 *Offset
= DatabaseSize
- SiglistSize
;
1441 SiglistSize
-= SigList
->SignatureListSize
;
1442 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1449 Enroll a new X509 certificate hash into Signature Database (dbx) without
1450 KEK's authentication.
1452 @param[in] PrivateData The module's private data.
1453 @param[in] HashAlg The hash algorithm to enroll the certificate.
1454 @param[in] RevocationDate The revocation date of the certificate.
1455 @param[in] RevocationTime The revocation time of the certificate.
1456 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1458 @retval EFI_SUCCESS New X509 is enrolled successfully.
1459 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1460 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1464 EnrollX509HashtoSigDB (
1465 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1467 IN EFI_HII_DATE
*RevocationDate
,
1468 IN EFI_HII_TIME
*RevocationTime
,
1469 IN BOOLEAN AlwaysRevocation
1475 EFI_SIGNATURE_LIST
*SignatureList
;
1476 UINTN SignatureListSize
;
1482 EFI_SIGNATURE_DATA
*SignatureData
;
1483 UINTN SignatureSize
;
1484 EFI_GUID SignatureType
;
1486 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1487 UINT16
* FilePostFix
;
1494 SignatureData
= NULL
;
1495 SignatureList
= NULL
;
1499 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1500 return EFI_INVALID_PARAMETER
;
1503 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1504 if (EFI_ERROR (Status
)) {
1509 // Parse the file's postfix.
1511 NameLength
= StrLen (Private
->FileContext
->FileName
);
1512 if (NameLength
<= 4) {
1513 return EFI_INVALID_PARAMETER
;
1515 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1516 if (!IsDerEncodeCertificate(FilePostFix
)) {
1518 // Only supports DER-encoded X509 certificate.
1520 return EFI_INVALID_PARAMETER
;
1524 // Get the certificate from file and calculate its hash.
1526 Status
= ReadFileContent (
1527 Private
->FileContext
->FHandle
,
1532 if (EFI_ERROR (Status
)) {
1535 ASSERT (X509Data
!= NULL
);
1537 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1542 // Get the variable for enrollment.
1545 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1546 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1547 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1549 return EFI_OUT_OF_RESOURCES
;
1552 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1553 if (EFI_ERROR (Status
)) {
1559 // Allocate memory for Signature and fill the Signature
1561 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1562 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1563 if (SignatureData
== NULL
) {
1564 return EFI_OUT_OF_RESOURCES
;
1566 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1567 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1572 if (!AlwaysRevocation
) {
1573 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1574 Time
->Year
= RevocationDate
->Year
;
1575 Time
->Month
= RevocationDate
->Month
;
1576 Time
->Day
= RevocationDate
->Day
;
1577 Time
->Hour
= RevocationTime
->Hour
;
1578 Time
->Minute
= RevocationTime
->Minute
;
1579 Time
->Second
= RevocationTime
->Second
;
1583 // Determine the GUID for certificate hash.
1586 case HASHALG_SHA256
:
1587 SignatureType
= gEfiCertX509Sha256Guid
;
1589 case HASHALG_SHA384
:
1590 SignatureType
= gEfiCertX509Sha384Guid
;
1592 case HASHALG_SHA512
:
1593 SignatureType
= gEfiCertX509Sha512Guid
;
1600 // Add signature into the new variable data buffer
1602 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1604 // Add the signature to the found signaturelist.
1606 DbSize
= DataSize
+ SignatureSize
;
1607 NewData
= AllocateZeroPool (DbSize
);
1608 if (NewData
== NULL
) {
1609 Status
= EFI_OUT_OF_RESOURCES
;
1613 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1614 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1615 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1617 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1618 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1620 Offset
+= SignatureListSize
;
1621 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1622 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1629 // Create a new signaturelist, and add the signature into the signaturelist.
1631 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1632 NewData
= AllocateZeroPool (DbSize
);
1633 if (NewData
== NULL
) {
1634 Status
= EFI_OUT_OF_RESOURCES
;
1638 // Fill Certificate Database parameters.
1640 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1641 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1642 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1643 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1644 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1645 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1646 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1647 CopyMem (NewData
, Data
, DataSize
);
1654 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1655 if (EFI_ERROR (Status
)) {
1659 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1660 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1661 Status
= gRT
->SetVariable(
1662 EFI_IMAGE_SECURITY_DATABASE1
,
1663 &gEfiImageSecurityDatabaseGuid
,
1668 if (EFI_ERROR (Status
)) {
1674 CloseEnrolledFile(Private
->FileContext
);
1676 if (Private
->SignatureGUID
!= NULL
) {
1677 FreePool (Private
->SignatureGUID
);
1678 Private
->SignatureGUID
= NULL
;
1685 if (SignatureData
!= NULL
) {
1686 FreePool (SignatureData
);
1689 if (X509Data
!= NULL
) {
1690 FreePool (X509Data
);
1697 Check whether a certificate from a file exists in dbx.
1699 @param[in] PrivateData The module's private data.
1700 @param[in] VariableName Variable name of signature database, must be
1701 EFI_IMAGE_SECURITY_DATABASE1.
1703 @retval TRUE The X509 certificate is found in dbx successfully.
1704 @retval FALSE The X509 certificate is not found in dbx.
1708 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1709 IN CHAR16
*VariableName
1718 // Read the certificate from file
1722 Status
= ReadFileContent (
1723 Private
->FileContext
->FHandle
,
1728 if (EFI_ERROR (Status
)) {
1733 // Check the raw certificate.
1736 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1742 // Check the hash of certificate.
1744 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1750 if (X509Data
!= NULL
) {
1751 FreePool (X509Data
);
1758 Reads contents of a PE/COFF image in memory buffer.
1760 Caution: This function may receive untrusted input.
1761 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1762 read is within the image buffer.
1764 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1765 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1766 @param ReadSize On input, the size in bytes of the requested read operation.
1767 On output, the number of bytes actually read.
1768 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1770 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1774 SecureBootConfigImageRead (
1775 IN VOID
*FileHandle
,
1776 IN UINTN FileOffset
,
1777 IN OUT UINTN
*ReadSize
,
1783 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1784 return EFI_INVALID_PARAMETER
;
1787 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1788 return EFI_INVALID_PARAMETER
;
1791 EndPosition
= FileOffset
+ *ReadSize
;
1792 if (EndPosition
> mImageSize
) {
1793 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1796 if (FileOffset
>= mImageSize
) {
1800 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1806 Load PE/COFF image information into internal buffer and check its validity.
1808 @retval EFI_SUCCESS Successful
1809 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1810 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1818 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1819 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1820 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1821 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1827 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1828 ImageContext
.Handle
= (VOID
*) mImageBase
;
1829 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1832 // Get information about the image being loaded
1834 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1835 if (EFI_ERROR (Status
)) {
1837 // The information can't be got from the invalid PeImage
1839 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1844 // Read the Dos header
1846 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1847 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1850 // DOS image header is present,
1851 // So read the PE header after the DOS image header
1853 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1857 mPeCoffHeaderOffset
= 0;
1861 // Read PE header and check the signature validity and machine compatibility
1863 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1864 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1866 return EFI_UNSUPPORTED
;
1869 mNtHeader
.Pe32
= NtHeader32
;
1872 // Check the architecture field of PE header and get the Certificate Data Directory data
1873 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1875 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1876 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1877 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1879 // 32-bits Architecture
1881 mImageType
= ImageType_IA32
;
1882 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1884 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1885 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1886 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1888 // 64-bits Architecture
1890 mImageType
= ImageType_X64
;
1891 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1892 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1894 return EFI_UNSUPPORTED
;
1901 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1902 PE/COFF Specification 8.0 Appendix A
1904 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1905 the function LoadPeImage ().
1907 @param[in] HashAlg Hash algorithm type.
1909 @retval TRUE Successfully hash image.
1910 @retval FALSE Fail in hash image.
1919 EFI_IMAGE_SECTION_HEADER
*Section
;
1924 UINTN SumOfBytesHashed
;
1925 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1930 SectionHeader
= NULL
;
1933 if (HashAlg
!= HASHALG_SHA256
) {
1938 // Initialize context of hash.
1940 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1942 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1943 mCertType
= gEfiCertSha256Guid
;
1945 CtxSize
= mHash
[HashAlg
].GetContextSize();
1947 HashCtx
= AllocatePool (CtxSize
);
1948 ASSERT (HashCtx
!= NULL
);
1950 // 1. Load the image header into memory.
1952 // 2. Initialize a SHA hash context.
1953 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1958 // Measuring PE/COFF Image Header;
1959 // But CheckSum field and SECURITY data directory (certificate) are excluded
1963 // 3. Calculate the distance from the base of the image header to the image checksum address.
1964 // 4. Hash the image header from its base to beginning of the image checksum.
1966 HashBase
= mImageBase
;
1967 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1971 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1974 // Use PE32+ offset.
1976 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1979 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1984 // 5. Skip over the image checksum (it occupies a single ULONG).
1985 // 6. Get the address of the beginning of the Cert Directory.
1986 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1988 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1992 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1993 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1996 // Use PE32+ offset.
1998 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1999 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
2002 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2007 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
2008 // 9. Hash everything from the end of the Cert Directory to the end of image header.
2010 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2014 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
2015 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
2018 // Use PE32+ offset.
2020 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
2021 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
2024 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2029 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
2031 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2035 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
2040 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
2044 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
2045 // structures in the image. The 'NumberOfSections' field of the image
2046 // header indicates how big the table should be. Do not include any
2047 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
2049 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
2050 ASSERT (SectionHeader
!= NULL
);
2052 // 12. Using the 'PointerToRawData' in the referenced section headers as
2053 // a key, arrange the elements in the table in ascending order. In other
2054 // words, sort the section headers according to the disk-file offset of
2057 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
2059 mPeCoffHeaderOffset
+
2061 sizeof (EFI_IMAGE_FILE_HEADER
) +
2062 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
2064 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
2066 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
2067 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
2070 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
2075 // 13. Walk through the sorted table, bring the corresponding section
2076 // into memory, and hash the entire section (using the 'SizeOfRawData'
2077 // field in the section header to determine the amount of data to hash).
2078 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2079 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
2081 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
2082 Section
= &SectionHeader
[Index
];
2083 if (Section
->SizeOfRawData
== 0) {
2086 HashBase
= mImageBase
+ Section
->PointerToRawData
;
2087 HashSize
= (UINTN
) Section
->SizeOfRawData
;
2089 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2094 SumOfBytesHashed
+= HashSize
;
2098 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2099 // data in the file that needs to be added to the hash. This data begins
2100 // at file offset SUM_OF_BYTES_HASHED and its length is:
2101 // FileSize - (CertDirectory->Size)
2103 if (mImageSize
> SumOfBytesHashed
) {
2104 HashBase
= mImageBase
+ SumOfBytesHashed
;
2105 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2111 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2115 // Use PE32+ offset.
2119 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2123 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2129 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2132 if (HashCtx
!= NULL
) {
2135 if (SectionHeader
!= NULL
) {
2136 FreePool (SectionHeader
);
2142 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2143 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2146 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2147 @retval EFI_SUCCESS Hash successfully.
2156 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2158 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2160 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2162 // Check the Hash algorithm in PE/COFF Authenticode.
2163 // According to PKCS#7 Definition:
2164 // SignedData ::= SEQUENCE {
2166 // digestAlgorithms DigestAlgorithmIdentifiers,
2167 // contentInfo ContentInfo,
2169 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2170 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2171 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2173 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2175 // Only support two bytes of Long Form of Length Encoding.
2181 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2186 if (Index
== HASHALG_MAX
) {
2187 return EFI_UNSUPPORTED
;
2191 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2193 if (!HashPeImage(Index
)) {
2194 return EFI_UNSUPPORTED
;
2201 Enroll a new signature of executable into Signature Database.
2203 @param[in] PrivateData The module's private data.
2204 @param[in] VariableName Variable name of signature database, must be
2205 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2206 or EFI_IMAGE_SECURITY_DATABASE2.
2208 @retval EFI_SUCCESS New signature is enrolled successfully.
2209 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2210 @retval EFI_UNSUPPORTED Unsupported command.
2211 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2215 EnrollAuthentication2Descriptor (
2216 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2217 IN CHAR16
*VariableName
2228 // DBT only support DER-X509 Cert Enrollment
2230 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2231 return EFI_UNSUPPORTED
;
2235 // Read the whole file content
2237 Status
= ReadFileContent(
2238 Private
->FileContext
->FHandle
,
2239 (VOID
**) &mImageBase
,
2243 if (EFI_ERROR (Status
)) {
2246 ASSERT (mImageBase
!= NULL
);
2248 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2249 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2252 // Check if SigDB variable has been already existed.
2253 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2254 // new signature data to original variable
2257 Status
= gRT
->GetVariable(
2259 &gEfiImageSecurityDatabaseGuid
,
2264 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2265 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2266 } else if (Status
!= EFI_NOT_FOUND
) {
2271 // Directly set AUTHENTICATION_2 data to SetVariable
2273 Status
= gRT
->SetVariable(
2275 &gEfiImageSecurityDatabaseGuid
,
2281 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2285 CloseEnrolledFile(Private
->FileContext
);
2291 if (mImageBase
!= NULL
) {
2292 FreePool (mImageBase
);
2302 Enroll a new signature of executable into Signature Database.
2304 @param[in] PrivateData The module's private data.
2305 @param[in] VariableName Variable name of signature database, must be
2306 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2307 or EFI_IMAGE_SECURITY_DATABASE2.
2309 @retval EFI_SUCCESS New signature is enrolled successfully.
2310 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2311 @retval EFI_UNSUPPORTED Unsupported command.
2312 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2316 EnrollImageSignatureToSigDB (
2317 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2318 IN CHAR16
*VariableName
2322 EFI_SIGNATURE_LIST
*SigDBCert
;
2323 EFI_SIGNATURE_DATA
*SigDBCertData
;
2328 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2331 GuidCertData
= NULL
;
2333 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2334 return EFI_UNSUPPORTED
;
2338 // Form the SigDB certificate list.
2339 // Format the data item into EFI_SIGNATURE_LIST type.
2341 // We need to parse signature data of executable from specified signed executable file.
2342 // In current implementation, we simply trust the pass-in signed executable file.
2343 // In reality, it's OS's responsibility to verify the signed executable file.
2347 // Read the whole file content
2349 Status
= ReadFileContent(
2350 Private
->FileContext
->FHandle
,
2351 (VOID
**) &mImageBase
,
2355 if (EFI_ERROR (Status
)) {
2358 ASSERT (mImageBase
!= NULL
);
2360 Status
= LoadPeImage ();
2361 if (EFI_ERROR (Status
)) {
2365 if (mSecDataDir
->SizeOfCert
== 0) {
2366 if (!HashPeImage (HASHALG_SHA256
)) {
2367 Status
= EFI_SECURITY_VIOLATION
;
2373 // Read the certificate data
2375 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2377 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2378 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2379 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2380 Status
= EFI_ABORTED
;
2384 if (!HashPeImage (HASHALG_SHA256
)) {
2385 Status
= EFI_ABORTED
;
2389 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2391 Status
= HashPeImageByType ();
2392 if (EFI_ERROR (Status
)) {
2396 Status
= EFI_ABORTED
;
2402 // Create a new SigDB entry.
2404 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2405 + sizeof(EFI_SIGNATURE_DATA
) - 1
2406 + (UINT32
) mImageDigestSize
;
2408 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2410 Status
= EFI_OUT_OF_RESOURCES
;
2415 // Adjust the Certificate Database parameters.
2417 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2418 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2419 SigDBCert
->SignatureHeaderSize
= 0;
2420 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2421 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2423 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2424 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2425 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2427 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2428 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2429 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2430 if (EFI_ERROR (Status
)) {
2431 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2436 // Check if SigDB variable has been already existed.
2437 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2438 // new signature data to original variable
2441 Status
= gRT
->GetVariable(
2443 &gEfiImageSecurityDatabaseGuid
,
2448 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2449 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2450 } else if (Status
!= EFI_NOT_FOUND
) {
2455 // Enroll the variable.
2457 Status
= gRT
->SetVariable(
2459 &gEfiImageSecurityDatabaseGuid
,
2464 if (EFI_ERROR (Status
)) {
2470 CloseEnrolledFile(Private
->FileContext
);
2472 if (Private
->SignatureGUID
!= NULL
) {
2473 FreePool (Private
->SignatureGUID
);
2474 Private
->SignatureGUID
= NULL
;
2481 if (mImageBase
!= NULL
) {
2482 FreePool (mImageBase
);
2490 Enroll signature into DB/DBX/DBT without KEK's authentication.
2491 The SignatureOwner GUID will be Private->SignatureGUID.
2493 @param[in] PrivateData The module's private data.
2494 @param[in] VariableName Variable name of signature database, must be
2495 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2497 @retval EFI_SUCCESS New signature enrolled successfully.
2498 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2499 @retval others Fail to enroll signature data.
2503 EnrollSignatureDatabase (
2504 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2505 IN CHAR16
*VariableName
2508 UINT16
* FilePostFix
;
2512 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2513 return EFI_INVALID_PARAMETER
;
2516 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2517 if (EFI_ERROR (Status
)) {
2522 // Parse the file's postfix.
2524 NameLength
= StrLen (Private
->FileContext
->FileName
);
2525 if (NameLength
<= 4) {
2526 return EFI_INVALID_PARAMETER
;
2528 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2529 if (IsDerEncodeCertificate (FilePostFix
)) {
2531 // Supports DER-encoded X509 certificate.
2533 return EnrollX509toSigDB (Private
, VariableName
);
2534 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2535 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2537 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2542 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2543 by GUID in the page for user to select and delete as needed.
2545 @param[in] PrivateData Module's private data.
2546 @param[in] VariableName The variable name of the vendor's signature database.
2547 @param[in] VendorGuid A unique identifier for the vendor.
2548 @param[in] LabelNumber Label number to insert opcodes.
2549 @param[in] FormId Form ID of current page.
2550 @param[in] QuestionIdBase Base question id of the signature list.
2552 @retval EFI_SUCCESS Success to update the signature list page
2553 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2558 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2559 IN CHAR16
*VariableName
,
2560 IN EFI_GUID
*VendorGuid
,
2561 IN UINT16 LabelNumber
,
2562 IN EFI_FORM_ID FormId
,
2563 IN EFI_QUESTION_ID QuestionIdBase
2570 VOID
*StartOpCodeHandle
;
2571 VOID
*EndOpCodeHandle
;
2572 EFI_IFR_GUID_LABEL
*StartLabel
;
2573 EFI_IFR_GUID_LABEL
*EndLabel
;
2576 EFI_SIGNATURE_LIST
*CertList
;
2577 EFI_SIGNATURE_DATA
*Cert
;
2578 UINT32 ItemDataSize
;
2580 EFI_STRING_ID GuidID
;
2587 StartOpCodeHandle
= NULL
;
2588 EndOpCodeHandle
= NULL
;
2591 // Initialize the container for dynamic opcodes.
2593 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2594 if (StartOpCodeHandle
== NULL
) {
2595 Status
= EFI_OUT_OF_RESOURCES
;
2599 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2600 if (EndOpCodeHandle
== NULL
) {
2601 Status
= EFI_OUT_OF_RESOURCES
;
2606 // Create Hii Extend Label OpCode.
2608 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2612 sizeof (EFI_IFR_GUID_LABEL
)
2614 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2615 StartLabel
->Number
= LabelNumber
;
2617 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2621 sizeof (EFI_IFR_GUID_LABEL
)
2623 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2624 EndLabel
->Number
= LABEL_END
;
2630 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2631 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2635 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2637 Status
= EFI_OUT_OF_RESOURCES
;
2641 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2642 if (EFI_ERROR (Status
)) {
2646 GuidStr
= AllocateZeroPool (100);
2647 if (GuidStr
== NULL
) {
2648 Status
= EFI_OUT_OF_RESOURCES
;
2653 // Enumerate all KEK pub data.
2655 ItemDataSize
= (UINT32
) DataSize
;
2656 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2659 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2661 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2662 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2663 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2664 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2665 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2666 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2667 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2668 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2669 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2670 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2671 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2672 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2673 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2674 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2677 // The signature type is not supported in current implementation.
2679 ItemDataSize
-= CertList
->SignatureListSize
;
2680 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2684 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2685 for (Index
= 0; Index
< CertCount
; Index
++) {
2686 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2687 + sizeof (EFI_SIGNATURE_LIST
)
2688 + CertList
->SignatureHeaderSize
2689 + Index
* CertList
->SignatureSize
);
2691 // Display GUID and help
2693 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2694 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2695 HiiCreateCheckBoxOpCode (
2697 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2702 EFI_IFR_FLAG_CALLBACK
,
2708 ItemDataSize
-= CertList
->SignatureListSize
;
2709 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2714 PrivateData
->HiiHandle
,
2715 &gSecureBootConfigFormSetGuid
,
2721 if (StartOpCodeHandle
!= NULL
) {
2722 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2725 if (EndOpCodeHandle
!= NULL
) {
2726 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2733 if (GuidStr
!= NULL
) {
2741 Delete a KEK entry from KEK database.
2743 @param[in] PrivateData Module's private data.
2744 @param[in] QuestionId Question id of the KEK item to delete.
2746 @retval EFI_SUCCESS Delete kek item successfully.
2747 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2751 DeleteKeyExchangeKey (
2752 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2753 IN EFI_QUESTION_ID QuestionId
2762 EFI_SIGNATURE_LIST
*CertList
;
2763 EFI_SIGNATURE_LIST
*NewCertList
;
2764 EFI_SIGNATURE_DATA
*Cert
;
2767 BOOLEAN IsKEKItemFound
;
2769 UINTN DeleteKekIndex
;
2777 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2779 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2780 if (EFI_ERROR (Status
)) {
2785 // Get original KEK variable.
2788 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2789 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2793 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2794 if (OldData
== NULL
) {
2795 Status
= EFI_OUT_OF_RESOURCES
;
2799 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2800 if (EFI_ERROR(Status
)) {
2805 // Allocate space for new variable.
2807 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2809 Status
= EFI_OUT_OF_RESOURCES
;
2814 // Enumerate all KEK pub data and erasing the target item.
2816 IsKEKItemFound
= FALSE
;
2817 KekDataSize
= (UINT32
) DataSize
;
2818 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2821 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2822 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2823 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2824 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2825 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2826 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2827 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2828 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2829 for (Index
= 0; Index
< CertCount
; Index
++) {
2830 if (GuidIndex
== DeleteKekIndex
) {
2832 // Find it! Skip it!
2834 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2835 IsKEKItemFound
= TRUE
;
2838 // This item doesn't match. Copy it to the Data buffer.
2840 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2841 Offset
+= CertList
->SignatureSize
;
2844 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2848 // This List doesn't match. Copy it to the Data buffer.
2850 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2851 Offset
+= CertList
->SignatureListSize
;
2854 KekDataSize
-= CertList
->SignatureListSize
;
2855 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2858 if (!IsKEKItemFound
) {
2860 // Doesn't find the Kek Item!
2862 Status
= EFI_NOT_FOUND
;
2867 // Delete the Signature header if there is no signature in the list.
2869 KekDataSize
= Offset
;
2870 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2872 ZeroMem (OldData
, KekDataSize
);
2873 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2874 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2875 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2876 if (CertCount
!= 0) {
2877 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2878 Offset
+= CertList
->SignatureListSize
;
2880 KekDataSize
-= CertList
->SignatureListSize
;
2881 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2885 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2886 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2887 if (EFI_ERROR (Status
)) {
2888 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2893 Status
= gRT
->SetVariable(
2894 EFI_KEY_EXCHANGE_KEY_NAME
,
2895 &gEfiGlobalVariableGuid
,
2900 if (EFI_ERROR (Status
)) {
2901 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2910 if (OldData
!= NULL
) {
2914 return UpdateDeletePage (
2916 EFI_KEY_EXCHANGE_KEY_NAME
,
2917 &gEfiGlobalVariableGuid
,
2919 FORMID_DELETE_KEK_FORM
,
2920 OPTION_DEL_KEK_QUESTION_ID
2925 Delete a signature entry from signature database.
2927 @param[in] PrivateData Module's private data.
2928 @param[in] VariableName The variable name of the vendor's signature database.
2929 @param[in] VendorGuid A unique identifier for the vendor.
2930 @param[in] LabelNumber Label number to insert opcodes.
2931 @param[in] FormId Form ID of current page.
2932 @param[in] QuestionIdBase Base question id of the signature list.
2933 @param[in] DeleteIndex Signature index to delete.
2935 @retval EFI_SUCCESS Delete signature successfully.
2936 @retval EFI_NOT_FOUND Can't find the signature item,
2937 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2941 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2942 IN CHAR16
*VariableName
,
2943 IN EFI_GUID
*VendorGuid
,
2944 IN UINT16 LabelNumber
,
2945 IN EFI_FORM_ID FormId
,
2946 IN EFI_QUESTION_ID QuestionIdBase
,
2947 IN UINTN DeleteIndex
2956 EFI_SIGNATURE_LIST
*CertList
;
2957 EFI_SIGNATURE_LIST
*NewCertList
;
2958 EFI_SIGNATURE_DATA
*Cert
;
2961 BOOLEAN IsItemFound
;
2962 UINT32 ItemDataSize
;
2971 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2972 if (EFI_ERROR (Status
)) {
2977 // Get original signature list data.
2980 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2981 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2985 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2986 if (OldData
== NULL
) {
2987 Status
= EFI_OUT_OF_RESOURCES
;
2991 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2992 if (EFI_ERROR(Status
)) {
2997 // Allocate space for new variable.
2999 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
3001 Status
= EFI_OUT_OF_RESOURCES
;
3006 // Enumerate all signature data and erasing the target item.
3008 IsItemFound
= FALSE
;
3009 ItemDataSize
= (UINT32
) DataSize
;
3010 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
3013 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
3014 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
3015 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
3016 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
3017 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
3018 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
3019 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
3020 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
3023 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
3025 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
3026 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
3027 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
3028 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
3029 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
3030 for (Index
= 0; Index
< CertCount
; Index
++) {
3031 if (GuidIndex
== DeleteIndex
) {
3033 // Find it! Skip it!
3035 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
3039 // This item doesn't match. Copy it to the Data buffer.
3041 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
3042 Offset
+= CertList
->SignatureSize
;
3045 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
3049 // This List doesn't match. Just copy it to the Data buffer.
3051 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
3052 Offset
+= CertList
->SignatureListSize
;
3055 ItemDataSize
-= CertList
->SignatureListSize
;
3056 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
3061 // Doesn't find the signature Item!
3063 Status
= EFI_NOT_FOUND
;
3068 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
3070 ItemDataSize
= Offset
;
3071 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
3073 ZeroMem (OldData
, ItemDataSize
);
3074 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
3075 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
3076 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
3077 if (CertCount
!= 0) {
3078 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
3079 Offset
+= CertList
->SignatureListSize
;
3081 ItemDataSize
-= CertList
->SignatureListSize
;
3082 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
3086 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3087 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
3088 if (EFI_ERROR (Status
)) {
3089 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
3094 Status
= gRT
->SetVariable(
3101 if (EFI_ERROR (Status
)) {
3102 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
3111 if (OldData
!= NULL
) {
3115 return UpdateDeletePage (
3126 This function to delete signature list or data, according by DelType.
3128 @param[in] PrivateData Module's private data.
3129 @param[in] DelType Indicate delete signature list or data.
3130 @param[in] CheckedCount Indicate how many signature data have
3131 been checked in current signature list.
3133 @retval EFI_SUCCESS Success to update the signature list page
3134 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3138 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3139 IN SIGNATURE_DELETE_TYPE DelType
,
3140 IN UINT32 CheckedCount
3144 EFI_SIGNATURE_LIST
*ListWalker
;
3145 EFI_SIGNATURE_LIST
*NewCertList
;
3146 EFI_SIGNATURE_DATA
*DataWalker
;
3147 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3148 UINT32 VariableAttr
;
3149 UINTN VariableDataSize
;
3150 UINTN RemainingSize
;
3154 UINT8
*VariableData
;
3155 UINT8
*NewVariableData
;
3157 Status
= EFI_SUCCESS
;
3159 VariableDataSize
= 0;
3162 VariableData
= NULL
;
3163 NewVariableData
= NULL
;
3165 if (PrivateData
->VariableName
== Variable_DB
) {
3166 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3167 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3168 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3169 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3170 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3175 Status
= gRT
->GetVariable (
3177 &gEfiImageSecurityDatabaseGuid
,
3182 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3186 VariableData
= AllocateZeroPool (VariableDataSize
);
3187 if (VariableData
== NULL
) {
3188 Status
= EFI_OUT_OF_RESOURCES
;
3192 Status
= gRT
->GetVariable (
3194 &gEfiImageSecurityDatabaseGuid
,
3199 if (EFI_ERROR (Status
)) {
3203 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3204 if (EFI_ERROR (Status
)) {
3208 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3209 if (NewVariableData
== NULL
) {
3210 Status
= EFI_OUT_OF_RESOURCES
;
3214 RemainingSize
= VariableDataSize
;
3215 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3216 if (DelType
== Delete_Signature_List_All
) {
3217 VariableDataSize
= 0;
3220 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3222 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3223 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3224 Offset
+= ListWalker
->SignatureListSize
;
3226 RemainingSize
-= ListWalker
->SignatureListSize
;
3227 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3232 // Handle the target EFI_SIGNATURE_LIST.
3233 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3234 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3236 if (CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
) && DelType
== Delete_Signature_Data
) {
3237 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3241 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3242 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3244 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3245 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
3246 if (PrivateData
->CheckArray
[Index
]) {
3248 // Delete checked signature data, and update the size of whole signature list.
3250 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3253 // Remain the unchecked signature data.
3255 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3256 Offset
+= ListWalker
->SignatureSize
;
3258 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3262 RemainingSize
-= ListWalker
->SignatureListSize
;
3263 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3266 // Copy remaining data, maybe 0.
3268 CopyMem((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3269 Offset
+= RemainingSize
;
3271 VariableDataSize
= Offset
;
3274 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3275 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3276 if (EFI_ERROR (Status
)) {
3277 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3282 Status
= gRT
->SetVariable (
3284 &gEfiImageSecurityDatabaseGuid
,
3289 if (EFI_ERROR (Status
)) {
3290 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3295 SECUREBOOT_FREE_NON_NULL (VariableData
);
3296 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3303 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3304 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3306 @param[in] PrivateData Module's private data.
3308 @return EFI_SUCCESS Update secure boot strings successfully.
3309 @return other Fail to update secure boot strings.
3313 UpdateSecureBootString(
3314 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3322 // Get current secure boot state.
3324 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3325 if (SecureBoot
== NULL
) {
3326 return EFI_NOT_FOUND
;
3329 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3330 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3332 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3335 FreePool(SecureBoot
);
3341 This function extracts configuration from variable.
3343 @param[in] Private Point to SecureBoot configuration driver private data.
3344 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3348 SecureBootExtractConfigFromVariable (
3349 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3350 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3353 UINT8
*SecureBootEnable
;
3355 UINT8
*SecureBootMode
;
3358 SecureBootEnable
= NULL
;
3360 SecureBootMode
= NULL
;
3363 // Initialize the Date and Time using system time.
3365 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3366 ConfigData
->AlwaysRevocation
= TRUE
;
3367 gRT
->GetTime (&CurrTime
, NULL
);
3368 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3369 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3370 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3371 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3372 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3373 ConfigData
->RevocationTime
.Second
= 0;
3374 if (Private
->FileContext
->FHandle
!= NULL
) {
3375 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3377 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3381 // If it is Physical Presence User, set the PhysicalPresent to true.
3383 if (UserPhysicalPresent()) {
3384 ConfigData
->PhysicalPresent
= TRUE
;
3386 ConfigData
->PhysicalPresent
= FALSE
;
3390 // If there is no PK then the Delete Pk button will be gray.
3392 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3393 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3394 ConfigData
->HasPk
= FALSE
;
3396 ConfigData
->HasPk
= TRUE
;
3400 // Check SecureBootEnable & Pk status, fix the inconsistency.
3401 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3404 ConfigData
->AttemptSecureBoot
= FALSE
;
3405 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3408 // Fix Pk and SecureBootEnable inconsistency
3410 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3411 ConfigData
->HideSecureBoot
= FALSE
;
3412 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3413 ConfigData
->AttemptSecureBoot
= TRUE
;
3416 ConfigData
->HideSecureBoot
= TRUE
;
3420 // Get the SecureBootMode from CustomMode variable.
3422 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3423 if (SecureBootMode
== NULL
) {
3424 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3426 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3429 if (SecureBootEnable
!= NULL
) {
3430 FreePool (SecureBootEnable
);
3432 if (SetupMode
!= NULL
) {
3433 FreePool (SetupMode
);
3435 if (SecureBootMode
!= NULL
) {
3436 FreePool (SecureBootMode
);
3441 This function allows a caller to extract the current configuration for one
3442 or more named elements from the target driver.
3444 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3445 @param[in] Request A null-terminated Unicode string in
3446 <ConfigRequest> format.
3447 @param[out] Progress On return, points to a character in the Request
3448 string. Points to the string's null terminator if
3449 request was successful. Points to the most recent
3450 '&' before the first failing name/value pair (or
3451 the beginning of the string if the failure is in
3452 the first name/value pair) if the request was not
3454 @param[out] Results A null-terminated Unicode string in
3455 <ConfigAltResp> format which has all values filled
3456 in for the names in the Request string. String to
3457 be allocated by the called function.
3459 @retval EFI_SUCCESS The Results is filled with the requested values.
3460 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3461 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3462 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3468 SecureBootExtractConfig (
3469 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3470 IN CONST EFI_STRING Request
,
3471 OUT EFI_STRING
*Progress
,
3472 OUT EFI_STRING
*Results
3478 SECUREBOOT_CONFIGURATION Configuration
;
3479 EFI_STRING ConfigRequest
;
3480 EFI_STRING ConfigRequestHdr
;
3481 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3482 BOOLEAN AllocatedRequest
;
3484 if (Progress
== NULL
|| Results
== NULL
) {
3485 return EFI_INVALID_PARAMETER
;
3488 AllocatedRequest
= FALSE
;
3489 ConfigRequestHdr
= NULL
;
3490 ConfigRequest
= NULL
;
3493 ZeroMem (&Configuration
, sizeof (Configuration
));
3494 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3495 *Progress
= Request
;
3497 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3498 return EFI_NOT_FOUND
;
3501 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3504 // Get Configuration from Variable.
3506 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3508 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3509 ConfigRequest
= Request
;
3510 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3512 // Request is set to NULL or OFFSET is NULL, construct full request string.
3514 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3515 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3517 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3518 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3519 ConfigRequest
= AllocateZeroPool (Size
);
3520 ASSERT (ConfigRequest
!= NULL
);
3521 AllocatedRequest
= TRUE
;
3522 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3523 FreePool (ConfigRequestHdr
);
3524 ConfigRequestHdr
= NULL
;
3527 Status
= gHiiConfigRouting
->BlockToConfig (
3530 (UINT8
*) &Configuration
,
3537 // Free the allocated config request string.
3539 if (AllocatedRequest
) {
3540 FreePool (ConfigRequest
);
3544 // Set Progress string to the original request string.
3546 if (Request
== NULL
) {
3548 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3549 *Progress
= Request
+ StrLen (Request
);
3556 This function processes the results of changes in configuration.
3558 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3559 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3561 @param[out] Progress A pointer to a string filled in with the offset of
3562 the most recent '&' before the first failing
3563 name/value pair (or the beginning of the string if
3564 the failure is in the first name/value pair) or
3565 the terminating NULL if all was successful.
3567 @retval EFI_SUCCESS The Results is processed successfully.
3568 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3569 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3575 SecureBootRouteConfig (
3576 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3577 IN CONST EFI_STRING Configuration
,
3578 OUT EFI_STRING
*Progress
3581 SECUREBOOT_CONFIGURATION IfrNvData
;
3583 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3586 if (Configuration
== NULL
|| Progress
== NULL
) {
3587 return EFI_INVALID_PARAMETER
;
3590 *Progress
= Configuration
;
3591 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3592 return EFI_NOT_FOUND
;
3595 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3598 // Get Configuration from Variable.
3600 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3603 // Map the Configuration to the configuration block.
3605 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3606 Status
= gHiiConfigRouting
->ConfigToBlock (
3609 (UINT8
*)&IfrNvData
,
3613 if (EFI_ERROR (Status
)) {
3618 // Store Buffer Storage back to EFI variable if needed
3620 if (!IfrNvData
.HideSecureBoot
) {
3621 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3622 if (EFI_ERROR (Status
)) {
3627 *Progress
= Configuration
+ StrLen (Configuration
);
3632 This function to load signature list, the update the menu page.
3634 @param[in] PrivateData Module's private data.
3635 @param[in] LabelId Label number to insert opcodes.
3636 @param[in] FormId Form ID of current page.
3637 @param[in] QuestionIdBase Base question id of the signature list.
3639 @retval EFI_SUCCESS Success to update the signature list page
3640 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3644 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3646 IN EFI_FORM_ID FormId
,
3647 IN EFI_QUESTION_ID QuestionIdBase
3651 EFI_STRING_ID ListType
;
3652 EFI_STRING FormatNameString
;
3653 EFI_STRING FormatHelpString
;
3654 EFI_STRING FormatTypeString
;
3655 EFI_SIGNATURE_LIST
*ListWalker
;
3656 EFI_IFR_GUID_LABEL
*StartLabel
;
3657 EFI_IFR_GUID_LABEL
*EndLabel
;
3658 EFI_IFR_GUID_LABEL
*StartGoto
;
3659 EFI_IFR_GUID_LABEL
*EndGoto
;
3660 EFI_FORM_ID DstFormId
;
3661 VOID
*StartOpCodeHandle
;
3662 VOID
*EndOpCodeHandle
;
3663 VOID
*StartGotoHandle
;
3664 VOID
*EndGotoHandle
;
3666 UINTN RemainingSize
;
3668 UINT8
*VariableData
;
3669 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3670 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3671 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3673 Status
= EFI_SUCCESS
;
3674 FormatNameString
= NULL
;
3675 FormatHelpString
= NULL
;
3676 StartOpCodeHandle
= NULL
;
3677 EndOpCodeHandle
= NULL
;
3678 StartGotoHandle
= NULL
;
3679 EndGotoHandle
= NULL
;
3681 VariableData
= NULL
;
3684 // Initialize the container for dynamic opcodes.
3686 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3687 if (StartOpCodeHandle
== NULL
) {
3688 Status
= EFI_OUT_OF_RESOURCES
;
3692 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3693 if (EndOpCodeHandle
== NULL
) {
3694 Status
= EFI_OUT_OF_RESOURCES
;
3698 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3699 if (StartGotoHandle
== NULL
) {
3700 Status
= EFI_OUT_OF_RESOURCES
;
3704 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3705 if (EndGotoHandle
== NULL
) {
3706 Status
= EFI_OUT_OF_RESOURCES
;
3711 // Create Hii Extend Label OpCode.
3713 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3717 sizeof (EFI_IFR_GUID_LABEL
)
3719 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3720 StartLabel
->Number
= LabelId
;
3722 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3726 sizeof (EFI_IFR_GUID_LABEL
)
3728 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3729 EndLabel
->Number
= LABEL_END
;
3731 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3735 sizeof(EFI_IFR_GUID_LABEL
)
3737 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3738 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3740 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3744 sizeof(EFI_IFR_GUID_LABEL
)
3746 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3747 EndGoto
->Number
= LABEL_END
;
3749 if (PrivateData
->VariableName
== Variable_DB
) {
3750 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3751 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3752 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3753 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3754 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3755 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3756 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3757 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3762 HiiCreateGotoOpCode (
3765 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3766 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3767 EFI_IFR_FLAG_CALLBACK
,
3768 KEY_SECURE_BOOT_DELETE_ALL_LIST
3772 // Read Variable, the variable name save in the PrivateData->VariableName.
3775 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3776 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3780 VariableData
= AllocateZeroPool (DataSize
);
3781 if (VariableData
== NULL
) {
3782 Status
= EFI_OUT_OF_RESOURCES
;
3785 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3786 if (EFI_ERROR (Status
)) {
3790 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3791 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3792 if (FormatNameString
== NULL
|| FormatHelpString
== NULL
) {
3796 RemainingSize
= DataSize
;
3797 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3798 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3799 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3800 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3801 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3802 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3803 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3804 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3805 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3806 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3807 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3808 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3809 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3810 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3811 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3812 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3814 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3816 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3817 if (FormatTypeString
== NULL
) {
3821 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3822 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3824 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3825 UnicodeSPrint (HelpBuffer
,
3826 sizeof (HelpBuffer
),
3829 SIGNATURE_DATA_COUNTS (ListWalker
)
3831 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3832 FormatTypeString
= NULL
;
3834 HiiCreateGotoOpCode (
3836 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3837 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3838 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3839 EFI_IFR_FLAG_CALLBACK
,
3840 QuestionIdBase
+ Index
++
3843 RemainingSize
-= ListWalker
->SignatureListSize
;
3844 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3849 PrivateData
->HiiHandle
,
3850 &gSecureBootConfigFormSetGuid
,
3857 PrivateData
->HiiHandle
,
3858 &gSecureBootConfigFormSetGuid
,
3864 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3865 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3866 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3867 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3869 SECUREBOOT_FREE_NON_NULL (VariableData
);
3870 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3871 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3873 PrivateData
->ListCount
= Index
;
3879 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3880 The buffer is callee allocated and should be freed by the caller.
3882 @param[in] ListEntry The pointer point to the signature list.
3883 @param[in] DataEntry The signature data we are processing.
3884 @param[out] BufferToReturn Buffer to save the hash value.
3886 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3887 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3888 @retval EFI_SUCCESS Operation success.
3892 IN EFI_SIGNATURE_LIST
*ListEntry
,
3893 IN EFI_SIGNATURE_DATA
*DataEntry
,
3894 OUT CHAR16
**BufferToReturn
3905 // Assume that, display 8 bytes in one line.
3909 if (ListEntry
== NULL
|| DataEntry
== NULL
|| BufferToReturn
== NULL
) {
3910 return EFI_INVALID_PARAMETER
;
3913 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3914 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3917 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3919 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof(CHAR16
));
3921 *BufferToReturn
= AllocateZeroPool(TotalSize
);
3922 if (*BufferToReturn
== NULL
) {
3923 return EFI_OUT_OF_RESOURCES
;
3926 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3927 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3928 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3930 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3932 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3938 Function to get the common name from the X509 format certificate.
3939 The buffer is callee allocated and should be freed by the caller.
3941 @param[in] ListEntry The pointer point to the signature list.
3942 @param[in] DataEntry The signature data we are processing.
3943 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3945 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3946 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3947 @retval EFI_SUCCESS Operation success.
3948 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3951 GetCommonNameFromX509 (
3952 IN EFI_SIGNATURE_LIST
*ListEntry
,
3953 IN EFI_SIGNATURE_DATA
*DataEntry
,
3954 OUT CHAR16
**BufferToReturn
3961 Status
= EFI_SUCCESS
;
3964 CNBuffer
= AllocateZeroPool(256);
3965 if (CNBuffer
== NULL
) {
3966 Status
= EFI_OUT_OF_RESOURCES
;
3972 (UINT8
*)DataEntry
+ sizeof(EFI_GUID
),
3973 ListEntry
->SignatureSize
- sizeof(EFI_GUID
),
3978 *BufferToReturn
= AllocateZeroPool(256 * sizeof(CHAR16
));
3979 if (*BufferToReturn
== NULL
) {
3980 Status
= EFI_OUT_OF_RESOURCES
;
3984 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3987 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3993 Format the help info for the signature data, each help info contain 3 parts.
3995 2. Content, depends on the type of the signature list.
3998 @param[in] PrivateData Module's private data.
3999 @param[in] ListEntry Point to the signature list.
4000 @param[in] DataEntry Point to the signature data we are processing.
4001 @param[out] StringId Save the string id of help info.
4003 @retval EFI_SUCCESS Operation success.
4004 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4008 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4009 IN EFI_SIGNATURE_LIST
*ListEntry
,
4010 IN EFI_SIGNATURE_DATA
*DataEntry
,
4011 OUT EFI_STRING_ID
*StringId
4016 EFI_STRING_ID ListTypeId
;
4017 EFI_STRING FormatHelpString
;
4018 EFI_STRING FormatTypeString
;
4020 UINTN HelpInfoIndex
;
4022 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
4023 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
4025 CHAR16
*HelpInfoString
;
4028 Status
= EFI_SUCCESS
;
4030 FormatTypeString
= NULL
;
4033 HelpInfoString
= NULL
;
4036 if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
4037 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256
);
4038 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
4040 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
4041 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509
);
4042 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
4044 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
4045 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA1
);
4047 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
4048 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA256
);
4050 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
4051 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA256
);
4053 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
4054 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
4055 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA384
);
4057 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
4058 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
4059 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA512
);
4061 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
4063 Status
= EFI_UNSUPPORTED
;
4067 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
4068 if (FormatTypeString
== NULL
) {
4073 HelpInfoString
= AllocateZeroPool (TotalSize
);
4074 if (HelpInfoString
== NULL
) {
4075 Status
= EFI_OUT_OF_RESOURCES
;
4080 // Format GUID part.
4082 ZeroMem (GuidString
, sizeof (GuidString
));
4083 GuidToString(&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
4084 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
4085 if (FormatHelpString
== NULL
) {
4088 HelpInfoIndex
+= UnicodeSPrint (
4089 &HelpInfoString
[HelpInfoIndex
],
4090 TotalSize
- sizeof(CHAR16
) * HelpInfoIndex
,
4094 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4095 FormatHelpString
= NULL
;
4098 // Format content part, it depends on the type of signature list, hash value or CN.
4101 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
4102 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
4105 // Format hash value for each signature data entry.
4107 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
4108 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
4110 if (FormatHelpString
== NULL
) {
4113 HelpInfoIndex
+= UnicodeSPrint (
4114 &HelpInfoString
[HelpInfoIndex
],
4115 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4121 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4122 FormatHelpString
= NULL
;
4125 // Format revocation time part.
4128 ZeroMem (TimeString
, sizeof (TimeString
));
4131 sizeof (TimeString
),
4132 L
"%d-%d-%d %d:%d:%d",
4140 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
4141 if (FormatHelpString
== NULL
) {
4145 &HelpInfoString
[HelpInfoIndex
],
4146 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4150 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4151 FormatHelpString
= NULL
;
4154 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
4156 SECUREBOOT_FREE_NON_NULL (DataString
);
4157 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
4159 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
4165 This function to load signature data under the signature list.
4167 @param[in] PrivateData Module's private data.
4168 @param[in] LabelId Label number to insert opcodes.
4169 @param[in] FormId Form ID of current page.
4170 @param[in] QuestionIdBase Base question id of the signature list.
4171 @param[in] ListIndex Indicate to load which signature list.
4173 @retval EFI_SUCCESS Success to update the signature list page
4174 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4178 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4180 IN EFI_FORM_ID FormId
,
4181 IN EFI_QUESTION_ID QuestionIdBase
,
4186 EFI_SIGNATURE_LIST
*ListWalker
;
4187 EFI_SIGNATURE_DATA
*DataWalker
;
4188 EFI_IFR_GUID_LABEL
*StartLabel
;
4189 EFI_IFR_GUID_LABEL
*EndLabel
;
4190 EFI_STRING_ID HelpStringId
;
4191 EFI_STRING FormatNameString
;
4192 VOID
*StartOpCodeHandle
;
4193 VOID
*EndOpCodeHandle
;
4195 UINTN RemainingSize
;
4197 UINT8
*VariableData
;
4198 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4199 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4201 Status
= EFI_SUCCESS
;
4202 FormatNameString
= NULL
;
4203 StartOpCodeHandle
= NULL
;
4204 EndOpCodeHandle
= NULL
;
4206 VariableData
= NULL
;
4209 // Initialize the container for dynamic opcodes.
4211 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4212 if (StartOpCodeHandle
== NULL
) {
4213 Status
= EFI_OUT_OF_RESOURCES
;
4217 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4218 if (EndOpCodeHandle
== NULL
) {
4219 Status
= EFI_OUT_OF_RESOURCES
;
4224 // Create Hii Extend Label OpCode.
4226 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4230 sizeof (EFI_IFR_GUID_LABEL
)
4232 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4233 StartLabel
->Number
= LabelId
;
4235 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4239 sizeof (EFI_IFR_GUID_LABEL
)
4241 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4242 EndLabel
->Number
= LABEL_END
;
4244 if (PrivateData
->VariableName
== Variable_DB
) {
4245 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4246 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4247 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4248 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4249 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4255 // Read Variable, the variable name save in the PrivateData->VariableName.
4258 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4259 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
4263 VariableData
= AllocateZeroPool (DataSize
);
4264 if (VariableData
== NULL
) {
4265 Status
= EFI_OUT_OF_RESOURCES
;
4268 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4269 if (EFI_ERROR (Status
)) {
4273 RemainingSize
= DataSize
;
4274 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4277 // Skip signature list.
4279 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4280 RemainingSize
-= ListWalker
->SignatureListSize
;
4281 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4284 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4285 if (FormatNameString
== NULL
) {
4289 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4290 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
4292 // Format name buffer.
4294 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4295 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4298 // Format help info buffer.
4300 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4301 if (EFI_ERROR (Status
)) {
4305 HiiCreateCheckBoxOpCode (
4307 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4310 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4312 EFI_IFR_FLAG_CALLBACK
,
4317 ZeroMem(NameBuffer
, 100);
4318 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4322 // Allocate a buffer to record which signature data will be checked.
4323 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4325 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4328 PrivateData
->HiiHandle
,
4329 &gSecureBootConfigFormSetGuid
,
4335 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4336 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4338 SECUREBOOT_FREE_NON_NULL (VariableData
);
4339 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4345 This function is called to provide results data to the driver.
4347 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4348 @param[in] Action Specifies the type of action taken by the browser.
4349 @param[in] QuestionId A unique value which is sent to the original
4350 exporting driver so that it can identify the type
4352 @param[in] Type The type of value for the question.
4353 @param[in] Value A pointer to the data being sent to the original
4355 @param[out] ActionRequest On return, points to the action requested by the
4358 @retval EFI_SUCCESS The callback successfully handled the action.
4359 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4360 variable and its data.
4361 @retval EFI_DEVICE_ERROR The variable could not be saved.
4362 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4368 SecureBootCallback (
4369 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4370 IN EFI_BROWSER_ACTION Action
,
4371 IN EFI_QUESTION_ID QuestionId
,
4373 IN EFI_IFR_TYPE_VALUE
*Value
,
4374 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4379 RETURN_STATUS RStatus
;
4380 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4382 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4384 UINT8
*SecureBootEnable
;
4386 UINT8
*SecureBootMode
;
4388 CHAR16 PromptString
[100];
4389 EFI_DEVICE_PATH_PROTOCOL
*File
;
4391 UINT16
*FilePostFix
;
4392 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4393 BOOLEAN GetBrowserDataResult
;
4394 ENROLL_KEY_ERROR EnrollKeyErrorCode
;
4396 Status
= EFI_SUCCESS
;
4397 SecureBootEnable
= NULL
;
4398 SecureBootMode
= NULL
;
4401 EnrollKeyErrorCode
= None_Error
;
4403 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4404 return EFI_INVALID_PARAMETER
;
4407 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4409 gSecureBootPrivateData
= Private
;
4412 // Retrieve uncommitted data from Browser
4414 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4415 IfrNvData
= AllocateZeroPool (BufferSize
);
4416 if (IfrNvData
== NULL
) {
4417 return EFI_OUT_OF_RESOURCES
;
4420 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
4422 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4423 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4425 // Update secure boot strings when opening this form
4427 Status
= UpdateSecureBootString(Private
);
4428 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4429 mIsEnterSecureBootForm
= TRUE
;
4432 // When entering SecureBoot OPTION Form
4433 // always close opened file & free resource
4435 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4436 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4437 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4438 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4439 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
4440 CloseEnrolledFile(Private
->FileContext
);
4441 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4443 // Update ListCount field in varstore
4444 // Button "Delete All Signature List" is
4445 // enable when ListCount is greater than 0.
4447 IfrNvData
->ListCount
= Private
->ListCount
;
4453 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4454 Status
= EFI_UNSUPPORTED
;
4455 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4456 if (mIsEnterSecureBootForm
) {
4457 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4458 Status
= EFI_SUCCESS
;
4464 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4465 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4466 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4467 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
4468 Status
= EFI_UNSUPPORTED
;
4472 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4474 switch (QuestionId
) {
4475 case KEY_SECURE_BOOT_ENABLE
:
4476 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4477 if (NULL
!= SecureBootEnable
) {
4478 FreePool (SecureBootEnable
);
4479 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4481 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4483 L
"Only Physical Presence User could disable secure boot!",
4486 Status
= EFI_UNSUPPORTED
;
4489 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4491 L
"Configuration changed, please reset the platform to take effect!",
4498 case KEY_SECURE_BOOT_KEK_OPTION
:
4499 case KEY_SECURE_BOOT_DB_OPTION
:
4500 case KEY_SECURE_BOOT_DBX_OPTION
:
4501 case KEY_SECURE_BOOT_DBT_OPTION
:
4502 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4504 // Clear Signature GUID.
4506 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4507 if (Private
->SignatureGUID
== NULL
) {
4508 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
4509 if (Private
->SignatureGUID
== NULL
) {
4510 return EFI_OUT_OF_RESOURCES
;
4515 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4517 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4519 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4520 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4521 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4522 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4523 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4524 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4526 LabelId
= FORMID_ENROLL_KEK_FORM
;
4530 // Refresh selected file.
4532 CleanUpPage (LabelId
, Private
);
4534 case KEY_SECURE_BOOT_PK_OPTION
:
4535 LabelId
= FORMID_ENROLL_PK_FORM
;
4537 // Refresh selected file.
4539 CleanUpPage (LabelId
, Private
);
4542 case FORMID_ENROLL_PK_FORM
:
4543 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4546 case FORMID_ENROLL_KEK_FORM
:
4547 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4550 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4551 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4554 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4555 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4557 if (Private
->FileContext
->FHandle
!= NULL
) {
4559 // Parse the file's postfix.
4561 NameLength
= StrLen (Private
->FileContext
->FileName
);
4562 if (NameLength
<= 4) {
4565 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4567 if (IsDerEncodeCertificate (FilePostFix
)) {
4569 // Supports DER-encoded X509 certificate.
4571 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4572 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
4573 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4575 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4577 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4580 // Clean up Certificate Format if File type is not X509 DER
4582 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4583 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4585 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4590 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4591 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4594 case KEY_SECURE_BOOT_DELETE_PK
:
4597 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4599 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4600 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4603 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
4604 Status
= DeletePlatformKey ();
4605 if (EFI_ERROR (Status
)) {
4607 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4609 L
"Only Physical Presence User could delete PK in custom mode!",
4617 case KEY_DELETE_KEK
:
4620 EFI_KEY_EXCHANGE_KEY_NAME
,
4621 &gEfiGlobalVariableGuid
,
4623 FORMID_DELETE_KEK_FORM
,
4624 OPTION_DEL_KEK_QUESTION_ID
4628 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4631 EFI_IMAGE_SECURITY_DATABASE
,
4632 &gEfiImageSecurityDatabaseGuid
,
4634 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4635 OPTION_DEL_DB_QUESTION_ID
4640 // From DBX option to the level-1 form, display signature list.
4642 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4643 Private
->VariableName
= Variable_DBX
;
4646 LABEL_SIGNATURE_LIST_START
,
4647 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4648 OPTION_SIGNATURE_LIST_QUESTION_ID
4653 // Delete all signature list and reload.
4655 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4657 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4659 L
"Press 'Y' to delete signature list.",
4660 L
"Press other key to cancel and exit.",
4664 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4665 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4670 LABEL_SIGNATURE_LIST_START
,
4671 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4672 OPTION_SIGNATURE_LIST_QUESTION_ID
4677 // Delete one signature list and reload.
4679 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4681 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4683 L
"Press 'Y' to delete signature data.",
4684 L
"Press other key to cancel and exit.",
4688 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4689 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4694 LABEL_SIGNATURE_LIST_START
,
4695 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4696 OPTION_SIGNATURE_LIST_QUESTION_ID
4701 // Delete checked signature data and reload.
4703 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4705 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4707 L
"Press 'Y' to delete signature data.",
4708 L
"Press other key to cancel and exit.",
4712 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4713 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4718 LABEL_SIGNATURE_LIST_START
,
4719 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4720 OPTION_SIGNATURE_LIST_QUESTION_ID
4724 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4727 EFI_IMAGE_SECURITY_DATABASE2
,
4728 &gEfiImageSecurityDatabaseGuid
,
4730 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4731 OPTION_DEL_DBT_QUESTION_ID
4736 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4737 Status
= EnrollKeyExchangeKey (Private
);
4738 if (EFI_ERROR (Status
)) {
4740 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4742 L
"ERROR: Unsupported file type!",
4743 L
"Only supports DER-encoded X509 certificate",
4749 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4750 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4751 if (EFI_ERROR (Status
)) {
4753 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4755 L
"ERROR: Unsupported file type!",
4756 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4762 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4763 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4765 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4767 L
"Enrollment failed! Same certificate had already been in the dbx!",
4772 // Cert already exists in DBX. Close opened file before exit.
4774 CloseEnrolledFile(Private
->FileContext
);
4778 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4779 Status
= EnrollX509HashtoSigDB (
4781 IfrNvData
->CertificateFormat
,
4782 &IfrNvData
->RevocationDate
,
4783 &IfrNvData
->RevocationTime
,
4784 IfrNvData
->AlwaysRevocation
4786 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4788 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4790 if (EFI_ERROR (Status
)) {
4792 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4794 L
"ERROR: Unsupported file type!",
4795 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4801 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4802 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4803 if (EFI_ERROR (Status
)) {
4805 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4807 L
"ERROR: Unsupported file type!",
4808 L
"Only supports DER-encoded X509 certificate.",
4813 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4815 // Check the suffix, encode type and the key strength of PK certificate.
4817 Status
= CheckX509Certificate (Private
->FileContext
, &EnrollKeyErrorCode
);
4818 if (EFI_ERROR (Status
)) {
4819 if (EnrollKeyErrorCode
!= None_Error
&& EnrollKeyErrorCode
< Enroll_Error_Max
) {
4821 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4823 mX509EnrollPromptTitle
[EnrollKeyErrorCode
],
4824 mX509EnrollPromptString
[EnrollKeyErrorCode
],
4830 Status
= EnrollPlatformKey (Private
);
4832 if (EFI_ERROR (Status
)) {
4835 sizeof (PromptString
),
4836 L
"Error status: %x.",
4840 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4842 L
"ERROR: Enrollment failed!",
4849 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4850 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4851 DeleteKeyExchangeKey (Private
, QuestionId
);
4852 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4853 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4856 EFI_IMAGE_SECURITY_DATABASE
,
4857 &gEfiImageSecurityDatabaseGuid
,
4859 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4860 OPTION_DEL_DB_QUESTION_ID
,
4861 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4863 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4864 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4867 LABEL_SIGNATURE_DATA_START
,
4868 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4869 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4870 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4872 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4873 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4874 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4875 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4876 IfrNvData
->CheckedDataCount
--;
4877 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4879 IfrNvData
->CheckedDataCount
++;
4880 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4882 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4883 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4886 EFI_IMAGE_SECURITY_DATABASE2
,
4887 &gEfiImageSecurityDatabaseGuid
,
4889 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4890 OPTION_DEL_DBT_QUESTION_ID
,
4891 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4896 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4897 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4898 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4899 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4900 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4901 CloseEnrolledFile(Private
->FileContext
);
4903 if (Private
->SignatureGUID
!= NULL
) {
4904 FreePool (Private
->SignatureGUID
);
4905 Private
->SignatureGUID
= NULL
;
4909 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4910 switch (QuestionId
) {
4911 case KEY_SECURE_BOOT_ENABLE
:
4912 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4914 case KEY_SECURE_BOOT_MODE
:
4915 mIsEnterSecureBootForm
= FALSE
;
4917 case KEY_SECURE_BOOT_KEK_GUID
:
4918 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4919 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4920 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4921 ASSERT (Private
->SignatureGUID
!= NULL
);
4922 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4923 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4924 Status
= EFI_INVALID_PARAMETER
;
4928 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4930 case KEY_SECURE_BOOT_DELETE_PK
:
4931 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4932 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
4933 IfrNvData
->DeletePk
= TRUE
;
4934 IfrNvData
->HasPk
= FALSE
;
4935 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4937 IfrNvData
->DeletePk
= FALSE
;
4938 IfrNvData
->HasPk
= TRUE
;
4939 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4941 if (SetupMode
!= NULL
) {
4942 FreePool (SetupMode
);
4948 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4949 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4950 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
4952 IfrNvData
->HideSecureBoot
= TRUE
;
4955 IfrNvData
->HideSecureBoot
= FALSE
;
4957 Value
->b
= IfrNvData
->HideSecureBoot
;
4959 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
4961 // Force the platform back to Standard Mode once user leave the setup screen.
4963 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
4964 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
4965 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
4966 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
4968 if (SecureBootMode
!= NULL
) {
4969 FreePool (SecureBootMode
);
4972 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
4974 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4976 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
4977 IfrNvData
->CheckedDataCount
= 0;
4983 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
4984 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4985 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
4988 FreePool (IfrNvData
);
4999 This function publish the SecureBoot configuration Form.
5001 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5003 @retval EFI_SUCCESS HII Form is installed successfully.
5004 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
5005 @retval Others Other errors as indicated.
5009 InstallSecureBootConfigForm (
5010 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5014 EFI_HII_HANDLE HiiHandle
;
5015 EFI_HANDLE DriverHandle
;
5016 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5018 DriverHandle
= NULL
;
5019 ConfigAccess
= &PrivateData
->ConfigAccess
;
5020 Status
= gBS
->InstallMultipleProtocolInterfaces (
5022 &gEfiDevicePathProtocolGuid
,
5023 &mSecureBootHiiVendorDevicePath
,
5024 &gEfiHiiConfigAccessProtocolGuid
,
5028 if (EFI_ERROR (Status
)) {
5032 PrivateData
->DriverHandle
= DriverHandle
;
5035 // Publish the HII package list
5037 HiiHandle
= HiiAddPackages (
5038 &gSecureBootConfigFormSetGuid
,
5040 SecureBootConfigDxeStrings
,
5041 SecureBootConfigBin
,
5044 if (HiiHandle
== NULL
) {
5045 gBS
->UninstallMultipleProtocolInterfaces (
5047 &gEfiDevicePathProtocolGuid
,
5048 &mSecureBootHiiVendorDevicePath
,
5049 &gEfiHiiConfigAccessProtocolGuid
,
5053 return EFI_OUT_OF_RESOURCES
;
5056 PrivateData
->HiiHandle
= HiiHandle
;
5058 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
5060 if (PrivateData
->FileContext
== NULL
) {
5061 UninstallSecureBootConfigForm (PrivateData
);
5062 return EFI_OUT_OF_RESOURCES
;
5066 // Init OpCode Handle and Allocate space for creation of Buffer
5068 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
5069 if (mStartOpCodeHandle
== NULL
) {
5070 UninstallSecureBootConfigForm (PrivateData
);
5071 return EFI_OUT_OF_RESOURCES
;
5074 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
5075 if (mEndOpCodeHandle
== NULL
) {
5076 UninstallSecureBootConfigForm (PrivateData
);
5077 return EFI_OUT_OF_RESOURCES
;
5081 // Create Hii Extend Label OpCode as the start opcode
5083 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
5087 sizeof (EFI_IFR_GUID_LABEL
)
5089 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5092 // Create Hii Extend Label OpCode as the end opcode
5094 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
5098 sizeof (EFI_IFR_GUID_LABEL
)
5100 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5101 mEndLabel
->Number
= LABEL_END
;
5107 This function removes SecureBoot configuration Form.
5109 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5113 UninstallSecureBootConfigForm (
5114 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5118 // Uninstall HII package list
5120 if (PrivateData
->HiiHandle
!= NULL
) {
5121 HiiRemovePackages (PrivateData
->HiiHandle
);
5122 PrivateData
->HiiHandle
= NULL
;
5126 // Uninstall HII Config Access Protocol
5128 if (PrivateData
->DriverHandle
!= NULL
) {
5129 gBS
->UninstallMultipleProtocolInterfaces (
5130 PrivateData
->DriverHandle
,
5131 &gEfiDevicePathProtocolGuid
,
5132 &mSecureBootHiiVendorDevicePath
,
5133 &gEfiHiiConfigAccessProtocolGuid
,
5134 &PrivateData
->ConfigAccess
,
5137 PrivateData
->DriverHandle
= NULL
;
5140 if (PrivateData
->SignatureGUID
!= NULL
) {
5141 FreePool (PrivateData
->SignatureGUID
);
5144 if (PrivateData
->FileContext
!= NULL
) {
5145 FreePool (PrivateData
->FileContext
);
5148 FreePool (PrivateData
);
5150 if (mStartOpCodeHandle
!= NULL
) {
5151 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5154 if (mEndOpCodeHandle
!= NULL
) {
5155 HiiFreeOpCodeHandle (mEndOpCodeHandle
);