2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2016, 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
;
52 BOOLEAN mIsSelectedSecureBootModeForm
= FALSE
;
53 BOOLEAN mIsSecureBootModeChanged
= FALSE
;
56 // OID ASN.1 Value for Hash Algorithms
58 UINT8 mHashOidValue
[] = {
59 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
60 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
64 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
67 HASH_TABLE mHash
[] = {
68 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
69 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
70 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
71 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
72 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
76 // Variable Definitions
78 UINT32 mPeCoffHeaderOffset
= 0;
79 WIN_CERTIFICATE
*mCertificate
= NULL
;
80 IMAGE_TYPE mImageType
;
81 UINT8
*mImageBase
= NULL
;
83 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
84 UINTN mImageDigestSize
;
86 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
87 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
90 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
92 CHAR16
* mDerEncodedSuffix
[] = {
98 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
101 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
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.
110 IsDerEncodeCertificate (
111 IN CONST CHAR16
*FileSuffix
115 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
116 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
124 Set Secure Boot option into variable space.
126 @param[in] VarValue The option of Secure Boot.
128 @retval EFI_SUCCESS The operation is finished successfully.
129 @retval Others Other errors as indicated.
133 SaveSecureBootVariable (
139 Status
= gRT
->SetVariable (
140 EFI_SECURE_BOOT_ENABLE_NAME
,
141 &gEfiSecureBootEnableDisableGuid
,
142 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
150 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
151 descriptor with the input data. NO authentication is required in this function.
153 @param[in, out] DataSize On input, the size of Data buffer in bytes.
154 On output, the size of data returned in Data
156 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
157 pointer to NULL to wrap an empty payload.
158 On output, Pointer to the new payload date buffer allocated from pool,
159 it's caller's responsibility to free the memory when finish using it.
161 @retval EFI_SUCCESS Create time based payload successfully.
162 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
163 @retval EFI_INVALID_PARAMETER The parameter is invalid.
164 @retval Others Unexpected error happens.
168 CreateTimeBasedPayload (
169 IN OUT UINTN
*DataSize
,
177 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
178 UINTN DescriptorSize
;
181 if (Data
== NULL
|| DataSize
== NULL
) {
182 return EFI_INVALID_PARAMETER
;
186 // In Setup mode or Custom mode, the variable does not need to be signed but the
187 // parameters to the SetVariable() call still need to be prepared as authenticated
188 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
192 PayloadSize
= *DataSize
;
194 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
195 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
196 if (NewData
== NULL
) {
197 return EFI_OUT_OF_RESOURCES
;
200 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
201 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
204 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
206 ZeroMem (&Time
, sizeof (EFI_TIME
));
207 Status
= gRT
->GetTime (&Time
, NULL
);
208 if (EFI_ERROR (Status
)) {
217 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
219 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
220 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
221 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
222 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
224 if (Payload
!= NULL
) {
228 *DataSize
= DescriptorSize
+ PayloadSize
;
234 Internal helper function to delete a Variable given its name and GUID, NO authentication
237 @param[in] VariableName Name of the Variable.
238 @param[in] VendorGuid GUID of the Variable.
240 @retval EFI_SUCCESS Variable deleted successfully.
241 @retval Others The driver failed to start the device.
246 IN CHAR16
*VariableName
,
247 IN EFI_GUID
*VendorGuid
256 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
257 if (Variable
== NULL
) {
264 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
265 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
267 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
268 if (EFI_ERROR (Status
)) {
269 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
273 Status
= gRT
->SetVariable (
288 Set the platform secure boot mode into "Custom" or "Standard" mode.
290 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
291 CUSTOM_SECURE_BOOT_MODE.
293 @return EFI_SUCCESS The platform has switched to the special mode successfully.
294 @return other Fail to operate the secure boot mode.
299 IN UINT8 SecureBootMode
302 return gRT
->SetVariable (
303 EFI_CUSTOM_MODE_NAME
,
304 &gEfiCustomModeEnableGuid
,
305 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
312 Generate the PK signature list from the X509 Certificate storing file (.cer)
314 @param[in] X509File FileHandle of X509 Certificate storing file.
315 @param[out] PkCert Point to the data buffer to store the signature list.
317 @return EFI_UNSUPPORTED Unsupported Key Length.
318 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
322 CreatePkX509SignatureList (
323 IN EFI_FILE_HANDLE X509File
,
324 OUT EFI_SIGNATURE_LIST
**PkCert
330 EFI_SIGNATURE_DATA
*PkCertData
;
336 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
337 if (EFI_ERROR (Status
)) {
340 ASSERT (X509Data
!= NULL
);
343 // Allocate space for PK certificate list and initialize it.
344 // Create PK database entry with SignatureHeaderSize equals 0.
346 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
347 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
350 if (*PkCert
== NULL
) {
351 Status
= EFI_OUT_OF_RESOURCES
;
355 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
356 + sizeof(EFI_SIGNATURE_DATA
) - 1
358 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
359 (*PkCert
)->SignatureHeaderSize
= 0;
360 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
361 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
362 + sizeof(EFI_SIGNATURE_LIST
)
363 + (*PkCert
)->SignatureHeaderSize
);
364 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
366 // Fill the PK database with PKpub data from X509 certificate file.
368 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
372 if (X509Data
!= NULL
) {
376 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
385 Enroll new PK into the System without original PK's authentication.
387 The SignatureOwner GUID will be the same with PK's vendorguid.
389 @param[in] PrivateData The module's private data.
391 @retval EFI_SUCCESS New PK enrolled successfully.
392 @retval EFI_INVALID_PARAMETER The parameter is invalid.
393 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
398 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
404 EFI_SIGNATURE_LIST
*PkCert
;
408 if (Private
->FileContext
->FileName
== NULL
) {
409 return EFI_INVALID_PARAMETER
;
414 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
415 if (EFI_ERROR (Status
)) {
420 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
422 NameLength
= StrLen (Private
->FileContext
->FileName
);
423 if (NameLength
<= 4) {
424 return EFI_INVALID_PARAMETER
;
426 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
427 if (!IsDerEncodeCertificate(FilePostFix
)) {
428 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
429 return EFI_INVALID_PARAMETER
;
431 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
432 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
435 // Prase the selected PK file and generature PK certificate list.
437 Status
= CreatePkX509SignatureList (
438 Private
->FileContext
->FHandle
,
441 if (EFI_ERROR (Status
)) {
444 ASSERT (PkCert
!= NULL
);
447 // Set Platform Key variable.
449 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
450 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
451 DataSize
= PkCert
->SignatureListSize
;
452 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
453 if (EFI_ERROR (Status
)) {
454 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
458 Status
= gRT
->SetVariable(
459 EFI_PLATFORM_KEY_NAME
,
460 &gEfiGlobalVariableGuid
,
465 if (EFI_ERROR (Status
)) {
466 if (Status
== EFI_OUT_OF_RESOURCES
) {
467 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
474 if (PkCert
!= NULL
) {
478 if (Private
->FileContext
->FHandle
!= NULL
) {
479 CloseFile (Private
->FileContext
->FHandle
);
480 Private
->FileContext
->FHandle
= NULL
;
487 Remove the PK variable.
489 @retval EFI_SUCCESS Delete PK successfully.
490 @retval Others Could not allow to delete PK.
500 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
501 if (EFI_ERROR (Status
)) {
505 Status
= DeleteVariable (
506 EFI_PLATFORM_KEY_NAME
,
507 &gEfiGlobalVariableGuid
513 Enroll a new KEK item from public key storing file (*.pbk).
515 @param[in] PrivateData The module's private data.
517 @retval EFI_SUCCESS New KEK enrolled successfully.
518 @retval EFI_INVALID_PARAMETER The parameter is invalid.
519 @retval EFI_UNSUPPORTED Unsupported command.
520 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
525 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
531 EFI_SIGNATURE_LIST
*KekSigList
;
534 CPL_KEY_INFO
*KeyInfo
;
535 EFI_SIGNATURE_DATA
*KEKSigData
;
536 UINTN KekSigListSize
;
551 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
552 // First, We have to parse out public key data from the pbk key file.
554 Status
= ReadFileContent (
555 Private
->FileContext
->FHandle
,
560 if (EFI_ERROR (Status
)) {
563 ASSERT (KeyBlob
!= NULL
);
564 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
565 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
566 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
567 Status
= EFI_UNSUPPORTED
;
572 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
574 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
575 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
576 if (KeyBuffer
== NULL
) {
577 Status
= EFI_OUT_OF_RESOURCES
;
581 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
582 KeyLenInBytes
/ sizeof (UINTN
),
586 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
589 // Form an new EFI_SIGNATURE_LIST.
591 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
592 + sizeof(EFI_SIGNATURE_DATA
) - 1
593 + WIN_CERT_UEFI_RSA2048_SIZE
;
595 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
596 if (KekSigList
== NULL
) {
597 Status
= EFI_OUT_OF_RESOURCES
;
601 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
602 + sizeof(EFI_SIGNATURE_DATA
) - 1
603 + WIN_CERT_UEFI_RSA2048_SIZE
;
604 KekSigList
->SignatureHeaderSize
= 0;
605 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
606 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
608 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
609 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
611 KEKSigData
->SignatureData
,
612 KeyBlob
+ sizeof(CPL_KEY_INFO
),
613 WIN_CERT_UEFI_RSA2048_SIZE
617 // Check if KEK entry has been already existed.
618 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
619 // new KEK to original variable.
621 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
622 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
623 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
624 if (EFI_ERROR (Status
)) {
625 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
629 Status
= gRT
->GetVariable(
630 EFI_KEY_EXCHANGE_KEY_NAME
,
631 &gEfiGlobalVariableGuid
,
636 if (Status
== EFI_BUFFER_TOO_SMALL
) {
637 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
638 } else if (Status
!= EFI_NOT_FOUND
) {
643 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
645 Status
= gRT
->SetVariable(
646 EFI_KEY_EXCHANGE_KEY_NAME
,
647 &gEfiGlobalVariableGuid
,
652 if (EFI_ERROR (Status
)) {
658 CloseFile (Private
->FileContext
->FHandle
);
659 Private
->FileContext
->FHandle
= NULL
;
660 Private
->FileContext
->FileName
= NULL
;
662 if (Private
->SignatureGUID
!= NULL
) {
663 FreePool (Private
->SignatureGUID
);
664 Private
->SignatureGUID
= NULL
;
667 if (KeyBlob
!= NULL
) {
670 if (KeyBuffer
!= NULL
) {
671 FreePool (KeyBuffer
);
673 if (KekSigList
!= NULL
) {
674 FreePool (KekSigList
);
681 Enroll a new KEK item from X509 certificate file.
683 @param[in] PrivateData The module's private data.
685 @retval EFI_SUCCESS New X509 is enrolled successfully.
686 @retval EFI_INVALID_PARAMETER The parameter is invalid.
687 @retval EFI_UNSUPPORTED Unsupported command.
688 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
693 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
699 EFI_SIGNATURE_DATA
*KEKSigData
;
700 EFI_SIGNATURE_LIST
*KekSigList
;
702 UINTN KekSigListSize
;
712 Status
= ReadFileContent (
713 Private
->FileContext
->FHandle
,
718 if (EFI_ERROR (Status
)) {
721 ASSERT (X509Data
!= NULL
);
723 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
724 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
725 if (KekSigList
== NULL
) {
726 Status
= EFI_OUT_OF_RESOURCES
;
731 // Fill Certificate Database parameters.
733 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
734 KekSigList
->SignatureHeaderSize
= 0;
735 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
736 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
738 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
739 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
740 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
743 // Check if KEK been already existed.
744 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
745 // new kek to original variable
747 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
748 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
749 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
750 if (EFI_ERROR (Status
)) {
751 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
755 Status
= gRT
->GetVariable(
756 EFI_KEY_EXCHANGE_KEY_NAME
,
757 &gEfiGlobalVariableGuid
,
762 if (Status
== EFI_BUFFER_TOO_SMALL
) {
763 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
764 } else if (Status
!= EFI_NOT_FOUND
) {
768 Status
= gRT
->SetVariable(
769 EFI_KEY_EXCHANGE_KEY_NAME
,
770 &gEfiGlobalVariableGuid
,
775 if (EFI_ERROR (Status
)) {
781 CloseFile (Private
->FileContext
->FHandle
);
782 Private
->FileContext
->FileName
= NULL
;
783 Private
->FileContext
->FHandle
= NULL
;
785 if (Private
->SignatureGUID
!= NULL
) {
786 FreePool (Private
->SignatureGUID
);
787 Private
->SignatureGUID
= NULL
;
790 if (KekSigList
!= NULL
) {
791 FreePool (KekSigList
);
798 Enroll new KEK into the System without PK's authentication.
799 The SignatureOwner GUID will be Private->SignatureGUID.
801 @param[in] PrivateData The module's private data.
803 @retval EFI_SUCCESS New KEK enrolled successful.
804 @retval EFI_INVALID_PARAMETER The parameter is invalid.
805 @retval others Fail to enroll KEK data.
809 EnrollKeyExchangeKey (
810 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
817 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
818 return EFI_INVALID_PARAMETER
;
821 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
822 if (EFI_ERROR (Status
)) {
827 // Parse the file's postfix. Supports DER-encoded X509 certificate,
828 // and .pbk as RSA public key file.
830 NameLength
= StrLen (Private
->FileContext
->FileName
);
831 if (NameLength
<= 4) {
832 return EFI_INVALID_PARAMETER
;
834 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
835 if (IsDerEncodeCertificate(FilePostFix
)) {
836 return EnrollX509ToKek (Private
);
837 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
838 return EnrollRsa2048ToKek (Private
);
840 return EFI_INVALID_PARAMETER
;
845 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
846 KEK's authentication.
848 @param[in] PrivateData The module's private data.
849 @param[in] VariableName Variable name of signature database, must be
850 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
852 @retval EFI_SUCCESS New X509 is enrolled successfully.
853 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
858 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
859 IN CHAR16
*VariableName
865 EFI_SIGNATURE_LIST
*SigDBCert
;
866 EFI_SIGNATURE_DATA
*SigDBCertData
;
877 SigDBCertData
= NULL
;
880 Status
= ReadFileContent (
881 Private
->FileContext
->FHandle
,
886 if (EFI_ERROR (Status
)) {
889 ASSERT (X509Data
!= NULL
);
891 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
893 Data
= AllocateZeroPool (SigDBSize
);
895 Status
= EFI_OUT_OF_RESOURCES
;
900 // Fill Certificate Database parameters.
902 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
903 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
904 SigDBCert
->SignatureHeaderSize
= 0;
905 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
906 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
908 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
909 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
910 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
913 // Check if signature database entry has been already existed.
914 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
915 // new signature data to original variable
917 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
918 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
919 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
920 if (EFI_ERROR (Status
)) {
921 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
925 Status
= gRT
->GetVariable(
927 &gEfiImageSecurityDatabaseGuid
,
932 if (Status
== EFI_BUFFER_TOO_SMALL
) {
933 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
934 } else if (Status
!= EFI_NOT_FOUND
) {
938 Status
= gRT
->SetVariable(
940 &gEfiImageSecurityDatabaseGuid
,
945 if (EFI_ERROR (Status
)) {
951 CloseFile (Private
->FileContext
->FHandle
);
952 Private
->FileContext
->FileName
= NULL
;
953 Private
->FileContext
->FHandle
= NULL
;
955 if (Private
->SignatureGUID
!= NULL
) {
956 FreePool (Private
->SignatureGUID
);
957 Private
->SignatureGUID
= NULL
;
964 if (X509Data
!= NULL
) {
972 Check whether signature is in specified database.
974 @param[in] VariableName Name of database variable that is searched in.
975 @param[in] Signature Pointer to signature that is searched for.
976 @param[in] SignatureSize Size of Signature.
978 @return TRUE Found the signature in the variable database.
979 @return FALSE Not found the signature in the variable database.
983 IsSignatureFoundInDatabase (
984 IN CHAR16
*VariableName
,
986 IN UINTN SignatureSize
990 EFI_SIGNATURE_LIST
*CertList
;
991 EFI_SIGNATURE_DATA
*Cert
;
999 // Read signature database variable.
1004 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1005 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1009 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1014 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1015 if (EFI_ERROR (Status
)) {
1020 // Enumerate all signature data in SigDB to check if executable's signature exists.
1022 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1023 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1024 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1025 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1026 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1027 for (Index
= 0; Index
< CertCount
; Index
++) {
1028 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1030 // Find the signature in database.
1035 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1043 DataSize
-= CertList
->SignatureListSize
;
1044 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1056 Calculate the hash of a certificate data with the specified hash algorithm.
1058 @param[in] CertData The certificate data to be hashed.
1059 @param[in] CertSize The certificate size in bytes.
1060 @param[in] HashAlg The specified hash algorithm.
1061 @param[out] CertHash The output digest of the certificate
1063 @retval TRUE Successfully got the hash of the CertData.
1064 @retval FALSE Failed to get the hash of CertData.
1084 if (HashAlg
>= HASHALG_MAX
) {
1089 // Retrieve the TBSCertificate for Hash Calculation.
1091 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1096 // 1. Initialize context of hash.
1098 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1099 HashCtx
= AllocatePool (CtxSize
);
1100 ASSERT (HashCtx
!= NULL
);
1103 // 2. Initialize a hash context.
1105 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1111 // 3. Calculate the hash.
1113 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1119 // 4. Get the hash result.
1121 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1122 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1125 if (HashCtx
!= NULL
) {
1133 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1135 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1136 @param[in] CertSize Size of X.509 Certificate.
1138 @return TRUE Found the certificate hash in the forbidden database.
1139 @return FALSE Certificate hash is Not found in the forbidden database.
1143 IsCertHashFoundInDbx (
1144 IN UINT8
*Certificate
,
1150 EFI_SIGNATURE_LIST
*DbxList
;
1151 EFI_SIGNATURE_DATA
*CertHash
;
1152 UINTN CertHashCount
;
1155 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1157 UINTN SiglistHeaderSize
;
1162 HashAlg
= HASHALG_MAX
;
1166 // Read signature database variable.
1169 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1170 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1174 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1179 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1180 if (EFI_ERROR (Status
)) {
1185 // Check whether the certificate hash exists in the forbidden database.
1187 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1188 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1190 // Determine Hash Algorithm of Certificate in the forbidden database.
1192 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1193 HashAlg
= HASHALG_SHA256
;
1194 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1195 HashAlg
= HASHALG_SHA384
;
1196 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1197 HashAlg
= HASHALG_SHA512
;
1199 DataSize
-= DbxList
->SignatureListSize
;
1200 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1205 // Calculate the hash value of current db certificate for comparision.
1207 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1211 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1212 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1213 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1214 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1216 // Iterate each Signature Data Node within this CertList for verify.
1218 DbxCertHash
= CertHash
->SignatureData
;
1219 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1221 // Hash of Certificate is found in forbidden database.
1226 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1229 DataSize
-= DbxList
->SignatureListSize
;
1230 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1242 Check whether the signature list exists in given variable data.
1244 It searches the signature list for the ceritificate hash by CertType.
1245 If the signature list is found, get the offset of Database for the
1246 next hash of a certificate.
1248 @param[in] Database Variable data to save signature list.
1249 @param[in] DatabaseSize Variable size.
1250 @param[in] SignatureType The type of the signature.
1251 @param[out] Offset The offset to save a new hash of certificate.
1253 @return TRUE The signature list is found in the forbidden database.
1254 @return FALSE The signature list is not found in the forbidden database.
1257 GetSignaturelistOffset (
1258 IN EFI_SIGNATURE_LIST
*Database
,
1259 IN UINTN DatabaseSize
,
1260 IN EFI_GUID
*SignatureType
,
1264 EFI_SIGNATURE_LIST
*SigList
;
1267 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1273 SiglistSize
= DatabaseSize
;
1274 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1275 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1276 *Offset
= DatabaseSize
- SiglistSize
;
1279 SiglistSize
-= SigList
->SignatureListSize
;
1280 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1287 Enroll a new X509 certificate hash into Signature Database (dbx) without
1288 KEK's authentication.
1290 @param[in] PrivateData The module's private data.
1291 @param[in] HashAlg The hash algorithm to enroll the certificate.
1292 @param[in] RevocationDate The revocation date of the certificate.
1293 @param[in] RevocationTime The revocation time of the certificate.
1294 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1296 @retval EFI_SUCCESS New X509 is enrolled successfully.
1297 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1298 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1302 EnrollX509HashtoSigDB (
1303 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1305 IN EFI_HII_DATE
*RevocationDate
,
1306 IN EFI_HII_TIME
*RevocationTime
,
1307 IN BOOLEAN AlwaysRevocation
1313 EFI_SIGNATURE_LIST
*SignatureList
;
1314 UINTN SignatureListSize
;
1320 EFI_SIGNATURE_DATA
*SignatureData
;
1321 UINTN SignatureSize
;
1322 EFI_GUID SignatureType
;
1324 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1325 UINT16
* FilePostFix
;
1332 SignatureData
= NULL
;
1333 SignatureList
= NULL
;
1337 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1338 return EFI_INVALID_PARAMETER
;
1341 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1342 if (EFI_ERROR (Status
)) {
1347 // Parse the file's postfix.
1349 NameLength
= StrLen (Private
->FileContext
->FileName
);
1350 if (NameLength
<= 4) {
1351 return EFI_INVALID_PARAMETER
;
1353 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1354 if (!IsDerEncodeCertificate(FilePostFix
)) {
1356 // Only supports DER-encoded X509 certificate.
1358 return EFI_INVALID_PARAMETER
;
1362 // Get the certificate from file and calculate its hash.
1364 Status
= ReadFileContent (
1365 Private
->FileContext
->FHandle
,
1370 if (EFI_ERROR (Status
)) {
1373 ASSERT (X509Data
!= NULL
);
1375 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1380 // Get the variable for enrollment.
1383 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1384 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1385 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1387 return EFI_OUT_OF_RESOURCES
;
1390 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1391 if (EFI_ERROR (Status
)) {
1397 // Allocate memory for Signature and fill the Signature
1399 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1400 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1401 if (SignatureData
== NULL
) {
1402 return EFI_OUT_OF_RESOURCES
;
1404 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1405 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1410 if (!AlwaysRevocation
) {
1411 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1412 Time
->Year
= RevocationDate
->Year
;
1413 Time
->Month
= RevocationDate
->Month
;
1414 Time
->Day
= RevocationDate
->Day
;
1415 Time
->Hour
= RevocationTime
->Hour
;
1416 Time
->Minute
= RevocationTime
->Minute
;
1417 Time
->Second
= RevocationTime
->Second
;
1421 // Determine the GUID for certificate hash.
1424 case HASHALG_SHA256
:
1425 SignatureType
= gEfiCertX509Sha256Guid
;
1427 case HASHALG_SHA384
:
1428 SignatureType
= gEfiCertX509Sha384Guid
;
1430 case HASHALG_SHA512
:
1431 SignatureType
= gEfiCertX509Sha512Guid
;
1438 // Add signature into the new variable data buffer
1440 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1442 // Add the signature to the found signaturelist.
1444 DbSize
= DataSize
+ SignatureSize
;
1445 NewData
= AllocateZeroPool (DbSize
);
1446 if (NewData
== NULL
) {
1447 Status
= EFI_OUT_OF_RESOURCES
;
1451 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1452 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1453 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1455 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1456 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1458 Offset
+= SignatureListSize
;
1459 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1460 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1467 // Create a new signaturelist, and add the signature into the signaturelist.
1469 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1470 NewData
= AllocateZeroPool (DbSize
);
1471 if (NewData
== NULL
) {
1472 Status
= EFI_OUT_OF_RESOURCES
;
1476 // Fill Certificate Database parameters.
1478 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1479 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1480 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1481 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1482 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1483 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1484 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1485 CopyMem (NewData
, Data
, DataSize
);
1492 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1493 if (EFI_ERROR (Status
)) {
1497 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1498 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1499 Status
= gRT
->SetVariable(
1500 EFI_IMAGE_SECURITY_DATABASE1
,
1501 &gEfiImageSecurityDatabaseGuid
,
1506 if (EFI_ERROR (Status
)) {
1511 CloseFile (Private
->FileContext
->FHandle
);
1512 Private
->FileContext
->FileName
= NULL
;
1513 Private
->FileContext
->FHandle
= NULL
;
1515 if (Private
->SignatureGUID
!= NULL
) {
1516 FreePool (Private
->SignatureGUID
);
1517 Private
->SignatureGUID
= NULL
;
1524 if (SignatureData
!= NULL
) {
1525 FreePool (SignatureData
);
1528 if (X509Data
!= NULL
) {
1529 FreePool (X509Data
);
1536 Check whether a certificate from a file exists in dbx.
1538 @param[in] PrivateData The module's private data.
1539 @param[in] VariableName Variable name of signature database, must be
1540 EFI_IMAGE_SECURITY_DATABASE1.
1542 @retval TRUE The X509 certificate is found in dbx successfully.
1543 @retval FALSE The X509 certificate is not found in dbx.
1547 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1548 IN CHAR16
*VariableName
1557 // Read the certificate from file
1561 Status
= ReadFileContent (
1562 Private
->FileContext
->FHandle
,
1567 if (EFI_ERROR (Status
)) {
1572 // Check the raw certificate.
1575 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1581 // Check the hash of certificate.
1583 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1589 if (X509Data
!= NULL
) {
1590 FreePool (X509Data
);
1597 Load PE/COFF image information into internal buffer and check its validity.
1599 @retval EFI_SUCCESS Successful
1600 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1601 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1609 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1610 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1611 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1616 // Read the Dos header
1618 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1619 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1622 // DOS image header is present,
1623 // So read the PE header after the DOS image header
1625 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1629 mPeCoffHeaderOffset
= 0;
1633 // Read PE header and check the signature validity and machine compatibility
1635 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1636 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1638 return EFI_UNSUPPORTED
;
1641 mNtHeader
.Pe32
= NtHeader32
;
1644 // Check the architecture field of PE header and get the Certificate Data Directory data
1645 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1647 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1648 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1649 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1651 // 32-bits Architecture
1653 mImageType
= ImageType_IA32
;
1654 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1656 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1657 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1658 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1660 // 64-bits Architecture
1662 mImageType
= ImageType_X64
;
1663 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1664 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1666 return EFI_UNSUPPORTED
;
1673 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1674 PE/COFF Specification 8.0 Appendix A
1676 @param[in] HashAlg Hash algorithm type.
1678 @retval TRUE Successfully hash image.
1679 @retval FALSE Fail in hash image.
1689 EFI_IMAGE_SECTION_HEADER
*Section
;
1694 UINTN SumOfBytesHashed
;
1695 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1700 SectionHeader
= NULL
;
1703 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1708 // Initialize context of hash.
1710 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1712 if (HashAlg
== HASHALG_SHA1
) {
1713 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1714 mCertType
= gEfiCertSha1Guid
;
1715 } else if (HashAlg
== HASHALG_SHA256
) {
1716 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1717 mCertType
= gEfiCertSha256Guid
;
1720 CtxSize
= mHash
[HashAlg
].GetContextSize();
1722 HashCtx
= AllocatePool (CtxSize
);
1723 ASSERT (HashCtx
!= NULL
);
1725 // 1. Load the image header into memory.
1727 // 2. Initialize a SHA hash context.
1728 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1733 // Measuring PE/COFF Image Header;
1734 // But CheckSum field and SECURITY data directory (certificate) are excluded
1736 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1738 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1739 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1740 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1741 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1743 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1746 // Get the magic value from the PE/COFF Optional Header
1748 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1752 // 3. Calculate the distance from the base of the image header to the image checksum address.
1753 // 4. Hash the image header from its base to beginning of the image checksum.
1755 HashBase
= mImageBase
;
1756 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1760 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1763 // Use PE32+ offset.
1765 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1768 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1773 // 5. Skip over the image checksum (it occupies a single ULONG).
1774 // 6. Get the address of the beginning of the Cert Directory.
1775 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1777 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1781 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1782 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1785 // Use PE32+ offset.
1787 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1788 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1791 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1796 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1797 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1799 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1803 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1804 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1807 // Use PE32+ offset.
1809 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1810 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1813 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1818 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1820 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1824 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1829 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1833 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1834 // structures in the image. The 'NumberOfSections' field of the image
1835 // header indicates how big the table should be. Do not include any
1836 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1838 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1839 ASSERT (SectionHeader
!= NULL
);
1841 // 12. Using the 'PointerToRawData' in the referenced section headers as
1842 // a key, arrange the elements in the table in ascending order. In other
1843 // words, sort the section headers according to the disk-file offset of
1846 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1848 mPeCoffHeaderOffset
+
1850 sizeof (EFI_IMAGE_FILE_HEADER
) +
1851 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1853 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1855 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1856 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1859 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1864 // 13. Walk through the sorted table, bring the corresponding section
1865 // into memory, and hash the entire section (using the 'SizeOfRawData'
1866 // field in the section header to determine the amount of data to hash).
1867 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1868 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1870 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1871 Section
= &SectionHeader
[Index
];
1872 if (Section
->SizeOfRawData
== 0) {
1875 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1876 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1878 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1883 SumOfBytesHashed
+= HashSize
;
1887 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1888 // data in the file that needs to be added to the hash. This data begins
1889 // at file offset SUM_OF_BYTES_HASHED and its length is:
1890 // FileSize - (CertDirectory->Size)
1892 if (mImageSize
> SumOfBytesHashed
) {
1893 HashBase
= mImageBase
+ SumOfBytesHashed
;
1894 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1900 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1904 // Use PE32+ offset.
1908 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1912 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1918 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1921 if (HashCtx
!= NULL
) {
1924 if (SectionHeader
!= NULL
) {
1925 FreePool (SectionHeader
);
1931 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
1932 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1935 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1936 @retval EFI_SUCCESS Hash successfully.
1945 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1947 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1949 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1951 // Check the Hash algorithm in PE/COFF Authenticode.
1952 // According to PKCS#7 Definition:
1953 // SignedData ::= SEQUENCE {
1955 // digestAlgorithms DigestAlgorithmIdentifiers,
1956 // contentInfo ContentInfo,
1958 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1959 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1960 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1962 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1964 // Only support two bytes of Long Form of Length Encoding.
1970 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1975 if (Index
== HASHALG_MAX
) {
1976 return EFI_UNSUPPORTED
;
1980 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1982 if (!HashPeImage(Index
)) {
1983 return EFI_UNSUPPORTED
;
1990 Enroll a new executable's signature into Signature Database.
1992 @param[in] PrivateData The module's private data.
1993 @param[in] VariableName Variable name of signature database, must be
1994 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
1995 or EFI_IMAGE_SECURITY_DATABASE2.
1997 @retval EFI_SUCCESS New signature is enrolled successfully.
1998 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1999 @retval EFI_UNSUPPORTED Unsupported command.
2000 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2004 EnrollImageSignatureToSigDB (
2005 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2006 IN CHAR16
*VariableName
2010 EFI_SIGNATURE_LIST
*SigDBCert
;
2011 EFI_SIGNATURE_DATA
*SigDBCertData
;
2016 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2019 GuidCertData
= NULL
;
2021 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2022 return EFI_UNSUPPORTED
;
2026 // Form the SigDB certificate list.
2027 // Format the data item into EFI_SIGNATURE_LIST type.
2029 // We need to parse executable's signature data from specified signed executable file.
2030 // In current implementation, we simply trust the pass-in signed executable file.
2031 // In reality, it's OS's responsibility to verify the signed executable file.
2035 // Read the whole file content
2037 Status
= ReadFileContent(
2038 Private
->FileContext
->FHandle
,
2039 (VOID
**) &mImageBase
,
2043 if (EFI_ERROR (Status
)) {
2046 ASSERT (mImageBase
!= NULL
);
2048 Status
= LoadPeImage ();
2049 if (EFI_ERROR (Status
)) {
2053 if (mSecDataDir
->SizeOfCert
== 0) {
2054 if (!HashPeImage (HASHALG_SHA256
)) {
2055 Status
= EFI_SECURITY_VIOLATION
;
2061 // Read the certificate data
2063 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2065 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2066 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2067 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2068 Status
= EFI_ABORTED
;
2072 if (!HashPeImage (HASHALG_SHA256
)) {
2073 Status
= EFI_ABORTED
;
2077 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2079 Status
= HashPeImageByType ();
2080 if (EFI_ERROR (Status
)) {
2084 Status
= EFI_ABORTED
;
2090 // Create a new SigDB entry.
2092 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2093 + sizeof(EFI_SIGNATURE_DATA
) - 1
2094 + (UINT32
) mImageDigestSize
;
2096 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2098 Status
= EFI_OUT_OF_RESOURCES
;
2103 // Adjust the Certificate Database parameters.
2105 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2106 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2107 SigDBCert
->SignatureHeaderSize
= 0;
2108 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2109 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2111 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2112 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2113 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2115 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2116 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2117 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2118 if (EFI_ERROR (Status
)) {
2119 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2124 // Check if SigDB variable has been already existed.
2125 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2126 // new signature data to original variable
2129 Status
= gRT
->GetVariable(
2131 &gEfiImageSecurityDatabaseGuid
,
2136 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2137 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2138 } else if (Status
!= EFI_NOT_FOUND
) {
2143 // Enroll the variable.
2145 Status
= gRT
->SetVariable(
2147 &gEfiImageSecurityDatabaseGuid
,
2152 if (EFI_ERROR (Status
)) {
2158 CloseFile (Private
->FileContext
->FHandle
);
2159 Private
->FileContext
->FHandle
= NULL
;
2160 Private
->FileContext
->FileName
= NULL
;
2162 if (Private
->SignatureGUID
!= NULL
) {
2163 FreePool (Private
->SignatureGUID
);
2164 Private
->SignatureGUID
= NULL
;
2171 if (mImageBase
!= NULL
) {
2172 FreePool (mImageBase
);
2180 Enroll signature into DB/DBX/DBT without KEK's authentication.
2181 The SignatureOwner GUID will be Private->SignatureGUID.
2183 @param[in] PrivateData The module's private data.
2184 @param[in] VariableName Variable name of signature database, must be
2185 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2187 @retval EFI_SUCCESS New signature enrolled successfully.
2188 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2189 @retval others Fail to enroll signature data.
2193 EnrollSignatureDatabase (
2194 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2195 IN CHAR16
*VariableName
2198 UINT16
* FilePostFix
;
2202 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2203 return EFI_INVALID_PARAMETER
;
2206 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2207 if (EFI_ERROR (Status
)) {
2212 // Parse the file's postfix.
2214 NameLength
= StrLen (Private
->FileContext
->FileName
);
2215 if (NameLength
<= 4) {
2216 return EFI_INVALID_PARAMETER
;
2218 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2219 if (IsDerEncodeCertificate (FilePostFix
)) {
2221 // Supports DER-encoded X509 certificate.
2223 return EnrollX509toSigDB (Private
, VariableName
);
2226 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2230 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2231 by GUID in the page for user to select and delete as needed.
2233 @param[in] PrivateData Module's private data.
2234 @param[in] VariableName The variable name of the vendor's signature database.
2235 @param[in] VendorGuid A unique identifier for the vendor.
2236 @param[in] LabelNumber Label number to insert opcodes.
2237 @param[in] FormId Form ID of current page.
2238 @param[in] QuestionIdBase Base question id of the signature list.
2240 @retval EFI_SUCCESS Success to update the signature list page
2241 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2246 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2247 IN CHAR16
*VariableName
,
2248 IN EFI_GUID
*VendorGuid
,
2249 IN UINT16 LabelNumber
,
2250 IN EFI_FORM_ID FormId
,
2251 IN EFI_QUESTION_ID QuestionIdBase
2258 VOID
*StartOpCodeHandle
;
2259 VOID
*EndOpCodeHandle
;
2260 EFI_IFR_GUID_LABEL
*StartLabel
;
2261 EFI_IFR_GUID_LABEL
*EndLabel
;
2264 EFI_SIGNATURE_LIST
*CertList
;
2265 EFI_SIGNATURE_DATA
*Cert
;
2266 UINT32 ItemDataSize
;
2268 EFI_STRING_ID GuidID
;
2275 StartOpCodeHandle
= NULL
;
2276 EndOpCodeHandle
= NULL
;
2279 // Initialize the container for dynamic opcodes.
2281 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2282 if (StartOpCodeHandle
== NULL
) {
2283 Status
= EFI_OUT_OF_RESOURCES
;
2287 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2288 if (EndOpCodeHandle
== NULL
) {
2289 Status
= EFI_OUT_OF_RESOURCES
;
2294 // Create Hii Extend Label OpCode.
2296 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2300 sizeof (EFI_IFR_GUID_LABEL
)
2302 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2303 StartLabel
->Number
= LabelNumber
;
2305 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2309 sizeof (EFI_IFR_GUID_LABEL
)
2311 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2312 EndLabel
->Number
= LABEL_END
;
2318 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2319 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2323 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2325 Status
= EFI_OUT_OF_RESOURCES
;
2329 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2330 if (EFI_ERROR (Status
)) {
2334 GuidStr
= AllocateZeroPool (100);
2335 if (GuidStr
== NULL
) {
2336 Status
= EFI_OUT_OF_RESOURCES
;
2341 // Enumerate all KEK pub data.
2343 ItemDataSize
= (UINT32
) DataSize
;
2344 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2347 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2349 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2350 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2351 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2352 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2353 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2354 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2355 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2356 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2357 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2358 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2359 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2360 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2361 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2362 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2365 // The signature type is not supported in current implementation.
2367 ItemDataSize
-= CertList
->SignatureListSize
;
2368 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2372 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2373 for (Index
= 0; Index
< CertCount
; Index
++) {
2374 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2375 + sizeof (EFI_SIGNATURE_LIST
)
2376 + CertList
->SignatureHeaderSize
2377 + Index
* CertList
->SignatureSize
);
2379 // Display GUID and help
2381 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2382 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2383 HiiCreateCheckBoxOpCode (
2385 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2390 EFI_IFR_FLAG_CALLBACK
,
2396 ItemDataSize
-= CertList
->SignatureListSize
;
2397 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2402 PrivateData
->HiiHandle
,
2403 &gSecureBootConfigFormSetGuid
,
2409 if (StartOpCodeHandle
!= NULL
) {
2410 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2413 if (EndOpCodeHandle
!= NULL
) {
2414 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2421 if (GuidStr
!= NULL
) {
2429 Delete a KEK entry from KEK database.
2431 @param[in] PrivateData Module's private data.
2432 @param[in] QuestionId Question id of the KEK item to delete.
2434 @retval EFI_SUCCESS Delete kek item successfully.
2435 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2439 DeleteKeyExchangeKey (
2440 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2441 IN EFI_QUESTION_ID QuestionId
2450 EFI_SIGNATURE_LIST
*CertList
;
2451 EFI_SIGNATURE_LIST
*NewCertList
;
2452 EFI_SIGNATURE_DATA
*Cert
;
2455 BOOLEAN IsKEKItemFound
;
2457 UINTN DeleteKekIndex
;
2465 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2467 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2468 if (EFI_ERROR (Status
)) {
2473 // Get original KEK variable.
2476 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2477 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2481 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2482 if (OldData
== NULL
) {
2483 Status
= EFI_OUT_OF_RESOURCES
;
2487 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2488 if (EFI_ERROR(Status
)) {
2493 // Allocate space for new variable.
2495 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2497 Status
= EFI_OUT_OF_RESOURCES
;
2502 // Enumerate all KEK pub data and erasing the target item.
2504 IsKEKItemFound
= FALSE
;
2505 KekDataSize
= (UINT32
) DataSize
;
2506 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2509 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2510 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2511 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2512 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2513 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2514 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2515 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2516 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2517 for (Index
= 0; Index
< CertCount
; Index
++) {
2518 if (GuidIndex
== DeleteKekIndex
) {
2520 // Find it! Skip it!
2522 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2523 IsKEKItemFound
= TRUE
;
2526 // This item doesn't match. Copy it to the Data buffer.
2528 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2529 Offset
+= CertList
->SignatureSize
;
2532 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2536 // This List doesn't match. Copy it to the Data buffer.
2538 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2539 Offset
+= CertList
->SignatureListSize
;
2542 KekDataSize
-= CertList
->SignatureListSize
;
2543 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2546 if (!IsKEKItemFound
) {
2548 // Doesn't find the Kek Item!
2550 Status
= EFI_NOT_FOUND
;
2555 // Delete the Signature header if there is no signature in the list.
2557 KekDataSize
= Offset
;
2558 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2560 ZeroMem (OldData
, KekDataSize
);
2561 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2562 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2563 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2564 if (CertCount
!= 0) {
2565 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2566 Offset
+= CertList
->SignatureListSize
;
2568 KekDataSize
-= CertList
->SignatureListSize
;
2569 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2573 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2574 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2575 if (EFI_ERROR (Status
)) {
2576 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2581 Status
= gRT
->SetVariable(
2582 EFI_KEY_EXCHANGE_KEY_NAME
,
2583 &gEfiGlobalVariableGuid
,
2588 if (EFI_ERROR (Status
)) {
2589 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2598 if (OldData
!= NULL
) {
2602 return UpdateDeletePage (
2604 EFI_KEY_EXCHANGE_KEY_NAME
,
2605 &gEfiGlobalVariableGuid
,
2607 FORMID_DELETE_KEK_FORM
,
2608 OPTION_DEL_KEK_QUESTION_ID
2613 Delete a signature entry from siganture database.
2615 @param[in] PrivateData Module's private data.
2616 @param[in] VariableName The variable name of the vendor's signature database.
2617 @param[in] VendorGuid A unique identifier for the vendor.
2618 @param[in] LabelNumber Label number to insert opcodes.
2619 @param[in] FormId Form ID of current page.
2620 @param[in] QuestionIdBase Base question id of the signature list.
2621 @param[in] DeleteIndex Signature index to delete.
2623 @retval EFI_SUCCESS Delete siganture successfully.
2624 @retval EFI_NOT_FOUND Can't find the signature item,
2625 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2629 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2630 IN CHAR16
*VariableName
,
2631 IN EFI_GUID
*VendorGuid
,
2632 IN UINT16 LabelNumber
,
2633 IN EFI_FORM_ID FormId
,
2634 IN EFI_QUESTION_ID QuestionIdBase
,
2635 IN UINTN DeleteIndex
2644 EFI_SIGNATURE_LIST
*CertList
;
2645 EFI_SIGNATURE_LIST
*NewCertList
;
2646 EFI_SIGNATURE_DATA
*Cert
;
2649 BOOLEAN IsItemFound
;
2650 UINT32 ItemDataSize
;
2659 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2660 if (EFI_ERROR (Status
)) {
2665 // Get original signature list data.
2668 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2669 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2673 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2674 if (OldData
== NULL
) {
2675 Status
= EFI_OUT_OF_RESOURCES
;
2679 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2680 if (EFI_ERROR(Status
)) {
2685 // Allocate space for new variable.
2687 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2689 Status
= EFI_OUT_OF_RESOURCES
;
2694 // Enumerate all signature data and erasing the target item.
2696 IsItemFound
= FALSE
;
2697 ItemDataSize
= (UINT32
) DataSize
;
2698 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2701 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2702 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2703 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2704 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2705 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2706 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2707 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2708 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2711 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2713 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2714 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2715 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2716 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2717 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2718 for (Index
= 0; Index
< CertCount
; Index
++) {
2719 if (GuidIndex
== DeleteIndex
) {
2721 // Find it! Skip it!
2723 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2727 // This item doesn't match. Copy it to the Data buffer.
2729 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2730 Offset
+= CertList
->SignatureSize
;
2733 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2737 // This List doesn't match. Just copy it to the Data buffer.
2739 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2740 Offset
+= CertList
->SignatureListSize
;
2743 ItemDataSize
-= CertList
->SignatureListSize
;
2744 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2749 // Doesn't find the signature Item!
2751 Status
= EFI_NOT_FOUND
;
2756 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2758 ItemDataSize
= Offset
;
2759 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2761 ZeroMem (OldData
, ItemDataSize
);
2762 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2763 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2764 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2765 if (CertCount
!= 0) {
2766 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2767 Offset
+= CertList
->SignatureListSize
;
2769 ItemDataSize
-= CertList
->SignatureListSize
;
2770 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2774 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2775 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2776 if (EFI_ERROR (Status
)) {
2777 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2782 Status
= gRT
->SetVariable(
2789 if (EFI_ERROR (Status
)) {
2790 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2799 if (OldData
!= NULL
) {
2803 return UpdateDeletePage (
2814 Perform secure boot mode transition from User Mode by setting AuditMode
2815 or DeployedMode variable.
2817 @param[in] NewMode New secure boot mode.
2819 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2822 TransitionFromUserMode(
2829 if (NewMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
2831 Status
= gRT
->SetVariable(
2832 EFI_AUDIT_MODE_NAME
,
2833 &gEfiGlobalVariableGuid
,
2834 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2839 } else if (NewMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
2841 Status
= gRT
->SetVariable(
2842 EFI_DEPLOYED_MODE_NAME
,
2843 &gEfiGlobalVariableGuid
,
2844 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2852 // Other case do nothing here. May Goto enroll PK page.
2858 Perform secure boot mode transition from Setup Mode by setting AuditMode
2861 @param[in] NewMode New secure boot mode.
2863 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2866 TransitionFromSetupMode(
2873 Status
= EFI_INVALID_PARAMETER
;
2875 if (NewMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
2877 Status
= gRT
->SetVariable(
2878 EFI_AUDIT_MODE_NAME
,
2879 &gEfiGlobalVariableGuid
,
2880 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2888 // Other case do nothing here. May Goto enroll PK page.
2894 Perform secure boot mode transition from Audit Mode. Nothing is done here,
2895 should goto enroll PK page.
2897 @param[in] NewMode New secure boot mode.
2899 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2902 TransitionFromAuditMode(
2907 // Other case do nothing here. Should Goto enroll PK page.
2913 Perform secure boot mode transition from Deployed Mode by setting Deployed Mode
2916 @param[in] NewMode New secure boot mode.
2918 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2921 TransitionFromDeployedMode(
2929 // Platform specific logic. when physical presence, Allow to set DeployedMode =:0
2930 // to switch back to UserMode
2932 if (NewMode
== SECURE_BOOT_MODE_USER_MODE
) {
2934 Status
= gRT
->SetVariable(
2935 EFI_DEPLOYED_MODE_NAME
,
2936 &gEfiGlobalVariableGuid
,
2937 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2941 DEBUG((EFI_D_INFO
, "DeployedMode Status %x\n", Status
));
2948 Perform main secure boot mode transition.
2950 @param[in] CurMode New secure boot mode.
2951 @param[in] NewMode New secure boot mode.
2953 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2956 SecureBootModeTransition(
2964 // Set platform to be customized mode to ensure platform specific mode switch sucess
2966 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2967 if (EFI_ERROR (Status
)) {
2972 // SecureBootMode transition
2975 case SECURE_BOOT_MODE_USER_MODE
:
2976 Status
= TransitionFromUserMode(NewMode
);
2979 case SECURE_BOOT_MODE_SETUP_MODE
:
2980 Status
= TransitionFromSetupMode(NewMode
);
2983 case SECURE_BOOT_MODE_AUDIT_MODE
:
2984 Status
= TransitionFromAuditMode(NewMode
);
2987 case SECURE_BOOT_MODE_DEPLOYED_MODE
:
2988 Status
= TransitionFromDeployedMode(NewMode
);
2992 Status
= EFI_INVALID_PARAMETER
;
3000 Get current secure boot mode by retrieve data from SetupMode/AuditMode/DeployedMode.
3002 @param[out] SecureBootMode Current secure boot mode.
3006 ExtractSecureBootModeFromVariable(
3007 OUT UINT8
*SecureBootMode
3012 UINT8
*DeployedMode
;
3016 DeployedMode
= NULL
;
3019 // Get AuditMode/DeployedMode from variable
3021 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3022 GetVariable2 (EFI_AUDIT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&AuditMode
, NULL
);
3023 GetVariable2 (EFI_DEPLOYED_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&DeployedMode
, NULL
);
3024 if (SetupMode
!= NULL
&& AuditMode
!= NULL
&& DeployedMode
!= NULL
) {
3025 if (*SetupMode
== 0 && *AuditMode
== 0 && *DeployedMode
== 0) {
3029 *SecureBootMode
= SECURE_BOOT_MODE_USER_MODE
;
3030 } else if (*SetupMode
== 1 && *AuditMode
== 0 && *DeployedMode
== 0) {
3034 *SecureBootMode
= SECURE_BOOT_MODE_SETUP_MODE
;
3035 } else if (*SetupMode
== 1 && *AuditMode
== 1 && *DeployedMode
== 0) {
3039 *SecureBootMode
= SECURE_BOOT_MODE_AUDIT_MODE
;
3040 } else if (*SetupMode
== 0 && *AuditMode
== 0 && *DeployedMode
== 1) {
3044 *SecureBootMode
= SECURE_BOOT_MODE_DEPLOYED_MODE
;
3052 if (SetupMode
!= NULL
) {
3053 FreePool (SetupMode
);
3055 if (DeployedMode
!= NULL
) {
3056 FreePool (DeployedMode
);
3058 if (AuditMode
!= NULL
) {
3059 FreePool (AuditMode
);
3065 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3066 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3068 @param[in] PrivateData Module's private data.
3070 @return EFI_SUCCESS Update secure boot strings successfully.
3071 @return other Fail to update secure boot strings.
3075 UpdateSecureBootString(
3076 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3078 UINT8 CurSecureBootMode
;
3084 // Get current secure boot state.
3086 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3087 if (SecureBoot
== NULL
) {
3088 return EFI_NOT_FOUND
;
3091 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3092 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3094 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3097 // Get current secure boot mode.
3099 ExtractSecureBootModeFromVariable(&CurSecureBootMode
);
3101 if (CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
) {
3102 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"UserMode", NULL
);
3103 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
) {
3104 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"SetupMode", NULL
);
3105 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3106 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"AuditMode", NULL
);
3107 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3108 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"DeployedMode", NULL
);
3111 FreePool(SecureBoot
);
3117 This function extracts configuration from variable.
3119 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3123 SecureBootExtractConfigFromVariable (
3124 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3127 UINT8
*SecureBootEnable
;
3128 UINT8
*SecureBootMode
;
3131 SecureBootEnable
= NULL
;
3132 SecureBootMode
= NULL
;
3135 // Initilize the Date and Time using system time.
3137 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3138 ConfigData
->AlwaysRevocation
= TRUE
;
3139 gRT
->GetTime (&CurrTime
, NULL
);
3140 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3141 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3142 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3143 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3144 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3145 ConfigData
->RevocationTime
.Second
= 0;
3148 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3151 ConfigData
->AttemptSecureBoot
= FALSE
;
3152 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3153 if (SecureBootEnable
== NULL
) {
3154 ConfigData
->HideSecureBoot
= TRUE
;
3156 ConfigData
->HideSecureBoot
= FALSE
;
3157 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
3158 ConfigData
->AttemptSecureBoot
= TRUE
;
3163 // If it is Physical Presence User, set the PhysicalPresent to true.
3165 if (UserPhysicalPresent()) {
3166 ConfigData
->PhysicalPresent
= TRUE
;
3168 ConfigData
->PhysicalPresent
= FALSE
;
3172 // Get the SecureBootMode from CustomMode variable.
3174 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3175 if (SecureBootMode
== NULL
) {
3176 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3178 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3182 // Extact current Secure Boot Mode
3184 ExtractSecureBootModeFromVariable(&ConfigData
->CurSecureBootMode
);
3187 // If there is no PK then the Delete Pk button will be gray.
3189 if (ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
|| ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3190 ConfigData
->HasPk
= FALSE
;
3192 ConfigData
->HasPk
= TRUE
;
3195 if (SecureBootEnable
!= NULL
) {
3196 FreePool (SecureBootEnable
);
3199 if (SecureBootMode
!= NULL
) {
3200 FreePool (SecureBootMode
);
3205 This function allows a caller to extract the current configuration for one
3206 or more named elements from the target driver.
3208 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3209 @param[in] Request A null-terminated Unicode string in
3210 <ConfigRequest> format.
3211 @param[out] Progress On return, points to a character in the Request
3212 string. Points to the string's null terminator if
3213 request was successful. Points to the most recent
3214 '&' before the first failing name/value pair (or
3215 the beginning of the string if the failure is in
3216 the first name/value pair) if the request was not
3218 @param[out] Results A null-terminated Unicode string in
3219 <ConfigAltResp> format which has all values filled
3220 in for the names in the Request string. String to
3221 be allocated by the called function.
3223 @retval EFI_SUCCESS The Results is filled with the requested values.
3224 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3225 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3226 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3232 SecureBootExtractConfig (
3233 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3234 IN CONST EFI_STRING Request
,
3235 OUT EFI_STRING
*Progress
,
3236 OUT EFI_STRING
*Results
3242 SECUREBOOT_CONFIGURATION Configuration
;
3243 EFI_STRING ConfigRequest
;
3244 EFI_STRING ConfigRequestHdr
;
3245 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3246 BOOLEAN AllocatedRequest
;
3248 if (Progress
== NULL
|| Results
== NULL
) {
3249 return EFI_INVALID_PARAMETER
;
3252 AllocatedRequest
= FALSE
;
3253 ConfigRequestHdr
= NULL
;
3254 ConfigRequest
= NULL
;
3257 ZeroMem (&Configuration
, sizeof (Configuration
));
3258 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3259 *Progress
= Request
;
3261 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3262 return EFI_NOT_FOUND
;
3266 // Get Configuration from Variable.
3268 SecureBootExtractConfigFromVariable (&Configuration
);
3270 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3271 ConfigRequest
= Request
;
3272 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3274 // Request is set to NULL or OFFSET is NULL, construct full request string.
3276 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3277 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3279 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3280 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3281 ConfigRequest
= AllocateZeroPool (Size
);
3282 ASSERT (ConfigRequest
!= NULL
);
3283 AllocatedRequest
= TRUE
;
3284 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3285 FreePool (ConfigRequestHdr
);
3286 ConfigRequestHdr
= NULL
;
3289 Status
= gHiiConfigRouting
->BlockToConfig (
3292 (UINT8
*) &Configuration
,
3299 // Free the allocated config request string.
3301 if (AllocatedRequest
) {
3302 FreePool (ConfigRequest
);
3306 // Set Progress string to the original request string.
3308 if (Request
== NULL
) {
3310 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3311 *Progress
= Request
+ StrLen (Request
);
3318 This function processes the results of changes in configuration.
3320 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3321 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3323 @param[out] Progress A pointer to a string filled in with the offset of
3324 the most recent '&' before the first failing
3325 name/value pair (or the beginning of the string if
3326 the failure is in the first name/value pair) or
3327 the terminating NULL if all was successful.
3329 @retval EFI_SUCCESS The Results is processed successfully.
3330 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3331 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3337 SecureBootRouteConfig (
3338 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3339 IN CONST EFI_STRING Configuration
,
3340 OUT EFI_STRING
*Progress
3343 UINT8
*SecureBootEnable
;
3344 SECUREBOOT_CONFIGURATION IfrNvData
;
3348 if (Configuration
== NULL
|| Progress
== NULL
) {
3349 return EFI_INVALID_PARAMETER
;
3352 *Progress
= Configuration
;
3353 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3354 return EFI_NOT_FOUND
;
3358 // Get Configuration from Variable.
3360 SecureBootExtractConfigFromVariable (&IfrNvData
);
3363 // Map the Configuration to the configuration block.
3365 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3366 Status
= gHiiConfigRouting
->ConfigToBlock (
3369 (UINT8
*)&IfrNvData
,
3373 if (EFI_ERROR (Status
)) {
3378 // Store Buffer Storage back to EFI variable if needed
3380 SecureBootEnable
= NULL
;
3381 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3382 if (NULL
!= SecureBootEnable
) {
3383 FreePool (SecureBootEnable
);
3384 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3385 if (EFI_ERROR (Status
)) {
3390 *Progress
= Configuration
+ StrLen (Configuration
);
3395 This function is called to provide results data to the driver.
3397 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3398 @param[in] Action Specifies the type of action taken by the browser.
3399 @param[in] QuestionId A unique value which is sent to the original
3400 exporting driver so that it can identify the type
3402 @param[in] Type The type of value for the question.
3403 @param[in] Value A pointer to the data being sent to the original
3405 @param[out] ActionRequest On return, points to the action requested by the
3408 @retval EFI_SUCCESS The callback successfully handled the action.
3409 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3410 variable and its data.
3411 @retval EFI_DEVICE_ERROR The variable could not be saved.
3412 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3418 SecureBootCallback (
3419 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3420 IN EFI_BROWSER_ACTION Action
,
3421 IN EFI_QUESTION_ID QuestionId
,
3423 IN EFI_IFR_TYPE_VALUE
*Value
,
3424 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3429 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3431 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3433 UINT8
*SecureBootEnable
;
3434 UINT8
*SecureBootMode
;
3435 CHAR16 PromptString
[100];
3436 UINT8 CurSecureBootMode
;
3438 Status
= EFI_SUCCESS
;
3439 SecureBootEnable
= NULL
;
3440 SecureBootMode
= NULL
;
3442 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3443 return EFI_INVALID_PARAMETER
;
3445 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3448 // Retrieve uncommitted data from Browser
3450 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3451 IfrNvData
= AllocateZeroPool (BufferSize
);
3452 if (IfrNvData
== NULL
) {
3453 return EFI_OUT_OF_RESOURCES
;
3456 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3458 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3459 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3461 // Update secure boot strings when opening this form
3463 Status
= UpdateSecureBootString(Private
);
3464 mIsEnterSecureBootForm
= TRUE
;
3465 } else if (QuestionId
== KEY_TRANS_SECURE_BOOT_MODE
){
3467 // Secure Boot Policy variable changes after transition. Re-sync CurSecureBootMode
3469 ExtractSecureBootModeFromVariable(&IfrNvData
->CurSecureBootMode
);
3470 mIsSelectedSecureBootModeForm
= TRUE
;
3471 mIsSecureBootModeChanged
= FALSE
;
3476 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3477 Status
= EFI_UNSUPPORTED
;
3478 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3479 if (mIsEnterSecureBootForm
) {
3480 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3481 Status
= EFI_SUCCESS
;
3483 } else if (QuestionId
== KEY_TRANS_SECURE_BOOT_MODE
) {
3484 if (mIsSelectedSecureBootModeForm
) {
3485 Value
->u8
= IfrNvData
->CurSecureBootMode
;
3486 Status
= EFI_SUCCESS
;
3492 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3493 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3494 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3495 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3496 Status
= EFI_UNSUPPORTED
;
3500 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3502 switch (QuestionId
) {
3503 case KEY_SECURE_BOOT_ENABLE
:
3504 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3505 if (NULL
!= SecureBootEnable
) {
3506 FreePool (SecureBootEnable
);
3507 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3509 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3511 L
"Only Physical Presence User could disable secure boot!",
3514 Status
= EFI_UNSUPPORTED
;
3517 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3519 L
"Configuration changed, please reset the platform to take effect!",
3526 case KEY_SECURE_BOOT_OPTION
:
3527 FreeMenu (&DirectoryMenu
);
3528 FreeMenu (&FsOptionMenu
);
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
:
3536 // Clear Signature GUID.
3538 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3539 if (Private
->SignatureGUID
== NULL
) {
3540 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3541 if (Private
->SignatureGUID
== NULL
) {
3542 return EFI_OUT_OF_RESOURCES
;
3546 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3547 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3548 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3549 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3550 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3551 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3553 LabelId
= FORMID_ENROLL_KEK_FORM
;
3557 // Refresh selected file.
3559 CleanUpPage (LabelId
, Private
);
3562 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
3563 case FORMID_ENROLL_KEK_FORM
:
3564 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3565 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3566 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3567 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
3568 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
3569 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
3570 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
3571 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
3572 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
3573 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
) {
3574 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
3575 IfrNvData
->CertificateFormat
= HASHALG_SHA256
;
3577 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbt
;
3580 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
3581 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
3582 UpdateFileExplorer (Private
, 0);
3585 case KEY_SECURE_BOOT_DELETE_PK
:
3588 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3590 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3591 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3594 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3595 Status
= DeletePlatformKey ();
3596 if (EFI_ERROR (Status
)) {
3598 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3600 L
"Only Physical Presence User could delete PK in custom mode!",
3608 case KEY_DELETE_KEK
:
3611 EFI_KEY_EXCHANGE_KEY_NAME
,
3612 &gEfiGlobalVariableGuid
,
3614 FORMID_DELETE_KEK_FORM
,
3615 OPTION_DEL_KEK_QUESTION_ID
3619 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3622 EFI_IMAGE_SECURITY_DATABASE
,
3623 &gEfiImageSecurityDatabaseGuid
,
3625 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3626 OPTION_DEL_DB_QUESTION_ID
3630 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3633 EFI_IMAGE_SECURITY_DATABASE1
,
3634 &gEfiImageSecurityDatabaseGuid
,
3636 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3637 OPTION_DEL_DBX_QUESTION_ID
3642 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3645 EFI_IMAGE_SECURITY_DATABASE2
,
3646 &gEfiImageSecurityDatabaseGuid
,
3648 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3649 OPTION_DEL_DBT_QUESTION_ID
3654 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3655 Status
= EnrollKeyExchangeKey (Private
);
3656 if (EFI_ERROR (Status
)) {
3658 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3660 L
"ERROR: Unsupported file type!",
3661 L
"Only supports DER-encoded X509 certificate",
3667 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3668 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3669 if (EFI_ERROR (Status
)) {
3671 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3673 L
"ERROR: Unsupported file type!",
3674 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3680 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3681 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3683 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3685 L
"Enrollment failed! Same certificate had already been in the dbx!",
3691 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3692 Status
= EnrollX509HashtoSigDB (
3694 IfrNvData
->CertificateFormat
,
3695 &IfrNvData
->RevocationDate
,
3696 &IfrNvData
->RevocationTime
,
3697 IfrNvData
->AlwaysRevocation
3700 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3702 if (EFI_ERROR (Status
)) {
3704 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3706 L
"ERROR: Unsupported file type!",
3707 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3713 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3714 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3715 if (EFI_ERROR (Status
)) {
3717 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3719 L
"ERROR: Unsupported file type!",
3720 L
"Only supports DER-encoded X509 certificate.",
3725 case KEY_TRANS_SECURE_BOOT_MODE
:
3727 // Pop up to alert user want to change secure boot mode
3729 if ((IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
&&
3730 (Value
->u8
== SECURE_BOOT_MODE_AUDIT_MODE
|| Value
->u8
== SECURE_BOOT_MODE_DEPLOYED_MODE
))
3731 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
&&
3732 Value
->u8
== SECURE_BOOT_MODE_AUDIT_MODE
)
3733 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
&&
3734 Value
->u8
== SECURE_BOOT_MODE_USER_MODE
&& IfrNvData
->PhysicalPresent
== 1)){
3736 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3738 L
"Are you sure you want to switch secure boot mode?",
3739 L
"Press 'Y' to switch secure boot mode, 'N' to discard change and return",
3742 if (Key
.UnicodeChar
!= 'y' && Key
.UnicodeChar
!= 'Y') {
3744 // If not 'Y'/''y' restore to defualt secure boot mode
3746 Value
->u8
= IfrNvData
->CurSecureBootMode
;
3749 } else if ((IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
&& Value
->u8
== SECURE_BOOT_MODE_USER_MODE
)
3750 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
&& Value
->u8
== SECURE_BOOT_MODE_SETUP_MODE
)
3751 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
&& Value
->u8
== SECURE_BOOT_MODE_DEPLOYED_MODE
)
3752 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
&& Value
->u8
== SECURE_BOOT_MODE_SETUP_MODE
)) {
3754 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3756 L
"Secure boot mode transition requires PK change",
3757 L
"Please go to link below to update PK",
3761 Status
= EFI_INVALID_PARAMETER
;
3765 Status
= SecureBootModeTransition(IfrNvData
->CurSecureBootMode
, Value
->u8
);
3767 // Secure Boot Policy variable may change after transition. Re-sync CurSecureBootMode
3769 ExtractSecureBootModeFromVariable(&CurSecureBootMode
);
3770 if (IfrNvData
->CurSecureBootMode
!= CurSecureBootMode
) {
3771 IfrNvData
->CurSecureBootMode
= CurSecureBootMode
;
3772 mIsSecureBootModeChanged
= TRUE
;
3777 if (QuestionId
>= FILE_OPTION_GOTO_OFFSET
) {
3778 UpdateFileExplorer (Private
, QuestionId
);
3779 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3780 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3781 DeleteKeyExchangeKey (Private
, QuestionId
);
3782 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3783 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3786 EFI_IMAGE_SECURITY_DATABASE
,
3787 &gEfiImageSecurityDatabaseGuid
,
3789 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3790 OPTION_DEL_DB_QUESTION_ID
,
3791 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3793 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3794 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3797 EFI_IMAGE_SECURITY_DATABASE1
,
3798 &gEfiImageSecurityDatabaseGuid
,
3800 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3801 OPTION_DEL_DBX_QUESTION_ID
,
3802 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3804 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3805 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3808 EFI_IMAGE_SECURITY_DATABASE2
,
3809 &gEfiImageSecurityDatabaseGuid
,
3811 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3812 OPTION_DEL_DBT_QUESTION_ID
,
3813 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3818 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3819 switch (QuestionId
) {
3820 case KEY_SECURE_BOOT_ENABLE
:
3821 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3823 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3824 Status
= EnrollPlatformKey (Private
);
3825 if (EFI_ERROR (Status
)) {
3828 sizeof (PromptString
),
3829 L
"Only DER encoded certificate file (%s) is supported.",
3833 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3835 L
"ERROR: Unsupported file type!",
3840 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3844 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3845 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3846 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3847 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3848 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3849 if (Private
->FileContext
->FHandle
!= NULL
) {
3850 CloseFile (Private
->FileContext
->FHandle
);
3851 Private
->FileContext
->FHandle
= NULL
;
3852 Private
->FileContext
->FileName
= NULL
;
3855 if (Private
->SignatureGUID
!= NULL
) {
3856 FreePool (Private
->SignatureGUID
);
3857 Private
->SignatureGUID
= NULL
;
3859 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3862 case KEY_SECURE_BOOT_MODE
:
3863 mIsEnterSecureBootForm
= FALSE
;
3865 case KEY_TRANS_SECURE_BOOT_MODE
:
3866 mIsSelectedSecureBootModeForm
= FALSE
;
3867 if (mIsSecureBootModeChanged
) {
3868 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3870 mIsSecureBootModeChanged
= FALSE
;
3872 case KEY_SECURE_BOOT_KEK_GUID
:
3873 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3874 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3875 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3876 ASSERT (Private
->SignatureGUID
!= NULL
);
3877 Status
= StringToGuid (
3878 IfrNvData
->SignatureGuid
,
3879 StrLen (IfrNvData
->SignatureGuid
),
3880 Private
->SignatureGUID
3882 if (EFI_ERROR (Status
)) {
3886 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3889 case KEY_SECURE_BOOT_DELETE_PK
:
3890 if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
|| IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3891 IfrNvData
->DeletePk
= TRUE
;
3892 IfrNvData
->HasPk
= FALSE
;
3893 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3895 IfrNvData
->DeletePk
= FALSE
;
3896 IfrNvData
->HasPk
= TRUE
;
3897 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3901 if (QuestionId
>= FILE_OPTION_OFFSET
&& QuestionId
< FILE_OPTION_GOTO_OFFSET
) {
3902 if (UpdateFileExplorer (Private
, QuestionId
)) {
3903 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3908 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3909 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3910 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3911 if (SecureBootEnable
== NULL
) {
3912 IfrNvData
->HideSecureBoot
= TRUE
;
3914 FreePool (SecureBootEnable
);
3915 IfrNvData
->HideSecureBoot
= FALSE
;
3917 Value
->b
= IfrNvData
->HideSecureBoot
;
3919 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3921 // Force the platform back to Standard Mode once user leave the setup screen.
3923 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3924 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3925 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3926 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3928 if (SecureBootMode
!= NULL
) {
3929 FreePool (SecureBootMode
);
3935 if (!EFI_ERROR (Status
)) {
3936 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3937 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3940 FreePool (IfrNvData
);
3946 This function publish the SecureBoot configuration Form.
3948 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3950 @retval EFI_SUCCESS HII Form is installed successfully.
3951 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3952 @retval Others Other errors as indicated.
3956 InstallSecureBootConfigForm (
3957 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3961 EFI_HII_HANDLE HiiHandle
;
3962 EFI_HANDLE DriverHandle
;
3963 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3965 DriverHandle
= NULL
;
3966 ConfigAccess
= &PrivateData
->ConfigAccess
;
3967 Status
= gBS
->InstallMultipleProtocolInterfaces (
3969 &gEfiDevicePathProtocolGuid
,
3970 &mSecureBootHiiVendorDevicePath
,
3971 &gEfiHiiConfigAccessProtocolGuid
,
3975 if (EFI_ERROR (Status
)) {
3979 PrivateData
->DriverHandle
= DriverHandle
;
3982 // Publish the HII package list
3984 HiiHandle
= HiiAddPackages (
3985 &gSecureBootConfigFormSetGuid
,
3987 SecureBootConfigDxeStrings
,
3988 SecureBootConfigBin
,
3991 if (HiiHandle
== NULL
) {
3992 gBS
->UninstallMultipleProtocolInterfaces (
3994 &gEfiDevicePathProtocolGuid
,
3995 &mSecureBootHiiVendorDevicePath
,
3996 &gEfiHiiConfigAccessProtocolGuid
,
4000 return EFI_OUT_OF_RESOURCES
;
4003 PrivateData
->HiiHandle
= HiiHandle
;
4005 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
4006 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
4008 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
4009 UninstallSecureBootConfigForm (PrivateData
);
4010 return EFI_OUT_OF_RESOURCES
;
4013 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
4014 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
4016 InitializeListHead (&FsOptionMenu
.Head
);
4017 InitializeListHead (&DirectoryMenu
.Head
);
4020 // Init OpCode Handle and Allocate space for creation of Buffer
4022 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4023 if (mStartOpCodeHandle
== NULL
) {
4024 UninstallSecureBootConfigForm (PrivateData
);
4025 return EFI_OUT_OF_RESOURCES
;
4028 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4029 if (mEndOpCodeHandle
== NULL
) {
4030 UninstallSecureBootConfigForm (PrivateData
);
4031 return EFI_OUT_OF_RESOURCES
;
4035 // Create Hii Extend Label OpCode as the start opcode
4037 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4041 sizeof (EFI_IFR_GUID_LABEL
)
4043 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4046 // Create Hii Extend Label OpCode as the end opcode
4048 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4052 sizeof (EFI_IFR_GUID_LABEL
)
4054 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4055 mEndLabel
->Number
= LABEL_END
;
4061 This function removes SecureBoot configuration Form.
4063 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4067 UninstallSecureBootConfigForm (
4068 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4072 // Uninstall HII package list
4074 if (PrivateData
->HiiHandle
!= NULL
) {
4075 HiiRemovePackages (PrivateData
->HiiHandle
);
4076 PrivateData
->HiiHandle
= NULL
;
4080 // Uninstall HII Config Access Protocol
4082 if (PrivateData
->DriverHandle
!= NULL
) {
4083 gBS
->UninstallMultipleProtocolInterfaces (
4084 PrivateData
->DriverHandle
,
4085 &gEfiDevicePathProtocolGuid
,
4086 &mSecureBootHiiVendorDevicePath
,
4087 &gEfiHiiConfigAccessProtocolGuid
,
4088 &PrivateData
->ConfigAccess
,
4091 PrivateData
->DriverHandle
= NULL
;
4094 if (PrivateData
->SignatureGUID
!= NULL
) {
4095 FreePool (PrivateData
->SignatureGUID
);
4098 if (PrivateData
->MenuEntry
!= NULL
) {
4099 FreePool (PrivateData
->MenuEntry
);
4102 if (PrivateData
->FileContext
!= NULL
) {
4103 FreePool (PrivateData
->FileContext
);
4106 FreePool (PrivateData
);
4108 FreeMenu (&DirectoryMenu
);
4109 FreeMenu (&FsOptionMenu
);
4111 if (mStartOpCodeHandle
!= NULL
) {
4112 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
4115 if (mEndOpCodeHandle
!= NULL
) {
4116 HiiFreeOpCodeHandle (mEndOpCodeHandle
);