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
3079 UINT8 CurSecureBootMode
;
3083 // Get current secure boot state.
3085 Status
= GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3086 if (EFI_ERROR(Status
)) {
3090 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3091 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3093 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3096 // Get current secure boot mode.
3098 ExtractSecureBootModeFromVariable(&CurSecureBootMode
);
3100 if (CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
) {
3101 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"UserMode", NULL
);
3102 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
) {
3103 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"SetupMode", NULL
);
3104 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3105 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"AuditMode", NULL
);
3106 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3107 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"DeployedMode", NULL
);
3110 FreePool(SecureBoot
);
3116 This function extracts configuration from variable.
3118 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3122 SecureBootExtractConfigFromVariable (
3123 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3126 UINT8
*SecureBootEnable
;
3127 UINT8
*SecureBootMode
;
3130 SecureBootEnable
= NULL
;
3131 SecureBootMode
= NULL
;
3134 // Initilize the Date and Time using system time.
3136 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3137 ConfigData
->AlwaysRevocation
= TRUE
;
3138 gRT
->GetTime (&CurrTime
, NULL
);
3139 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3140 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3141 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3142 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3143 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3144 ConfigData
->RevocationTime
.Second
= 0;
3147 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3150 ConfigData
->AttemptSecureBoot
= FALSE
;
3151 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3152 if (SecureBootEnable
== NULL
) {
3153 ConfigData
->HideSecureBoot
= TRUE
;
3155 ConfigData
->HideSecureBoot
= FALSE
;
3156 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
3157 ConfigData
->AttemptSecureBoot
= TRUE
;
3162 // If it is Physical Presence User, set the PhysicalPresent to true.
3164 if (UserPhysicalPresent()) {
3165 ConfigData
->PhysicalPresent
= TRUE
;
3167 ConfigData
->PhysicalPresent
= FALSE
;
3171 // Get the SecureBootMode from CustomMode variable.
3173 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3174 if (SecureBootMode
== NULL
) {
3175 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3177 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3181 // Extact current Secure Boot Mode
3183 ExtractSecureBootModeFromVariable(&ConfigData
->CurSecureBootMode
);
3186 // If there is no PK then the Delete Pk button will be gray.
3188 if (ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
|| ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3189 ConfigData
->HasPk
= FALSE
;
3191 ConfigData
->HasPk
= TRUE
;
3194 if (SecureBootEnable
!= NULL
) {
3195 FreePool (SecureBootEnable
);
3198 if (SecureBootMode
!= NULL
) {
3199 FreePool (SecureBootMode
);
3204 This function allows a caller to extract the current configuration for one
3205 or more named elements from the target driver.
3207 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3208 @param[in] Request A null-terminated Unicode string in
3209 <ConfigRequest> format.
3210 @param[out] Progress On return, points to a character in the Request
3211 string. Points to the string's null terminator if
3212 request was successful. Points to the most recent
3213 '&' before the first failing name/value pair (or
3214 the beginning of the string if the failure is in
3215 the first name/value pair) if the request was not
3217 @param[out] Results A null-terminated Unicode string in
3218 <ConfigAltResp> format which has all values filled
3219 in for the names in the Request string. String to
3220 be allocated by the called function.
3222 @retval EFI_SUCCESS The Results is filled with the requested values.
3223 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3224 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3225 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3231 SecureBootExtractConfig (
3232 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3233 IN CONST EFI_STRING Request
,
3234 OUT EFI_STRING
*Progress
,
3235 OUT EFI_STRING
*Results
3241 SECUREBOOT_CONFIGURATION Configuration
;
3242 EFI_STRING ConfigRequest
;
3243 EFI_STRING ConfigRequestHdr
;
3244 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3245 BOOLEAN AllocatedRequest
;
3247 if (Progress
== NULL
|| Results
== NULL
) {
3248 return EFI_INVALID_PARAMETER
;
3251 AllocatedRequest
= FALSE
;
3252 ConfigRequestHdr
= NULL
;
3253 ConfigRequest
= NULL
;
3256 ZeroMem (&Configuration
, sizeof (Configuration
));
3257 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3258 *Progress
= Request
;
3260 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3261 return EFI_NOT_FOUND
;
3265 // Get Configuration from Variable.
3267 SecureBootExtractConfigFromVariable (&Configuration
);
3269 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3270 ConfigRequest
= Request
;
3271 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3273 // Request is set to NULL or OFFSET is NULL, construct full request string.
3275 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3276 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3278 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3279 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3280 ConfigRequest
= AllocateZeroPool (Size
);
3281 ASSERT (ConfigRequest
!= NULL
);
3282 AllocatedRequest
= TRUE
;
3283 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3284 FreePool (ConfigRequestHdr
);
3285 ConfigRequestHdr
= NULL
;
3288 Status
= gHiiConfigRouting
->BlockToConfig (
3291 (UINT8
*) &Configuration
,
3298 // Free the allocated config request string.
3300 if (AllocatedRequest
) {
3301 FreePool (ConfigRequest
);
3305 // Set Progress string to the original request string.
3307 if (Request
== NULL
) {
3309 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3310 *Progress
= Request
+ StrLen (Request
);
3317 This function processes the results of changes in configuration.
3319 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3320 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3322 @param[out] Progress A pointer to a string filled in with the offset of
3323 the most recent '&' before the first failing
3324 name/value pair (or the beginning of the string if
3325 the failure is in the first name/value pair) or
3326 the terminating NULL if all was successful.
3328 @retval EFI_SUCCESS The Results is processed successfully.
3329 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3330 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3336 SecureBootRouteConfig (
3337 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3338 IN CONST EFI_STRING Configuration
,
3339 OUT EFI_STRING
*Progress
3342 UINT8
*SecureBootEnable
;
3343 SECUREBOOT_CONFIGURATION IfrNvData
;
3347 if (Configuration
== NULL
|| Progress
== NULL
) {
3348 return EFI_INVALID_PARAMETER
;
3351 *Progress
= Configuration
;
3352 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3353 return EFI_NOT_FOUND
;
3357 // Get Configuration from Variable.
3359 SecureBootExtractConfigFromVariable (&IfrNvData
);
3362 // Map the Configuration to the configuration block.
3364 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3365 Status
= gHiiConfigRouting
->ConfigToBlock (
3368 (UINT8
*)&IfrNvData
,
3372 if (EFI_ERROR (Status
)) {
3377 // Store Buffer Storage back to EFI variable if needed
3379 SecureBootEnable
= NULL
;
3380 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3381 if (NULL
!= SecureBootEnable
) {
3382 FreePool (SecureBootEnable
);
3383 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3384 if (EFI_ERROR (Status
)) {
3389 *Progress
= Configuration
+ StrLen (Configuration
);
3394 This function is called to provide results data to the driver.
3396 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3397 @param[in] Action Specifies the type of action taken by the browser.
3398 @param[in] QuestionId A unique value which is sent to the original
3399 exporting driver so that it can identify the type
3401 @param[in] Type The type of value for the question.
3402 @param[in] Value A pointer to the data being sent to the original
3404 @param[out] ActionRequest On return, points to the action requested by the
3407 @retval EFI_SUCCESS The callback successfully handled the action.
3408 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3409 variable and its data.
3410 @retval EFI_DEVICE_ERROR The variable could not be saved.
3411 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3417 SecureBootCallback (
3418 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3419 IN EFI_BROWSER_ACTION Action
,
3420 IN EFI_QUESTION_ID QuestionId
,
3422 IN EFI_IFR_TYPE_VALUE
*Value
,
3423 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3428 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3430 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3432 UINT8
*SecureBootEnable
;
3433 UINT8
*SecureBootMode
;
3434 CHAR16 PromptString
[100];
3435 UINT8 CurSecureBootMode
;
3437 Status
= EFI_SUCCESS
;
3438 SecureBootEnable
= NULL
;
3439 SecureBootMode
= NULL
;
3441 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3442 return EFI_INVALID_PARAMETER
;
3444 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3447 // Retrieve uncommitted data from Browser
3449 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3450 IfrNvData
= AllocateZeroPool (BufferSize
);
3451 if (IfrNvData
== NULL
) {
3452 return EFI_OUT_OF_RESOURCES
;
3455 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3457 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3458 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3460 // Update secure boot strings when opening this form
3462 Status
= UpdateSecureBootString(Private
);
3463 mIsEnterSecureBootForm
= TRUE
;
3464 } else if (QuestionId
== KEY_TRANS_SECURE_BOOT_MODE
){
3466 // Secure Boot Policy variable changes after transition. Re-sync CurSecureBootMode
3468 ExtractSecureBootModeFromVariable(&IfrNvData
->CurSecureBootMode
);
3469 mIsSelectedSecureBootModeForm
= TRUE
;
3470 mIsSecureBootModeChanged
= FALSE
;
3475 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3476 Status
= EFI_UNSUPPORTED
;
3477 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3478 if (mIsEnterSecureBootForm
) {
3479 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3480 Status
= EFI_SUCCESS
;
3482 } else if (QuestionId
== KEY_TRANS_SECURE_BOOT_MODE
) {
3483 if (mIsSelectedSecureBootModeForm
) {
3484 Value
->u8
= IfrNvData
->CurSecureBootMode
;
3485 Status
= EFI_SUCCESS
;
3491 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3492 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3493 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3494 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3495 Status
= EFI_UNSUPPORTED
;
3499 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3501 switch (QuestionId
) {
3502 case KEY_SECURE_BOOT_ENABLE
:
3503 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3504 if (NULL
!= SecureBootEnable
) {
3505 FreePool (SecureBootEnable
);
3506 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3508 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3510 L
"Only Physical Presence User could disable secure boot!",
3513 Status
= EFI_UNSUPPORTED
;
3516 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3518 L
"Configuration changed, please reset the platform to take effect!",
3525 case KEY_SECURE_BOOT_OPTION
:
3526 FreeMenu (&DirectoryMenu
);
3527 FreeMenu (&FsOptionMenu
);
3530 case KEY_SECURE_BOOT_KEK_OPTION
:
3531 case KEY_SECURE_BOOT_DB_OPTION
:
3532 case KEY_SECURE_BOOT_DBX_OPTION
:
3533 case KEY_SECURE_BOOT_DBT_OPTION
:
3535 // Clear Signature GUID.
3537 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3538 if (Private
->SignatureGUID
== NULL
) {
3539 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3540 if (Private
->SignatureGUID
== NULL
) {
3541 return EFI_OUT_OF_RESOURCES
;
3545 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3546 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3547 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3548 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3549 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3550 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3552 LabelId
= FORMID_ENROLL_KEK_FORM
;
3556 // Refresh selected file.
3558 CleanUpPage (LabelId
, Private
);
3561 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
3562 case FORMID_ENROLL_KEK_FORM
:
3563 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3564 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3565 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3566 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
3567 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
3568 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
3569 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
3570 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
3571 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
3572 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
) {
3573 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
3574 IfrNvData
->CertificateFormat
= HASHALG_SHA256
;
3576 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbt
;
3579 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
3580 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
3581 UpdateFileExplorer (Private
, 0);
3584 case KEY_SECURE_BOOT_DELETE_PK
:
3587 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3589 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3590 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3593 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3594 Status
= DeletePlatformKey ();
3595 if (EFI_ERROR (Status
)) {
3597 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3599 L
"Only Physical Presence User could delete PK in custom mode!",
3607 case KEY_DELETE_KEK
:
3610 EFI_KEY_EXCHANGE_KEY_NAME
,
3611 &gEfiGlobalVariableGuid
,
3613 FORMID_DELETE_KEK_FORM
,
3614 OPTION_DEL_KEK_QUESTION_ID
3618 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3621 EFI_IMAGE_SECURITY_DATABASE
,
3622 &gEfiImageSecurityDatabaseGuid
,
3624 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3625 OPTION_DEL_DB_QUESTION_ID
3629 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3632 EFI_IMAGE_SECURITY_DATABASE1
,
3633 &gEfiImageSecurityDatabaseGuid
,
3635 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3636 OPTION_DEL_DBX_QUESTION_ID
3641 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3644 EFI_IMAGE_SECURITY_DATABASE2
,
3645 &gEfiImageSecurityDatabaseGuid
,
3647 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3648 OPTION_DEL_DBT_QUESTION_ID
3653 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3654 Status
= EnrollKeyExchangeKey (Private
);
3655 if (EFI_ERROR (Status
)) {
3657 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3659 L
"ERROR: Unsupported file type!",
3660 L
"Only supports DER-encoded X509 certificate",
3666 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3667 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3668 if (EFI_ERROR (Status
)) {
3670 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3672 L
"ERROR: Unsupported file type!",
3673 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3679 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3680 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3682 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3684 L
"Enrollment failed! Same certificate had already been in the dbx!",
3690 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3691 Status
= EnrollX509HashtoSigDB (
3693 IfrNvData
->CertificateFormat
,
3694 &IfrNvData
->RevocationDate
,
3695 &IfrNvData
->RevocationTime
,
3696 IfrNvData
->AlwaysRevocation
3699 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3701 if (EFI_ERROR (Status
)) {
3703 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3705 L
"ERROR: Unsupported file type!",
3706 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3712 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3713 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3714 if (EFI_ERROR (Status
)) {
3716 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3718 L
"ERROR: Unsupported file type!",
3719 L
"Only supports DER-encoded X509 certificate.",
3724 case KEY_TRANS_SECURE_BOOT_MODE
:
3726 // Pop up to alert user want to change secure boot mode
3728 if ((IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
&&
3729 (Value
->u8
== SECURE_BOOT_MODE_AUDIT_MODE
|| Value
->u8
== SECURE_BOOT_MODE_DEPLOYED_MODE
))
3730 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
&&
3731 Value
->u8
== SECURE_BOOT_MODE_AUDIT_MODE
)
3732 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
&&
3733 Value
->u8
== SECURE_BOOT_MODE_USER_MODE
&& IfrNvData
->PhysicalPresent
== 1)){
3735 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3737 L
"Are you sure you want to switch secure boot mode?",
3738 L
"Press 'Y' to switch secure boot mode, 'N' to discard change and return",
3741 if (Key
.UnicodeChar
!= 'y' && Key
.UnicodeChar
!= 'Y') {
3743 // If not 'Y'/''y' restore to defualt secure boot mode
3745 Value
->u8
= IfrNvData
->CurSecureBootMode
;
3748 } else if ((IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
&& Value
->u8
== SECURE_BOOT_MODE_USER_MODE
)
3749 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
&& Value
->u8
== SECURE_BOOT_MODE_SETUP_MODE
)
3750 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
&& Value
->u8
== SECURE_BOOT_MODE_DEPLOYED_MODE
)
3751 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
&& Value
->u8
== SECURE_BOOT_MODE_SETUP_MODE
)) {
3753 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3755 L
"Secure boot mode transition requires PK change",
3756 L
"Please go to link below to update PK",
3760 Status
= EFI_INVALID_PARAMETER
;
3764 Status
= SecureBootModeTransition(IfrNvData
->CurSecureBootMode
, Value
->u8
);
3766 // Secure Boot Policy variable may change after transition. Re-sync CurSecureBootMode
3768 ExtractSecureBootModeFromVariable(&CurSecureBootMode
);
3769 if (IfrNvData
->CurSecureBootMode
!= CurSecureBootMode
) {
3770 IfrNvData
->CurSecureBootMode
= CurSecureBootMode
;
3771 mIsSecureBootModeChanged
= TRUE
;
3776 if (QuestionId
>= FILE_OPTION_GOTO_OFFSET
) {
3777 UpdateFileExplorer (Private
, QuestionId
);
3778 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3779 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3780 DeleteKeyExchangeKey (Private
, QuestionId
);
3781 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3782 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3785 EFI_IMAGE_SECURITY_DATABASE
,
3786 &gEfiImageSecurityDatabaseGuid
,
3788 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3789 OPTION_DEL_DB_QUESTION_ID
,
3790 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3792 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3793 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3796 EFI_IMAGE_SECURITY_DATABASE1
,
3797 &gEfiImageSecurityDatabaseGuid
,
3799 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3800 OPTION_DEL_DBX_QUESTION_ID
,
3801 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3803 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3804 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3807 EFI_IMAGE_SECURITY_DATABASE2
,
3808 &gEfiImageSecurityDatabaseGuid
,
3810 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3811 OPTION_DEL_DBT_QUESTION_ID
,
3812 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3817 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3818 switch (QuestionId
) {
3819 case KEY_SECURE_BOOT_ENABLE
:
3820 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3822 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3823 Status
= EnrollPlatformKey (Private
);
3824 if (EFI_ERROR (Status
)) {
3827 sizeof (PromptString
),
3828 L
"Only DER encoded certificate file (%s) is supported.",
3832 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3834 L
"ERROR: Unsupported file type!",
3839 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3843 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3844 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3845 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3846 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3847 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3848 if (Private
->FileContext
->FHandle
!= NULL
) {
3849 CloseFile (Private
->FileContext
->FHandle
);
3850 Private
->FileContext
->FHandle
= NULL
;
3851 Private
->FileContext
->FileName
= NULL
;
3854 if (Private
->SignatureGUID
!= NULL
) {
3855 FreePool (Private
->SignatureGUID
);
3856 Private
->SignatureGUID
= NULL
;
3858 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3861 case KEY_SECURE_BOOT_MODE
:
3862 mIsEnterSecureBootForm
= FALSE
;
3864 case KEY_TRANS_SECURE_BOOT_MODE
:
3865 mIsSelectedSecureBootModeForm
= FALSE
;
3866 if (mIsSecureBootModeChanged
) {
3867 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3869 mIsSecureBootModeChanged
= FALSE
;
3871 case KEY_SECURE_BOOT_KEK_GUID
:
3872 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3873 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3874 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3875 ASSERT (Private
->SignatureGUID
!= NULL
);
3876 Status
= StringToGuid (
3877 IfrNvData
->SignatureGuid
,
3878 StrLen (IfrNvData
->SignatureGuid
),
3879 Private
->SignatureGUID
3881 if (EFI_ERROR (Status
)) {
3885 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3888 case KEY_SECURE_BOOT_DELETE_PK
:
3889 if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
|| IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3890 IfrNvData
->DeletePk
= TRUE
;
3891 IfrNvData
->HasPk
= FALSE
;
3892 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3894 IfrNvData
->DeletePk
= FALSE
;
3895 IfrNvData
->HasPk
= TRUE
;
3896 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3900 if (QuestionId
>= FILE_OPTION_OFFSET
&& QuestionId
< FILE_OPTION_GOTO_OFFSET
) {
3901 if (UpdateFileExplorer (Private
, QuestionId
)) {
3902 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3907 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3908 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3909 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3910 if (SecureBootEnable
== NULL
) {
3911 IfrNvData
->HideSecureBoot
= TRUE
;
3913 FreePool (SecureBootEnable
);
3914 IfrNvData
->HideSecureBoot
= FALSE
;
3916 Value
->b
= IfrNvData
->HideSecureBoot
;
3918 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3920 // Force the platform back to Standard Mode once user leave the setup screen.
3922 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3923 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3924 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3925 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3927 if (SecureBootMode
!= NULL
) {
3928 FreePool (SecureBootMode
);
3934 if (!EFI_ERROR (Status
)) {
3935 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3936 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3939 FreePool (IfrNvData
);
3945 This function publish the SecureBoot configuration Form.
3947 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3949 @retval EFI_SUCCESS HII Form is installed successfully.
3950 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3951 @retval Others Other errors as indicated.
3955 InstallSecureBootConfigForm (
3956 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3960 EFI_HII_HANDLE HiiHandle
;
3961 EFI_HANDLE DriverHandle
;
3962 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3964 DriverHandle
= NULL
;
3965 ConfigAccess
= &PrivateData
->ConfigAccess
;
3966 Status
= gBS
->InstallMultipleProtocolInterfaces (
3968 &gEfiDevicePathProtocolGuid
,
3969 &mSecureBootHiiVendorDevicePath
,
3970 &gEfiHiiConfigAccessProtocolGuid
,
3974 if (EFI_ERROR (Status
)) {
3978 PrivateData
->DriverHandle
= DriverHandle
;
3981 // Publish the HII package list
3983 HiiHandle
= HiiAddPackages (
3984 &gSecureBootConfigFormSetGuid
,
3986 SecureBootConfigDxeStrings
,
3987 SecureBootConfigBin
,
3990 if (HiiHandle
== NULL
) {
3991 gBS
->UninstallMultipleProtocolInterfaces (
3993 &gEfiDevicePathProtocolGuid
,
3994 &mSecureBootHiiVendorDevicePath
,
3995 &gEfiHiiConfigAccessProtocolGuid
,
3999 return EFI_OUT_OF_RESOURCES
;
4002 PrivateData
->HiiHandle
= HiiHandle
;
4004 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
4005 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
4007 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
4008 UninstallSecureBootConfigForm (PrivateData
);
4009 return EFI_OUT_OF_RESOURCES
;
4012 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
4013 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
4015 InitializeListHead (&FsOptionMenu
.Head
);
4016 InitializeListHead (&DirectoryMenu
.Head
);
4019 // Init OpCode Handle and Allocate space for creation of Buffer
4021 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4022 if (mStartOpCodeHandle
== NULL
) {
4023 UninstallSecureBootConfigForm (PrivateData
);
4024 return EFI_OUT_OF_RESOURCES
;
4027 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4028 if (mEndOpCodeHandle
== NULL
) {
4029 UninstallSecureBootConfigForm (PrivateData
);
4030 return EFI_OUT_OF_RESOURCES
;
4034 // Create Hii Extend Label OpCode as the start opcode
4036 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4040 sizeof (EFI_IFR_GUID_LABEL
)
4042 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4045 // Create Hii Extend Label OpCode as the end opcode
4047 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4051 sizeof (EFI_IFR_GUID_LABEL
)
4053 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4054 mEndLabel
->Number
= LABEL_END
;
4060 This function removes SecureBoot configuration Form.
4062 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4066 UninstallSecureBootConfigForm (
4067 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4071 // Uninstall HII package list
4073 if (PrivateData
->HiiHandle
!= NULL
) {
4074 HiiRemovePackages (PrivateData
->HiiHandle
);
4075 PrivateData
->HiiHandle
= NULL
;
4079 // Uninstall HII Config Access Protocol
4081 if (PrivateData
->DriverHandle
!= NULL
) {
4082 gBS
->UninstallMultipleProtocolInterfaces (
4083 PrivateData
->DriverHandle
,
4084 &gEfiDevicePathProtocolGuid
,
4085 &mSecureBootHiiVendorDevicePath
,
4086 &gEfiHiiConfigAccessProtocolGuid
,
4087 &PrivateData
->ConfigAccess
,
4090 PrivateData
->DriverHandle
= NULL
;
4093 if (PrivateData
->SignatureGUID
!= NULL
) {
4094 FreePool (PrivateData
->SignatureGUID
);
4097 if (PrivateData
->MenuEntry
!= NULL
) {
4098 FreePool (PrivateData
->MenuEntry
);
4101 if (PrivateData
->FileContext
!= NULL
) {
4102 FreePool (PrivateData
->FileContext
);
4105 FreePool (PrivateData
);
4107 FreeMenu (&DirectoryMenu
);
4108 FreeMenu (&FsOptionMenu
);
4110 if (mStartOpCodeHandle
!= NULL
) {
4111 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
4114 if (mEndOpCodeHandle
!= NULL
) {
4115 HiiFreeOpCodeHandle (mEndOpCodeHandle
);