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>
12 #include <Library/SecureBootVariableLib.h>
13 #include <Library/SecureBootVariableProvisionLib.h>
15 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
17 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
18 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
20 SecureBootExtractConfig
,
21 SecureBootRouteConfig
,
26 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
32 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
33 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
36 SECUREBOOT_CONFIG_FORM_SET_GUID
40 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
42 (UINT8
) (END_DEVICE_PATH_LENGTH
),
43 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
49 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
52 // OID ASN.1 Value for Hash Algorithms
54 UINT8 mHashOidValue
[] = {
55 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
56 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
63 HASH_TABLE mHash
[] = {
64 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
65 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
66 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
67 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
71 // Variable Definitions
73 UINT32 mPeCoffHeaderOffset
= 0;
74 WIN_CERTIFICATE
*mCertificate
= NULL
;
75 IMAGE_TYPE mImageType
;
76 UINT8
*mImageBase
= NULL
;
78 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
79 UINTN mImageDigestSize
;
81 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
82 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
85 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
87 CHAR16
* mDerEncodedSuffix
[] = {
93 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
96 // Prompt strings during certificate enrollment.
98 CHAR16
* mX509EnrollPromptTitle
[] = {
100 L
"ERROR: Unsupported file type!",
101 L
"ERROR: Unsupported certificate!",
104 CHAR16
* mX509EnrollPromptString
[] = {
106 L
"Only DER encoded certificate file (*.cer/der/crt) is supported.",
107 L
"Public key length should be equal to or greater than 2048 bits.",
111 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
114 This code cleans up enrolled file by closing file & free related resources attached to
117 @param[in] FileContext FileContext cached in SecureBootConfig driver
122 IN SECUREBOOT_FILE_CONTEXT
*FileContext
125 if (FileContext
->FHandle
!= NULL
) {
126 CloseFile (FileContext
->FHandle
);
127 FileContext
->FHandle
= NULL
;
130 if (FileContext
->FileName
!= NULL
){
131 FreePool(FileContext
->FileName
);
132 FileContext
->FileName
= NULL
;
134 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
139 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
141 @param[in] FileSuffix The suffix of the input certificate file
143 @retval TRUE It's a DER-encoded certificate.
144 @retval FALSE It's NOT a DER-encoded certificate.
148 IsDerEncodeCertificate (
149 IN CONST CHAR16
*FileSuffix
153 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
154 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
162 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
163 The function reads file content but won't open/close given FileHandle.
165 @param[in] FileHandle The FileHandle to be checked
167 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
168 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
172 IsAuthentication2Format (
173 IN EFI_FILE_HANDLE FileHandle
177 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
178 BOOLEAN IsAuth2Format
;
180 IsAuth2Format
= FALSE
;
183 // Read the whole file content
185 Status
= ReadFileContent(
187 (VOID
**) &mImageBase
,
191 if (EFI_ERROR (Status
)) {
195 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
196 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
200 if (CompareGuid(&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
201 IsAuth2Format
= TRUE
;
206 // Do not close File. simply check file content
208 if (mImageBase
!= NULL
) {
209 FreePool (mImageBase
);
213 return IsAuth2Format
;
217 Set Secure Boot option into variable space.
219 @param[in] VarValue The option of Secure Boot.
221 @retval EFI_SUCCESS The operation is finished successfully.
222 @retval Others Other errors as indicated.
226 SaveSecureBootVariable (
232 Status
= gRT
->SetVariable (
233 EFI_SECURE_BOOT_ENABLE_NAME
,
234 &gEfiSecureBootEnableDisableGuid
,
235 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
243 This code checks if the encode type and key strength of X.509
244 certificate is qualified.
246 @param[in] X509FileContext FileContext of X.509 certificate storing
248 @param[out] Error Error type checked in the certificate.
250 @return EFI_SUCCESS The certificate checked successfully.
251 @return EFI_INVALID_PARAMETER The parameter is invalid.
252 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
256 CheckX509Certificate (
257 IN SECUREBOOT_FILE_CONTEXT
* X509FileContext
,
258 OUT ENROLL_KEY_ERROR
* Error
269 if (X509FileContext
->FileName
== NULL
) {
270 *Error
= Unsupported_Type
;
271 return EFI_INVALID_PARAMETER
;
280 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
282 NameLength
= StrLen (X509FileContext
->FileName
);
283 if (NameLength
<= 4) {
284 DEBUG ((DEBUG_ERROR
, "Wrong X509 NameLength\n"));
285 *Error
= Unsupported_Type
;
286 return EFI_INVALID_PARAMETER
;
288 FilePostFix
= X509FileContext
->FileName
+ NameLength
- 4;
289 if (!IsDerEncodeCertificate (FilePostFix
)) {
290 DEBUG ((DEBUG_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix
));
291 *Error
= Unsupported_Type
;
292 return EFI_INVALID_PARAMETER
;
294 DEBUG ((DEBUG_INFO
, "FileName= %s\n", X509FileContext
->FileName
));
295 DEBUG ((DEBUG_INFO
, "FilePostFix = %s\n", FilePostFix
));
298 // Read the certificate file content
300 Status
= ReadFileContent (X509FileContext
->FHandle
, (VOID
**) &X509Data
, &X509DataSize
, 0);
301 if (EFI_ERROR (Status
)) {
302 DEBUG ((DEBUG_ERROR
, "Error occured while reading the file.\n"));
307 // Parse the public key context.
309 if (RsaGetPublicKeyFromX509 (X509Data
, X509DataSize
, &X509PubKey
) == FALSE
) {
310 DEBUG ((DEBUG_ERROR
, "Error occured while parsing the pubkey from certificate.\n"));
311 Status
= EFI_INVALID_PARAMETER
;
312 *Error
= Unsupported_Type
;
317 // Parse Module size of public key using interface provided by CryptoPkg, which is
318 // actually the size of public key.
320 if (X509PubKey
!= NULL
) {
321 RsaGetKey (X509PubKey
, RsaKeyN
, NULL
, &PubKeyModSize
);
322 if (PubKeyModSize
< CER_PUBKEY_MIN_SIZE
) {
323 DEBUG ((DEBUG_ERROR
, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
324 Status
= EFI_INVALID_PARAMETER
;
325 *Error
= Unqualified_Key
;
327 RsaFree (X509PubKey
);
331 if (X509Data
!= NULL
) {
339 Generate the PK signature list from the X509 Certificate storing file (.cer)
341 @param[in] X509File FileHandle of X509 Certificate storing file.
342 @param[out] PkCert Point to the data buffer to store the signature list.
344 @return EFI_UNSUPPORTED Unsupported Key Length.
345 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
349 CreatePkX509SignatureList (
350 IN EFI_FILE_HANDLE X509File
,
351 OUT EFI_SIGNATURE_LIST
**PkCert
357 EFI_SIGNATURE_DATA
*PkCertData
;
363 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
364 if (EFI_ERROR (Status
)) {
367 ASSERT (X509Data
!= NULL
);
370 // Allocate space for PK certificate list and initialize it.
371 // Create PK database entry with SignatureHeaderSize equals 0.
373 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
374 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
377 if (*PkCert
== NULL
) {
378 Status
= EFI_OUT_OF_RESOURCES
;
382 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
383 + sizeof(EFI_SIGNATURE_DATA
) - 1
385 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
386 (*PkCert
)->SignatureHeaderSize
= 0;
387 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
388 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
389 + sizeof(EFI_SIGNATURE_LIST
)
390 + (*PkCert
)->SignatureHeaderSize
);
391 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
393 // Fill the PK database with PKpub data from X509 certificate file.
395 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
399 if (X509Data
!= NULL
) {
403 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
412 Enroll new PK into the System without original PK's authentication.
414 The SignatureOwner GUID will be the same with PK's vendorguid.
416 @param[in] PrivateData The module's private data.
418 @retval EFI_SUCCESS New PK enrolled successfully.
419 @retval EFI_INVALID_PARAMETER The parameter is invalid.
420 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
425 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
431 EFI_SIGNATURE_LIST
*PkCert
;
435 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
436 if (EFI_ERROR (Status
)) {
441 // Prase the selected PK file and generate PK certificate list.
443 Status
= CreatePkX509SignatureList (
444 Private
->FileContext
->FHandle
,
447 if (EFI_ERROR (Status
)) {
450 ASSERT (PkCert
!= NULL
);
453 // Set Platform Key variable.
455 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
456 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
457 DataSize
= PkCert
->SignatureListSize
;
458 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
459 if (EFI_ERROR (Status
)) {
460 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
464 Status
= gRT
->SetVariable(
465 EFI_PLATFORM_KEY_NAME
,
466 &gEfiGlobalVariableGuid
,
471 if (EFI_ERROR (Status
)) {
472 if (Status
== EFI_OUT_OF_RESOURCES
) {
473 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
480 if (PkCert
!= NULL
) {
484 CloseEnrolledFile(Private
->FileContext
);
490 Enroll a new KEK item from public key storing file (*.pbk).
492 @param[in] PrivateData The module's private data.
494 @retval EFI_SUCCESS New KEK enrolled successfully.
495 @retval EFI_INVALID_PARAMETER The parameter is invalid.
496 @retval EFI_UNSUPPORTED Unsupported command.
497 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
502 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
508 EFI_SIGNATURE_LIST
*KekSigList
;
511 CPL_KEY_INFO
*KeyInfo
;
512 EFI_SIGNATURE_DATA
*KEKSigData
;
513 UINTN KekSigListSize
;
528 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
529 // First, We have to parse out public key data from the pbk key file.
531 Status
= ReadFileContent (
532 Private
->FileContext
->FHandle
,
537 if (EFI_ERROR (Status
)) {
540 ASSERT (KeyBlob
!= NULL
);
541 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
542 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
543 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
544 Status
= EFI_UNSUPPORTED
;
549 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
551 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
552 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
553 if (KeyBuffer
== NULL
) {
554 Status
= EFI_OUT_OF_RESOURCES
;
558 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
559 KeyLenInBytes
/ sizeof (UINTN
),
563 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
566 // Form an new EFI_SIGNATURE_LIST.
568 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
569 + sizeof(EFI_SIGNATURE_DATA
) - 1
570 + WIN_CERT_UEFI_RSA2048_SIZE
;
572 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
573 if (KekSigList
== NULL
) {
574 Status
= EFI_OUT_OF_RESOURCES
;
578 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
579 + sizeof(EFI_SIGNATURE_DATA
) - 1
580 + WIN_CERT_UEFI_RSA2048_SIZE
;
581 KekSigList
->SignatureHeaderSize
= 0;
582 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
583 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
585 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
586 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
588 KEKSigData
->SignatureData
,
589 KeyBlob
+ sizeof(CPL_KEY_INFO
),
590 WIN_CERT_UEFI_RSA2048_SIZE
594 // Check if KEK entry has been already existed.
595 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
596 // new KEK to original variable.
598 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
599 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
600 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
601 if (EFI_ERROR (Status
)) {
602 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
606 Status
= gRT
->GetVariable(
607 EFI_KEY_EXCHANGE_KEY_NAME
,
608 &gEfiGlobalVariableGuid
,
613 if (Status
== EFI_BUFFER_TOO_SMALL
) {
614 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
615 } else if (Status
!= EFI_NOT_FOUND
) {
620 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
622 Status
= gRT
->SetVariable(
623 EFI_KEY_EXCHANGE_KEY_NAME
,
624 &gEfiGlobalVariableGuid
,
629 if (EFI_ERROR (Status
)) {
635 CloseEnrolledFile(Private
->FileContext
);
637 if (Private
->SignatureGUID
!= NULL
) {
638 FreePool (Private
->SignatureGUID
);
639 Private
->SignatureGUID
= NULL
;
642 if (KeyBlob
!= NULL
) {
645 if (KeyBuffer
!= NULL
) {
646 FreePool (KeyBuffer
);
648 if (KekSigList
!= NULL
) {
649 FreePool (KekSigList
);
656 Enroll a new KEK item from X509 certificate file.
658 @param[in] PrivateData The module's private data.
660 @retval EFI_SUCCESS New X509 is enrolled successfully.
661 @retval EFI_INVALID_PARAMETER The parameter is invalid.
662 @retval EFI_UNSUPPORTED Unsupported command.
663 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
668 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
674 EFI_SIGNATURE_DATA
*KEKSigData
;
675 EFI_SIGNATURE_LIST
*KekSigList
;
677 UINTN KekSigListSize
;
687 Status
= ReadFileContent (
688 Private
->FileContext
->FHandle
,
693 if (EFI_ERROR (Status
)) {
696 ASSERT (X509Data
!= NULL
);
698 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
699 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
700 if (KekSigList
== NULL
) {
701 Status
= EFI_OUT_OF_RESOURCES
;
706 // Fill Certificate Database parameters.
708 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
709 KekSigList
->SignatureHeaderSize
= 0;
710 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
711 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
713 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
714 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
715 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
718 // Check if KEK been already existed.
719 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
720 // new kek to original variable
722 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
723 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
724 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
725 if (EFI_ERROR (Status
)) {
726 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
730 Status
= gRT
->GetVariable(
731 EFI_KEY_EXCHANGE_KEY_NAME
,
732 &gEfiGlobalVariableGuid
,
737 if (Status
== EFI_BUFFER_TOO_SMALL
) {
738 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
739 } else if (Status
!= EFI_NOT_FOUND
) {
743 Status
= gRT
->SetVariable(
744 EFI_KEY_EXCHANGE_KEY_NAME
,
745 &gEfiGlobalVariableGuid
,
750 if (EFI_ERROR (Status
)) {
756 CloseEnrolledFile(Private
->FileContext
);
758 if (Private
->SignatureGUID
!= NULL
) {
759 FreePool (Private
->SignatureGUID
);
760 Private
->SignatureGUID
= NULL
;
763 if (KekSigList
!= NULL
) {
764 FreePool (KekSigList
);
771 Enroll new KEK into the System without PK's authentication.
772 The SignatureOwner GUID will be Private->SignatureGUID.
774 @param[in] PrivateData The module's private data.
776 @retval EFI_SUCCESS New KEK enrolled successful.
777 @retval EFI_INVALID_PARAMETER The parameter is invalid.
778 @retval others Fail to enroll KEK data.
782 EnrollKeyExchangeKey (
783 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
790 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
791 return EFI_INVALID_PARAMETER
;
794 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
795 if (EFI_ERROR (Status
)) {
800 // Parse the file's postfix. Supports DER-encoded X509 certificate,
801 // and .pbk as RSA public key file.
803 NameLength
= StrLen (Private
->FileContext
->FileName
);
804 if (NameLength
<= 4) {
805 return EFI_INVALID_PARAMETER
;
807 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
808 if (IsDerEncodeCertificate(FilePostFix
)) {
809 return EnrollX509ToKek (Private
);
810 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
811 return EnrollRsa2048ToKek (Private
);
814 // File type is wrong, simply close it
816 CloseEnrolledFile(Private
->FileContext
);
818 return EFI_INVALID_PARAMETER
;
823 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
824 KEK's authentication.
826 @param[in] PrivateData The module's private data.
827 @param[in] VariableName Variable name of signature database, must be
828 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
830 @retval EFI_SUCCESS New X509 is enrolled successfully.
831 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
836 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
837 IN CHAR16
*VariableName
843 EFI_SIGNATURE_LIST
*SigDBCert
;
844 EFI_SIGNATURE_DATA
*SigDBCertData
;
855 SigDBCertData
= NULL
;
858 Status
= ReadFileContent (
859 Private
->FileContext
->FHandle
,
864 if (EFI_ERROR (Status
)) {
867 ASSERT (X509Data
!= NULL
);
869 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
871 Data
= AllocateZeroPool (SigDBSize
);
873 Status
= EFI_OUT_OF_RESOURCES
;
878 // Fill Certificate Database parameters.
880 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
881 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
882 SigDBCert
->SignatureHeaderSize
= 0;
883 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
884 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
886 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
887 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
888 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
891 // Check if signature database entry has been already existed.
892 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
893 // new signature data to original variable
895 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
896 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
897 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
898 if (EFI_ERROR (Status
)) {
899 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
903 Status
= gRT
->GetVariable(
905 &gEfiImageSecurityDatabaseGuid
,
910 if (Status
== EFI_BUFFER_TOO_SMALL
) {
911 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
912 } else if (Status
!= EFI_NOT_FOUND
) {
916 Status
= gRT
->SetVariable(
918 &gEfiImageSecurityDatabaseGuid
,
923 if (EFI_ERROR (Status
)) {
929 CloseEnrolledFile(Private
->FileContext
);
931 if (Private
->SignatureGUID
!= NULL
) {
932 FreePool (Private
->SignatureGUID
);
933 Private
->SignatureGUID
= NULL
;
940 if (X509Data
!= NULL
) {
948 Check whether signature is in specified database.
950 @param[in] VariableName Name of database variable that is searched in.
951 @param[in] Signature Pointer to signature that is searched for.
952 @param[in] SignatureSize Size of Signature.
954 @return TRUE Found the signature in the variable database.
955 @return FALSE Not found the signature in the variable database.
959 IsSignatureFoundInDatabase (
960 IN CHAR16
*VariableName
,
962 IN UINTN SignatureSize
966 EFI_SIGNATURE_LIST
*CertList
;
967 EFI_SIGNATURE_DATA
*Cert
;
975 // Read signature database variable.
980 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
981 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
985 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
990 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
991 if (EFI_ERROR (Status
)) {
996 // Enumerate all signature data in SigDB to check if signature exists for executable.
998 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
999 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1000 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1001 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1002 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1003 for (Index
= 0; Index
< CertCount
; Index
++) {
1004 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1006 // Find the signature in database.
1011 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1019 DataSize
-= CertList
->SignatureListSize
;
1020 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1032 Calculate the hash of a certificate data with the specified hash algorithm.
1034 @param[in] CertData The certificate data to be hashed.
1035 @param[in] CertSize The certificate size in bytes.
1036 @param[in] HashAlg The specified hash algorithm.
1037 @param[out] CertHash The output digest of the certificate
1039 @retval TRUE Successfully got the hash of the CertData.
1040 @retval FALSE Failed to get the hash of CertData.
1060 if (HashAlg
>= HASHALG_MAX
) {
1065 // Retrieve the TBSCertificate for Hash Calculation.
1067 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1072 // 1. Initialize context of hash.
1074 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1075 HashCtx
= AllocatePool (CtxSize
);
1076 ASSERT (HashCtx
!= NULL
);
1079 // 2. Initialize a hash context.
1081 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1087 // 3. Calculate the hash.
1089 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1095 // 4. Get the hash result.
1097 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1098 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1101 if (HashCtx
!= NULL
) {
1109 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1111 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1112 @param[in] CertSize Size of X.509 Certificate.
1114 @return TRUE Found the certificate hash in the forbidden database.
1115 @return FALSE Certificate hash is Not found in the forbidden database.
1119 IsCertHashFoundInDbx (
1120 IN UINT8
*Certificate
,
1126 EFI_SIGNATURE_LIST
*DbxList
;
1127 EFI_SIGNATURE_DATA
*CertHash
;
1128 UINTN CertHashCount
;
1131 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1133 UINTN SiglistHeaderSize
;
1138 HashAlg
= HASHALG_MAX
;
1142 // Read signature database variable.
1145 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1146 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1150 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1155 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1156 if (EFI_ERROR (Status
)) {
1161 // Check whether the certificate hash exists in the forbidden database.
1163 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1164 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1166 // Determine Hash Algorithm of Certificate in the forbidden database.
1168 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1169 HashAlg
= HASHALG_SHA256
;
1170 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1171 HashAlg
= HASHALG_SHA384
;
1172 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1173 HashAlg
= HASHALG_SHA512
;
1175 DataSize
-= DbxList
->SignatureListSize
;
1176 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1181 // Calculate the hash value of current db certificate for comparision.
1183 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1187 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1188 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1189 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1190 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1192 // Iterate each Signature Data Node within this CertList for verify.
1194 DbxCertHash
= CertHash
->SignatureData
;
1195 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1197 // Hash of Certificate is found in forbidden database.
1202 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1205 DataSize
-= DbxList
->SignatureListSize
;
1206 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1218 Check whether the signature list exists in given variable data.
1220 It searches the signature list for the certificate hash by CertType.
1221 If the signature list is found, get the offset of Database for the
1222 next hash of a certificate.
1224 @param[in] Database Variable data to save signature list.
1225 @param[in] DatabaseSize Variable size.
1226 @param[in] SignatureType The type of the signature.
1227 @param[out] Offset The offset to save a new hash of certificate.
1229 @return TRUE The signature list is found in the forbidden database.
1230 @return FALSE The signature list is not found in the forbidden database.
1233 GetSignaturelistOffset (
1234 IN EFI_SIGNATURE_LIST
*Database
,
1235 IN UINTN DatabaseSize
,
1236 IN EFI_GUID
*SignatureType
,
1240 EFI_SIGNATURE_LIST
*SigList
;
1243 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1249 SiglistSize
= DatabaseSize
;
1250 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1251 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1252 *Offset
= DatabaseSize
- SiglistSize
;
1255 SiglistSize
-= SigList
->SignatureListSize
;
1256 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1263 Enroll a new X509 certificate hash into Signature Database (dbx) without
1264 KEK's authentication.
1266 @param[in] PrivateData The module's private data.
1267 @param[in] HashAlg The hash algorithm to enroll the certificate.
1268 @param[in] RevocationDate The revocation date of the certificate.
1269 @param[in] RevocationTime The revocation time of the certificate.
1270 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1272 @retval EFI_SUCCESS New X509 is enrolled successfully.
1273 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1274 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1278 EnrollX509HashtoSigDB (
1279 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1281 IN EFI_HII_DATE
*RevocationDate
,
1282 IN EFI_HII_TIME
*RevocationTime
,
1283 IN BOOLEAN AlwaysRevocation
1289 EFI_SIGNATURE_LIST
*SignatureList
;
1290 UINTN SignatureListSize
;
1296 EFI_SIGNATURE_DATA
*SignatureData
;
1297 UINTN SignatureSize
;
1298 EFI_GUID SignatureType
;
1300 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1301 UINT16
* FilePostFix
;
1308 SignatureData
= NULL
;
1309 SignatureList
= NULL
;
1313 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1314 return EFI_INVALID_PARAMETER
;
1317 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1318 if (EFI_ERROR (Status
)) {
1323 // Parse the file's postfix.
1325 NameLength
= StrLen (Private
->FileContext
->FileName
);
1326 if (NameLength
<= 4) {
1327 return EFI_INVALID_PARAMETER
;
1329 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1330 if (!IsDerEncodeCertificate(FilePostFix
)) {
1332 // Only supports DER-encoded X509 certificate.
1334 return EFI_INVALID_PARAMETER
;
1338 // Get the certificate from file and calculate its hash.
1340 Status
= ReadFileContent (
1341 Private
->FileContext
->FHandle
,
1346 if (EFI_ERROR (Status
)) {
1349 ASSERT (X509Data
!= NULL
);
1351 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1356 // Get the variable for enrollment.
1359 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1360 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1361 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1363 return EFI_OUT_OF_RESOURCES
;
1366 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1367 if (EFI_ERROR (Status
)) {
1373 // Allocate memory for Signature and fill the Signature
1375 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1376 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1377 if (SignatureData
== NULL
) {
1378 return EFI_OUT_OF_RESOURCES
;
1380 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1381 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1386 if (!AlwaysRevocation
) {
1387 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1388 Time
->Year
= RevocationDate
->Year
;
1389 Time
->Month
= RevocationDate
->Month
;
1390 Time
->Day
= RevocationDate
->Day
;
1391 Time
->Hour
= RevocationTime
->Hour
;
1392 Time
->Minute
= RevocationTime
->Minute
;
1393 Time
->Second
= RevocationTime
->Second
;
1397 // Determine the GUID for certificate hash.
1400 case HASHALG_SHA256
:
1401 SignatureType
= gEfiCertX509Sha256Guid
;
1403 case HASHALG_SHA384
:
1404 SignatureType
= gEfiCertX509Sha384Guid
;
1406 case HASHALG_SHA512
:
1407 SignatureType
= gEfiCertX509Sha512Guid
;
1414 // Add signature into the new variable data buffer
1416 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1418 // Add the signature to the found signaturelist.
1420 DbSize
= DataSize
+ SignatureSize
;
1421 NewData
= AllocateZeroPool (DbSize
);
1422 if (NewData
== NULL
) {
1423 Status
= EFI_OUT_OF_RESOURCES
;
1427 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1428 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1429 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1431 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1432 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1434 Offset
+= SignatureListSize
;
1435 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1436 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1443 // Create a new signaturelist, and add the signature into the signaturelist.
1445 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1446 NewData
= AllocateZeroPool (DbSize
);
1447 if (NewData
== NULL
) {
1448 Status
= EFI_OUT_OF_RESOURCES
;
1452 // Fill Certificate Database parameters.
1454 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1455 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1456 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1457 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1458 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1459 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1460 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1461 CopyMem (NewData
, Data
, DataSize
);
1468 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1469 if (EFI_ERROR (Status
)) {
1473 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1474 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1475 Status
= gRT
->SetVariable(
1476 EFI_IMAGE_SECURITY_DATABASE1
,
1477 &gEfiImageSecurityDatabaseGuid
,
1482 if (EFI_ERROR (Status
)) {
1488 CloseEnrolledFile(Private
->FileContext
);
1490 if (Private
->SignatureGUID
!= NULL
) {
1491 FreePool (Private
->SignatureGUID
);
1492 Private
->SignatureGUID
= NULL
;
1499 if (SignatureData
!= NULL
) {
1500 FreePool (SignatureData
);
1503 if (X509Data
!= NULL
) {
1504 FreePool (X509Data
);
1511 Check whether a certificate from a file exists in dbx.
1513 @param[in] PrivateData The module's private data.
1514 @param[in] VariableName Variable name of signature database, must be
1515 EFI_IMAGE_SECURITY_DATABASE1.
1517 @retval TRUE The X509 certificate is found in dbx successfully.
1518 @retval FALSE The X509 certificate is not found in dbx.
1522 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1523 IN CHAR16
*VariableName
1532 // Read the certificate from file
1536 Status
= ReadFileContent (
1537 Private
->FileContext
->FHandle
,
1542 if (EFI_ERROR (Status
)) {
1547 // Check the raw certificate.
1550 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1556 // Check the hash of certificate.
1558 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1564 if (X509Data
!= NULL
) {
1565 FreePool (X509Data
);
1572 Reads contents of a PE/COFF image in memory buffer.
1574 Caution: This function may receive untrusted input.
1575 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1576 read is within the image buffer.
1578 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1579 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1580 @param ReadSize On input, the size in bytes of the requested read operation.
1581 On output, the number of bytes actually read.
1582 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1584 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1588 SecureBootConfigImageRead (
1589 IN VOID
*FileHandle
,
1590 IN UINTN FileOffset
,
1591 IN OUT UINTN
*ReadSize
,
1597 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1598 return EFI_INVALID_PARAMETER
;
1601 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1602 return EFI_INVALID_PARAMETER
;
1605 EndPosition
= FileOffset
+ *ReadSize
;
1606 if (EndPosition
> mImageSize
) {
1607 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1610 if (FileOffset
>= mImageSize
) {
1614 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1620 Load PE/COFF image information into internal buffer and check its validity.
1622 @retval EFI_SUCCESS Successful
1623 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1624 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1632 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1633 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1634 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1635 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1641 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1642 ImageContext
.Handle
= (VOID
*) mImageBase
;
1643 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1646 // Get information about the image being loaded
1648 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1649 if (EFI_ERROR (Status
)) {
1651 // The information can't be got from the invalid PeImage
1653 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1658 // Read the Dos header
1660 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1661 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1664 // DOS image header is present,
1665 // So read the PE header after the DOS image header
1667 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1671 mPeCoffHeaderOffset
= 0;
1675 // Read PE header and check the signature validity and machine compatibility
1677 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1678 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1680 return EFI_UNSUPPORTED
;
1683 mNtHeader
.Pe32
= NtHeader32
;
1686 // Check the architecture field of PE header and get the Certificate Data Directory data
1687 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1689 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1690 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1691 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1693 // 32-bits Architecture
1695 mImageType
= ImageType_IA32
;
1696 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1698 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1699 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1700 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1702 // 64-bits Architecture
1704 mImageType
= ImageType_X64
;
1705 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1706 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1708 return EFI_UNSUPPORTED
;
1715 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1716 PE/COFF Specification 8.0 Appendix A
1718 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1719 the function LoadPeImage ().
1721 @param[in] HashAlg Hash algorithm type.
1723 @retval TRUE Successfully hash image.
1724 @retval FALSE Fail in hash image.
1733 EFI_IMAGE_SECTION_HEADER
*Section
;
1738 UINTN SumOfBytesHashed
;
1739 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1744 SectionHeader
= NULL
;
1747 if (HashAlg
!= HASHALG_SHA256
) {
1752 // Initialize context of hash.
1754 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1756 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1757 mCertType
= gEfiCertSha256Guid
;
1759 CtxSize
= mHash
[HashAlg
].GetContextSize();
1761 HashCtx
= AllocatePool (CtxSize
);
1762 ASSERT (HashCtx
!= NULL
);
1764 // 1. Load the image header into memory.
1766 // 2. Initialize a SHA hash context.
1767 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1772 // Measuring PE/COFF Image Header;
1773 // But CheckSum field and SECURITY data directory (certificate) are excluded
1777 // 3. Calculate the distance from the base of the image header to the image checksum address.
1778 // 4. Hash the image header from its base to beginning of the image checksum.
1780 HashBase
= mImageBase
;
1781 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1785 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1788 // Use PE32+ offset.
1790 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1793 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1798 // 5. Skip over the image checksum (it occupies a single ULONG).
1799 // 6. Get the address of the beginning of the Cert Directory.
1800 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1802 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1806 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1807 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1810 // Use PE32+ offset.
1812 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1813 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1816 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1821 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1822 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1824 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1828 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1829 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1832 // Use PE32+ offset.
1834 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1835 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1838 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1843 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1845 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1849 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1854 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1858 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1859 // structures in the image. The 'NumberOfSections' field of the image
1860 // header indicates how big the table should be. Do not include any
1861 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1863 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1864 ASSERT (SectionHeader
!= NULL
);
1866 // 12. Using the 'PointerToRawData' in the referenced section headers as
1867 // a key, arrange the elements in the table in ascending order. In other
1868 // words, sort the section headers according to the disk-file offset of
1871 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1873 mPeCoffHeaderOffset
+
1875 sizeof (EFI_IMAGE_FILE_HEADER
) +
1876 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1878 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1880 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1881 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1884 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1889 // 13. Walk through the sorted table, bring the corresponding section
1890 // into memory, and hash the entire section (using the 'SizeOfRawData'
1891 // field in the section header to determine the amount of data to hash).
1892 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1893 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1895 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1896 Section
= &SectionHeader
[Index
];
1897 if (Section
->SizeOfRawData
== 0) {
1900 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1901 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1903 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1908 SumOfBytesHashed
+= HashSize
;
1912 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1913 // data in the file that needs to be added to the hash. This data begins
1914 // at file offset SUM_OF_BYTES_HASHED and its length is:
1915 // FileSize - (CertDirectory->Size)
1917 if (mImageSize
> SumOfBytesHashed
) {
1918 HashBase
= mImageBase
+ SumOfBytesHashed
;
1919 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1925 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1929 // Use PE32+ offset.
1933 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1937 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1943 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1946 if (HashCtx
!= NULL
) {
1949 if (SectionHeader
!= NULL
) {
1950 FreePool (SectionHeader
);
1956 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
1957 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1960 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1961 @retval EFI_SUCCESS Hash successfully.
1970 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1972 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1974 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1976 // Check the Hash algorithm in PE/COFF Authenticode.
1977 // According to PKCS#7 Definition:
1978 // SignedData ::= SEQUENCE {
1980 // digestAlgorithms DigestAlgorithmIdentifiers,
1981 // contentInfo ContentInfo,
1983 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1984 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1985 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1987 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1989 // Only support two bytes of Long Form of Length Encoding.
1995 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2000 if (Index
== HASHALG_MAX
) {
2001 return EFI_UNSUPPORTED
;
2005 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2007 if (!HashPeImage(Index
)) {
2008 return EFI_UNSUPPORTED
;
2015 Enroll a new signature of executable into Signature Database.
2017 @param[in] PrivateData The module's private data.
2018 @param[in] VariableName Variable name of signature database, must be
2019 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2020 or EFI_IMAGE_SECURITY_DATABASE2.
2022 @retval EFI_SUCCESS New signature is enrolled successfully.
2023 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2024 @retval EFI_UNSUPPORTED Unsupported command.
2025 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2029 EnrollAuthentication2Descriptor (
2030 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2031 IN CHAR16
*VariableName
2042 // DBT only support DER-X509 Cert Enrollment
2044 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2045 return EFI_UNSUPPORTED
;
2049 // Read the whole file content
2051 Status
= ReadFileContent(
2052 Private
->FileContext
->FHandle
,
2053 (VOID
**) &mImageBase
,
2057 if (EFI_ERROR (Status
)) {
2060 ASSERT (mImageBase
!= NULL
);
2062 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2063 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2066 // Check if SigDB variable has been already existed.
2067 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2068 // new signature data to original variable
2071 Status
= gRT
->GetVariable(
2073 &gEfiImageSecurityDatabaseGuid
,
2078 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2079 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2080 } else if (Status
!= EFI_NOT_FOUND
) {
2085 // Directly set AUTHENTICATION_2 data to SetVariable
2087 Status
= gRT
->SetVariable(
2089 &gEfiImageSecurityDatabaseGuid
,
2095 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2099 CloseEnrolledFile(Private
->FileContext
);
2105 if (mImageBase
!= NULL
) {
2106 FreePool (mImageBase
);
2116 Enroll a new signature of executable into Signature Database.
2118 @param[in] PrivateData The module's private data.
2119 @param[in] VariableName Variable name of signature database, must be
2120 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2121 or EFI_IMAGE_SECURITY_DATABASE2.
2123 @retval EFI_SUCCESS New signature is enrolled successfully.
2124 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2125 @retval EFI_UNSUPPORTED Unsupported command.
2126 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2130 EnrollImageSignatureToSigDB (
2131 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2132 IN CHAR16
*VariableName
2136 EFI_SIGNATURE_LIST
*SigDBCert
;
2137 EFI_SIGNATURE_DATA
*SigDBCertData
;
2142 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2145 GuidCertData
= NULL
;
2147 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2148 return EFI_UNSUPPORTED
;
2152 // Form the SigDB certificate list.
2153 // Format the data item into EFI_SIGNATURE_LIST type.
2155 // We need to parse signature data of executable from specified signed executable file.
2156 // In current implementation, we simply trust the pass-in signed executable file.
2157 // In reality, it's OS's responsibility to verify the signed executable file.
2161 // Read the whole file content
2163 Status
= ReadFileContent(
2164 Private
->FileContext
->FHandle
,
2165 (VOID
**) &mImageBase
,
2169 if (EFI_ERROR (Status
)) {
2172 ASSERT (mImageBase
!= NULL
);
2174 Status
= LoadPeImage ();
2175 if (EFI_ERROR (Status
)) {
2179 if (mSecDataDir
->SizeOfCert
== 0) {
2180 if (!HashPeImage (HASHALG_SHA256
)) {
2181 Status
= EFI_SECURITY_VIOLATION
;
2187 // Read the certificate data
2189 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2191 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2192 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2193 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2194 Status
= EFI_ABORTED
;
2198 if (!HashPeImage (HASHALG_SHA256
)) {
2199 Status
= EFI_ABORTED
;
2203 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2205 Status
= HashPeImageByType ();
2206 if (EFI_ERROR (Status
)) {
2210 Status
= EFI_ABORTED
;
2216 // Create a new SigDB entry.
2218 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2219 + sizeof(EFI_SIGNATURE_DATA
) - 1
2220 + (UINT32
) mImageDigestSize
;
2222 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2224 Status
= EFI_OUT_OF_RESOURCES
;
2229 // Adjust the Certificate Database parameters.
2231 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2232 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2233 SigDBCert
->SignatureHeaderSize
= 0;
2234 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2235 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2237 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2238 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2239 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2241 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2242 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2243 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2244 if (EFI_ERROR (Status
)) {
2245 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2250 // Check if SigDB variable has been already existed.
2251 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2252 // new signature data to original variable
2255 Status
= gRT
->GetVariable(
2257 &gEfiImageSecurityDatabaseGuid
,
2262 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2263 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2264 } else if (Status
!= EFI_NOT_FOUND
) {
2269 // Enroll the variable.
2271 Status
= gRT
->SetVariable(
2273 &gEfiImageSecurityDatabaseGuid
,
2278 if (EFI_ERROR (Status
)) {
2284 CloseEnrolledFile(Private
->FileContext
);
2286 if (Private
->SignatureGUID
!= NULL
) {
2287 FreePool (Private
->SignatureGUID
);
2288 Private
->SignatureGUID
= NULL
;
2295 if (mImageBase
!= NULL
) {
2296 FreePool (mImageBase
);
2304 Enroll signature into DB/DBX/DBT without KEK's authentication.
2305 The SignatureOwner GUID will be Private->SignatureGUID.
2307 @param[in] PrivateData The module's private data.
2308 @param[in] VariableName Variable name of signature database, must be
2309 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2311 @retval EFI_SUCCESS New signature enrolled successfully.
2312 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2313 @retval others Fail to enroll signature data.
2317 EnrollSignatureDatabase (
2318 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2319 IN CHAR16
*VariableName
2322 UINT16
* FilePostFix
;
2326 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2327 return EFI_INVALID_PARAMETER
;
2330 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2331 if (EFI_ERROR (Status
)) {
2336 // Parse the file's postfix.
2338 NameLength
= StrLen (Private
->FileContext
->FileName
);
2339 if (NameLength
<= 4) {
2340 return EFI_INVALID_PARAMETER
;
2342 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2343 if (IsDerEncodeCertificate (FilePostFix
)) {
2345 // Supports DER-encoded X509 certificate.
2347 return EnrollX509toSigDB (Private
, VariableName
);
2348 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2349 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2351 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2356 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2357 by GUID in the page for user to select and delete as needed.
2359 @param[in] PrivateData Module's private data.
2360 @param[in] VariableName The variable name of the vendor's signature database.
2361 @param[in] VendorGuid A unique identifier for the vendor.
2362 @param[in] LabelNumber Label number to insert opcodes.
2363 @param[in] FormId Form ID of current page.
2364 @param[in] QuestionIdBase Base question id of the signature list.
2366 @retval EFI_SUCCESS Success to update the signature list page
2367 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2372 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2373 IN CHAR16
*VariableName
,
2374 IN EFI_GUID
*VendorGuid
,
2375 IN UINT16 LabelNumber
,
2376 IN EFI_FORM_ID FormId
,
2377 IN EFI_QUESTION_ID QuestionIdBase
2384 VOID
*StartOpCodeHandle
;
2385 VOID
*EndOpCodeHandle
;
2386 EFI_IFR_GUID_LABEL
*StartLabel
;
2387 EFI_IFR_GUID_LABEL
*EndLabel
;
2390 EFI_SIGNATURE_LIST
*CertList
;
2391 EFI_SIGNATURE_DATA
*Cert
;
2392 UINT32 ItemDataSize
;
2394 EFI_STRING_ID GuidID
;
2401 StartOpCodeHandle
= NULL
;
2402 EndOpCodeHandle
= NULL
;
2405 // Initialize the container for dynamic opcodes.
2407 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2408 if (StartOpCodeHandle
== NULL
) {
2409 Status
= EFI_OUT_OF_RESOURCES
;
2413 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2414 if (EndOpCodeHandle
== NULL
) {
2415 Status
= EFI_OUT_OF_RESOURCES
;
2420 // Create Hii Extend Label OpCode.
2422 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2426 sizeof (EFI_IFR_GUID_LABEL
)
2428 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2429 StartLabel
->Number
= LabelNumber
;
2431 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2435 sizeof (EFI_IFR_GUID_LABEL
)
2437 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2438 EndLabel
->Number
= LABEL_END
;
2444 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2445 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2449 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2451 Status
= EFI_OUT_OF_RESOURCES
;
2455 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2456 if (EFI_ERROR (Status
)) {
2460 GuidStr
= AllocateZeroPool (100);
2461 if (GuidStr
== NULL
) {
2462 Status
= EFI_OUT_OF_RESOURCES
;
2467 // Enumerate all KEK pub data.
2469 ItemDataSize
= (UINT32
) DataSize
;
2470 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2473 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2475 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2476 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2477 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2478 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2479 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2480 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2481 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2482 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2483 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2484 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2485 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2486 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2487 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2488 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2491 // The signature type is not supported in current implementation.
2493 ItemDataSize
-= CertList
->SignatureListSize
;
2494 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2498 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2499 for (Index
= 0; Index
< CertCount
; Index
++) {
2500 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2501 + sizeof (EFI_SIGNATURE_LIST
)
2502 + CertList
->SignatureHeaderSize
2503 + Index
* CertList
->SignatureSize
);
2505 // Display GUID and help
2507 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2508 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2509 HiiCreateCheckBoxOpCode (
2511 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2516 EFI_IFR_FLAG_CALLBACK
,
2522 ItemDataSize
-= CertList
->SignatureListSize
;
2523 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2528 PrivateData
->HiiHandle
,
2529 &gSecureBootConfigFormSetGuid
,
2535 if (StartOpCodeHandle
!= NULL
) {
2536 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2539 if (EndOpCodeHandle
!= NULL
) {
2540 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2547 if (GuidStr
!= NULL
) {
2555 Delete a KEK entry from KEK database.
2557 @param[in] PrivateData Module's private data.
2558 @param[in] QuestionId Question id of the KEK item to delete.
2560 @retval EFI_SUCCESS Delete kek item successfully.
2561 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2565 DeleteKeyExchangeKey (
2566 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2567 IN EFI_QUESTION_ID QuestionId
2576 EFI_SIGNATURE_LIST
*CertList
;
2577 EFI_SIGNATURE_LIST
*NewCertList
;
2578 EFI_SIGNATURE_DATA
*Cert
;
2581 BOOLEAN IsKEKItemFound
;
2583 UINTN DeleteKekIndex
;
2591 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2593 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2594 if (EFI_ERROR (Status
)) {
2599 // Get original KEK variable.
2602 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2603 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2607 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2608 if (OldData
== NULL
) {
2609 Status
= EFI_OUT_OF_RESOURCES
;
2613 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2614 if (EFI_ERROR(Status
)) {
2619 // Allocate space for new variable.
2621 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2623 Status
= EFI_OUT_OF_RESOURCES
;
2628 // Enumerate all KEK pub data and erasing the target item.
2630 IsKEKItemFound
= FALSE
;
2631 KekDataSize
= (UINT32
) DataSize
;
2632 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2635 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2636 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2637 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2638 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2639 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2640 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2641 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2642 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2643 for (Index
= 0; Index
< CertCount
; Index
++) {
2644 if (GuidIndex
== DeleteKekIndex
) {
2646 // Find it! Skip it!
2648 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2649 IsKEKItemFound
= TRUE
;
2652 // This item doesn't match. Copy it to the Data buffer.
2654 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2655 Offset
+= CertList
->SignatureSize
;
2658 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2662 // This List doesn't match. Copy it to the Data buffer.
2664 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2665 Offset
+= CertList
->SignatureListSize
;
2668 KekDataSize
-= CertList
->SignatureListSize
;
2669 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2672 if (!IsKEKItemFound
) {
2674 // Doesn't find the Kek Item!
2676 Status
= EFI_NOT_FOUND
;
2681 // Delete the Signature header if there is no signature in the list.
2683 KekDataSize
= Offset
;
2684 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2686 ZeroMem (OldData
, KekDataSize
);
2687 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2688 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2689 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2690 if (CertCount
!= 0) {
2691 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2692 Offset
+= CertList
->SignatureListSize
;
2694 KekDataSize
-= CertList
->SignatureListSize
;
2695 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2699 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2700 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2701 if (EFI_ERROR (Status
)) {
2702 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2707 Status
= gRT
->SetVariable(
2708 EFI_KEY_EXCHANGE_KEY_NAME
,
2709 &gEfiGlobalVariableGuid
,
2714 if (EFI_ERROR (Status
)) {
2715 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2724 if (OldData
!= NULL
) {
2728 return UpdateDeletePage (
2730 EFI_KEY_EXCHANGE_KEY_NAME
,
2731 &gEfiGlobalVariableGuid
,
2733 FORMID_DELETE_KEK_FORM
,
2734 OPTION_DEL_KEK_QUESTION_ID
2739 Delete a signature entry from signature database.
2741 @param[in] PrivateData Module's private data.
2742 @param[in] VariableName The variable name of the vendor's signature database.
2743 @param[in] VendorGuid A unique identifier for the vendor.
2744 @param[in] LabelNumber Label number to insert opcodes.
2745 @param[in] FormId Form ID of current page.
2746 @param[in] QuestionIdBase Base question id of the signature list.
2747 @param[in] DeleteIndex Signature index to delete.
2749 @retval EFI_SUCCESS Delete signature successfully.
2750 @retval EFI_NOT_FOUND Can't find the signature item,
2751 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2755 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2756 IN CHAR16
*VariableName
,
2757 IN EFI_GUID
*VendorGuid
,
2758 IN UINT16 LabelNumber
,
2759 IN EFI_FORM_ID FormId
,
2760 IN EFI_QUESTION_ID QuestionIdBase
,
2761 IN UINTN DeleteIndex
2770 EFI_SIGNATURE_LIST
*CertList
;
2771 EFI_SIGNATURE_LIST
*NewCertList
;
2772 EFI_SIGNATURE_DATA
*Cert
;
2775 BOOLEAN IsItemFound
;
2776 UINT32 ItemDataSize
;
2785 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2786 if (EFI_ERROR (Status
)) {
2791 // Get original signature list data.
2794 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2795 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2799 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2800 if (OldData
== NULL
) {
2801 Status
= EFI_OUT_OF_RESOURCES
;
2805 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2806 if (EFI_ERROR(Status
)) {
2811 // Allocate space for new variable.
2813 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2815 Status
= EFI_OUT_OF_RESOURCES
;
2820 // Enumerate all signature data and erasing the target item.
2822 IsItemFound
= FALSE
;
2823 ItemDataSize
= (UINT32
) DataSize
;
2824 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2827 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2828 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2829 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2830 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2831 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2832 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2833 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2834 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2837 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2839 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2840 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2841 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2842 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2843 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2844 for (Index
= 0; Index
< CertCount
; Index
++) {
2845 if (GuidIndex
== DeleteIndex
) {
2847 // Find it! Skip it!
2849 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2853 // This item doesn't match. Copy it to the Data buffer.
2855 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2856 Offset
+= CertList
->SignatureSize
;
2859 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2863 // This List doesn't match. Just copy it to the Data buffer.
2865 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2866 Offset
+= CertList
->SignatureListSize
;
2869 ItemDataSize
-= CertList
->SignatureListSize
;
2870 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2875 // Doesn't find the signature Item!
2877 Status
= EFI_NOT_FOUND
;
2882 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2884 ItemDataSize
= Offset
;
2885 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2887 ZeroMem (OldData
, ItemDataSize
);
2888 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2889 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2890 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2891 if (CertCount
!= 0) {
2892 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2893 Offset
+= CertList
->SignatureListSize
;
2895 ItemDataSize
-= CertList
->SignatureListSize
;
2896 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2900 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2901 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2902 if (EFI_ERROR (Status
)) {
2903 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2908 Status
= gRT
->SetVariable(
2915 if (EFI_ERROR (Status
)) {
2916 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2925 if (OldData
!= NULL
) {
2929 return UpdateDeletePage (
2940 This function to delete signature list or data, according by DelType.
2942 @param[in] PrivateData Module's private data.
2943 @param[in] DelType Indicate delete signature list or data.
2944 @param[in] CheckedCount Indicate how many signature data have
2945 been checked in current signature list.
2947 @retval EFI_SUCCESS Success to update the signature list page
2948 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2952 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2953 IN SIGNATURE_DELETE_TYPE DelType
,
2954 IN UINT32 CheckedCount
2958 EFI_SIGNATURE_LIST
*ListWalker
;
2959 EFI_SIGNATURE_LIST
*NewCertList
;
2960 EFI_SIGNATURE_DATA
*DataWalker
;
2961 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
2962 UINT32 VariableAttr
;
2963 UINTN VariableDataSize
;
2964 UINTN RemainingSize
;
2968 UINT8
*VariableData
;
2969 UINT8
*NewVariableData
;
2971 Status
= EFI_SUCCESS
;
2973 VariableDataSize
= 0;
2976 VariableData
= NULL
;
2977 NewVariableData
= NULL
;
2979 if (PrivateData
->VariableName
== Variable_DB
) {
2980 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
2981 } else if (PrivateData
->VariableName
== Variable_DBX
) {
2982 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
2983 } else if (PrivateData
->VariableName
== Variable_DBT
) {
2984 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
2989 Status
= gRT
->GetVariable (
2991 &gEfiImageSecurityDatabaseGuid
,
2996 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3000 VariableData
= AllocateZeroPool (VariableDataSize
);
3001 if (VariableData
== NULL
) {
3002 Status
= EFI_OUT_OF_RESOURCES
;
3006 Status
= gRT
->GetVariable (
3008 &gEfiImageSecurityDatabaseGuid
,
3013 if (EFI_ERROR (Status
)) {
3017 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3018 if (EFI_ERROR (Status
)) {
3022 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3023 if (NewVariableData
== NULL
) {
3024 Status
= EFI_OUT_OF_RESOURCES
;
3028 RemainingSize
= VariableDataSize
;
3029 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3030 if (DelType
== Delete_Signature_List_All
) {
3031 VariableDataSize
= 0;
3034 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3036 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3037 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3038 Offset
+= ListWalker
->SignatureListSize
;
3040 RemainingSize
-= ListWalker
->SignatureListSize
;
3041 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3046 // Handle the target EFI_SIGNATURE_LIST.
3047 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3048 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3050 if (CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
) && DelType
== Delete_Signature_Data
) {
3051 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3055 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3056 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3058 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3059 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
3060 if (PrivateData
->CheckArray
[Index
]) {
3062 // Delete checked signature data, and update the size of whole signature list.
3064 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3067 // Remain the unchecked signature data.
3069 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3070 Offset
+= ListWalker
->SignatureSize
;
3072 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3076 RemainingSize
-= ListWalker
->SignatureListSize
;
3077 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3080 // Copy remaining data, maybe 0.
3082 CopyMem((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3083 Offset
+= RemainingSize
;
3085 VariableDataSize
= Offset
;
3088 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3089 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3090 if (EFI_ERROR (Status
)) {
3091 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3096 Status
= gRT
->SetVariable (
3098 &gEfiImageSecurityDatabaseGuid
,
3103 if (EFI_ERROR (Status
)) {
3104 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3109 SECUREBOOT_FREE_NON_NULL (VariableData
);
3110 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3117 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3118 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3120 @param[in] PrivateData Module's private data.
3122 @return EFI_SUCCESS Update secure boot strings successfully.
3123 @return other Fail to update secure boot strings.
3127 UpdateSecureBootString(
3128 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3136 // Get current secure boot state.
3138 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3139 if (SecureBoot
== NULL
) {
3140 return EFI_NOT_FOUND
;
3143 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3144 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3146 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3149 FreePool(SecureBoot
);
3155 This function extracts configuration from variable.
3157 @param[in] Private Point to SecureBoot configuration driver private data.
3158 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3162 SecureBootExtractConfigFromVariable (
3163 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3164 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3167 UINT8
*SecureBootEnable
;
3169 UINT8
*SecureBootMode
;
3172 SecureBootEnable
= NULL
;
3174 SecureBootMode
= NULL
;
3177 // Initialize the Date and Time using system time.
3179 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3180 ConfigData
->AlwaysRevocation
= TRUE
;
3181 gRT
->GetTime (&CurrTime
, NULL
);
3182 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3183 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3184 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3185 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3186 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3187 ConfigData
->RevocationTime
.Second
= 0;
3188 if (Private
->FileContext
->FHandle
!= NULL
) {
3189 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3191 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3195 // If it is Physical Presence User, set the PhysicalPresent to true.
3197 if (UserPhysicalPresent()) {
3198 ConfigData
->PhysicalPresent
= TRUE
;
3200 ConfigData
->PhysicalPresent
= FALSE
;
3204 // If there is no PK then the Delete Pk button will be gray.
3206 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3207 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3208 ConfigData
->HasPk
= FALSE
;
3210 ConfigData
->HasPk
= TRUE
;
3214 // Check SecureBootEnable & Pk status, fix the inconsistency.
3215 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3218 ConfigData
->AttemptSecureBoot
= FALSE
;
3219 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3222 // Fix Pk and SecureBootEnable inconsistency
3224 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3225 ConfigData
->HideSecureBoot
= FALSE
;
3226 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3227 ConfigData
->AttemptSecureBoot
= TRUE
;
3230 ConfigData
->HideSecureBoot
= TRUE
;
3234 // Get the SecureBootMode from CustomMode variable.
3236 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3237 if (SecureBootMode
== NULL
) {
3238 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3240 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3243 if (SecureBootEnable
!= NULL
) {
3244 FreePool (SecureBootEnable
);
3246 if (SetupMode
!= NULL
) {
3247 FreePool (SetupMode
);
3249 if (SecureBootMode
!= NULL
) {
3250 FreePool (SecureBootMode
);
3255 This function allows a caller to extract the current configuration for one
3256 or more named elements from the target driver.
3258 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3259 @param[in] Request A null-terminated Unicode string in
3260 <ConfigRequest> format.
3261 @param[out] Progress On return, points to a character in the Request
3262 string. Points to the string's null terminator if
3263 request was successful. Points to the most recent
3264 '&' before the first failing name/value pair (or
3265 the beginning of the string if the failure is in
3266 the first name/value pair) if the request was not
3268 @param[out] Results A null-terminated Unicode string in
3269 <ConfigAltResp> format which has all values filled
3270 in for the names in the Request string. String to
3271 be allocated by the called function.
3273 @retval EFI_SUCCESS The Results is filled with the requested values.
3274 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3275 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3276 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3282 SecureBootExtractConfig (
3283 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3284 IN CONST EFI_STRING Request
,
3285 OUT EFI_STRING
*Progress
,
3286 OUT EFI_STRING
*Results
3292 SECUREBOOT_CONFIGURATION Configuration
;
3293 EFI_STRING ConfigRequest
;
3294 EFI_STRING ConfigRequestHdr
;
3295 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3296 BOOLEAN AllocatedRequest
;
3298 if (Progress
== NULL
|| Results
== NULL
) {
3299 return EFI_INVALID_PARAMETER
;
3302 AllocatedRequest
= FALSE
;
3303 ConfigRequestHdr
= NULL
;
3304 ConfigRequest
= NULL
;
3307 ZeroMem (&Configuration
, sizeof (Configuration
));
3308 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3309 *Progress
= Request
;
3311 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3312 return EFI_NOT_FOUND
;
3315 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3318 // Get Configuration from Variable.
3320 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3322 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3323 ConfigRequest
= Request
;
3324 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3326 // Request is set to NULL or OFFSET is NULL, construct full request string.
3328 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3329 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3331 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3332 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3333 ConfigRequest
= AllocateZeroPool (Size
);
3334 ASSERT (ConfigRequest
!= NULL
);
3335 AllocatedRequest
= TRUE
;
3336 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3337 FreePool (ConfigRequestHdr
);
3338 ConfigRequestHdr
= NULL
;
3341 Status
= gHiiConfigRouting
->BlockToConfig (
3344 (UINT8
*) &Configuration
,
3351 // Free the allocated config request string.
3353 if (AllocatedRequest
) {
3354 FreePool (ConfigRequest
);
3358 // Set Progress string to the original request string.
3360 if (Request
== NULL
) {
3362 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3363 *Progress
= Request
+ StrLen (Request
);
3370 This function processes the results of changes in configuration.
3372 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3373 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3375 @param[out] Progress A pointer to a string filled in with the offset of
3376 the most recent '&' before the first failing
3377 name/value pair (or the beginning of the string if
3378 the failure is in the first name/value pair) or
3379 the terminating NULL if all was successful.
3381 @retval EFI_SUCCESS The Results is processed successfully.
3382 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3383 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3389 SecureBootRouteConfig (
3390 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3391 IN CONST EFI_STRING Configuration
,
3392 OUT EFI_STRING
*Progress
3395 SECUREBOOT_CONFIGURATION IfrNvData
;
3397 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3400 if (Configuration
== NULL
|| Progress
== NULL
) {
3401 return EFI_INVALID_PARAMETER
;
3404 *Progress
= Configuration
;
3405 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3406 return EFI_NOT_FOUND
;
3409 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3412 // Get Configuration from Variable.
3414 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3417 // Map the Configuration to the configuration block.
3419 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3420 Status
= gHiiConfigRouting
->ConfigToBlock (
3423 (UINT8
*)&IfrNvData
,
3427 if (EFI_ERROR (Status
)) {
3432 // Store Buffer Storage back to EFI variable if needed
3434 if (!IfrNvData
.HideSecureBoot
) {
3435 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3436 if (EFI_ERROR (Status
)) {
3441 *Progress
= Configuration
+ StrLen (Configuration
);
3446 This function to load signature list, the update the menu page.
3448 @param[in] PrivateData Module's private data.
3449 @param[in] LabelId Label number to insert opcodes.
3450 @param[in] FormId Form ID of current page.
3451 @param[in] QuestionIdBase Base question id of the signature list.
3453 @retval EFI_SUCCESS Success to update the signature list page
3454 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3458 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3460 IN EFI_FORM_ID FormId
,
3461 IN EFI_QUESTION_ID QuestionIdBase
3465 EFI_STRING_ID ListType
;
3466 EFI_STRING FormatNameString
;
3467 EFI_STRING FormatHelpString
;
3468 EFI_STRING FormatTypeString
;
3469 EFI_SIGNATURE_LIST
*ListWalker
;
3470 EFI_IFR_GUID_LABEL
*StartLabel
;
3471 EFI_IFR_GUID_LABEL
*EndLabel
;
3472 EFI_IFR_GUID_LABEL
*StartGoto
;
3473 EFI_IFR_GUID_LABEL
*EndGoto
;
3474 EFI_FORM_ID DstFormId
;
3475 VOID
*StartOpCodeHandle
;
3476 VOID
*EndOpCodeHandle
;
3477 VOID
*StartGotoHandle
;
3478 VOID
*EndGotoHandle
;
3480 UINTN RemainingSize
;
3482 UINT8
*VariableData
;
3483 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3484 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3485 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3487 Status
= EFI_SUCCESS
;
3488 FormatNameString
= NULL
;
3489 FormatHelpString
= NULL
;
3490 StartOpCodeHandle
= NULL
;
3491 EndOpCodeHandle
= NULL
;
3492 StartGotoHandle
= NULL
;
3493 EndGotoHandle
= NULL
;
3495 VariableData
= NULL
;
3498 // Initialize the container for dynamic opcodes.
3500 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3501 if (StartOpCodeHandle
== NULL
) {
3502 Status
= EFI_OUT_OF_RESOURCES
;
3506 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3507 if (EndOpCodeHandle
== NULL
) {
3508 Status
= EFI_OUT_OF_RESOURCES
;
3512 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3513 if (StartGotoHandle
== NULL
) {
3514 Status
= EFI_OUT_OF_RESOURCES
;
3518 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3519 if (EndGotoHandle
== NULL
) {
3520 Status
= EFI_OUT_OF_RESOURCES
;
3525 // Create Hii Extend Label OpCode.
3527 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3531 sizeof (EFI_IFR_GUID_LABEL
)
3533 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3534 StartLabel
->Number
= LabelId
;
3536 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3540 sizeof (EFI_IFR_GUID_LABEL
)
3542 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3543 EndLabel
->Number
= LABEL_END
;
3545 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3549 sizeof(EFI_IFR_GUID_LABEL
)
3551 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3552 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3554 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3558 sizeof(EFI_IFR_GUID_LABEL
)
3560 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3561 EndGoto
->Number
= LABEL_END
;
3563 if (PrivateData
->VariableName
== Variable_DB
) {
3564 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3565 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3566 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3567 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3568 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3569 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3570 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3571 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3576 HiiCreateGotoOpCode (
3579 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3580 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3581 EFI_IFR_FLAG_CALLBACK
,
3582 KEY_SECURE_BOOT_DELETE_ALL_LIST
3586 // Read Variable, the variable name save in the PrivateData->VariableName.
3589 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3590 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3594 VariableData
= AllocateZeroPool (DataSize
);
3595 if (VariableData
== NULL
) {
3596 Status
= EFI_OUT_OF_RESOURCES
;
3599 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3600 if (EFI_ERROR (Status
)) {
3604 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3605 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3606 if (FormatNameString
== NULL
|| FormatHelpString
== NULL
) {
3610 RemainingSize
= DataSize
;
3611 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3612 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3613 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3614 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3615 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3616 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3617 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3618 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3619 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3620 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3621 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3622 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3623 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3624 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3625 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3626 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3628 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3630 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3631 if (FormatTypeString
== NULL
) {
3635 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3636 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3638 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3639 UnicodeSPrint (HelpBuffer
,
3640 sizeof (HelpBuffer
),
3643 SIGNATURE_DATA_COUNTS (ListWalker
)
3645 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3646 FormatTypeString
= NULL
;
3648 HiiCreateGotoOpCode (
3650 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3651 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3652 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3653 EFI_IFR_FLAG_CALLBACK
,
3654 QuestionIdBase
+ Index
++
3657 RemainingSize
-= ListWalker
->SignatureListSize
;
3658 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3663 PrivateData
->HiiHandle
,
3664 &gSecureBootConfigFormSetGuid
,
3671 PrivateData
->HiiHandle
,
3672 &gSecureBootConfigFormSetGuid
,
3678 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3679 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3680 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3681 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3683 SECUREBOOT_FREE_NON_NULL (VariableData
);
3684 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3685 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3687 PrivateData
->ListCount
= Index
;
3693 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3694 The buffer is callee allocated and should be freed by the caller.
3696 @param[in] ListEntry The pointer point to the signature list.
3697 @param[in] DataEntry The signature data we are processing.
3698 @param[out] BufferToReturn Buffer to save the hash value.
3700 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3701 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3702 @retval EFI_SUCCESS Operation success.
3706 IN EFI_SIGNATURE_LIST
*ListEntry
,
3707 IN EFI_SIGNATURE_DATA
*DataEntry
,
3708 OUT CHAR16
**BufferToReturn
3719 // Assume that, display 8 bytes in one line.
3723 if (ListEntry
== NULL
|| DataEntry
== NULL
|| BufferToReturn
== NULL
) {
3724 return EFI_INVALID_PARAMETER
;
3727 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3728 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3731 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3733 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof(CHAR16
));
3735 *BufferToReturn
= AllocateZeroPool(TotalSize
);
3736 if (*BufferToReturn
== NULL
) {
3737 return EFI_OUT_OF_RESOURCES
;
3740 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3741 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3742 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3744 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3746 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3752 Function to get the common name from the X509 format certificate.
3753 The buffer is callee allocated and should be freed by the caller.
3755 @param[in] ListEntry The pointer point to the signature list.
3756 @param[in] DataEntry The signature data we are processing.
3757 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3759 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3760 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3761 @retval EFI_SUCCESS Operation success.
3762 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3765 GetCommonNameFromX509 (
3766 IN EFI_SIGNATURE_LIST
*ListEntry
,
3767 IN EFI_SIGNATURE_DATA
*DataEntry
,
3768 OUT CHAR16
**BufferToReturn
3775 Status
= EFI_SUCCESS
;
3778 CNBuffer
= AllocateZeroPool(256);
3779 if (CNBuffer
== NULL
) {
3780 Status
= EFI_OUT_OF_RESOURCES
;
3786 (UINT8
*)DataEntry
+ sizeof(EFI_GUID
),
3787 ListEntry
->SignatureSize
- sizeof(EFI_GUID
),
3792 *BufferToReturn
= AllocateZeroPool(256 * sizeof(CHAR16
));
3793 if (*BufferToReturn
== NULL
) {
3794 Status
= EFI_OUT_OF_RESOURCES
;
3798 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3801 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3807 Format the help info for the signature data, each help info contain 3 parts.
3809 2. Content, depends on the type of the signature list.
3812 @param[in] PrivateData Module's private data.
3813 @param[in] ListEntry Point to the signature list.
3814 @param[in] DataEntry Point to the signature data we are processing.
3815 @param[out] StringId Save the string id of help info.
3817 @retval EFI_SUCCESS Operation success.
3818 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3822 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3823 IN EFI_SIGNATURE_LIST
*ListEntry
,
3824 IN EFI_SIGNATURE_DATA
*DataEntry
,
3825 OUT EFI_STRING_ID
*StringId
3830 EFI_STRING_ID ListTypeId
;
3831 EFI_STRING FormatHelpString
;
3832 EFI_STRING FormatTypeString
;
3834 UINTN HelpInfoIndex
;
3836 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3837 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3839 CHAR16
*HelpInfoString
;
3842 Status
= EFI_SUCCESS
;
3844 FormatTypeString
= NULL
;
3847 HelpInfoString
= NULL
;
3850 if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3851 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256
);
3852 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3854 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
3855 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509
);
3856 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3858 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
3859 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA1
);
3861 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
3862 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA256
);
3864 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3865 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA256
);
3867 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3868 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3869 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA384
);
3871 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3872 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3873 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA512
);
3875 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3877 Status
= EFI_UNSUPPORTED
;
3881 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
3882 if (FormatTypeString
== NULL
) {
3887 HelpInfoString
= AllocateZeroPool (TotalSize
);
3888 if (HelpInfoString
== NULL
) {
3889 Status
= EFI_OUT_OF_RESOURCES
;
3894 // Format GUID part.
3896 ZeroMem (GuidString
, sizeof (GuidString
));
3897 GuidToString(&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
3898 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
3899 if (FormatHelpString
== NULL
) {
3902 HelpInfoIndex
+= UnicodeSPrint (
3903 &HelpInfoString
[HelpInfoIndex
],
3904 TotalSize
- sizeof(CHAR16
) * HelpInfoIndex
,
3908 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3909 FormatHelpString
= NULL
;
3912 // Format content part, it depends on the type of signature list, hash value or CN.
3915 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
3916 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
3919 // Format hash value for each signature data entry.
3921 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
3922 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
3924 if (FormatHelpString
== NULL
) {
3927 HelpInfoIndex
+= UnicodeSPrint (
3928 &HelpInfoString
[HelpInfoIndex
],
3929 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3935 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3936 FormatHelpString
= NULL
;
3939 // Format revocation time part.
3942 ZeroMem (TimeString
, sizeof (TimeString
));
3945 sizeof (TimeString
),
3946 L
"%d-%d-%d %d:%d:%d",
3954 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
3955 if (FormatHelpString
== NULL
) {
3959 &HelpInfoString
[HelpInfoIndex
],
3960 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
3964 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3965 FormatHelpString
= NULL
;
3968 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
3970 SECUREBOOT_FREE_NON_NULL (DataString
);
3971 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
3973 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3979 This function to load signature data under the signature list.
3981 @param[in] PrivateData Module's private data.
3982 @param[in] LabelId Label number to insert opcodes.
3983 @param[in] FormId Form ID of current page.
3984 @param[in] QuestionIdBase Base question id of the signature list.
3985 @param[in] ListIndex Indicate to load which signature list.
3987 @retval EFI_SUCCESS Success to update the signature list page
3988 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3992 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3994 IN EFI_FORM_ID FormId
,
3995 IN EFI_QUESTION_ID QuestionIdBase
,
4000 EFI_SIGNATURE_LIST
*ListWalker
;
4001 EFI_SIGNATURE_DATA
*DataWalker
;
4002 EFI_IFR_GUID_LABEL
*StartLabel
;
4003 EFI_IFR_GUID_LABEL
*EndLabel
;
4004 EFI_STRING_ID HelpStringId
;
4005 EFI_STRING FormatNameString
;
4006 VOID
*StartOpCodeHandle
;
4007 VOID
*EndOpCodeHandle
;
4009 UINTN RemainingSize
;
4011 UINT8
*VariableData
;
4012 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4013 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4015 Status
= EFI_SUCCESS
;
4016 FormatNameString
= NULL
;
4017 StartOpCodeHandle
= NULL
;
4018 EndOpCodeHandle
= NULL
;
4020 VariableData
= NULL
;
4023 // Initialize the container for dynamic opcodes.
4025 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4026 if (StartOpCodeHandle
== NULL
) {
4027 Status
= EFI_OUT_OF_RESOURCES
;
4031 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4032 if (EndOpCodeHandle
== NULL
) {
4033 Status
= EFI_OUT_OF_RESOURCES
;
4038 // Create Hii Extend Label OpCode.
4040 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4044 sizeof (EFI_IFR_GUID_LABEL
)
4046 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4047 StartLabel
->Number
= LabelId
;
4049 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4053 sizeof (EFI_IFR_GUID_LABEL
)
4055 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4056 EndLabel
->Number
= LABEL_END
;
4058 if (PrivateData
->VariableName
== Variable_DB
) {
4059 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4060 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4061 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4062 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4063 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4069 // Read Variable, the variable name save in the PrivateData->VariableName.
4072 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4073 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
4077 VariableData
= AllocateZeroPool (DataSize
);
4078 if (VariableData
== NULL
) {
4079 Status
= EFI_OUT_OF_RESOURCES
;
4082 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4083 if (EFI_ERROR (Status
)) {
4087 RemainingSize
= DataSize
;
4088 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4091 // Skip signature list.
4093 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4094 RemainingSize
-= ListWalker
->SignatureListSize
;
4095 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4098 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4099 if (FormatNameString
== NULL
) {
4103 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4104 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
4106 // Format name buffer.
4108 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4109 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4112 // Format help info buffer.
4114 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4115 if (EFI_ERROR (Status
)) {
4119 HiiCreateCheckBoxOpCode (
4121 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4124 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4126 EFI_IFR_FLAG_CALLBACK
,
4131 ZeroMem(NameBuffer
, 100);
4132 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4136 // Allocate a buffer to record which signature data will be checked.
4137 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4139 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4142 PrivateData
->HiiHandle
,
4143 &gSecureBootConfigFormSetGuid
,
4149 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4150 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4152 SECUREBOOT_FREE_NON_NULL (VariableData
);
4153 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4159 This function is called to provide results data to the driver.
4161 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4162 @param[in] Action Specifies the type of action taken by the browser.
4163 @param[in] QuestionId A unique value which is sent to the original
4164 exporting driver so that it can identify the type
4166 @param[in] Type The type of value for the question.
4167 @param[in] Value A pointer to the data being sent to the original
4169 @param[out] ActionRequest On return, points to the action requested by the
4172 @retval EFI_SUCCESS The callback successfully handled the action.
4173 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4174 variable and its data.
4175 @retval EFI_DEVICE_ERROR The variable could not be saved.
4176 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4182 SecureBootCallback (
4183 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4184 IN EFI_BROWSER_ACTION Action
,
4185 IN EFI_QUESTION_ID QuestionId
,
4187 IN EFI_IFR_TYPE_VALUE
*Value
,
4188 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4193 RETURN_STATUS RStatus
;
4194 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4196 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4198 UINT8
*SecureBootEnable
;
4200 UINT8
*SecureBootMode
;
4202 CHAR16 PromptString
[100];
4203 EFI_DEVICE_PATH_PROTOCOL
*File
;
4205 UINT16
*FilePostFix
;
4206 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4207 BOOLEAN GetBrowserDataResult
;
4208 ENROLL_KEY_ERROR EnrollKeyErrorCode
;
4210 Status
= EFI_SUCCESS
;
4211 SecureBootEnable
= NULL
;
4212 SecureBootMode
= NULL
;
4215 EnrollKeyErrorCode
= None_Error
;
4217 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4218 return EFI_INVALID_PARAMETER
;
4221 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4223 gSecureBootPrivateData
= Private
;
4226 // Retrieve uncommitted data from Browser
4228 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4229 IfrNvData
= AllocateZeroPool (BufferSize
);
4230 if (IfrNvData
== NULL
) {
4231 return EFI_OUT_OF_RESOURCES
;
4234 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
4236 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4237 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4239 // Update secure boot strings when opening this form
4241 Status
= UpdateSecureBootString(Private
);
4242 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4243 mIsEnterSecureBootForm
= TRUE
;
4246 // When entering SecureBoot OPTION Form
4247 // always close opened file & free resource
4249 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4250 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4251 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4252 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4253 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
4254 CloseEnrolledFile(Private
->FileContext
);
4255 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4257 // Update ListCount field in varstore
4258 // Button "Delete All Signature List" is
4259 // enable when ListCount is greater than 0.
4261 IfrNvData
->ListCount
= Private
->ListCount
;
4267 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4268 Status
= EFI_UNSUPPORTED
;
4269 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4270 if (mIsEnterSecureBootForm
) {
4271 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4272 Status
= EFI_SUCCESS
;
4278 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4279 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4280 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4281 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
4282 Status
= EFI_UNSUPPORTED
;
4286 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4288 switch (QuestionId
) {
4289 case KEY_SECURE_BOOT_ENABLE
:
4290 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4291 if (NULL
!= SecureBootEnable
) {
4292 FreePool (SecureBootEnable
);
4293 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4295 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4297 L
"Only Physical Presence User could disable secure boot!",
4300 Status
= EFI_UNSUPPORTED
;
4303 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4305 L
"Configuration changed, please reset the platform to take effect!",
4312 case KEY_SECURE_BOOT_KEK_OPTION
:
4313 case KEY_SECURE_BOOT_DB_OPTION
:
4314 case KEY_SECURE_BOOT_DBX_OPTION
:
4315 case KEY_SECURE_BOOT_DBT_OPTION
:
4316 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4318 // Clear Signature GUID.
4320 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4321 if (Private
->SignatureGUID
== NULL
) {
4322 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
4323 if (Private
->SignatureGUID
== NULL
) {
4324 return EFI_OUT_OF_RESOURCES
;
4329 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4331 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4333 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4334 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4335 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4336 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4337 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4338 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4340 LabelId
= FORMID_ENROLL_KEK_FORM
;
4344 // Refresh selected file.
4346 CleanUpPage (LabelId
, Private
);
4348 case KEY_SECURE_BOOT_PK_OPTION
:
4349 LabelId
= FORMID_ENROLL_PK_FORM
;
4351 // Refresh selected file.
4353 CleanUpPage (LabelId
, Private
);
4356 case FORMID_ENROLL_PK_FORM
:
4357 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4360 case FORMID_ENROLL_KEK_FORM
:
4361 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4364 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4365 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4368 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4369 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4371 if (Private
->FileContext
->FHandle
!= NULL
) {
4373 // Parse the file's postfix.
4375 NameLength
= StrLen (Private
->FileContext
->FileName
);
4376 if (NameLength
<= 4) {
4379 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4381 if (IsDerEncodeCertificate (FilePostFix
)) {
4383 // Supports DER-encoded X509 certificate.
4385 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4386 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
4387 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4389 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4391 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4394 // Clean up Certificate Format if File type is not X509 DER
4396 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4397 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4399 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4404 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4405 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4408 case KEY_SECURE_BOOT_DELETE_PK
:
4411 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4413 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4414 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4417 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
4418 Status
= DeletePlatformKey ();
4419 if (EFI_ERROR (Status
)) {
4421 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4423 L
"Only Physical Presence User could delete PK in custom mode!",
4431 case KEY_DELETE_KEK
:
4434 EFI_KEY_EXCHANGE_KEY_NAME
,
4435 &gEfiGlobalVariableGuid
,
4437 FORMID_DELETE_KEK_FORM
,
4438 OPTION_DEL_KEK_QUESTION_ID
4442 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4445 EFI_IMAGE_SECURITY_DATABASE
,
4446 &gEfiImageSecurityDatabaseGuid
,
4448 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4449 OPTION_DEL_DB_QUESTION_ID
4454 // From DBX option to the level-1 form, display signature list.
4456 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4457 Private
->VariableName
= Variable_DBX
;
4460 LABEL_SIGNATURE_LIST_START
,
4461 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4462 OPTION_SIGNATURE_LIST_QUESTION_ID
4467 // Delete all signature list and reload.
4469 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4471 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4473 L
"Press 'Y' to delete signature list.",
4474 L
"Press other key to cancel and exit.",
4478 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4479 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4484 LABEL_SIGNATURE_LIST_START
,
4485 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4486 OPTION_SIGNATURE_LIST_QUESTION_ID
4491 // Delete one signature list and reload.
4493 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4495 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4497 L
"Press 'Y' to delete signature data.",
4498 L
"Press other key to cancel and exit.",
4502 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4503 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4508 LABEL_SIGNATURE_LIST_START
,
4509 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4510 OPTION_SIGNATURE_LIST_QUESTION_ID
4515 // Delete checked signature data and reload.
4517 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4519 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4521 L
"Press 'Y' to delete signature data.",
4522 L
"Press other key to cancel and exit.",
4526 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4527 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4532 LABEL_SIGNATURE_LIST_START
,
4533 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4534 OPTION_SIGNATURE_LIST_QUESTION_ID
4538 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4541 EFI_IMAGE_SECURITY_DATABASE2
,
4542 &gEfiImageSecurityDatabaseGuid
,
4544 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4545 OPTION_DEL_DBT_QUESTION_ID
4550 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4551 Status
= EnrollKeyExchangeKey (Private
);
4552 if (EFI_ERROR (Status
)) {
4554 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4556 L
"ERROR: Unsupported file type!",
4557 L
"Only supports DER-encoded X509 certificate",
4563 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4564 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4565 if (EFI_ERROR (Status
)) {
4567 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4569 L
"ERROR: Unsupported file type!",
4570 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4576 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4577 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4579 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4581 L
"Enrollment failed! Same certificate had already been in the dbx!",
4586 // Cert already exists in DBX. Close opened file before exit.
4588 CloseEnrolledFile(Private
->FileContext
);
4592 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4593 Status
= EnrollX509HashtoSigDB (
4595 IfrNvData
->CertificateFormat
,
4596 &IfrNvData
->RevocationDate
,
4597 &IfrNvData
->RevocationTime
,
4598 IfrNvData
->AlwaysRevocation
4600 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4602 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4604 if (EFI_ERROR (Status
)) {
4606 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4608 L
"ERROR: Unsupported file type!",
4609 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4615 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4616 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4617 if (EFI_ERROR (Status
)) {
4619 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4621 L
"ERROR: Unsupported file type!",
4622 L
"Only supports DER-encoded X509 certificate.",
4627 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4629 // Check the suffix, encode type and the key strength of PK certificate.
4631 Status
= CheckX509Certificate (Private
->FileContext
, &EnrollKeyErrorCode
);
4632 if (EFI_ERROR (Status
)) {
4633 if (EnrollKeyErrorCode
!= None_Error
&& EnrollKeyErrorCode
< Enroll_Error_Max
) {
4635 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4637 mX509EnrollPromptTitle
[EnrollKeyErrorCode
],
4638 mX509EnrollPromptString
[EnrollKeyErrorCode
],
4644 Status
= EnrollPlatformKey (Private
);
4646 if (EFI_ERROR (Status
)) {
4649 sizeof (PromptString
),
4650 L
"Error status: %x.",
4654 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4656 L
"ERROR: Enrollment failed!",
4663 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4664 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4665 DeleteKeyExchangeKey (Private
, QuestionId
);
4666 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4667 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4670 EFI_IMAGE_SECURITY_DATABASE
,
4671 &gEfiImageSecurityDatabaseGuid
,
4673 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4674 OPTION_DEL_DB_QUESTION_ID
,
4675 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4677 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4678 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4681 LABEL_SIGNATURE_DATA_START
,
4682 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4683 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4684 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4686 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4687 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4688 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4689 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4690 IfrNvData
->CheckedDataCount
--;
4691 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4693 IfrNvData
->CheckedDataCount
++;
4694 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4696 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4697 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4700 EFI_IMAGE_SECURITY_DATABASE2
,
4701 &gEfiImageSecurityDatabaseGuid
,
4703 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4704 OPTION_DEL_DBT_QUESTION_ID
,
4705 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4710 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4711 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4712 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4713 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4714 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4715 CloseEnrolledFile(Private
->FileContext
);
4717 if (Private
->SignatureGUID
!= NULL
) {
4718 FreePool (Private
->SignatureGUID
);
4719 Private
->SignatureGUID
= NULL
;
4723 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4724 switch (QuestionId
) {
4725 case KEY_SECURE_BOOT_ENABLE
:
4726 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4728 case KEY_SECURE_BOOT_MODE
:
4729 mIsEnterSecureBootForm
= FALSE
;
4731 case KEY_SECURE_BOOT_KEK_GUID
:
4732 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4733 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4734 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4735 ASSERT (Private
->SignatureGUID
!= NULL
);
4736 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4737 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4738 Status
= EFI_INVALID_PARAMETER
;
4742 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4744 case KEY_SECURE_BOOT_DELETE_PK
:
4745 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4746 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
4747 IfrNvData
->DeletePk
= TRUE
;
4748 IfrNvData
->HasPk
= FALSE
;
4749 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4751 IfrNvData
->DeletePk
= FALSE
;
4752 IfrNvData
->HasPk
= TRUE
;
4753 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4755 if (SetupMode
!= NULL
) {
4756 FreePool (SetupMode
);
4762 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4763 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4764 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
4766 IfrNvData
->HideSecureBoot
= TRUE
;
4769 IfrNvData
->HideSecureBoot
= FALSE
;
4771 Value
->b
= IfrNvData
->HideSecureBoot
;
4773 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
4775 // Force the platform back to Standard Mode once user leave the setup screen.
4777 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
4778 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
4779 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
4780 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
4782 if (SecureBootMode
!= NULL
) {
4783 FreePool (SecureBootMode
);
4786 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
4788 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4790 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
4791 IfrNvData
->CheckedDataCount
= 0;
4797 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
4798 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4799 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
4802 FreePool (IfrNvData
);
4813 This function publish the SecureBoot configuration Form.
4815 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4817 @retval EFI_SUCCESS HII Form is installed successfully.
4818 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
4819 @retval Others Other errors as indicated.
4823 InstallSecureBootConfigForm (
4824 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4828 EFI_HII_HANDLE HiiHandle
;
4829 EFI_HANDLE DriverHandle
;
4830 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4832 DriverHandle
= NULL
;
4833 ConfigAccess
= &PrivateData
->ConfigAccess
;
4834 Status
= gBS
->InstallMultipleProtocolInterfaces (
4836 &gEfiDevicePathProtocolGuid
,
4837 &mSecureBootHiiVendorDevicePath
,
4838 &gEfiHiiConfigAccessProtocolGuid
,
4842 if (EFI_ERROR (Status
)) {
4846 PrivateData
->DriverHandle
= DriverHandle
;
4849 // Publish the HII package list
4851 HiiHandle
= HiiAddPackages (
4852 &gSecureBootConfigFormSetGuid
,
4854 SecureBootConfigDxeStrings
,
4855 SecureBootConfigBin
,
4858 if (HiiHandle
== NULL
) {
4859 gBS
->UninstallMultipleProtocolInterfaces (
4861 &gEfiDevicePathProtocolGuid
,
4862 &mSecureBootHiiVendorDevicePath
,
4863 &gEfiHiiConfigAccessProtocolGuid
,
4867 return EFI_OUT_OF_RESOURCES
;
4870 PrivateData
->HiiHandle
= HiiHandle
;
4872 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
4874 if (PrivateData
->FileContext
== NULL
) {
4875 UninstallSecureBootConfigForm (PrivateData
);
4876 return EFI_OUT_OF_RESOURCES
;
4880 // Init OpCode Handle and Allocate space for creation of Buffer
4882 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4883 if (mStartOpCodeHandle
== NULL
) {
4884 UninstallSecureBootConfigForm (PrivateData
);
4885 return EFI_OUT_OF_RESOURCES
;
4888 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4889 if (mEndOpCodeHandle
== NULL
) {
4890 UninstallSecureBootConfigForm (PrivateData
);
4891 return EFI_OUT_OF_RESOURCES
;
4895 // Create Hii Extend Label OpCode as the start opcode
4897 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4901 sizeof (EFI_IFR_GUID_LABEL
)
4903 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4906 // Create Hii Extend Label OpCode as the end opcode
4908 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4912 sizeof (EFI_IFR_GUID_LABEL
)
4914 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4915 mEndLabel
->Number
= LABEL_END
;
4921 This function removes SecureBoot configuration Form.
4923 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4927 UninstallSecureBootConfigForm (
4928 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4932 // Uninstall HII package list
4934 if (PrivateData
->HiiHandle
!= NULL
) {
4935 HiiRemovePackages (PrivateData
->HiiHandle
);
4936 PrivateData
->HiiHandle
= NULL
;
4940 // Uninstall HII Config Access Protocol
4942 if (PrivateData
->DriverHandle
!= NULL
) {
4943 gBS
->UninstallMultipleProtocolInterfaces (
4944 PrivateData
->DriverHandle
,
4945 &gEfiDevicePathProtocolGuid
,
4946 &mSecureBootHiiVendorDevicePath
,
4947 &gEfiHiiConfigAccessProtocolGuid
,
4948 &PrivateData
->ConfigAccess
,
4951 PrivateData
->DriverHandle
= NULL
;
4954 if (PrivateData
->SignatureGUID
!= NULL
) {
4955 FreePool (PrivateData
->SignatureGUID
);
4958 if (PrivateData
->FileContext
!= NULL
) {
4959 FreePool (PrivateData
->FileContext
);
4962 FreePool (PrivateData
);
4964 if (mStartOpCodeHandle
!= NULL
) {
4965 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
4968 if (mEndOpCodeHandle
!= NULL
) {
4969 HiiFreeOpCodeHandle (mEndOpCodeHandle
);