2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "SecureBootConfigImpl.h"
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
) (END_DEVICE_PATH_LENGTH
),
45 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
51 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
54 // OID ASN.1 Value for Hash Algorithms
56 UINT8 mHashOidValue
[] = {
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
65 HASH_TABLE mHash
[] = {
66 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
67 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
68 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
69 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
73 // Variable Definitions
75 UINT32 mPeCoffHeaderOffset
= 0;
76 WIN_CERTIFICATE
*mCertificate
= NULL
;
77 IMAGE_TYPE mImageType
;
78 UINT8
*mImageBase
= NULL
;
80 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
81 UINTN mImageDigestSize
;
83 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
84 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
87 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
89 CHAR16
* mDerEncodedSuffix
[] = {
95 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
97 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
100 This code cleans up enrolled file by closing file & free related resources attached to
103 @param[in] FileContext FileContext cached in SecureBootConfig driver
108 IN SECUREBOOT_FILE_CONTEXT
*FileContext
111 if (FileContext
->FHandle
!= NULL
) {
112 CloseFile (FileContext
->FHandle
);
113 FileContext
->FHandle
= NULL
;
116 if (FileContext
->FileName
!= NULL
){
117 FreePool(FileContext
->FileName
);
118 FileContext
->FileName
= NULL
;
120 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
125 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
127 @param[in] FileSuffix The suffix of the input certificate file
129 @retval TRUE It's a DER-encoded certificate.
130 @retval FALSE It's NOT a DER-encoded certificate.
134 IsDerEncodeCertificate (
135 IN CONST CHAR16
*FileSuffix
139 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
140 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
148 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
149 The function reads file content but won't open/close given FileHandle.
151 @param[in] FileHandle The FileHandle to be checked
153 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
154 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
158 IsAuthentication2Format (
159 IN EFI_FILE_HANDLE FileHandle
163 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
164 BOOLEAN IsAuth2Format
;
166 IsAuth2Format
= FALSE
;
169 // Read the whole file content
171 Status
= ReadFileContent(
173 (VOID
**) &mImageBase
,
177 if (EFI_ERROR (Status
)) {
181 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
182 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
186 if (CompareGuid(&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
187 IsAuth2Format
= TRUE
;
192 // Do not close File. simply check file content
194 if (mImageBase
!= NULL
) {
195 FreePool (mImageBase
);
199 return IsAuth2Format
;
203 Set Secure Boot option into variable space.
205 @param[in] VarValue The option of Secure Boot.
207 @retval EFI_SUCCESS The operation is finished successfully.
208 @retval Others Other errors as indicated.
212 SaveSecureBootVariable (
218 Status
= gRT
->SetVariable (
219 EFI_SECURE_BOOT_ENABLE_NAME
,
220 &gEfiSecureBootEnableDisableGuid
,
221 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
229 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
230 descriptor with the input data. NO authentication is required in this function.
232 @param[in, out] DataSize On input, the size of Data buffer in bytes.
233 On output, the size of data returned in Data
235 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
236 pointer to NULL to wrap an empty payload.
237 On output, Pointer to the new payload date buffer allocated from pool,
238 it's caller's responsibility to free the memory when finish using it.
240 @retval EFI_SUCCESS Create time based payload successfully.
241 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
242 @retval EFI_INVALID_PARAMETER The parameter is invalid.
243 @retval Others Unexpected error happens.
247 CreateTimeBasedPayload (
248 IN OUT UINTN
*DataSize
,
256 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
257 UINTN DescriptorSize
;
260 if (Data
== NULL
|| DataSize
== NULL
) {
261 return EFI_INVALID_PARAMETER
;
265 // In Setup mode or Custom mode, the variable does not need to be signed but the
266 // parameters to the SetVariable() call still need to be prepared as authenticated
267 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
271 PayloadSize
= *DataSize
;
273 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
274 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
275 if (NewData
== NULL
) {
276 return EFI_OUT_OF_RESOURCES
;
279 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
280 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
283 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
285 ZeroMem (&Time
, sizeof (EFI_TIME
));
286 Status
= gRT
->GetTime (&Time
, NULL
);
287 if (EFI_ERROR (Status
)) {
296 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
298 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
299 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
300 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
301 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
303 if (Payload
!= NULL
) {
307 *DataSize
= DescriptorSize
+ PayloadSize
;
313 Internal helper function to delete a Variable given its name and GUID, NO authentication
316 @param[in] VariableName Name of the Variable.
317 @param[in] VendorGuid GUID of the Variable.
319 @retval EFI_SUCCESS Variable deleted successfully.
320 @retval Others The driver failed to start the device.
325 IN CHAR16
*VariableName
,
326 IN EFI_GUID
*VendorGuid
335 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
336 if (Variable
== NULL
) {
343 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
344 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
346 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
347 if (EFI_ERROR (Status
)) {
348 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
352 Status
= gRT
->SetVariable (
367 Set the platform secure boot mode into "Custom" or "Standard" mode.
369 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
370 CUSTOM_SECURE_BOOT_MODE.
372 @return EFI_SUCCESS The platform has switched to the special mode successfully.
373 @return other Fail to operate the secure boot mode.
378 IN UINT8 SecureBootMode
381 return gRT
->SetVariable (
382 EFI_CUSTOM_MODE_NAME
,
383 &gEfiCustomModeEnableGuid
,
384 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
391 Generate the PK signature list from the X509 Certificate storing file (.cer)
393 @param[in] X509File FileHandle of X509 Certificate storing file.
394 @param[out] PkCert Point to the data buffer to store the signature list.
396 @return EFI_UNSUPPORTED Unsupported Key Length.
397 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
401 CreatePkX509SignatureList (
402 IN EFI_FILE_HANDLE X509File
,
403 OUT EFI_SIGNATURE_LIST
**PkCert
409 EFI_SIGNATURE_DATA
*PkCertData
;
415 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
416 if (EFI_ERROR (Status
)) {
419 ASSERT (X509Data
!= NULL
);
422 // Allocate space for PK certificate list and initialize it.
423 // Create PK database entry with SignatureHeaderSize equals 0.
425 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
426 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
429 if (*PkCert
== NULL
) {
430 Status
= EFI_OUT_OF_RESOURCES
;
434 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
435 + sizeof(EFI_SIGNATURE_DATA
) - 1
437 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
438 (*PkCert
)->SignatureHeaderSize
= 0;
439 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
440 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
441 + sizeof(EFI_SIGNATURE_LIST
)
442 + (*PkCert
)->SignatureHeaderSize
);
443 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
445 // Fill the PK database with PKpub data from X509 certificate file.
447 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
451 if (X509Data
!= NULL
) {
455 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
464 Enroll new PK into the System without original PK's authentication.
466 The SignatureOwner GUID will be the same with PK's vendorguid.
468 @param[in] PrivateData The module's private data.
470 @retval EFI_SUCCESS New PK enrolled successfully.
471 @retval EFI_INVALID_PARAMETER The parameter is invalid.
472 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
477 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
483 EFI_SIGNATURE_LIST
*PkCert
;
487 if (Private
->FileContext
->FileName
== NULL
) {
488 return EFI_INVALID_PARAMETER
;
493 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
494 if (EFI_ERROR (Status
)) {
499 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
501 NameLength
= StrLen (Private
->FileContext
->FileName
);
502 if (NameLength
<= 4) {
503 return EFI_INVALID_PARAMETER
;
505 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
506 if (!IsDerEncodeCertificate(FilePostFix
)) {
507 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
508 return EFI_INVALID_PARAMETER
;
510 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
511 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
514 // Prase the selected PK file and generature PK certificate list.
516 Status
= CreatePkX509SignatureList (
517 Private
->FileContext
->FHandle
,
520 if (EFI_ERROR (Status
)) {
523 ASSERT (PkCert
!= NULL
);
526 // Set Platform Key variable.
528 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
529 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
530 DataSize
= PkCert
->SignatureListSize
;
531 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
532 if (EFI_ERROR (Status
)) {
533 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
537 Status
= gRT
->SetVariable(
538 EFI_PLATFORM_KEY_NAME
,
539 &gEfiGlobalVariableGuid
,
544 if (EFI_ERROR (Status
)) {
545 if (Status
== EFI_OUT_OF_RESOURCES
) {
546 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
553 if (PkCert
!= NULL
) {
557 CloseEnrolledFile(Private
->FileContext
);
563 Remove the PK variable.
565 @retval EFI_SUCCESS Delete PK successfully.
566 @retval Others Could not allow to delete PK.
576 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
577 if (EFI_ERROR (Status
)) {
581 Status
= DeleteVariable (
582 EFI_PLATFORM_KEY_NAME
,
583 &gEfiGlobalVariableGuid
589 Enroll a new KEK item from public key storing file (*.pbk).
591 @param[in] PrivateData The module's private data.
593 @retval EFI_SUCCESS New KEK enrolled successfully.
594 @retval EFI_INVALID_PARAMETER The parameter is invalid.
595 @retval EFI_UNSUPPORTED Unsupported command.
596 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
601 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
607 EFI_SIGNATURE_LIST
*KekSigList
;
610 CPL_KEY_INFO
*KeyInfo
;
611 EFI_SIGNATURE_DATA
*KEKSigData
;
612 UINTN KekSigListSize
;
627 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
628 // First, We have to parse out public key data from the pbk key file.
630 Status
= ReadFileContent (
631 Private
->FileContext
->FHandle
,
636 if (EFI_ERROR (Status
)) {
639 ASSERT (KeyBlob
!= NULL
);
640 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
641 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
642 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
643 Status
= EFI_UNSUPPORTED
;
648 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
650 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
651 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
652 if (KeyBuffer
== NULL
) {
653 Status
= EFI_OUT_OF_RESOURCES
;
657 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
658 KeyLenInBytes
/ sizeof (UINTN
),
662 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
665 // Form an new EFI_SIGNATURE_LIST.
667 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
668 + sizeof(EFI_SIGNATURE_DATA
) - 1
669 + WIN_CERT_UEFI_RSA2048_SIZE
;
671 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
672 if (KekSigList
== NULL
) {
673 Status
= EFI_OUT_OF_RESOURCES
;
677 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
678 + sizeof(EFI_SIGNATURE_DATA
) - 1
679 + WIN_CERT_UEFI_RSA2048_SIZE
;
680 KekSigList
->SignatureHeaderSize
= 0;
681 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
682 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
684 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
685 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
687 KEKSigData
->SignatureData
,
688 KeyBlob
+ sizeof(CPL_KEY_INFO
),
689 WIN_CERT_UEFI_RSA2048_SIZE
693 // Check if KEK entry has been already existed.
694 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
695 // new KEK to original variable.
697 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
698 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
699 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
700 if (EFI_ERROR (Status
)) {
701 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
705 Status
= gRT
->GetVariable(
706 EFI_KEY_EXCHANGE_KEY_NAME
,
707 &gEfiGlobalVariableGuid
,
712 if (Status
== EFI_BUFFER_TOO_SMALL
) {
713 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
714 } else if (Status
!= EFI_NOT_FOUND
) {
719 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
721 Status
= gRT
->SetVariable(
722 EFI_KEY_EXCHANGE_KEY_NAME
,
723 &gEfiGlobalVariableGuid
,
728 if (EFI_ERROR (Status
)) {
734 CloseEnrolledFile(Private
->FileContext
);
736 if (Private
->SignatureGUID
!= NULL
) {
737 FreePool (Private
->SignatureGUID
);
738 Private
->SignatureGUID
= NULL
;
741 if (KeyBlob
!= NULL
) {
744 if (KeyBuffer
!= NULL
) {
745 FreePool (KeyBuffer
);
747 if (KekSigList
!= NULL
) {
748 FreePool (KekSigList
);
755 Enroll a new KEK item from X509 certificate file.
757 @param[in] PrivateData The module's private data.
759 @retval EFI_SUCCESS New X509 is enrolled successfully.
760 @retval EFI_INVALID_PARAMETER The parameter is invalid.
761 @retval EFI_UNSUPPORTED Unsupported command.
762 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
767 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
773 EFI_SIGNATURE_DATA
*KEKSigData
;
774 EFI_SIGNATURE_LIST
*KekSigList
;
776 UINTN KekSigListSize
;
786 Status
= ReadFileContent (
787 Private
->FileContext
->FHandle
,
792 if (EFI_ERROR (Status
)) {
795 ASSERT (X509Data
!= NULL
);
797 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
798 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
799 if (KekSigList
== NULL
) {
800 Status
= EFI_OUT_OF_RESOURCES
;
805 // Fill Certificate Database parameters.
807 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
808 KekSigList
->SignatureHeaderSize
= 0;
809 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
810 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
812 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
813 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
814 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
817 // Check if KEK been already existed.
818 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
819 // new kek to original variable
821 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
822 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
823 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
824 if (EFI_ERROR (Status
)) {
825 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
829 Status
= gRT
->GetVariable(
830 EFI_KEY_EXCHANGE_KEY_NAME
,
831 &gEfiGlobalVariableGuid
,
836 if (Status
== EFI_BUFFER_TOO_SMALL
) {
837 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
838 } else if (Status
!= EFI_NOT_FOUND
) {
842 Status
= gRT
->SetVariable(
843 EFI_KEY_EXCHANGE_KEY_NAME
,
844 &gEfiGlobalVariableGuid
,
849 if (EFI_ERROR (Status
)) {
855 CloseEnrolledFile(Private
->FileContext
);
857 if (Private
->SignatureGUID
!= NULL
) {
858 FreePool (Private
->SignatureGUID
);
859 Private
->SignatureGUID
= NULL
;
862 if (KekSigList
!= NULL
) {
863 FreePool (KekSigList
);
870 Enroll new KEK into the System without PK's authentication.
871 The SignatureOwner GUID will be Private->SignatureGUID.
873 @param[in] PrivateData The module's private data.
875 @retval EFI_SUCCESS New KEK enrolled successful.
876 @retval EFI_INVALID_PARAMETER The parameter is invalid.
877 @retval others Fail to enroll KEK data.
881 EnrollKeyExchangeKey (
882 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
889 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
890 return EFI_INVALID_PARAMETER
;
893 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
894 if (EFI_ERROR (Status
)) {
899 // Parse the file's postfix. Supports DER-encoded X509 certificate,
900 // and .pbk as RSA public key file.
902 NameLength
= StrLen (Private
->FileContext
->FileName
);
903 if (NameLength
<= 4) {
904 return EFI_INVALID_PARAMETER
;
906 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
907 if (IsDerEncodeCertificate(FilePostFix
)) {
908 return EnrollX509ToKek (Private
);
909 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
910 return EnrollRsa2048ToKek (Private
);
913 // File type is wrong, simply close it
915 CloseEnrolledFile(Private
->FileContext
);
917 return EFI_INVALID_PARAMETER
;
922 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
923 KEK's authentication.
925 @param[in] PrivateData The module's private data.
926 @param[in] VariableName Variable name of signature database, must be
927 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
929 @retval EFI_SUCCESS New X509 is enrolled successfully.
930 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
935 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
936 IN CHAR16
*VariableName
942 EFI_SIGNATURE_LIST
*SigDBCert
;
943 EFI_SIGNATURE_DATA
*SigDBCertData
;
954 SigDBCertData
= NULL
;
957 Status
= ReadFileContent (
958 Private
->FileContext
->FHandle
,
963 if (EFI_ERROR (Status
)) {
966 ASSERT (X509Data
!= NULL
);
968 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
970 Data
= AllocateZeroPool (SigDBSize
);
972 Status
= EFI_OUT_OF_RESOURCES
;
977 // Fill Certificate Database parameters.
979 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
980 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
981 SigDBCert
->SignatureHeaderSize
= 0;
982 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
983 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
985 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
986 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
987 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
990 // Check if signature database entry has been already existed.
991 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
992 // new signature data to original variable
994 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
995 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
996 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
997 if (EFI_ERROR (Status
)) {
998 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1002 Status
= gRT
->GetVariable(
1004 &gEfiImageSecurityDatabaseGuid
,
1009 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1010 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1011 } else if (Status
!= EFI_NOT_FOUND
) {
1015 Status
= gRT
->SetVariable(
1017 &gEfiImageSecurityDatabaseGuid
,
1022 if (EFI_ERROR (Status
)) {
1028 CloseEnrolledFile(Private
->FileContext
);
1030 if (Private
->SignatureGUID
!= NULL
) {
1031 FreePool (Private
->SignatureGUID
);
1032 Private
->SignatureGUID
= NULL
;
1039 if (X509Data
!= NULL
) {
1040 FreePool (X509Data
);
1047 Check whether signature is in specified database.
1049 @param[in] VariableName Name of database variable that is searched in.
1050 @param[in] Signature Pointer to signature that is searched for.
1051 @param[in] SignatureSize Size of Signature.
1053 @return TRUE Found the signature in the variable database.
1054 @return FALSE Not found the signature in the variable database.
1058 IsSignatureFoundInDatabase (
1059 IN CHAR16
*VariableName
,
1060 IN UINT8
*Signature
,
1061 IN UINTN SignatureSize
1065 EFI_SIGNATURE_LIST
*CertList
;
1066 EFI_SIGNATURE_DATA
*Cert
;
1074 // Read signature database variable.
1079 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1080 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1084 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1089 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1090 if (EFI_ERROR (Status
)) {
1095 // Enumerate all signature data in SigDB to check if executable's signature exists.
1097 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1098 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1099 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1100 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1101 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1102 for (Index
= 0; Index
< CertCount
; Index
++) {
1103 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1105 // Find the signature in database.
1110 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1118 DataSize
-= CertList
->SignatureListSize
;
1119 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1131 Calculate the hash of a certificate data with the specified hash algorithm.
1133 @param[in] CertData The certificate data to be hashed.
1134 @param[in] CertSize The certificate size in bytes.
1135 @param[in] HashAlg The specified hash algorithm.
1136 @param[out] CertHash The output digest of the certificate
1138 @retval TRUE Successfully got the hash of the CertData.
1139 @retval FALSE Failed to get the hash of CertData.
1159 if (HashAlg
>= HASHALG_MAX
) {
1164 // Retrieve the TBSCertificate for Hash Calculation.
1166 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1171 // 1. Initialize context of hash.
1173 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1174 HashCtx
= AllocatePool (CtxSize
);
1175 ASSERT (HashCtx
!= NULL
);
1178 // 2. Initialize a hash context.
1180 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1186 // 3. Calculate the hash.
1188 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1194 // 4. Get the hash result.
1196 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1197 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1200 if (HashCtx
!= NULL
) {
1208 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1210 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1211 @param[in] CertSize Size of X.509 Certificate.
1213 @return TRUE Found the certificate hash in the forbidden database.
1214 @return FALSE Certificate hash is Not found in the forbidden database.
1218 IsCertHashFoundInDbx (
1219 IN UINT8
*Certificate
,
1225 EFI_SIGNATURE_LIST
*DbxList
;
1226 EFI_SIGNATURE_DATA
*CertHash
;
1227 UINTN CertHashCount
;
1230 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1232 UINTN SiglistHeaderSize
;
1237 HashAlg
= HASHALG_MAX
;
1241 // Read signature database variable.
1244 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1245 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1249 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1254 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1255 if (EFI_ERROR (Status
)) {
1260 // Check whether the certificate hash exists in the forbidden database.
1262 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1263 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1265 // Determine Hash Algorithm of Certificate in the forbidden database.
1267 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1268 HashAlg
= HASHALG_SHA256
;
1269 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1270 HashAlg
= HASHALG_SHA384
;
1271 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1272 HashAlg
= HASHALG_SHA512
;
1274 DataSize
-= DbxList
->SignatureListSize
;
1275 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1280 // Calculate the hash value of current db certificate for comparision.
1282 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1286 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1287 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1288 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1289 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1291 // Iterate each Signature Data Node within this CertList for verify.
1293 DbxCertHash
= CertHash
->SignatureData
;
1294 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1296 // Hash of Certificate is found in forbidden database.
1301 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1304 DataSize
-= DbxList
->SignatureListSize
;
1305 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1317 Check whether the signature list exists in given variable data.
1319 It searches the signature list for the ceritificate hash by CertType.
1320 If the signature list is found, get the offset of Database for the
1321 next hash of a certificate.
1323 @param[in] Database Variable data to save signature list.
1324 @param[in] DatabaseSize Variable size.
1325 @param[in] SignatureType The type of the signature.
1326 @param[out] Offset The offset to save a new hash of certificate.
1328 @return TRUE The signature list is found in the forbidden database.
1329 @return FALSE The signature list is not found in the forbidden database.
1332 GetSignaturelistOffset (
1333 IN EFI_SIGNATURE_LIST
*Database
,
1334 IN UINTN DatabaseSize
,
1335 IN EFI_GUID
*SignatureType
,
1339 EFI_SIGNATURE_LIST
*SigList
;
1342 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1348 SiglistSize
= DatabaseSize
;
1349 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1350 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1351 *Offset
= DatabaseSize
- SiglistSize
;
1354 SiglistSize
-= SigList
->SignatureListSize
;
1355 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1362 Enroll a new X509 certificate hash into Signature Database (dbx) without
1363 KEK's authentication.
1365 @param[in] PrivateData The module's private data.
1366 @param[in] HashAlg The hash algorithm to enroll the certificate.
1367 @param[in] RevocationDate The revocation date of the certificate.
1368 @param[in] RevocationTime The revocation time of the certificate.
1369 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1371 @retval EFI_SUCCESS New X509 is enrolled successfully.
1372 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1373 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1377 EnrollX509HashtoSigDB (
1378 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1380 IN EFI_HII_DATE
*RevocationDate
,
1381 IN EFI_HII_TIME
*RevocationTime
,
1382 IN BOOLEAN AlwaysRevocation
1388 EFI_SIGNATURE_LIST
*SignatureList
;
1389 UINTN SignatureListSize
;
1395 EFI_SIGNATURE_DATA
*SignatureData
;
1396 UINTN SignatureSize
;
1397 EFI_GUID SignatureType
;
1399 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1400 UINT16
* FilePostFix
;
1407 SignatureData
= NULL
;
1408 SignatureList
= NULL
;
1412 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1413 return EFI_INVALID_PARAMETER
;
1416 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1417 if (EFI_ERROR (Status
)) {
1422 // Parse the file's postfix.
1424 NameLength
= StrLen (Private
->FileContext
->FileName
);
1425 if (NameLength
<= 4) {
1426 return EFI_INVALID_PARAMETER
;
1428 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1429 if (!IsDerEncodeCertificate(FilePostFix
)) {
1431 // Only supports DER-encoded X509 certificate.
1433 return EFI_INVALID_PARAMETER
;
1437 // Get the certificate from file and calculate its hash.
1439 Status
= ReadFileContent (
1440 Private
->FileContext
->FHandle
,
1445 if (EFI_ERROR (Status
)) {
1448 ASSERT (X509Data
!= NULL
);
1450 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1455 // Get the variable for enrollment.
1458 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1459 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1460 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1462 return EFI_OUT_OF_RESOURCES
;
1465 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1466 if (EFI_ERROR (Status
)) {
1472 // Allocate memory for Signature and fill the Signature
1474 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1475 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1476 if (SignatureData
== NULL
) {
1477 return EFI_OUT_OF_RESOURCES
;
1479 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1480 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1485 if (!AlwaysRevocation
) {
1486 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1487 Time
->Year
= RevocationDate
->Year
;
1488 Time
->Month
= RevocationDate
->Month
;
1489 Time
->Day
= RevocationDate
->Day
;
1490 Time
->Hour
= RevocationTime
->Hour
;
1491 Time
->Minute
= RevocationTime
->Minute
;
1492 Time
->Second
= RevocationTime
->Second
;
1496 // Determine the GUID for certificate hash.
1499 case HASHALG_SHA256
:
1500 SignatureType
= gEfiCertX509Sha256Guid
;
1502 case HASHALG_SHA384
:
1503 SignatureType
= gEfiCertX509Sha384Guid
;
1505 case HASHALG_SHA512
:
1506 SignatureType
= gEfiCertX509Sha512Guid
;
1513 // Add signature into the new variable data buffer
1515 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1517 // Add the signature to the found signaturelist.
1519 DbSize
= DataSize
+ SignatureSize
;
1520 NewData
= AllocateZeroPool (DbSize
);
1521 if (NewData
== NULL
) {
1522 Status
= EFI_OUT_OF_RESOURCES
;
1526 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1527 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1528 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1530 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1531 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1533 Offset
+= SignatureListSize
;
1534 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1535 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1542 // Create a new signaturelist, and add the signature into the signaturelist.
1544 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1545 NewData
= AllocateZeroPool (DbSize
);
1546 if (NewData
== NULL
) {
1547 Status
= EFI_OUT_OF_RESOURCES
;
1551 // Fill Certificate Database parameters.
1553 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1554 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1555 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1556 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1557 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1558 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1559 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1560 CopyMem (NewData
, Data
, DataSize
);
1567 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1568 if (EFI_ERROR (Status
)) {
1572 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1573 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1574 Status
= gRT
->SetVariable(
1575 EFI_IMAGE_SECURITY_DATABASE1
,
1576 &gEfiImageSecurityDatabaseGuid
,
1581 if (EFI_ERROR (Status
)) {
1587 CloseEnrolledFile(Private
->FileContext
);
1589 if (Private
->SignatureGUID
!= NULL
) {
1590 FreePool (Private
->SignatureGUID
);
1591 Private
->SignatureGUID
= NULL
;
1598 if (SignatureData
!= NULL
) {
1599 FreePool (SignatureData
);
1602 if (X509Data
!= NULL
) {
1603 FreePool (X509Data
);
1610 Check whether a certificate from a file exists in dbx.
1612 @param[in] PrivateData The module's private data.
1613 @param[in] VariableName Variable name of signature database, must be
1614 EFI_IMAGE_SECURITY_DATABASE1.
1616 @retval TRUE The X509 certificate is found in dbx successfully.
1617 @retval FALSE The X509 certificate is not found in dbx.
1621 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1622 IN CHAR16
*VariableName
1631 // Read the certificate from file
1635 Status
= ReadFileContent (
1636 Private
->FileContext
->FHandle
,
1641 if (EFI_ERROR (Status
)) {
1646 // Check the raw certificate.
1649 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1655 // Check the hash of certificate.
1657 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1663 if (X509Data
!= NULL
) {
1664 FreePool (X509Data
);
1671 Reads contents of a PE/COFF image in memory buffer.
1673 Caution: This function may receive untrusted input.
1674 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1675 read is within the image buffer.
1677 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1678 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1679 @param ReadSize On input, the size in bytes of the requested read operation.
1680 On output, the number of bytes actually read.
1681 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1683 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1687 SecureBootConfigImageRead (
1688 IN VOID
*FileHandle
,
1689 IN UINTN FileOffset
,
1690 IN OUT UINTN
*ReadSize
,
1696 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1697 return EFI_INVALID_PARAMETER
;
1700 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1701 return EFI_INVALID_PARAMETER
;
1704 EndPosition
= FileOffset
+ *ReadSize
;
1705 if (EndPosition
> mImageSize
) {
1706 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1709 if (FileOffset
>= mImageSize
) {
1713 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1719 Load PE/COFF image information into internal buffer and check its validity.
1721 @retval EFI_SUCCESS Successful
1722 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1723 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1731 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1732 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1733 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1734 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1740 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1741 ImageContext
.Handle
= (VOID
*) mImageBase
;
1742 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1745 // Get information about the image being loaded
1747 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1748 if (EFI_ERROR (Status
)) {
1750 // The information can't be got from the invalid PeImage
1752 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1757 // Read the Dos header
1759 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1760 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1763 // DOS image header is present,
1764 // So read the PE header after the DOS image header
1766 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1770 mPeCoffHeaderOffset
= 0;
1774 // Read PE header and check the signature validity and machine compatibility
1776 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1777 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1779 return EFI_UNSUPPORTED
;
1782 mNtHeader
.Pe32
= NtHeader32
;
1785 // Check the architecture field of PE header and get the Certificate Data Directory data
1786 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1788 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1789 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1790 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1792 // 32-bits Architecture
1794 mImageType
= ImageType_IA32
;
1795 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1797 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1798 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1799 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1801 // 64-bits Architecture
1803 mImageType
= ImageType_X64
;
1804 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1805 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1807 return EFI_UNSUPPORTED
;
1814 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1815 PE/COFF Specification 8.0 Appendix A
1817 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1818 the function LoadPeImage ().
1820 @param[in] HashAlg Hash algorithm type.
1822 @retval TRUE Successfully hash image.
1823 @retval FALSE Fail in hash image.
1833 EFI_IMAGE_SECTION_HEADER
*Section
;
1838 UINTN SumOfBytesHashed
;
1839 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1844 SectionHeader
= NULL
;
1847 if (HashAlg
!= HASHALG_SHA256
) {
1852 // Initialize context of hash.
1854 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1856 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1857 mCertType
= gEfiCertSha256Guid
;
1859 CtxSize
= mHash
[HashAlg
].GetContextSize();
1861 HashCtx
= AllocatePool (CtxSize
);
1862 ASSERT (HashCtx
!= NULL
);
1864 // 1. Load the image header into memory.
1866 // 2. Initialize a SHA hash context.
1867 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1872 // Measuring PE/COFF Image Header;
1873 // But CheckSum field and SECURITY data directory (certificate) are excluded
1875 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1877 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1878 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1879 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1880 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1882 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1885 // Get the magic value from the PE/COFF Optional Header
1887 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1891 // 3. Calculate the distance from the base of the image header to the image checksum address.
1892 // 4. Hash the image header from its base to beginning of the image checksum.
1894 HashBase
= mImageBase
;
1895 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1899 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1902 // Use PE32+ offset.
1904 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1907 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1912 // 5. Skip over the image checksum (it occupies a single ULONG).
1913 // 6. Get the address of the beginning of the Cert Directory.
1914 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1916 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1920 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1921 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1924 // Use PE32+ offset.
1926 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1927 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1930 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1935 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1936 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1938 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1942 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1943 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1946 // Use PE32+ offset.
1948 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1949 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1952 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1957 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1959 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1963 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1968 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1972 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1973 // structures in the image. The 'NumberOfSections' field of the image
1974 // header indicates how big the table should be. Do not include any
1975 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1977 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1978 ASSERT (SectionHeader
!= NULL
);
1980 // 12. Using the 'PointerToRawData' in the referenced section headers as
1981 // a key, arrange the elements in the table in ascending order. In other
1982 // words, sort the section headers according to the disk-file offset of
1985 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1987 mPeCoffHeaderOffset
+
1989 sizeof (EFI_IMAGE_FILE_HEADER
) +
1990 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1992 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1994 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1995 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1998 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
2003 // 13. Walk through the sorted table, bring the corresponding section
2004 // into memory, and hash the entire section (using the 'SizeOfRawData'
2005 // field in the section header to determine the amount of data to hash).
2006 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2007 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
2009 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
2010 Section
= &SectionHeader
[Index
];
2011 if (Section
->SizeOfRawData
== 0) {
2014 HashBase
= mImageBase
+ Section
->PointerToRawData
;
2015 HashSize
= (UINTN
) Section
->SizeOfRawData
;
2017 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2022 SumOfBytesHashed
+= HashSize
;
2026 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2027 // data in the file that needs to be added to the hash. This data begins
2028 // at file offset SUM_OF_BYTES_HASHED and its length is:
2029 // FileSize - (CertDirectory->Size)
2031 if (mImageSize
> SumOfBytesHashed
) {
2032 HashBase
= mImageBase
+ SumOfBytesHashed
;
2033 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2039 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2043 // Use PE32+ offset.
2047 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2051 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2057 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2060 if (HashCtx
!= NULL
) {
2063 if (SectionHeader
!= NULL
) {
2064 FreePool (SectionHeader
);
2070 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2071 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2074 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2075 @retval EFI_SUCCESS Hash successfully.
2084 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2086 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2088 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2090 // Check the Hash algorithm in PE/COFF Authenticode.
2091 // According to PKCS#7 Definition:
2092 // SignedData ::= SEQUENCE {
2094 // digestAlgorithms DigestAlgorithmIdentifiers,
2095 // contentInfo ContentInfo,
2097 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2098 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2099 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2101 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2103 // Only support two bytes of Long Form of Length Encoding.
2109 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2114 if (Index
== HASHALG_MAX
) {
2115 return EFI_UNSUPPORTED
;
2119 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2121 if (!HashPeImage(Index
)) {
2122 return EFI_UNSUPPORTED
;
2129 Enroll a new executable's signature into Signature Database.
2131 @param[in] PrivateData The module's private data.
2132 @param[in] VariableName Variable name of signature database, must be
2133 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2134 or EFI_IMAGE_SECURITY_DATABASE2.
2136 @retval EFI_SUCCESS New signature is enrolled successfully.
2137 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2138 @retval EFI_UNSUPPORTED Unsupported command.
2139 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2143 EnrollAuthentication2Descriptor (
2144 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2145 IN CHAR16
*VariableName
2156 // DBT only support DER-X509 Cert Enrollment
2158 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2159 return EFI_UNSUPPORTED
;
2163 // Read the whole file content
2165 Status
= ReadFileContent(
2166 Private
->FileContext
->FHandle
,
2167 (VOID
**) &mImageBase
,
2171 if (EFI_ERROR (Status
)) {
2174 ASSERT (mImageBase
!= NULL
);
2176 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2177 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2180 // Check if SigDB variable has been already existed.
2181 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2182 // new signature data to original variable
2185 Status
= gRT
->GetVariable(
2187 &gEfiImageSecurityDatabaseGuid
,
2192 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2193 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2194 } else if (Status
!= EFI_NOT_FOUND
) {
2199 // Diretly set AUTHENTICATION_2 data to SetVariable
2201 Status
= gRT
->SetVariable(
2203 &gEfiImageSecurityDatabaseGuid
,
2209 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2213 CloseEnrolledFile(Private
->FileContext
);
2219 if (mImageBase
!= NULL
) {
2220 FreePool (mImageBase
);
2230 Enroll a new executable's signature into Signature Database.
2232 @param[in] PrivateData The module's private data.
2233 @param[in] VariableName Variable name of signature database, must be
2234 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2235 or EFI_IMAGE_SECURITY_DATABASE2.
2237 @retval EFI_SUCCESS New signature is enrolled successfully.
2238 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2239 @retval EFI_UNSUPPORTED Unsupported command.
2240 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2244 EnrollImageSignatureToSigDB (
2245 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2246 IN CHAR16
*VariableName
2250 EFI_SIGNATURE_LIST
*SigDBCert
;
2251 EFI_SIGNATURE_DATA
*SigDBCertData
;
2256 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2259 GuidCertData
= NULL
;
2261 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2262 return EFI_UNSUPPORTED
;
2266 // Form the SigDB certificate list.
2267 // Format the data item into EFI_SIGNATURE_LIST type.
2269 // We need to parse executable's signature data from specified signed executable file.
2270 // In current implementation, we simply trust the pass-in signed executable file.
2271 // In reality, it's OS's responsibility to verify the signed executable file.
2275 // Read the whole file content
2277 Status
= ReadFileContent(
2278 Private
->FileContext
->FHandle
,
2279 (VOID
**) &mImageBase
,
2283 if (EFI_ERROR (Status
)) {
2286 ASSERT (mImageBase
!= NULL
);
2288 Status
= LoadPeImage ();
2289 if (EFI_ERROR (Status
)) {
2293 if (mSecDataDir
->SizeOfCert
== 0) {
2294 if (!HashPeImage (HASHALG_SHA256
)) {
2295 Status
= EFI_SECURITY_VIOLATION
;
2301 // Read the certificate data
2303 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2305 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2306 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2307 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2308 Status
= EFI_ABORTED
;
2312 if (!HashPeImage (HASHALG_SHA256
)) {
2313 Status
= EFI_ABORTED
;
2317 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2319 Status
= HashPeImageByType ();
2320 if (EFI_ERROR (Status
)) {
2324 Status
= EFI_ABORTED
;
2330 // Create a new SigDB entry.
2332 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2333 + sizeof(EFI_SIGNATURE_DATA
) - 1
2334 + (UINT32
) mImageDigestSize
;
2336 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2338 Status
= EFI_OUT_OF_RESOURCES
;
2343 // Adjust the Certificate Database parameters.
2345 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2346 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2347 SigDBCert
->SignatureHeaderSize
= 0;
2348 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2349 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2351 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2352 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2353 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2355 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2356 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2357 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2358 if (EFI_ERROR (Status
)) {
2359 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2364 // Check if SigDB variable has been already existed.
2365 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2366 // new signature data to original variable
2369 Status
= gRT
->GetVariable(
2371 &gEfiImageSecurityDatabaseGuid
,
2376 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2377 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2378 } else if (Status
!= EFI_NOT_FOUND
) {
2383 // Enroll the variable.
2385 Status
= gRT
->SetVariable(
2387 &gEfiImageSecurityDatabaseGuid
,
2392 if (EFI_ERROR (Status
)) {
2398 CloseEnrolledFile(Private
->FileContext
);
2400 if (Private
->SignatureGUID
!= NULL
) {
2401 FreePool (Private
->SignatureGUID
);
2402 Private
->SignatureGUID
= NULL
;
2409 if (mImageBase
!= NULL
) {
2410 FreePool (mImageBase
);
2418 Enroll signature into DB/DBX/DBT without KEK's authentication.
2419 The SignatureOwner GUID will be Private->SignatureGUID.
2421 @param[in] PrivateData The module's private data.
2422 @param[in] VariableName Variable name of signature database, must be
2423 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2425 @retval EFI_SUCCESS New signature enrolled successfully.
2426 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2427 @retval others Fail to enroll signature data.
2431 EnrollSignatureDatabase (
2432 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2433 IN CHAR16
*VariableName
2436 UINT16
* FilePostFix
;
2440 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2441 return EFI_INVALID_PARAMETER
;
2444 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2445 if (EFI_ERROR (Status
)) {
2450 // Parse the file's postfix.
2452 NameLength
= StrLen (Private
->FileContext
->FileName
);
2453 if (NameLength
<= 4) {
2454 return EFI_INVALID_PARAMETER
;
2456 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2457 if (IsDerEncodeCertificate (FilePostFix
)) {
2459 // Supports DER-encoded X509 certificate.
2461 return EnrollX509toSigDB (Private
, VariableName
);
2462 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2463 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2465 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2470 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2471 by GUID in the page for user to select and delete as needed.
2473 @param[in] PrivateData Module's private data.
2474 @param[in] VariableName The variable name of the vendor's signature database.
2475 @param[in] VendorGuid A unique identifier for the vendor.
2476 @param[in] LabelNumber Label number to insert opcodes.
2477 @param[in] FormId Form ID of current page.
2478 @param[in] QuestionIdBase Base question id of the signature list.
2480 @retval EFI_SUCCESS Success to update the signature list page
2481 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2486 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2487 IN CHAR16
*VariableName
,
2488 IN EFI_GUID
*VendorGuid
,
2489 IN UINT16 LabelNumber
,
2490 IN EFI_FORM_ID FormId
,
2491 IN EFI_QUESTION_ID QuestionIdBase
2498 VOID
*StartOpCodeHandle
;
2499 VOID
*EndOpCodeHandle
;
2500 EFI_IFR_GUID_LABEL
*StartLabel
;
2501 EFI_IFR_GUID_LABEL
*EndLabel
;
2504 EFI_SIGNATURE_LIST
*CertList
;
2505 EFI_SIGNATURE_DATA
*Cert
;
2506 UINT32 ItemDataSize
;
2508 EFI_STRING_ID GuidID
;
2515 StartOpCodeHandle
= NULL
;
2516 EndOpCodeHandle
= NULL
;
2519 // Initialize the container for dynamic opcodes.
2521 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2522 if (StartOpCodeHandle
== NULL
) {
2523 Status
= EFI_OUT_OF_RESOURCES
;
2527 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2528 if (EndOpCodeHandle
== NULL
) {
2529 Status
= EFI_OUT_OF_RESOURCES
;
2534 // Create Hii Extend Label OpCode.
2536 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2540 sizeof (EFI_IFR_GUID_LABEL
)
2542 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2543 StartLabel
->Number
= LabelNumber
;
2545 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2549 sizeof (EFI_IFR_GUID_LABEL
)
2551 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2552 EndLabel
->Number
= LABEL_END
;
2558 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2559 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2563 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2565 Status
= EFI_OUT_OF_RESOURCES
;
2569 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2570 if (EFI_ERROR (Status
)) {
2574 GuidStr
= AllocateZeroPool (100);
2575 if (GuidStr
== NULL
) {
2576 Status
= EFI_OUT_OF_RESOURCES
;
2581 // Enumerate all KEK pub data.
2583 ItemDataSize
= (UINT32
) DataSize
;
2584 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2587 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2589 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2590 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2591 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2592 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2593 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2594 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2595 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2596 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2597 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2598 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2599 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2600 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2601 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2602 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2605 // The signature type is not supported in current implementation.
2607 ItemDataSize
-= CertList
->SignatureListSize
;
2608 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2612 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2613 for (Index
= 0; Index
< CertCount
; Index
++) {
2614 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2615 + sizeof (EFI_SIGNATURE_LIST
)
2616 + CertList
->SignatureHeaderSize
2617 + Index
* CertList
->SignatureSize
);
2619 // Display GUID and help
2621 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2622 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2623 HiiCreateCheckBoxOpCode (
2625 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2630 EFI_IFR_FLAG_CALLBACK
,
2636 ItemDataSize
-= CertList
->SignatureListSize
;
2637 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2642 PrivateData
->HiiHandle
,
2643 &gSecureBootConfigFormSetGuid
,
2649 if (StartOpCodeHandle
!= NULL
) {
2650 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2653 if (EndOpCodeHandle
!= NULL
) {
2654 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2661 if (GuidStr
!= NULL
) {
2669 Delete a KEK entry from KEK database.
2671 @param[in] PrivateData Module's private data.
2672 @param[in] QuestionId Question id of the KEK item to delete.
2674 @retval EFI_SUCCESS Delete kek item successfully.
2675 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2679 DeleteKeyExchangeKey (
2680 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2681 IN EFI_QUESTION_ID QuestionId
2690 EFI_SIGNATURE_LIST
*CertList
;
2691 EFI_SIGNATURE_LIST
*NewCertList
;
2692 EFI_SIGNATURE_DATA
*Cert
;
2695 BOOLEAN IsKEKItemFound
;
2697 UINTN DeleteKekIndex
;
2705 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2707 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2708 if (EFI_ERROR (Status
)) {
2713 // Get original KEK variable.
2716 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2717 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2721 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2722 if (OldData
== NULL
) {
2723 Status
= EFI_OUT_OF_RESOURCES
;
2727 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2728 if (EFI_ERROR(Status
)) {
2733 // Allocate space for new variable.
2735 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2737 Status
= EFI_OUT_OF_RESOURCES
;
2742 // Enumerate all KEK pub data and erasing the target item.
2744 IsKEKItemFound
= FALSE
;
2745 KekDataSize
= (UINT32
) DataSize
;
2746 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2749 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2750 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2751 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2752 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2753 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2754 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2755 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2756 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2757 for (Index
= 0; Index
< CertCount
; Index
++) {
2758 if (GuidIndex
== DeleteKekIndex
) {
2760 // Find it! Skip it!
2762 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2763 IsKEKItemFound
= TRUE
;
2766 // This item doesn't match. Copy it to the Data buffer.
2768 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2769 Offset
+= CertList
->SignatureSize
;
2772 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2776 // This List doesn't match. Copy it to the Data buffer.
2778 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2779 Offset
+= CertList
->SignatureListSize
;
2782 KekDataSize
-= CertList
->SignatureListSize
;
2783 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2786 if (!IsKEKItemFound
) {
2788 // Doesn't find the Kek Item!
2790 Status
= EFI_NOT_FOUND
;
2795 // Delete the Signature header if there is no signature in the list.
2797 KekDataSize
= Offset
;
2798 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2800 ZeroMem (OldData
, KekDataSize
);
2801 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2802 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2803 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2804 if (CertCount
!= 0) {
2805 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2806 Offset
+= CertList
->SignatureListSize
;
2808 KekDataSize
-= CertList
->SignatureListSize
;
2809 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2813 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2814 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2815 if (EFI_ERROR (Status
)) {
2816 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2821 Status
= gRT
->SetVariable(
2822 EFI_KEY_EXCHANGE_KEY_NAME
,
2823 &gEfiGlobalVariableGuid
,
2828 if (EFI_ERROR (Status
)) {
2829 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2838 if (OldData
!= NULL
) {
2842 return UpdateDeletePage (
2844 EFI_KEY_EXCHANGE_KEY_NAME
,
2845 &gEfiGlobalVariableGuid
,
2847 FORMID_DELETE_KEK_FORM
,
2848 OPTION_DEL_KEK_QUESTION_ID
2853 Delete a signature entry from siganture database.
2855 @param[in] PrivateData Module's private data.
2856 @param[in] VariableName The variable name of the vendor's signature database.
2857 @param[in] VendorGuid A unique identifier for the vendor.
2858 @param[in] LabelNumber Label number to insert opcodes.
2859 @param[in] FormId Form ID of current page.
2860 @param[in] QuestionIdBase Base question id of the signature list.
2861 @param[in] DeleteIndex Signature index to delete.
2863 @retval EFI_SUCCESS Delete siganture successfully.
2864 @retval EFI_NOT_FOUND Can't find the signature item,
2865 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2869 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2870 IN CHAR16
*VariableName
,
2871 IN EFI_GUID
*VendorGuid
,
2872 IN UINT16 LabelNumber
,
2873 IN EFI_FORM_ID FormId
,
2874 IN EFI_QUESTION_ID QuestionIdBase
,
2875 IN UINTN DeleteIndex
2884 EFI_SIGNATURE_LIST
*CertList
;
2885 EFI_SIGNATURE_LIST
*NewCertList
;
2886 EFI_SIGNATURE_DATA
*Cert
;
2889 BOOLEAN IsItemFound
;
2890 UINT32 ItemDataSize
;
2899 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2900 if (EFI_ERROR (Status
)) {
2905 // Get original signature list data.
2908 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2909 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2913 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2914 if (OldData
== NULL
) {
2915 Status
= EFI_OUT_OF_RESOURCES
;
2919 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2920 if (EFI_ERROR(Status
)) {
2925 // Allocate space for new variable.
2927 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2929 Status
= EFI_OUT_OF_RESOURCES
;
2934 // Enumerate all signature data and erasing the target item.
2936 IsItemFound
= FALSE
;
2937 ItemDataSize
= (UINT32
) DataSize
;
2938 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2941 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2942 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2943 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2944 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2945 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2946 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2947 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2948 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2951 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2953 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2954 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2955 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2956 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2957 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2958 for (Index
= 0; Index
< CertCount
; Index
++) {
2959 if (GuidIndex
== DeleteIndex
) {
2961 // Find it! Skip it!
2963 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2967 // This item doesn't match. Copy it to the Data buffer.
2969 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2970 Offset
+= CertList
->SignatureSize
;
2973 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2977 // This List doesn't match. Just copy it to the Data buffer.
2979 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2980 Offset
+= CertList
->SignatureListSize
;
2983 ItemDataSize
-= CertList
->SignatureListSize
;
2984 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2989 // Doesn't find the signature Item!
2991 Status
= EFI_NOT_FOUND
;
2996 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2998 ItemDataSize
= Offset
;
2999 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
3001 ZeroMem (OldData
, ItemDataSize
);
3002 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
3003 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
3004 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
3005 if (CertCount
!= 0) {
3006 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
3007 Offset
+= CertList
->SignatureListSize
;
3009 ItemDataSize
-= CertList
->SignatureListSize
;
3010 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
3014 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3015 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
3016 if (EFI_ERROR (Status
)) {
3017 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
3022 Status
= gRT
->SetVariable(
3029 if (EFI_ERROR (Status
)) {
3030 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
3039 if (OldData
!= NULL
) {
3043 return UpdateDeletePage (
3055 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3056 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3058 @param[in] PrivateData Module's private data.
3060 @return EFI_SUCCESS Update secure boot strings successfully.
3061 @return other Fail to update secure boot strings.
3065 UpdateSecureBootString(
3066 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3074 // Get current secure boot state.
3076 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3077 if (SecureBoot
== NULL
) {
3078 return EFI_NOT_FOUND
;
3081 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3082 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3084 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3087 FreePool(SecureBoot
);
3093 This function extracts configuration from variable.
3095 @param[in] Private Point to SecureBoot configuration driver private data.
3096 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3100 SecureBootExtractConfigFromVariable (
3101 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3102 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3105 UINT8
*SecureBootEnable
;
3107 UINT8
*SecureBootMode
;
3110 SecureBootEnable
= NULL
;
3112 SecureBootMode
= NULL
;
3115 // Initilize the Date and Time using system time.
3117 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3118 ConfigData
->AlwaysRevocation
= TRUE
;
3119 gRT
->GetTime (&CurrTime
, NULL
);
3120 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3121 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3122 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3123 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3124 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3125 ConfigData
->RevocationTime
.Second
= 0;
3126 if (Private
->FileContext
->FHandle
!= NULL
) {
3127 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3129 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3133 // If it is Physical Presence User, set the PhysicalPresent to true.
3135 if (UserPhysicalPresent()) {
3136 ConfigData
->PhysicalPresent
= TRUE
;
3138 ConfigData
->PhysicalPresent
= FALSE
;
3142 // If there is no PK then the Delete Pk button will be gray.
3144 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3145 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3146 ConfigData
->HasPk
= FALSE
;
3148 ConfigData
->HasPk
= TRUE
;
3152 // Check SecureBootEnable & Pk status, fix the inconsistence.
3153 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3156 ConfigData
->AttemptSecureBoot
= FALSE
;
3157 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3160 // Fix Pk, SecureBootEnable inconsistence
3162 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3163 ConfigData
->HideSecureBoot
= FALSE
;
3164 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3165 ConfigData
->AttemptSecureBoot
= TRUE
;
3168 ConfigData
->HideSecureBoot
= TRUE
;
3172 // Get the SecureBootMode from CustomMode variable.
3174 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3175 if (SecureBootMode
== NULL
) {
3176 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3178 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3181 if (SecureBootEnable
!= NULL
) {
3182 FreePool (SecureBootEnable
);
3184 if (SetupMode
!= NULL
) {
3185 FreePool (SetupMode
);
3187 if (SecureBootMode
!= NULL
) {
3188 FreePool (SecureBootMode
);
3193 This function allows a caller to extract the current configuration for one
3194 or more named elements from the target driver.
3196 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3197 @param[in] Request A null-terminated Unicode string in
3198 <ConfigRequest> format.
3199 @param[out] Progress On return, points to a character in the Request
3200 string. Points to the string's null terminator if
3201 request was successful. Points to the most recent
3202 '&' before the first failing name/value pair (or
3203 the beginning of the string if the failure is in
3204 the first name/value pair) if the request was not
3206 @param[out] Results A null-terminated Unicode string in
3207 <ConfigAltResp> format which has all values filled
3208 in for the names in the Request string. String to
3209 be allocated by the called function.
3211 @retval EFI_SUCCESS The Results is filled with the requested values.
3212 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3213 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3214 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3220 SecureBootExtractConfig (
3221 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3222 IN CONST EFI_STRING Request
,
3223 OUT EFI_STRING
*Progress
,
3224 OUT EFI_STRING
*Results
3230 SECUREBOOT_CONFIGURATION Configuration
;
3231 EFI_STRING ConfigRequest
;
3232 EFI_STRING ConfigRequestHdr
;
3233 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3234 BOOLEAN AllocatedRequest
;
3236 if (Progress
== NULL
|| Results
== NULL
) {
3237 return EFI_INVALID_PARAMETER
;
3240 AllocatedRequest
= FALSE
;
3241 ConfigRequestHdr
= NULL
;
3242 ConfigRequest
= NULL
;
3245 ZeroMem (&Configuration
, sizeof (Configuration
));
3246 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3247 *Progress
= Request
;
3249 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3250 return EFI_NOT_FOUND
;
3253 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3256 // Get Configuration from Variable.
3258 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3260 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3261 ConfigRequest
= Request
;
3262 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3264 // Request is set to NULL or OFFSET is NULL, construct full request string.
3266 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3267 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3269 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3270 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3271 ConfigRequest
= AllocateZeroPool (Size
);
3272 ASSERT (ConfigRequest
!= NULL
);
3273 AllocatedRequest
= TRUE
;
3274 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3275 FreePool (ConfigRequestHdr
);
3276 ConfigRequestHdr
= NULL
;
3279 Status
= gHiiConfigRouting
->BlockToConfig (
3282 (UINT8
*) &Configuration
,
3289 // Free the allocated config request string.
3291 if (AllocatedRequest
) {
3292 FreePool (ConfigRequest
);
3296 // Set Progress string to the original request string.
3298 if (Request
== NULL
) {
3300 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3301 *Progress
= Request
+ StrLen (Request
);
3308 This function processes the results of changes in configuration.
3310 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3311 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3313 @param[out] Progress A pointer to a string filled in with the offset of
3314 the most recent '&' before the first failing
3315 name/value pair (or the beginning of the string if
3316 the failure is in the first name/value pair) or
3317 the terminating NULL if all was successful.
3319 @retval EFI_SUCCESS The Results is processed successfully.
3320 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3321 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3327 SecureBootRouteConfig (
3328 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3329 IN CONST EFI_STRING Configuration
,
3330 OUT EFI_STRING
*Progress
3333 SECUREBOOT_CONFIGURATION IfrNvData
;
3335 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3338 if (Configuration
== NULL
|| Progress
== NULL
) {
3339 return EFI_INVALID_PARAMETER
;
3342 *Progress
= Configuration
;
3343 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3344 return EFI_NOT_FOUND
;
3347 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3350 // Get Configuration from Variable.
3352 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3355 // Map the Configuration to the configuration block.
3357 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3358 Status
= gHiiConfigRouting
->ConfigToBlock (
3361 (UINT8
*)&IfrNvData
,
3365 if (EFI_ERROR (Status
)) {
3370 // Store Buffer Storage back to EFI variable if needed
3372 if (!IfrNvData
.HideSecureBoot
) {
3373 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3374 if (EFI_ERROR (Status
)) {
3379 *Progress
= Configuration
+ StrLen (Configuration
);
3384 This function is called to provide results data to the driver.
3386 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3387 @param[in] Action Specifies the type of action taken by the browser.
3388 @param[in] QuestionId A unique value which is sent to the original
3389 exporting driver so that it can identify the type
3391 @param[in] Type The type of value for the question.
3392 @param[in] Value A pointer to the data being sent to the original
3394 @param[out] ActionRequest On return, points to the action requested by the
3397 @retval EFI_SUCCESS The callback successfully handled the action.
3398 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3399 variable and its data.
3400 @retval EFI_DEVICE_ERROR The variable could not be saved.
3401 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3407 SecureBootCallback (
3408 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3409 IN EFI_BROWSER_ACTION Action
,
3410 IN EFI_QUESTION_ID QuestionId
,
3412 IN EFI_IFR_TYPE_VALUE
*Value
,
3413 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3418 RETURN_STATUS RStatus
;
3419 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3421 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3423 UINT8
*SecureBootEnable
;
3425 UINT8
*SecureBootMode
;
3427 CHAR16 PromptString
[100];
3428 EFI_DEVICE_PATH_PROTOCOL
*File
;
3430 UINT16
*FilePostFix
;
3431 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3433 Status
= EFI_SUCCESS
;
3434 SecureBootEnable
= NULL
;
3435 SecureBootMode
= NULL
;
3439 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3440 return EFI_INVALID_PARAMETER
;
3443 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3445 gSecureBootPrivateData
= Private
;
3448 // Retrieve uncommitted data from Browser
3450 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3451 IfrNvData
= AllocateZeroPool (BufferSize
);
3452 if (IfrNvData
== NULL
) {
3453 return EFI_OUT_OF_RESOURCES
;
3456 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3458 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3459 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3461 // Update secure boot strings when opening this form
3463 Status
= UpdateSecureBootString(Private
);
3464 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
3465 mIsEnterSecureBootForm
= TRUE
;
3468 // When entering SecureBoot OPTION Form
3469 // always close opened file & free resource
3471 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
3472 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
3473 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
3474 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
3475 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
3476 CloseEnrolledFile(Private
->FileContext
);
3482 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3483 Status
= EFI_UNSUPPORTED
;
3484 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3485 if (mIsEnterSecureBootForm
) {
3486 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3487 Status
= EFI_SUCCESS
;
3493 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3494 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3495 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3496 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3497 Status
= EFI_UNSUPPORTED
;
3501 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3503 switch (QuestionId
) {
3504 case KEY_SECURE_BOOT_ENABLE
:
3505 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3506 if (NULL
!= SecureBootEnable
) {
3507 FreePool (SecureBootEnable
);
3508 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3510 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3512 L
"Only Physical Presence User could disable secure boot!",
3515 Status
= EFI_UNSUPPORTED
;
3518 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3520 L
"Configuration changed, please reset the platform to take effect!",
3527 case KEY_SECURE_BOOT_KEK_OPTION
:
3528 case KEY_SECURE_BOOT_DB_OPTION
:
3529 case KEY_SECURE_BOOT_DBX_OPTION
:
3530 case KEY_SECURE_BOOT_DBT_OPTION
:
3531 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3533 // Clear Signature GUID.
3535 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3536 if (Private
->SignatureGUID
== NULL
) {
3537 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3538 if (Private
->SignatureGUID
== NULL
) {
3539 return EFI_OUT_OF_RESOURCES
;
3544 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
3546 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
3548 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3549 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3550 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3551 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3552 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3553 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3555 LabelId
= FORMID_ENROLL_KEK_FORM
;
3559 // Refresh selected file.
3561 CleanUpPage (LabelId
, Private
);
3563 case KEY_SECURE_BOOT_PK_OPTION
:
3564 LabelId
= FORMID_ENROLL_PK_FORM
;
3566 // Refresh selected file.
3568 CleanUpPage (LabelId
, Private
);
3571 case FORMID_ENROLL_PK_FORM
:
3572 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
3575 case FORMID_ENROLL_KEK_FORM
:
3576 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
3579 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3580 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
3583 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3584 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
3586 if (Private
->FileContext
->FHandle
!= NULL
) {
3588 // Parse the file's postfix.
3590 NameLength
= StrLen (Private
->FileContext
->FileName
);
3591 if (NameLength
<= 4) {
3594 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
3596 if (IsDerEncodeCertificate (FilePostFix
)) {
3598 // Supports DER-encoded X509 certificate.
3600 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
3601 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
3602 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
3604 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
3606 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
3609 // Clean up Certificate Format if File type is not X509 DER
3611 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
3612 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
3614 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
3619 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3620 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
3623 case KEY_SECURE_BOOT_DELETE_PK
:
3626 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3628 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3629 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3632 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3633 Status
= DeletePlatformKey ();
3634 if (EFI_ERROR (Status
)) {
3636 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3638 L
"Only Physical Presence User could delete PK in custom mode!",
3646 case KEY_DELETE_KEK
:
3649 EFI_KEY_EXCHANGE_KEY_NAME
,
3650 &gEfiGlobalVariableGuid
,
3652 FORMID_DELETE_KEK_FORM
,
3653 OPTION_DEL_KEK_QUESTION_ID
3657 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3660 EFI_IMAGE_SECURITY_DATABASE
,
3661 &gEfiImageSecurityDatabaseGuid
,
3663 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3664 OPTION_DEL_DB_QUESTION_ID
3668 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3671 EFI_IMAGE_SECURITY_DATABASE1
,
3672 &gEfiImageSecurityDatabaseGuid
,
3674 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3675 OPTION_DEL_DBX_QUESTION_ID
3680 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3683 EFI_IMAGE_SECURITY_DATABASE2
,
3684 &gEfiImageSecurityDatabaseGuid
,
3686 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3687 OPTION_DEL_DBT_QUESTION_ID
3692 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3693 Status
= EnrollKeyExchangeKey (Private
);
3694 if (EFI_ERROR (Status
)) {
3696 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3698 L
"ERROR: Unsupported file type!",
3699 L
"Only supports DER-encoded X509 certificate",
3705 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3706 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3707 if (EFI_ERROR (Status
)) {
3709 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3711 L
"ERROR: Unsupported file type!",
3712 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3718 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3719 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3721 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3723 L
"Enrollment failed! Same certificate had already been in the dbx!",
3728 // Cert already exists in DBX. Close opened file before exit.
3730 CloseEnrolledFile(Private
->FileContext
);
3734 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3735 Status
= EnrollX509HashtoSigDB (
3737 IfrNvData
->CertificateFormat
,
3738 &IfrNvData
->RevocationDate
,
3739 &IfrNvData
->RevocationTime
,
3740 IfrNvData
->AlwaysRevocation
3742 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
3744 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3746 if (EFI_ERROR (Status
)) {
3748 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3750 L
"ERROR: Unsupported file type!",
3751 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
3757 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3758 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3759 if (EFI_ERROR (Status
)) {
3761 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3763 L
"ERROR: Unsupported file type!",
3764 L
"Only supports DER-encoded X509 certificate.",
3769 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3770 Status
= EnrollPlatformKey (Private
);
3771 if (EFI_ERROR (Status
)) {
3774 sizeof (PromptString
),
3775 L
"Only DER encoded certificate file (%s) is supported.",
3779 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3781 L
"ERROR: Unsupported file type!",
3788 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3789 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3790 DeleteKeyExchangeKey (Private
, QuestionId
);
3791 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3792 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3795 EFI_IMAGE_SECURITY_DATABASE
,
3796 &gEfiImageSecurityDatabaseGuid
,
3798 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3799 OPTION_DEL_DB_QUESTION_ID
,
3800 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3802 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3803 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3806 EFI_IMAGE_SECURITY_DATABASE1
,
3807 &gEfiImageSecurityDatabaseGuid
,
3809 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3810 OPTION_DEL_DBX_QUESTION_ID
,
3811 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3813 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3814 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3817 EFI_IMAGE_SECURITY_DATABASE2
,
3818 &gEfiImageSecurityDatabaseGuid
,
3820 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3821 OPTION_DEL_DBT_QUESTION_ID
,
3822 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3827 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3828 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3829 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3830 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3831 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3832 CloseEnrolledFile(Private
->FileContext
);
3834 if (Private
->SignatureGUID
!= NULL
) {
3835 FreePool (Private
->SignatureGUID
);
3836 Private
->SignatureGUID
= NULL
;
3840 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3841 switch (QuestionId
) {
3842 case KEY_SECURE_BOOT_ENABLE
:
3843 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3845 case KEY_SECURE_BOOT_MODE
:
3846 mIsEnterSecureBootForm
= FALSE
;
3848 case KEY_SECURE_BOOT_KEK_GUID
:
3849 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3850 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3851 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3852 ASSERT (Private
->SignatureGUID
!= NULL
);
3853 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
3854 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
3855 Status
= EFI_INVALID_PARAMETER
;
3859 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3861 case KEY_SECURE_BOOT_DELETE_PK
:
3862 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3863 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3864 IfrNvData
->DeletePk
= TRUE
;
3865 IfrNvData
->HasPk
= FALSE
;
3866 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3868 IfrNvData
->DeletePk
= FALSE
;
3869 IfrNvData
->HasPk
= TRUE
;
3870 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3872 if (SetupMode
!= NULL
) {
3873 FreePool (SetupMode
);
3879 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3880 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3881 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
3883 IfrNvData
->HideSecureBoot
= TRUE
;
3886 IfrNvData
->HideSecureBoot
= FALSE
;
3888 Value
->b
= IfrNvData
->HideSecureBoot
;
3890 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3892 // Force the platform back to Standard Mode once user leave the setup screen.
3894 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3895 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3896 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3897 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3899 if (SecureBootMode
!= NULL
) {
3900 FreePool (SecureBootMode
);
3906 if (!EFI_ERROR (Status
)) {
3907 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3908 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3911 FreePool (IfrNvData
);
3922 This function publish the SecureBoot configuration Form.
3924 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3926 @retval EFI_SUCCESS HII Form is installed successfully.
3927 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3928 @retval Others Other errors as indicated.
3932 InstallSecureBootConfigForm (
3933 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3937 EFI_HII_HANDLE HiiHandle
;
3938 EFI_HANDLE DriverHandle
;
3939 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3941 DriverHandle
= NULL
;
3942 ConfigAccess
= &PrivateData
->ConfigAccess
;
3943 Status
= gBS
->InstallMultipleProtocolInterfaces (
3945 &gEfiDevicePathProtocolGuid
,
3946 &mSecureBootHiiVendorDevicePath
,
3947 &gEfiHiiConfigAccessProtocolGuid
,
3951 if (EFI_ERROR (Status
)) {
3955 PrivateData
->DriverHandle
= DriverHandle
;
3958 // Publish the HII package list
3960 HiiHandle
= HiiAddPackages (
3961 &gSecureBootConfigFormSetGuid
,
3963 SecureBootConfigDxeStrings
,
3964 SecureBootConfigBin
,
3967 if (HiiHandle
== NULL
) {
3968 gBS
->UninstallMultipleProtocolInterfaces (
3970 &gEfiDevicePathProtocolGuid
,
3971 &mSecureBootHiiVendorDevicePath
,
3972 &gEfiHiiConfigAccessProtocolGuid
,
3976 return EFI_OUT_OF_RESOURCES
;
3979 PrivateData
->HiiHandle
= HiiHandle
;
3981 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
3983 if (PrivateData
->FileContext
== NULL
) {
3984 UninstallSecureBootConfigForm (PrivateData
);
3985 return EFI_OUT_OF_RESOURCES
;
3989 // Init OpCode Handle and Allocate space for creation of Buffer
3991 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3992 if (mStartOpCodeHandle
== NULL
) {
3993 UninstallSecureBootConfigForm (PrivateData
);
3994 return EFI_OUT_OF_RESOURCES
;
3997 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3998 if (mEndOpCodeHandle
== NULL
) {
3999 UninstallSecureBootConfigForm (PrivateData
);
4000 return EFI_OUT_OF_RESOURCES
;
4004 // Create Hii Extend Label OpCode as the start opcode
4006 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4010 sizeof (EFI_IFR_GUID_LABEL
)
4012 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4015 // Create Hii Extend Label OpCode as the end opcode
4017 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4021 sizeof (EFI_IFR_GUID_LABEL
)
4023 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4024 mEndLabel
->Number
= LABEL_END
;
4030 This function removes SecureBoot configuration Form.
4032 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4036 UninstallSecureBootConfigForm (
4037 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4041 // Uninstall HII package list
4043 if (PrivateData
->HiiHandle
!= NULL
) {
4044 HiiRemovePackages (PrivateData
->HiiHandle
);
4045 PrivateData
->HiiHandle
= NULL
;
4049 // Uninstall HII Config Access Protocol
4051 if (PrivateData
->DriverHandle
!= NULL
) {
4052 gBS
->UninstallMultipleProtocolInterfaces (
4053 PrivateData
->DriverHandle
,
4054 &gEfiDevicePathProtocolGuid
,
4055 &mSecureBootHiiVendorDevicePath
,
4056 &gEfiHiiConfigAccessProtocolGuid
,
4057 &PrivateData
->ConfigAccess
,
4060 PrivateData
->DriverHandle
= NULL
;
4063 if (PrivateData
->SignatureGUID
!= NULL
) {
4064 FreePool (PrivateData
->SignatureGUID
);
4067 if (PrivateData
->FileContext
!= NULL
) {
4068 FreePool (PrivateData
->FileContext
);
4071 FreePool (PrivateData
);
4073 if (mStartOpCodeHandle
!= NULL
) {
4074 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
4077 if (mEndOpCodeHandle
!= NULL
) {
4078 HiiFreeOpCodeHandle (mEndOpCodeHandle
);