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] FileSuffix The suffix of the input certificate file
105 @retval TRUE It's a DER-encoded certificate.
106 @retval FALSE It's NOT a DER-encoded certificate.
112 IN SECUREBOOT_FILE_CONTEXT
*FileContext
115 if (FileContext
->FHandle
!= NULL
) {
116 CloseFile (FileContext
->FHandle
);
117 FileContext
->FHandle
= NULL
;
120 if (FileContext
->FileName
!= NULL
){
121 FreePool(FileContext
->FileName
);
122 FileContext
->FileName
= NULL
;
124 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
129 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
131 @param[in] FileSuffix The suffix of the input certificate file
133 @retval TRUE It's a DER-encoded certificate.
134 @retval FALSE It's NOT a DER-encoded certificate.
138 IsDerEncodeCertificate (
139 IN CONST CHAR16
*FileSuffix
143 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
144 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
152 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
153 The function reads file content but won't open/close given FileHandle.
155 @param[in] FileHandle The FileHandle to be checked
157 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
158 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
162 IsAuthentication2Format (
163 IN EFI_FILE_HANDLE FileHandle
167 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
168 BOOLEAN IsAuth2Format
;
170 IsAuth2Format
= FALSE
;
173 // Read the whole file content
175 Status
= ReadFileContent(
177 (VOID
**) &mImageBase
,
181 if (EFI_ERROR (Status
)) {
185 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
186 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
190 if (CompareGuid(&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
191 IsAuth2Format
= TRUE
;
196 // Do not close File. simply check file content
198 if (mImageBase
!= NULL
) {
199 FreePool (mImageBase
);
203 return IsAuth2Format
;
207 Set Secure Boot option into variable space.
209 @param[in] VarValue The option of Secure Boot.
211 @retval EFI_SUCCESS The operation is finished successfully.
212 @retval Others Other errors as indicated.
216 SaveSecureBootVariable (
222 Status
= gRT
->SetVariable (
223 EFI_SECURE_BOOT_ENABLE_NAME
,
224 &gEfiSecureBootEnableDisableGuid
,
225 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
233 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
234 descriptor with the input data. NO authentication is required in this function.
236 @param[in, out] DataSize On input, the size of Data buffer in bytes.
237 On output, the size of data returned in Data
239 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
240 pointer to NULL to wrap an empty payload.
241 On output, Pointer to the new payload date buffer allocated from pool,
242 it's caller's responsibility to free the memory when finish using it.
244 @retval EFI_SUCCESS Create time based payload successfully.
245 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
246 @retval EFI_INVALID_PARAMETER The parameter is invalid.
247 @retval Others Unexpected error happens.
251 CreateTimeBasedPayload (
252 IN OUT UINTN
*DataSize
,
260 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
261 UINTN DescriptorSize
;
264 if (Data
== NULL
|| DataSize
== NULL
) {
265 return EFI_INVALID_PARAMETER
;
269 // In Setup mode or Custom mode, the variable does not need to be signed but the
270 // parameters to the SetVariable() call still need to be prepared as authenticated
271 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
275 PayloadSize
= *DataSize
;
277 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
278 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
279 if (NewData
== NULL
) {
280 return EFI_OUT_OF_RESOURCES
;
283 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
284 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
287 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
289 ZeroMem (&Time
, sizeof (EFI_TIME
));
290 Status
= gRT
->GetTime (&Time
, NULL
);
291 if (EFI_ERROR (Status
)) {
300 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
302 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
303 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
304 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
305 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
307 if (Payload
!= NULL
) {
311 *DataSize
= DescriptorSize
+ PayloadSize
;
317 Internal helper function to delete a Variable given its name and GUID, NO authentication
320 @param[in] VariableName Name of the Variable.
321 @param[in] VendorGuid GUID of the Variable.
323 @retval EFI_SUCCESS Variable deleted successfully.
324 @retval Others The driver failed to start the device.
329 IN CHAR16
*VariableName
,
330 IN EFI_GUID
*VendorGuid
339 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
340 if (Variable
== NULL
) {
347 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
348 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
350 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
351 if (EFI_ERROR (Status
)) {
352 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
356 Status
= gRT
->SetVariable (
371 Set the platform secure boot mode into "Custom" or "Standard" mode.
373 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
374 CUSTOM_SECURE_BOOT_MODE.
376 @return EFI_SUCCESS The platform has switched to the special mode successfully.
377 @return other Fail to operate the secure boot mode.
382 IN UINT8 SecureBootMode
385 return gRT
->SetVariable (
386 EFI_CUSTOM_MODE_NAME
,
387 &gEfiCustomModeEnableGuid
,
388 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
395 Generate the PK signature list from the X509 Certificate storing file (.cer)
397 @param[in] X509File FileHandle of X509 Certificate storing file.
398 @param[out] PkCert Point to the data buffer to store the signature list.
400 @return EFI_UNSUPPORTED Unsupported Key Length.
401 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
405 CreatePkX509SignatureList (
406 IN EFI_FILE_HANDLE X509File
,
407 OUT EFI_SIGNATURE_LIST
**PkCert
413 EFI_SIGNATURE_DATA
*PkCertData
;
419 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
420 if (EFI_ERROR (Status
)) {
423 ASSERT (X509Data
!= NULL
);
426 // Allocate space for PK certificate list and initialize it.
427 // Create PK database entry with SignatureHeaderSize equals 0.
429 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
430 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
433 if (*PkCert
== NULL
) {
434 Status
= EFI_OUT_OF_RESOURCES
;
438 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
439 + sizeof(EFI_SIGNATURE_DATA
) - 1
441 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
442 (*PkCert
)->SignatureHeaderSize
= 0;
443 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
444 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
445 + sizeof(EFI_SIGNATURE_LIST
)
446 + (*PkCert
)->SignatureHeaderSize
);
447 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
449 // Fill the PK database with PKpub data from X509 certificate file.
451 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
455 if (X509Data
!= NULL
) {
459 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
468 Enroll new PK into the System without original PK's authentication.
470 The SignatureOwner GUID will be the same with PK's vendorguid.
472 @param[in] PrivateData The module's private data.
474 @retval EFI_SUCCESS New PK enrolled successfully.
475 @retval EFI_INVALID_PARAMETER The parameter is invalid.
476 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
481 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
487 EFI_SIGNATURE_LIST
*PkCert
;
491 if (Private
->FileContext
->FileName
== NULL
) {
492 return EFI_INVALID_PARAMETER
;
497 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
498 if (EFI_ERROR (Status
)) {
503 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
505 NameLength
= StrLen (Private
->FileContext
->FileName
);
506 if (NameLength
<= 4) {
507 return EFI_INVALID_PARAMETER
;
509 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
510 if (!IsDerEncodeCertificate(FilePostFix
)) {
511 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
512 return EFI_INVALID_PARAMETER
;
514 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
515 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
518 // Prase the selected PK file and generature PK certificate list.
520 Status
= CreatePkX509SignatureList (
521 Private
->FileContext
->FHandle
,
524 if (EFI_ERROR (Status
)) {
527 ASSERT (PkCert
!= NULL
);
530 // Set Platform Key variable.
532 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
533 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
534 DataSize
= PkCert
->SignatureListSize
;
535 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
536 if (EFI_ERROR (Status
)) {
537 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
541 Status
= gRT
->SetVariable(
542 EFI_PLATFORM_KEY_NAME
,
543 &gEfiGlobalVariableGuid
,
548 if (EFI_ERROR (Status
)) {
549 if (Status
== EFI_OUT_OF_RESOURCES
) {
550 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
557 if (PkCert
!= NULL
) {
561 CloseEnrolledFile(Private
->FileContext
);
567 Remove the PK variable.
569 @retval EFI_SUCCESS Delete PK successfully.
570 @retval Others Could not allow to delete PK.
580 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
581 if (EFI_ERROR (Status
)) {
585 Status
= DeleteVariable (
586 EFI_PLATFORM_KEY_NAME
,
587 &gEfiGlobalVariableGuid
593 Enroll a new KEK item from public key storing file (*.pbk).
595 @param[in] PrivateData The module's private data.
597 @retval EFI_SUCCESS New KEK enrolled successfully.
598 @retval EFI_INVALID_PARAMETER The parameter is invalid.
599 @retval EFI_UNSUPPORTED Unsupported command.
600 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
605 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
611 EFI_SIGNATURE_LIST
*KekSigList
;
614 CPL_KEY_INFO
*KeyInfo
;
615 EFI_SIGNATURE_DATA
*KEKSigData
;
616 UINTN KekSigListSize
;
631 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
632 // First, We have to parse out public key data from the pbk key file.
634 Status
= ReadFileContent (
635 Private
->FileContext
->FHandle
,
640 if (EFI_ERROR (Status
)) {
643 ASSERT (KeyBlob
!= NULL
);
644 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
645 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
646 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
647 Status
= EFI_UNSUPPORTED
;
652 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
654 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
655 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
656 if (KeyBuffer
== NULL
) {
657 Status
= EFI_OUT_OF_RESOURCES
;
661 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
662 KeyLenInBytes
/ sizeof (UINTN
),
666 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
669 // Form an new EFI_SIGNATURE_LIST.
671 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
672 + sizeof(EFI_SIGNATURE_DATA
) - 1
673 + WIN_CERT_UEFI_RSA2048_SIZE
;
675 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
676 if (KekSigList
== NULL
) {
677 Status
= EFI_OUT_OF_RESOURCES
;
681 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
682 + sizeof(EFI_SIGNATURE_DATA
) - 1
683 + WIN_CERT_UEFI_RSA2048_SIZE
;
684 KekSigList
->SignatureHeaderSize
= 0;
685 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
686 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
688 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
689 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
691 KEKSigData
->SignatureData
,
692 KeyBlob
+ sizeof(CPL_KEY_INFO
),
693 WIN_CERT_UEFI_RSA2048_SIZE
697 // Check if KEK entry has been already existed.
698 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
699 // new KEK to original variable.
701 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
702 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
703 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
704 if (EFI_ERROR (Status
)) {
705 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
709 Status
= gRT
->GetVariable(
710 EFI_KEY_EXCHANGE_KEY_NAME
,
711 &gEfiGlobalVariableGuid
,
716 if (Status
== EFI_BUFFER_TOO_SMALL
) {
717 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
718 } else if (Status
!= EFI_NOT_FOUND
) {
723 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
725 Status
= gRT
->SetVariable(
726 EFI_KEY_EXCHANGE_KEY_NAME
,
727 &gEfiGlobalVariableGuid
,
732 if (EFI_ERROR (Status
)) {
738 CloseEnrolledFile(Private
->FileContext
);
740 if (Private
->SignatureGUID
!= NULL
) {
741 FreePool (Private
->SignatureGUID
);
742 Private
->SignatureGUID
= NULL
;
745 if (KeyBlob
!= NULL
) {
748 if (KeyBuffer
!= NULL
) {
749 FreePool (KeyBuffer
);
751 if (KekSigList
!= NULL
) {
752 FreePool (KekSigList
);
759 Enroll a new KEK item from X509 certificate file.
761 @param[in] PrivateData The module's private data.
763 @retval EFI_SUCCESS New X509 is enrolled successfully.
764 @retval EFI_INVALID_PARAMETER The parameter is invalid.
765 @retval EFI_UNSUPPORTED Unsupported command.
766 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
771 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
777 EFI_SIGNATURE_DATA
*KEKSigData
;
778 EFI_SIGNATURE_LIST
*KekSigList
;
780 UINTN KekSigListSize
;
790 Status
= ReadFileContent (
791 Private
->FileContext
->FHandle
,
796 if (EFI_ERROR (Status
)) {
799 ASSERT (X509Data
!= NULL
);
801 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
802 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
803 if (KekSigList
== NULL
) {
804 Status
= EFI_OUT_OF_RESOURCES
;
809 // Fill Certificate Database parameters.
811 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
812 KekSigList
->SignatureHeaderSize
= 0;
813 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
814 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
816 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
817 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
818 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
821 // Check if KEK been already existed.
822 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
823 // new kek to original variable
825 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
826 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
827 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
828 if (EFI_ERROR (Status
)) {
829 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
833 Status
= gRT
->GetVariable(
834 EFI_KEY_EXCHANGE_KEY_NAME
,
835 &gEfiGlobalVariableGuid
,
840 if (Status
== EFI_BUFFER_TOO_SMALL
) {
841 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
842 } else if (Status
!= EFI_NOT_FOUND
) {
846 Status
= gRT
->SetVariable(
847 EFI_KEY_EXCHANGE_KEY_NAME
,
848 &gEfiGlobalVariableGuid
,
853 if (EFI_ERROR (Status
)) {
859 CloseEnrolledFile(Private
->FileContext
);
861 if (Private
->SignatureGUID
!= NULL
) {
862 FreePool (Private
->SignatureGUID
);
863 Private
->SignatureGUID
= NULL
;
866 if (KekSigList
!= NULL
) {
867 FreePool (KekSigList
);
874 Enroll new KEK into the System without PK's authentication.
875 The SignatureOwner GUID will be Private->SignatureGUID.
877 @param[in] PrivateData The module's private data.
879 @retval EFI_SUCCESS New KEK enrolled successful.
880 @retval EFI_INVALID_PARAMETER The parameter is invalid.
881 @retval others Fail to enroll KEK data.
885 EnrollKeyExchangeKey (
886 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
893 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
894 return EFI_INVALID_PARAMETER
;
897 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
898 if (EFI_ERROR (Status
)) {
903 // Parse the file's postfix. Supports DER-encoded X509 certificate,
904 // and .pbk as RSA public key file.
906 NameLength
= StrLen (Private
->FileContext
->FileName
);
907 if (NameLength
<= 4) {
908 return EFI_INVALID_PARAMETER
;
910 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
911 if (IsDerEncodeCertificate(FilePostFix
)) {
912 return EnrollX509ToKek (Private
);
913 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
914 return EnrollRsa2048ToKek (Private
);
917 // File type is wrong, simply close it
919 CloseEnrolledFile(Private
->FileContext
);
921 return EFI_INVALID_PARAMETER
;
926 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
927 KEK's authentication.
929 @param[in] PrivateData The module's private data.
930 @param[in] VariableName Variable name of signature database, must be
931 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
933 @retval EFI_SUCCESS New X509 is enrolled successfully.
934 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
939 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
940 IN CHAR16
*VariableName
946 EFI_SIGNATURE_LIST
*SigDBCert
;
947 EFI_SIGNATURE_DATA
*SigDBCertData
;
958 SigDBCertData
= NULL
;
961 Status
= ReadFileContent (
962 Private
->FileContext
->FHandle
,
967 if (EFI_ERROR (Status
)) {
970 ASSERT (X509Data
!= NULL
);
972 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
974 Data
= AllocateZeroPool (SigDBSize
);
976 Status
= EFI_OUT_OF_RESOURCES
;
981 // Fill Certificate Database parameters.
983 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
984 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
985 SigDBCert
->SignatureHeaderSize
= 0;
986 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
987 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
989 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
990 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
991 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
994 // Check if signature database entry has been already existed.
995 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
996 // new signature data to original variable
998 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
999 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1000 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
1001 if (EFI_ERROR (Status
)) {
1002 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1006 Status
= gRT
->GetVariable(
1008 &gEfiImageSecurityDatabaseGuid
,
1013 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1014 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1015 } else if (Status
!= EFI_NOT_FOUND
) {
1019 Status
= gRT
->SetVariable(
1021 &gEfiImageSecurityDatabaseGuid
,
1026 if (EFI_ERROR (Status
)) {
1032 CloseEnrolledFile(Private
->FileContext
);
1034 if (Private
->SignatureGUID
!= NULL
) {
1035 FreePool (Private
->SignatureGUID
);
1036 Private
->SignatureGUID
= NULL
;
1043 if (X509Data
!= NULL
) {
1044 FreePool (X509Data
);
1051 Check whether signature is in specified database.
1053 @param[in] VariableName Name of database variable that is searched in.
1054 @param[in] Signature Pointer to signature that is searched for.
1055 @param[in] SignatureSize Size of Signature.
1057 @return TRUE Found the signature in the variable database.
1058 @return FALSE Not found the signature in the variable database.
1062 IsSignatureFoundInDatabase (
1063 IN CHAR16
*VariableName
,
1064 IN UINT8
*Signature
,
1065 IN UINTN SignatureSize
1069 EFI_SIGNATURE_LIST
*CertList
;
1070 EFI_SIGNATURE_DATA
*Cert
;
1078 // Read signature database variable.
1083 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1084 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1088 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1093 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1094 if (EFI_ERROR (Status
)) {
1099 // Enumerate all signature data in SigDB to check if executable's signature exists.
1101 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1102 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1103 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1104 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1105 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1106 for (Index
= 0; Index
< CertCount
; Index
++) {
1107 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1109 // Find the signature in database.
1114 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1122 DataSize
-= CertList
->SignatureListSize
;
1123 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1135 Calculate the hash of a certificate data with the specified hash algorithm.
1137 @param[in] CertData The certificate data to be hashed.
1138 @param[in] CertSize The certificate size in bytes.
1139 @param[in] HashAlg The specified hash algorithm.
1140 @param[out] CertHash The output digest of the certificate
1142 @retval TRUE Successfully got the hash of the CertData.
1143 @retval FALSE Failed to get the hash of CertData.
1163 if (HashAlg
>= HASHALG_MAX
) {
1168 // Retrieve the TBSCertificate for Hash Calculation.
1170 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1175 // 1. Initialize context of hash.
1177 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1178 HashCtx
= AllocatePool (CtxSize
);
1179 ASSERT (HashCtx
!= NULL
);
1182 // 2. Initialize a hash context.
1184 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1190 // 3. Calculate the hash.
1192 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1198 // 4. Get the hash result.
1200 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1201 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1204 if (HashCtx
!= NULL
) {
1212 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1214 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1215 @param[in] CertSize Size of X.509 Certificate.
1217 @return TRUE Found the certificate hash in the forbidden database.
1218 @return FALSE Certificate hash is Not found in the forbidden database.
1222 IsCertHashFoundInDbx (
1223 IN UINT8
*Certificate
,
1229 EFI_SIGNATURE_LIST
*DbxList
;
1230 EFI_SIGNATURE_DATA
*CertHash
;
1231 UINTN CertHashCount
;
1234 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1236 UINTN SiglistHeaderSize
;
1241 HashAlg
= HASHALG_MAX
;
1245 // Read signature database variable.
1248 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1249 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1253 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1258 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1259 if (EFI_ERROR (Status
)) {
1264 // Check whether the certificate hash exists in the forbidden database.
1266 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1267 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1269 // Determine Hash Algorithm of Certificate in the forbidden database.
1271 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1272 HashAlg
= HASHALG_SHA256
;
1273 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1274 HashAlg
= HASHALG_SHA384
;
1275 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1276 HashAlg
= HASHALG_SHA512
;
1278 DataSize
-= DbxList
->SignatureListSize
;
1279 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1284 // Calculate the hash value of current db certificate for comparision.
1286 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1290 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1291 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1292 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1293 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1295 // Iterate each Signature Data Node within this CertList for verify.
1297 DbxCertHash
= CertHash
->SignatureData
;
1298 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1300 // Hash of Certificate is found in forbidden database.
1305 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1308 DataSize
-= DbxList
->SignatureListSize
;
1309 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1321 Check whether the signature list exists in given variable data.
1323 It searches the signature list for the ceritificate hash by CertType.
1324 If the signature list is found, get the offset of Database for the
1325 next hash of a certificate.
1327 @param[in] Database Variable data to save signature list.
1328 @param[in] DatabaseSize Variable size.
1329 @param[in] SignatureType The type of the signature.
1330 @param[out] Offset The offset to save a new hash of certificate.
1332 @return TRUE The signature list is found in the forbidden database.
1333 @return FALSE The signature list is not found in the forbidden database.
1336 GetSignaturelistOffset (
1337 IN EFI_SIGNATURE_LIST
*Database
,
1338 IN UINTN DatabaseSize
,
1339 IN EFI_GUID
*SignatureType
,
1343 EFI_SIGNATURE_LIST
*SigList
;
1346 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1352 SiglistSize
= DatabaseSize
;
1353 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1354 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1355 *Offset
= DatabaseSize
- SiglistSize
;
1358 SiglistSize
-= SigList
->SignatureListSize
;
1359 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1366 Enroll a new X509 certificate hash into Signature Database (dbx) without
1367 KEK's authentication.
1369 @param[in] PrivateData The module's private data.
1370 @param[in] HashAlg The hash algorithm to enroll the certificate.
1371 @param[in] RevocationDate The revocation date of the certificate.
1372 @param[in] RevocationTime The revocation time of the certificate.
1373 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1375 @retval EFI_SUCCESS New X509 is enrolled successfully.
1376 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1377 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1381 EnrollX509HashtoSigDB (
1382 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1384 IN EFI_HII_DATE
*RevocationDate
,
1385 IN EFI_HII_TIME
*RevocationTime
,
1386 IN BOOLEAN AlwaysRevocation
1392 EFI_SIGNATURE_LIST
*SignatureList
;
1393 UINTN SignatureListSize
;
1399 EFI_SIGNATURE_DATA
*SignatureData
;
1400 UINTN SignatureSize
;
1401 EFI_GUID SignatureType
;
1403 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1404 UINT16
* FilePostFix
;
1411 SignatureData
= NULL
;
1412 SignatureList
= NULL
;
1416 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1417 return EFI_INVALID_PARAMETER
;
1420 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1421 if (EFI_ERROR (Status
)) {
1426 // Parse the file's postfix.
1428 NameLength
= StrLen (Private
->FileContext
->FileName
);
1429 if (NameLength
<= 4) {
1430 return EFI_INVALID_PARAMETER
;
1432 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1433 if (!IsDerEncodeCertificate(FilePostFix
)) {
1435 // Only supports DER-encoded X509 certificate.
1437 return EFI_INVALID_PARAMETER
;
1441 // Get the certificate from file and calculate its hash.
1443 Status
= ReadFileContent (
1444 Private
->FileContext
->FHandle
,
1449 if (EFI_ERROR (Status
)) {
1452 ASSERT (X509Data
!= NULL
);
1454 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1459 // Get the variable for enrollment.
1462 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1463 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1464 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1466 return EFI_OUT_OF_RESOURCES
;
1469 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1470 if (EFI_ERROR (Status
)) {
1476 // Allocate memory for Signature and fill the Signature
1478 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1479 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1480 if (SignatureData
== NULL
) {
1481 return EFI_OUT_OF_RESOURCES
;
1483 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1484 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1489 if (!AlwaysRevocation
) {
1490 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1491 Time
->Year
= RevocationDate
->Year
;
1492 Time
->Month
= RevocationDate
->Month
;
1493 Time
->Day
= RevocationDate
->Day
;
1494 Time
->Hour
= RevocationTime
->Hour
;
1495 Time
->Minute
= RevocationTime
->Minute
;
1496 Time
->Second
= RevocationTime
->Second
;
1500 // Determine the GUID for certificate hash.
1503 case HASHALG_SHA256
:
1504 SignatureType
= gEfiCertX509Sha256Guid
;
1506 case HASHALG_SHA384
:
1507 SignatureType
= gEfiCertX509Sha384Guid
;
1509 case HASHALG_SHA512
:
1510 SignatureType
= gEfiCertX509Sha512Guid
;
1517 // Add signature into the new variable data buffer
1519 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1521 // Add the signature to the found signaturelist.
1523 DbSize
= DataSize
+ SignatureSize
;
1524 NewData
= AllocateZeroPool (DbSize
);
1525 if (NewData
== NULL
) {
1526 Status
= EFI_OUT_OF_RESOURCES
;
1530 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1531 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1532 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1534 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1535 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1537 Offset
+= SignatureListSize
;
1538 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1539 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1546 // Create a new signaturelist, and add the signature into the signaturelist.
1548 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1549 NewData
= AllocateZeroPool (DbSize
);
1550 if (NewData
== NULL
) {
1551 Status
= EFI_OUT_OF_RESOURCES
;
1555 // Fill Certificate Database parameters.
1557 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1558 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1559 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1560 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1561 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1562 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1563 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1564 CopyMem (NewData
, Data
, DataSize
);
1571 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1572 if (EFI_ERROR (Status
)) {
1576 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1577 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1578 Status
= gRT
->SetVariable(
1579 EFI_IMAGE_SECURITY_DATABASE1
,
1580 &gEfiImageSecurityDatabaseGuid
,
1585 if (EFI_ERROR (Status
)) {
1591 CloseEnrolledFile(Private
->FileContext
);
1593 if (Private
->SignatureGUID
!= NULL
) {
1594 FreePool (Private
->SignatureGUID
);
1595 Private
->SignatureGUID
= NULL
;
1602 if (SignatureData
!= NULL
) {
1603 FreePool (SignatureData
);
1606 if (X509Data
!= NULL
) {
1607 FreePool (X509Data
);
1614 Check whether a certificate from a file exists in dbx.
1616 @param[in] PrivateData The module's private data.
1617 @param[in] VariableName Variable name of signature database, must be
1618 EFI_IMAGE_SECURITY_DATABASE1.
1620 @retval TRUE The X509 certificate is found in dbx successfully.
1621 @retval FALSE The X509 certificate is not found in dbx.
1625 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1626 IN CHAR16
*VariableName
1635 // Read the certificate from file
1639 Status
= ReadFileContent (
1640 Private
->FileContext
->FHandle
,
1645 if (EFI_ERROR (Status
)) {
1650 // Check the raw certificate.
1653 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1659 // Check the hash of certificate.
1661 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1667 if (X509Data
!= NULL
) {
1668 FreePool (X509Data
);
1675 Reads contents of a PE/COFF image in memory buffer.
1677 Caution: This function may receive untrusted input.
1678 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1679 read is within the image buffer.
1681 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1682 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1683 @param ReadSize On input, the size in bytes of the requested read operation.
1684 On output, the number of bytes actually read.
1685 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1687 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1691 SecureBootConfigImageRead (
1692 IN VOID
*FileHandle
,
1693 IN UINTN FileOffset
,
1694 IN OUT UINTN
*ReadSize
,
1700 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1701 return EFI_INVALID_PARAMETER
;
1704 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1705 return EFI_INVALID_PARAMETER
;
1708 EndPosition
= FileOffset
+ *ReadSize
;
1709 if (EndPosition
> mImageSize
) {
1710 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1713 if (FileOffset
>= mImageSize
) {
1717 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1723 Load PE/COFF image information into internal buffer and check its validity.
1725 @retval EFI_SUCCESS Successful
1726 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1727 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1735 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1736 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1737 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1738 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1744 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1745 ImageContext
.Handle
= (VOID
*) mImageBase
;
1746 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1749 // Get information about the image being loaded
1751 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1752 if (EFI_ERROR (Status
)) {
1754 // The information can't be got from the invalid PeImage
1756 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1761 // Read the Dos header
1763 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1764 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1767 // DOS image header is present,
1768 // So read the PE header after the DOS image header
1770 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1774 mPeCoffHeaderOffset
= 0;
1778 // Read PE header and check the signature validity and machine compatibility
1780 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1781 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1783 return EFI_UNSUPPORTED
;
1786 mNtHeader
.Pe32
= NtHeader32
;
1789 // Check the architecture field of PE header and get the Certificate Data Directory data
1790 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1792 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1793 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1794 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1796 // 32-bits Architecture
1798 mImageType
= ImageType_IA32
;
1799 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1801 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1802 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1803 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1805 // 64-bits Architecture
1807 mImageType
= ImageType_X64
;
1808 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1809 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1811 return EFI_UNSUPPORTED
;
1818 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1819 PE/COFF Specification 8.0 Appendix A
1821 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1822 the function LoadPeImage ().
1824 @param[in] HashAlg Hash algorithm type.
1826 @retval TRUE Successfully hash image.
1827 @retval FALSE Fail in hash image.
1837 EFI_IMAGE_SECTION_HEADER
*Section
;
1842 UINTN SumOfBytesHashed
;
1843 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1848 SectionHeader
= NULL
;
1851 if (HashAlg
!= HASHALG_SHA256
) {
1856 // Initialize context of hash.
1858 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1860 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1861 mCertType
= gEfiCertSha256Guid
;
1863 CtxSize
= mHash
[HashAlg
].GetContextSize();
1865 HashCtx
= AllocatePool (CtxSize
);
1866 ASSERT (HashCtx
!= NULL
);
1868 // 1. Load the image header into memory.
1870 // 2. Initialize a SHA hash context.
1871 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1876 // Measuring PE/COFF Image Header;
1877 // But CheckSum field and SECURITY data directory (certificate) are excluded
1879 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1881 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1882 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1883 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1884 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1886 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1889 // Get the magic value from the PE/COFF Optional Header
1891 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1895 // 3. Calculate the distance from the base of the image header to the image checksum address.
1896 // 4. Hash the image header from its base to beginning of the image checksum.
1898 HashBase
= mImageBase
;
1899 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1903 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1906 // Use PE32+ offset.
1908 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1911 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1916 // 5. Skip over the image checksum (it occupies a single ULONG).
1917 // 6. Get the address of the beginning of the Cert Directory.
1918 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1920 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1924 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1925 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1928 // Use PE32+ offset.
1930 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1931 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1934 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1939 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1940 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1942 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1946 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1947 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1950 // Use PE32+ offset.
1952 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1953 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1956 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1961 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1963 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1967 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1972 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1976 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1977 // structures in the image. The 'NumberOfSections' field of the image
1978 // header indicates how big the table should be. Do not include any
1979 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1981 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1982 ASSERT (SectionHeader
!= NULL
);
1984 // 12. Using the 'PointerToRawData' in the referenced section headers as
1985 // a key, arrange the elements in the table in ascending order. In other
1986 // words, sort the section headers according to the disk-file offset of
1989 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1991 mPeCoffHeaderOffset
+
1993 sizeof (EFI_IMAGE_FILE_HEADER
) +
1994 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1996 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1998 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1999 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
2002 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
2007 // 13. Walk through the sorted table, bring the corresponding section
2008 // into memory, and hash the entire section (using the 'SizeOfRawData'
2009 // field in the section header to determine the amount of data to hash).
2010 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2011 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
2013 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
2014 Section
= &SectionHeader
[Index
];
2015 if (Section
->SizeOfRawData
== 0) {
2018 HashBase
= mImageBase
+ Section
->PointerToRawData
;
2019 HashSize
= (UINTN
) Section
->SizeOfRawData
;
2021 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2026 SumOfBytesHashed
+= HashSize
;
2030 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2031 // data in the file that needs to be added to the hash. This data begins
2032 // at file offset SUM_OF_BYTES_HASHED and its length is:
2033 // FileSize - (CertDirectory->Size)
2035 if (mImageSize
> SumOfBytesHashed
) {
2036 HashBase
= mImageBase
+ SumOfBytesHashed
;
2037 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2043 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2047 // Use PE32+ offset.
2051 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2055 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2061 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2064 if (HashCtx
!= NULL
) {
2067 if (SectionHeader
!= NULL
) {
2068 FreePool (SectionHeader
);
2074 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2075 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2078 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2079 @retval EFI_SUCCESS Hash successfully.
2088 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2090 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2092 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2094 // Check the Hash algorithm in PE/COFF Authenticode.
2095 // According to PKCS#7 Definition:
2096 // SignedData ::= SEQUENCE {
2098 // digestAlgorithms DigestAlgorithmIdentifiers,
2099 // contentInfo ContentInfo,
2101 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2102 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2103 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2105 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2107 // Only support two bytes of Long Form of Length Encoding.
2113 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2118 if (Index
== HASHALG_MAX
) {
2119 return EFI_UNSUPPORTED
;
2123 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2125 if (!HashPeImage(Index
)) {
2126 return EFI_UNSUPPORTED
;
2133 Enroll a new executable's signature into Signature Database.
2135 @param[in] PrivateData The module's private data.
2136 @param[in] VariableName Variable name of signature database, must be
2137 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2138 or EFI_IMAGE_SECURITY_DATABASE2.
2140 @retval EFI_SUCCESS New signature is enrolled successfully.
2141 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2142 @retval EFI_UNSUPPORTED Unsupported command.
2143 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2147 EnrollAuthentication2Descriptor (
2148 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2149 IN CHAR16
*VariableName
2160 // DBT only support DER-X509 Cert Enrollment
2162 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2163 return EFI_UNSUPPORTED
;
2167 // Read the whole file content
2169 Status
= ReadFileContent(
2170 Private
->FileContext
->FHandle
,
2171 (VOID
**) &mImageBase
,
2175 if (EFI_ERROR (Status
)) {
2178 ASSERT (mImageBase
!= NULL
);
2180 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2181 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2184 // Check if SigDB variable has been already existed.
2185 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2186 // new signature data to original variable
2189 Status
= gRT
->GetVariable(
2191 &gEfiImageSecurityDatabaseGuid
,
2196 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2197 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2198 } else if (Status
!= EFI_NOT_FOUND
) {
2203 // Diretly set AUTHENTICATION_2 data to SetVariable
2205 Status
= gRT
->SetVariable(
2207 &gEfiImageSecurityDatabaseGuid
,
2213 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2217 CloseEnrolledFile(Private
->FileContext
);
2223 if (mImageBase
!= NULL
) {
2224 FreePool (mImageBase
);
2234 Enroll a new executable's signature into Signature Database.
2236 @param[in] PrivateData The module's private data.
2237 @param[in] VariableName Variable name of signature database, must be
2238 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2239 or EFI_IMAGE_SECURITY_DATABASE2.
2241 @retval EFI_SUCCESS New signature is enrolled successfully.
2242 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2243 @retval EFI_UNSUPPORTED Unsupported command.
2244 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2248 EnrollImageSignatureToSigDB (
2249 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2250 IN CHAR16
*VariableName
2254 EFI_SIGNATURE_LIST
*SigDBCert
;
2255 EFI_SIGNATURE_DATA
*SigDBCertData
;
2260 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2263 GuidCertData
= NULL
;
2265 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2266 return EFI_UNSUPPORTED
;
2270 // Form the SigDB certificate list.
2271 // Format the data item into EFI_SIGNATURE_LIST type.
2273 // We need to parse executable's signature data from specified signed executable file.
2274 // In current implementation, we simply trust the pass-in signed executable file.
2275 // In reality, it's OS's responsibility to verify the signed executable file.
2279 // Read the whole file content
2281 Status
= ReadFileContent(
2282 Private
->FileContext
->FHandle
,
2283 (VOID
**) &mImageBase
,
2287 if (EFI_ERROR (Status
)) {
2290 ASSERT (mImageBase
!= NULL
);
2292 Status
= LoadPeImage ();
2293 if (EFI_ERROR (Status
)) {
2297 if (mSecDataDir
->SizeOfCert
== 0) {
2298 if (!HashPeImage (HASHALG_SHA256
)) {
2299 Status
= EFI_SECURITY_VIOLATION
;
2305 // Read the certificate data
2307 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2309 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2310 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2311 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2312 Status
= EFI_ABORTED
;
2316 if (!HashPeImage (HASHALG_SHA256
)) {
2317 Status
= EFI_ABORTED
;
2321 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2323 Status
= HashPeImageByType ();
2324 if (EFI_ERROR (Status
)) {
2328 Status
= EFI_ABORTED
;
2334 // Create a new SigDB entry.
2336 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2337 + sizeof(EFI_SIGNATURE_DATA
) - 1
2338 + (UINT32
) mImageDigestSize
;
2340 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2342 Status
= EFI_OUT_OF_RESOURCES
;
2347 // Adjust the Certificate Database parameters.
2349 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2350 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2351 SigDBCert
->SignatureHeaderSize
= 0;
2352 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2353 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2355 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2356 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2357 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2359 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2360 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2361 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2362 if (EFI_ERROR (Status
)) {
2363 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2368 // Check if SigDB variable has been already existed.
2369 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2370 // new signature data to original variable
2373 Status
= gRT
->GetVariable(
2375 &gEfiImageSecurityDatabaseGuid
,
2380 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2381 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2382 } else if (Status
!= EFI_NOT_FOUND
) {
2387 // Enroll the variable.
2389 Status
= gRT
->SetVariable(
2391 &gEfiImageSecurityDatabaseGuid
,
2396 if (EFI_ERROR (Status
)) {
2402 CloseEnrolledFile(Private
->FileContext
);
2404 if (Private
->SignatureGUID
!= NULL
) {
2405 FreePool (Private
->SignatureGUID
);
2406 Private
->SignatureGUID
= NULL
;
2413 if (mImageBase
!= NULL
) {
2414 FreePool (mImageBase
);
2422 Enroll signature into DB/DBX/DBT without KEK's authentication.
2423 The SignatureOwner GUID will be Private->SignatureGUID.
2425 @param[in] PrivateData The module's private data.
2426 @param[in] VariableName Variable name of signature database, must be
2427 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2429 @retval EFI_SUCCESS New signature enrolled successfully.
2430 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2431 @retval others Fail to enroll signature data.
2435 EnrollSignatureDatabase (
2436 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2437 IN CHAR16
*VariableName
2440 UINT16
* FilePostFix
;
2444 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2445 return EFI_INVALID_PARAMETER
;
2448 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2449 if (EFI_ERROR (Status
)) {
2454 // Parse the file's postfix.
2456 NameLength
= StrLen (Private
->FileContext
->FileName
);
2457 if (NameLength
<= 4) {
2458 return EFI_INVALID_PARAMETER
;
2460 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2461 if (IsDerEncodeCertificate (FilePostFix
)) {
2463 // Supports DER-encoded X509 certificate.
2465 return EnrollX509toSigDB (Private
, VariableName
);
2466 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2467 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2469 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2474 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2475 by GUID in the page for user to select and delete as needed.
2477 @param[in] PrivateData Module's private data.
2478 @param[in] VariableName The variable name of the vendor's signature database.
2479 @param[in] VendorGuid A unique identifier for the vendor.
2480 @param[in] LabelNumber Label number to insert opcodes.
2481 @param[in] FormId Form ID of current page.
2482 @param[in] QuestionIdBase Base question id of the signature list.
2484 @retval EFI_SUCCESS Success to update the signature list page
2485 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2490 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2491 IN CHAR16
*VariableName
,
2492 IN EFI_GUID
*VendorGuid
,
2493 IN UINT16 LabelNumber
,
2494 IN EFI_FORM_ID FormId
,
2495 IN EFI_QUESTION_ID QuestionIdBase
2502 VOID
*StartOpCodeHandle
;
2503 VOID
*EndOpCodeHandle
;
2504 EFI_IFR_GUID_LABEL
*StartLabel
;
2505 EFI_IFR_GUID_LABEL
*EndLabel
;
2508 EFI_SIGNATURE_LIST
*CertList
;
2509 EFI_SIGNATURE_DATA
*Cert
;
2510 UINT32 ItemDataSize
;
2512 EFI_STRING_ID GuidID
;
2519 StartOpCodeHandle
= NULL
;
2520 EndOpCodeHandle
= NULL
;
2523 // Initialize the container for dynamic opcodes.
2525 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2526 if (StartOpCodeHandle
== NULL
) {
2527 Status
= EFI_OUT_OF_RESOURCES
;
2531 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2532 if (EndOpCodeHandle
== NULL
) {
2533 Status
= EFI_OUT_OF_RESOURCES
;
2538 // Create Hii Extend Label OpCode.
2540 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2544 sizeof (EFI_IFR_GUID_LABEL
)
2546 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2547 StartLabel
->Number
= LabelNumber
;
2549 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2553 sizeof (EFI_IFR_GUID_LABEL
)
2555 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2556 EndLabel
->Number
= LABEL_END
;
2562 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2563 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2567 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2569 Status
= EFI_OUT_OF_RESOURCES
;
2573 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2574 if (EFI_ERROR (Status
)) {
2578 GuidStr
= AllocateZeroPool (100);
2579 if (GuidStr
== NULL
) {
2580 Status
= EFI_OUT_OF_RESOURCES
;
2585 // Enumerate all KEK pub data.
2587 ItemDataSize
= (UINT32
) DataSize
;
2588 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2591 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2593 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2594 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2595 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2596 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2597 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2598 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2599 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2600 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2601 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2602 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2603 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2604 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2605 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2606 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2609 // The signature type is not supported in current implementation.
2611 ItemDataSize
-= CertList
->SignatureListSize
;
2612 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2616 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2617 for (Index
= 0; Index
< CertCount
; Index
++) {
2618 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2619 + sizeof (EFI_SIGNATURE_LIST
)
2620 + CertList
->SignatureHeaderSize
2621 + Index
* CertList
->SignatureSize
);
2623 // Display GUID and help
2625 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2626 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2627 HiiCreateCheckBoxOpCode (
2629 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2634 EFI_IFR_FLAG_CALLBACK
,
2640 ItemDataSize
-= CertList
->SignatureListSize
;
2641 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2646 PrivateData
->HiiHandle
,
2647 &gSecureBootConfigFormSetGuid
,
2653 if (StartOpCodeHandle
!= NULL
) {
2654 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2657 if (EndOpCodeHandle
!= NULL
) {
2658 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2665 if (GuidStr
!= NULL
) {
2673 Delete a KEK entry from KEK database.
2675 @param[in] PrivateData Module's private data.
2676 @param[in] QuestionId Question id of the KEK item to delete.
2678 @retval EFI_SUCCESS Delete kek item successfully.
2679 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2683 DeleteKeyExchangeKey (
2684 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2685 IN EFI_QUESTION_ID QuestionId
2694 EFI_SIGNATURE_LIST
*CertList
;
2695 EFI_SIGNATURE_LIST
*NewCertList
;
2696 EFI_SIGNATURE_DATA
*Cert
;
2699 BOOLEAN IsKEKItemFound
;
2701 UINTN DeleteKekIndex
;
2709 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2711 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2712 if (EFI_ERROR (Status
)) {
2717 // Get original KEK variable.
2720 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2721 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2725 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2726 if (OldData
== NULL
) {
2727 Status
= EFI_OUT_OF_RESOURCES
;
2731 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2732 if (EFI_ERROR(Status
)) {
2737 // Allocate space for new variable.
2739 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2741 Status
= EFI_OUT_OF_RESOURCES
;
2746 // Enumerate all KEK pub data and erasing the target item.
2748 IsKEKItemFound
= FALSE
;
2749 KekDataSize
= (UINT32
) DataSize
;
2750 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2753 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2754 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2755 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2756 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2757 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2758 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2759 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2760 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2761 for (Index
= 0; Index
< CertCount
; Index
++) {
2762 if (GuidIndex
== DeleteKekIndex
) {
2764 // Find it! Skip it!
2766 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2767 IsKEKItemFound
= TRUE
;
2770 // This item doesn't match. Copy it to the Data buffer.
2772 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2773 Offset
+= CertList
->SignatureSize
;
2776 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2780 // This List doesn't match. Copy it to the Data buffer.
2782 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2783 Offset
+= CertList
->SignatureListSize
;
2786 KekDataSize
-= CertList
->SignatureListSize
;
2787 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2790 if (!IsKEKItemFound
) {
2792 // Doesn't find the Kek Item!
2794 Status
= EFI_NOT_FOUND
;
2799 // Delete the Signature header if there is no signature in the list.
2801 KekDataSize
= Offset
;
2802 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2804 ZeroMem (OldData
, KekDataSize
);
2805 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2806 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2807 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2808 if (CertCount
!= 0) {
2809 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2810 Offset
+= CertList
->SignatureListSize
;
2812 KekDataSize
-= CertList
->SignatureListSize
;
2813 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2817 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2818 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2819 if (EFI_ERROR (Status
)) {
2820 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2825 Status
= gRT
->SetVariable(
2826 EFI_KEY_EXCHANGE_KEY_NAME
,
2827 &gEfiGlobalVariableGuid
,
2832 if (EFI_ERROR (Status
)) {
2833 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2842 if (OldData
!= NULL
) {
2846 return UpdateDeletePage (
2848 EFI_KEY_EXCHANGE_KEY_NAME
,
2849 &gEfiGlobalVariableGuid
,
2851 FORMID_DELETE_KEK_FORM
,
2852 OPTION_DEL_KEK_QUESTION_ID
2857 Delete a signature entry from siganture database.
2859 @param[in] PrivateData Module's private data.
2860 @param[in] VariableName The variable name of the vendor's signature database.
2861 @param[in] VendorGuid A unique identifier for the vendor.
2862 @param[in] LabelNumber Label number to insert opcodes.
2863 @param[in] FormId Form ID of current page.
2864 @param[in] QuestionIdBase Base question id of the signature list.
2865 @param[in] DeleteIndex Signature index to delete.
2867 @retval EFI_SUCCESS Delete siganture successfully.
2868 @retval EFI_NOT_FOUND Can't find the signature item,
2869 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2873 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2874 IN CHAR16
*VariableName
,
2875 IN EFI_GUID
*VendorGuid
,
2876 IN UINT16 LabelNumber
,
2877 IN EFI_FORM_ID FormId
,
2878 IN EFI_QUESTION_ID QuestionIdBase
,
2879 IN UINTN DeleteIndex
2888 EFI_SIGNATURE_LIST
*CertList
;
2889 EFI_SIGNATURE_LIST
*NewCertList
;
2890 EFI_SIGNATURE_DATA
*Cert
;
2893 BOOLEAN IsItemFound
;
2894 UINT32 ItemDataSize
;
2903 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2904 if (EFI_ERROR (Status
)) {
2909 // Get original signature list data.
2912 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2913 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2917 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2918 if (OldData
== NULL
) {
2919 Status
= EFI_OUT_OF_RESOURCES
;
2923 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2924 if (EFI_ERROR(Status
)) {
2929 // Allocate space for new variable.
2931 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2933 Status
= EFI_OUT_OF_RESOURCES
;
2938 // Enumerate all signature data and erasing the target item.
2940 IsItemFound
= FALSE
;
2941 ItemDataSize
= (UINT32
) DataSize
;
2942 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2945 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2946 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2947 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2948 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2949 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2950 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2951 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2952 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2955 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2957 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2958 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2959 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2960 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2961 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2962 for (Index
= 0; Index
< CertCount
; Index
++) {
2963 if (GuidIndex
== DeleteIndex
) {
2965 // Find it! Skip it!
2967 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2971 // This item doesn't match. Copy it to the Data buffer.
2973 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2974 Offset
+= CertList
->SignatureSize
;
2977 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2981 // This List doesn't match. Just copy it to the Data buffer.
2983 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2984 Offset
+= CertList
->SignatureListSize
;
2987 ItemDataSize
-= CertList
->SignatureListSize
;
2988 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2993 // Doesn't find the signature Item!
2995 Status
= EFI_NOT_FOUND
;
3000 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
3002 ItemDataSize
= Offset
;
3003 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
3005 ZeroMem (OldData
, ItemDataSize
);
3006 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
3007 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
3008 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
3009 if (CertCount
!= 0) {
3010 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
3011 Offset
+= CertList
->SignatureListSize
;
3013 ItemDataSize
-= CertList
->SignatureListSize
;
3014 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
3018 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3019 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
3020 if (EFI_ERROR (Status
)) {
3021 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
3026 Status
= gRT
->SetVariable(
3033 if (EFI_ERROR (Status
)) {
3034 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
3043 if (OldData
!= NULL
) {
3047 return UpdateDeletePage (
3059 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3060 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3062 @param[in] PrivateData Module's private data.
3064 @return EFI_SUCCESS Update secure boot strings successfully.
3065 @return other Fail to update secure boot strings.
3069 UpdateSecureBootString(
3070 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3078 // Get current secure boot state.
3080 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3081 if (SecureBoot
== NULL
) {
3082 return EFI_NOT_FOUND
;
3085 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3086 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3088 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3091 FreePool(SecureBoot
);
3097 This function extracts configuration from variable.
3099 @param[in] Private Point to SecureBoot configuration driver private data.
3100 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3104 SecureBootExtractConfigFromVariable (
3105 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3106 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3109 UINT8
*SecureBootEnable
;
3111 UINT8
*SecureBootMode
;
3114 SecureBootEnable
= NULL
;
3116 SecureBootMode
= NULL
;
3119 // Initilize the Date and Time using system time.
3121 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3122 ConfigData
->AlwaysRevocation
= TRUE
;
3123 gRT
->GetTime (&CurrTime
, NULL
);
3124 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3125 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3126 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3127 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3128 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3129 ConfigData
->RevocationTime
.Second
= 0;
3130 if (Private
->FileContext
->FHandle
!= NULL
) {
3131 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3133 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3137 // If it is Physical Presence User, set the PhysicalPresent to true.
3139 if (UserPhysicalPresent()) {
3140 ConfigData
->PhysicalPresent
= TRUE
;
3142 ConfigData
->PhysicalPresent
= FALSE
;
3146 // If there is no PK then the Delete Pk button will be gray.
3148 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3149 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3150 ConfigData
->HasPk
= FALSE
;
3152 ConfigData
->HasPk
= TRUE
;
3156 // Check SecureBootEnable & Pk status, fix the inconsistence.
3157 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3160 ConfigData
->AttemptSecureBoot
= FALSE
;
3161 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3164 // Fix Pk, SecureBootEnable inconsistence
3166 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3167 ConfigData
->HideSecureBoot
= FALSE
;
3168 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3169 ConfigData
->AttemptSecureBoot
= TRUE
;
3172 ConfigData
->HideSecureBoot
= TRUE
;
3176 // Get the SecureBootMode from CustomMode variable.
3178 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3179 if (SecureBootMode
== NULL
) {
3180 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3182 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3185 if (SecureBootEnable
!= NULL
) {
3186 FreePool (SecureBootEnable
);
3188 if (SetupMode
!= NULL
) {
3189 FreePool (SetupMode
);
3191 if (SecureBootMode
!= NULL
) {
3192 FreePool (SecureBootMode
);
3197 This function allows a caller to extract the current configuration for one
3198 or more named elements from the target driver.
3200 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3201 @param[in] Request A null-terminated Unicode string in
3202 <ConfigRequest> format.
3203 @param[out] Progress On return, points to a character in the Request
3204 string. Points to the string's null terminator if
3205 request was successful. Points to the most recent
3206 '&' before the first failing name/value pair (or
3207 the beginning of the string if the failure is in
3208 the first name/value pair) if the request was not
3210 @param[out] Results A null-terminated Unicode string in
3211 <ConfigAltResp> format which has all values filled
3212 in for the names in the Request string. String to
3213 be allocated by the called function.
3215 @retval EFI_SUCCESS The Results is filled with the requested values.
3216 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3217 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3218 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3224 SecureBootExtractConfig (
3225 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3226 IN CONST EFI_STRING Request
,
3227 OUT EFI_STRING
*Progress
,
3228 OUT EFI_STRING
*Results
3234 SECUREBOOT_CONFIGURATION Configuration
;
3235 EFI_STRING ConfigRequest
;
3236 EFI_STRING ConfigRequestHdr
;
3237 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3238 BOOLEAN AllocatedRequest
;
3240 if (Progress
== NULL
|| Results
== NULL
) {
3241 return EFI_INVALID_PARAMETER
;
3244 AllocatedRequest
= FALSE
;
3245 ConfigRequestHdr
= NULL
;
3246 ConfigRequest
= NULL
;
3249 ZeroMem (&Configuration
, sizeof (Configuration
));
3250 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3251 *Progress
= Request
;
3253 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3254 return EFI_NOT_FOUND
;
3257 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3260 // Get Configuration from Variable.
3262 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3264 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3265 ConfigRequest
= Request
;
3266 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3268 // Request is set to NULL or OFFSET is NULL, construct full request string.
3270 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3271 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3273 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3274 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3275 ConfigRequest
= AllocateZeroPool (Size
);
3276 ASSERT (ConfigRequest
!= NULL
);
3277 AllocatedRequest
= TRUE
;
3278 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3279 FreePool (ConfigRequestHdr
);
3280 ConfigRequestHdr
= NULL
;
3283 Status
= gHiiConfigRouting
->BlockToConfig (
3286 (UINT8
*) &Configuration
,
3293 // Free the allocated config request string.
3295 if (AllocatedRequest
) {
3296 FreePool (ConfigRequest
);
3300 // Set Progress string to the original request string.
3302 if (Request
== NULL
) {
3304 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3305 *Progress
= Request
+ StrLen (Request
);
3312 This function processes the results of changes in configuration.
3314 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3315 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3317 @param[out] Progress A pointer to a string filled in with the offset of
3318 the most recent '&' before the first failing
3319 name/value pair (or the beginning of the string if
3320 the failure is in the first name/value pair) or
3321 the terminating NULL if all was successful.
3323 @retval EFI_SUCCESS The Results is processed successfully.
3324 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3325 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3331 SecureBootRouteConfig (
3332 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3333 IN CONST EFI_STRING Configuration
,
3334 OUT EFI_STRING
*Progress
3337 SECUREBOOT_CONFIGURATION IfrNvData
;
3339 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3342 if (Configuration
== NULL
|| Progress
== NULL
) {
3343 return EFI_INVALID_PARAMETER
;
3346 *Progress
= Configuration
;
3347 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3348 return EFI_NOT_FOUND
;
3351 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3354 // Get Configuration from Variable.
3356 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3359 // Map the Configuration to the configuration block.
3361 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3362 Status
= gHiiConfigRouting
->ConfigToBlock (
3365 (UINT8
*)&IfrNvData
,
3369 if (EFI_ERROR (Status
)) {
3374 // Store Buffer Storage back to EFI variable if needed
3376 if (!IfrNvData
.HideSecureBoot
) {
3377 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3378 if (EFI_ERROR (Status
)) {
3383 *Progress
= Configuration
+ StrLen (Configuration
);
3388 This function is called to provide results data to the driver.
3390 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3391 @param[in] Action Specifies the type of action taken by the browser.
3392 @param[in] QuestionId A unique value which is sent to the original
3393 exporting driver so that it can identify the type
3395 @param[in] Type The type of value for the question.
3396 @param[in] Value A pointer to the data being sent to the original
3398 @param[out] ActionRequest On return, points to the action requested by the
3401 @retval EFI_SUCCESS The callback successfully handled the action.
3402 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3403 variable and its data.
3404 @retval EFI_DEVICE_ERROR The variable could not be saved.
3405 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3411 SecureBootCallback (
3412 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3413 IN EFI_BROWSER_ACTION Action
,
3414 IN EFI_QUESTION_ID QuestionId
,
3416 IN EFI_IFR_TYPE_VALUE
*Value
,
3417 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3422 RETURN_STATUS RStatus
;
3423 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3425 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3427 UINT8
*SecureBootEnable
;
3429 UINT8
*SecureBootMode
;
3431 CHAR16 PromptString
[100];
3432 EFI_DEVICE_PATH_PROTOCOL
*File
;
3434 UINT16
*FilePostFix
;
3435 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3437 Status
= EFI_SUCCESS
;
3438 SecureBootEnable
= NULL
;
3439 SecureBootMode
= NULL
;
3443 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3444 return EFI_INVALID_PARAMETER
;
3447 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3449 gSecureBootPrivateData
= Private
;
3452 // Retrieve uncommitted data from Browser
3454 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3455 IfrNvData
= AllocateZeroPool (BufferSize
);
3456 if (IfrNvData
== NULL
) {
3457 return EFI_OUT_OF_RESOURCES
;
3460 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3462 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3463 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3465 // Update secure boot strings when opening this form
3467 Status
= UpdateSecureBootString(Private
);
3468 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
3469 mIsEnterSecureBootForm
= TRUE
;
3472 // When entering SecureBoot OPTION Form
3473 // always close opened file & free resource
3475 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
3476 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
3477 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
3478 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
3479 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
3480 CloseEnrolledFile(Private
->FileContext
);
3486 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3487 Status
= EFI_UNSUPPORTED
;
3488 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3489 if (mIsEnterSecureBootForm
) {
3490 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3491 Status
= EFI_SUCCESS
;
3497 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3498 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3499 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3500 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3501 Status
= EFI_UNSUPPORTED
;
3505 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3507 switch (QuestionId
) {
3508 case KEY_SECURE_BOOT_ENABLE
:
3509 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3510 if (NULL
!= SecureBootEnable
) {
3511 FreePool (SecureBootEnable
);
3512 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3514 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3516 L
"Only Physical Presence User could disable secure boot!",
3519 Status
= EFI_UNSUPPORTED
;
3522 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3524 L
"Configuration changed, please reset the platform to take effect!",
3531 case KEY_SECURE_BOOT_KEK_OPTION
:
3532 case KEY_SECURE_BOOT_DB_OPTION
:
3533 case KEY_SECURE_BOOT_DBX_OPTION
:
3534 case KEY_SECURE_BOOT_DBT_OPTION
:
3535 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3537 // Clear Signature GUID.
3539 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3540 if (Private
->SignatureGUID
== NULL
) {
3541 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3542 if (Private
->SignatureGUID
== NULL
) {
3543 return EFI_OUT_OF_RESOURCES
;
3548 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
3550 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
3552 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3553 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3554 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3555 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3556 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3557 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3559 LabelId
= FORMID_ENROLL_KEK_FORM
;
3563 // Refresh selected file.
3565 CleanUpPage (LabelId
, Private
);
3567 case KEY_SECURE_BOOT_PK_OPTION
:
3568 LabelId
= FORMID_ENROLL_PK_FORM
;
3570 // Refresh selected file.
3572 CleanUpPage (LabelId
, Private
);
3575 case FORMID_ENROLL_PK_FORM
:
3576 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
3579 case FORMID_ENROLL_KEK_FORM
:
3580 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
3583 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3584 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
3587 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3588 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
3590 if (Private
->FileContext
->FHandle
!= NULL
) {
3592 // Parse the file's postfix.
3594 NameLength
= StrLen (Private
->FileContext
->FileName
);
3595 if (NameLength
<= 4) {
3598 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
3600 if (IsDerEncodeCertificate (FilePostFix
)) {
3602 // Supports DER-encoded X509 certificate.
3604 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
3605 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
3606 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
3608 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
3610 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
3613 // Clean up Certificate Format if File type is not X509 DER
3615 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
3616 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
3618 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
3623 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3624 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
3627 case KEY_SECURE_BOOT_DELETE_PK
:
3630 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3632 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3633 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3636 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3637 Status
= DeletePlatformKey ();
3638 if (EFI_ERROR (Status
)) {
3640 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3642 L
"Only Physical Presence User could delete PK in custom mode!",
3650 case KEY_DELETE_KEK
:
3653 EFI_KEY_EXCHANGE_KEY_NAME
,
3654 &gEfiGlobalVariableGuid
,
3656 FORMID_DELETE_KEK_FORM
,
3657 OPTION_DEL_KEK_QUESTION_ID
3661 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3664 EFI_IMAGE_SECURITY_DATABASE
,
3665 &gEfiImageSecurityDatabaseGuid
,
3667 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3668 OPTION_DEL_DB_QUESTION_ID
3672 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3675 EFI_IMAGE_SECURITY_DATABASE1
,
3676 &gEfiImageSecurityDatabaseGuid
,
3678 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3679 OPTION_DEL_DBX_QUESTION_ID
3684 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3687 EFI_IMAGE_SECURITY_DATABASE2
,
3688 &gEfiImageSecurityDatabaseGuid
,
3690 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3691 OPTION_DEL_DBT_QUESTION_ID
3696 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3697 Status
= EnrollKeyExchangeKey (Private
);
3698 if (EFI_ERROR (Status
)) {
3700 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3702 L
"ERROR: Unsupported file type!",
3703 L
"Only supports DER-encoded X509 certificate",
3709 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3710 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3711 if (EFI_ERROR (Status
)) {
3713 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3715 L
"ERROR: Unsupported file type!",
3716 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3722 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3723 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3725 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3727 L
"Enrollment failed! Same certificate had already been in the dbx!",
3732 // Cert already exists in DBX. Close opened file before exit.
3734 CloseEnrolledFile(Private
->FileContext
);
3738 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3739 Status
= EnrollX509HashtoSigDB (
3741 IfrNvData
->CertificateFormat
,
3742 &IfrNvData
->RevocationDate
,
3743 &IfrNvData
->RevocationTime
,
3744 IfrNvData
->AlwaysRevocation
3746 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
3748 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3750 if (EFI_ERROR (Status
)) {
3752 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3754 L
"ERROR: Unsupported file type!",
3755 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
3761 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3762 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3763 if (EFI_ERROR (Status
)) {
3765 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3767 L
"ERROR: Unsupported file type!",
3768 L
"Only supports DER-encoded X509 certificate.",
3773 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3774 Status
= EnrollPlatformKey (Private
);
3775 if (EFI_ERROR (Status
)) {
3778 sizeof (PromptString
),
3779 L
"Only DER encoded certificate file (%s) is supported.",
3783 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3785 L
"ERROR: Unsupported file type!",
3792 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3793 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3794 DeleteKeyExchangeKey (Private
, QuestionId
);
3795 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3796 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3799 EFI_IMAGE_SECURITY_DATABASE
,
3800 &gEfiImageSecurityDatabaseGuid
,
3802 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3803 OPTION_DEL_DB_QUESTION_ID
,
3804 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3806 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3807 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3810 EFI_IMAGE_SECURITY_DATABASE1
,
3811 &gEfiImageSecurityDatabaseGuid
,
3813 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3814 OPTION_DEL_DBX_QUESTION_ID
,
3815 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3817 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3818 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3821 EFI_IMAGE_SECURITY_DATABASE2
,
3822 &gEfiImageSecurityDatabaseGuid
,
3824 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3825 OPTION_DEL_DBT_QUESTION_ID
,
3826 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3831 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3832 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3833 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3834 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3835 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3836 CloseEnrolledFile(Private
->FileContext
);
3838 if (Private
->SignatureGUID
!= NULL
) {
3839 FreePool (Private
->SignatureGUID
);
3840 Private
->SignatureGUID
= NULL
;
3844 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3845 switch (QuestionId
) {
3846 case KEY_SECURE_BOOT_ENABLE
:
3847 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3849 case KEY_SECURE_BOOT_MODE
:
3850 mIsEnterSecureBootForm
= FALSE
;
3852 case KEY_SECURE_BOOT_KEK_GUID
:
3853 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3854 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3855 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3856 ASSERT (Private
->SignatureGUID
!= NULL
);
3857 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
3858 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
3859 Status
= EFI_INVALID_PARAMETER
;
3863 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3865 case KEY_SECURE_BOOT_DELETE_PK
:
3866 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3867 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3868 IfrNvData
->DeletePk
= TRUE
;
3869 IfrNvData
->HasPk
= FALSE
;
3870 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3872 IfrNvData
->DeletePk
= FALSE
;
3873 IfrNvData
->HasPk
= TRUE
;
3874 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3876 if (SetupMode
!= NULL
) {
3877 FreePool (SetupMode
);
3883 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3884 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3885 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
3887 IfrNvData
->HideSecureBoot
= TRUE
;
3890 IfrNvData
->HideSecureBoot
= FALSE
;
3892 Value
->b
= IfrNvData
->HideSecureBoot
;
3894 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3896 // Force the platform back to Standard Mode once user leave the setup screen.
3898 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3899 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3900 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3901 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3903 if (SecureBootMode
!= NULL
) {
3904 FreePool (SecureBootMode
);
3910 if (!EFI_ERROR (Status
)) {
3911 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3912 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3915 FreePool (IfrNvData
);
3926 This function publish the SecureBoot configuration Form.
3928 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3930 @retval EFI_SUCCESS HII Form is installed successfully.
3931 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3932 @retval Others Other errors as indicated.
3936 InstallSecureBootConfigForm (
3937 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3941 EFI_HII_HANDLE HiiHandle
;
3942 EFI_HANDLE DriverHandle
;
3943 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3945 DriverHandle
= NULL
;
3946 ConfigAccess
= &PrivateData
->ConfigAccess
;
3947 Status
= gBS
->InstallMultipleProtocolInterfaces (
3949 &gEfiDevicePathProtocolGuid
,
3950 &mSecureBootHiiVendorDevicePath
,
3951 &gEfiHiiConfigAccessProtocolGuid
,
3955 if (EFI_ERROR (Status
)) {
3959 PrivateData
->DriverHandle
= DriverHandle
;
3962 // Publish the HII package list
3964 HiiHandle
= HiiAddPackages (
3965 &gSecureBootConfigFormSetGuid
,
3967 SecureBootConfigDxeStrings
,
3968 SecureBootConfigBin
,
3971 if (HiiHandle
== NULL
) {
3972 gBS
->UninstallMultipleProtocolInterfaces (
3974 &gEfiDevicePathProtocolGuid
,
3975 &mSecureBootHiiVendorDevicePath
,
3976 &gEfiHiiConfigAccessProtocolGuid
,
3980 return EFI_OUT_OF_RESOURCES
;
3983 PrivateData
->HiiHandle
= HiiHandle
;
3985 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
3987 if (PrivateData
->FileContext
== NULL
) {
3988 UninstallSecureBootConfigForm (PrivateData
);
3989 return EFI_OUT_OF_RESOURCES
;
3993 // Init OpCode Handle and Allocate space for creation of Buffer
3995 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3996 if (mStartOpCodeHandle
== NULL
) {
3997 UninstallSecureBootConfigForm (PrivateData
);
3998 return EFI_OUT_OF_RESOURCES
;
4001 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4002 if (mEndOpCodeHandle
== NULL
) {
4003 UninstallSecureBootConfigForm (PrivateData
);
4004 return EFI_OUT_OF_RESOURCES
;
4008 // Create Hii Extend Label OpCode as the start opcode
4010 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4014 sizeof (EFI_IFR_GUID_LABEL
)
4016 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4019 // Create Hii Extend Label OpCode as the end opcode
4021 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4025 sizeof (EFI_IFR_GUID_LABEL
)
4027 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4028 mEndLabel
->Number
= LABEL_END
;
4034 This function removes SecureBoot configuration Form.
4036 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4040 UninstallSecureBootConfigForm (
4041 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4045 // Uninstall HII package list
4047 if (PrivateData
->HiiHandle
!= NULL
) {
4048 HiiRemovePackages (PrivateData
->HiiHandle
);
4049 PrivateData
->HiiHandle
= NULL
;
4053 // Uninstall HII Config Access Protocol
4055 if (PrivateData
->DriverHandle
!= NULL
) {
4056 gBS
->UninstallMultipleProtocolInterfaces (
4057 PrivateData
->DriverHandle
,
4058 &gEfiDevicePathProtocolGuid
,
4059 &mSecureBootHiiVendorDevicePath
,
4060 &gEfiHiiConfigAccessProtocolGuid
,
4061 &PrivateData
->ConfigAccess
,
4064 PrivateData
->DriverHandle
= NULL
;
4067 if (PrivateData
->SignatureGUID
!= NULL
) {
4068 FreePool (PrivateData
->SignatureGUID
);
4071 if (PrivateData
->FileContext
!= NULL
) {
4072 FreePool (PrivateData
->FileContext
);
4075 FreePool (PrivateData
);
4077 if (mStartOpCodeHandle
!= NULL
) {
4078 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
4081 if (mEndOpCodeHandle
!= NULL
) {
4082 HiiFreeOpCodeHandle (mEndOpCodeHandle
);