2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2015, 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
);
3064 This function extracts configuration from variable.
3066 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3070 SecureBootExtractConfigFromVariable (
3071 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3074 UINT8
*SecureBootEnable
;
3075 UINT8
*SecureBootMode
;
3078 SecureBootEnable
= NULL
;
3079 SecureBootMode
= NULL
;
3082 // Initilize the Date and Time using system time.
3084 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3085 ConfigData
->AlwaysRevocation
= TRUE
;
3086 gRT
->GetTime (&CurrTime
, NULL
);
3087 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3088 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3089 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3090 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3091 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3092 ConfigData
->RevocationTime
.Second
= 0;
3095 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3098 ConfigData
->AttemptSecureBoot
= FALSE
;
3099 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3100 if (SecureBootEnable
== NULL
) {
3101 ConfigData
->HideSecureBoot
= TRUE
;
3103 ConfigData
->HideSecureBoot
= FALSE
;
3104 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
3105 ConfigData
->AttemptSecureBoot
= TRUE
;
3110 // If it is Physical Presence User, set the PhysicalPresent to true.
3112 if (UserPhysicalPresent()) {
3113 ConfigData
->PhysicalPresent
= TRUE
;
3115 ConfigData
->PhysicalPresent
= FALSE
;
3119 // Get the SecureBootMode from CustomMode variable.
3121 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3122 if (SecureBootMode
== NULL
) {
3123 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3125 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3129 // Extact current Secure Boot Mode
3131 ExtractSecureBootModeFromVariable(&ConfigData
->CurSecureBootMode
);
3134 // If there is no PK then the Delete Pk button will be gray.
3136 if (ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
|| ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3137 ConfigData
->HasPk
= FALSE
;
3139 ConfigData
->HasPk
= TRUE
;
3142 if (SecureBootEnable
!= NULL
) {
3143 FreePool (SecureBootEnable
);
3146 if (SecureBootMode
!= NULL
) {
3147 FreePool (SecureBootMode
);
3152 This function allows a caller to extract the current configuration for one
3153 or more named elements from the target driver.
3155 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3156 @param[in] Request A null-terminated Unicode string in
3157 <ConfigRequest> format.
3158 @param[out] Progress On return, points to a character in the Request
3159 string. Points to the string's null terminator if
3160 request was successful. Points to the most recent
3161 '&' before the first failing name/value pair (or
3162 the beginning of the string if the failure is in
3163 the first name/value pair) if the request was not
3165 @param[out] Results A null-terminated Unicode string in
3166 <ConfigAltResp> format which has all values filled
3167 in for the names in the Request string. String to
3168 be allocated by the called function.
3170 @retval EFI_SUCCESS The Results is filled with the requested values.
3171 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3172 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3173 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3179 SecureBootExtractConfig (
3180 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3181 IN CONST EFI_STRING Request
,
3182 OUT EFI_STRING
*Progress
,
3183 OUT EFI_STRING
*Results
3189 SECUREBOOT_CONFIGURATION Configuration
;
3190 EFI_STRING ConfigRequest
;
3191 EFI_STRING ConfigRequestHdr
;
3192 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3193 BOOLEAN AllocatedRequest
;
3196 if (Progress
== NULL
|| Results
== NULL
) {
3197 return EFI_INVALID_PARAMETER
;
3200 AllocatedRequest
= FALSE
;
3201 ConfigRequestHdr
= NULL
;
3202 ConfigRequest
= NULL
;
3206 ZeroMem (&Configuration
, sizeof (Configuration
));
3207 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3208 *Progress
= Request
;
3210 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3211 return EFI_NOT_FOUND
;
3215 // Get Configuration from Variable.
3217 SecureBootExtractConfigFromVariable (&Configuration
);
3220 // Get current secure boot state.
3222 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3224 if (SecureBoot
!= NULL
&& *SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3225 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3227 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3231 // Get current secure boot mode
3233 DEBUG((EFI_D_INFO
, "Configuration.CurSecureBootMode %d\n", Configuration
.CurSecureBootMode
));
3234 if (Configuration
.CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
) {
3235 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"UserMode", NULL
);
3236 } else if (Configuration
.CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
) {
3237 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"SetupMode", NULL
);
3238 } else if (Configuration
.CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3239 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"AuditMode", NULL
);
3240 } else if (Configuration
.CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3241 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"DeployedMode", NULL
);
3244 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3245 ConfigRequest
= Request
;
3246 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3248 // Request is set to NULL or OFFSET is NULL, construct full request string.
3250 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3251 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3253 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3254 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3255 ConfigRequest
= AllocateZeroPool (Size
);
3256 ASSERT (ConfigRequest
!= NULL
);
3257 AllocatedRequest
= TRUE
;
3258 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3259 FreePool (ConfigRequestHdr
);
3260 ConfigRequestHdr
= NULL
;
3263 Status
= gHiiConfigRouting
->BlockToConfig (
3266 (UINT8
*) &Configuration
,
3273 // Free the allocated config request string.
3275 if (AllocatedRequest
) {
3276 FreePool (ConfigRequest
);
3280 // Set Progress string to the original request string.
3282 if (Request
== NULL
) {
3284 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3285 *Progress
= Request
+ StrLen (Request
);
3288 if (SecureBoot
!= NULL
) {
3289 FreePool (SecureBoot
);
3296 This function processes the results of changes in configuration.
3298 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3299 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3301 @param[out] Progress A pointer to a string filled in with the offset of
3302 the most recent '&' before the first failing
3303 name/value pair (or the beginning of the string if
3304 the failure is in the first name/value pair) or
3305 the terminating NULL if all was successful.
3307 @retval EFI_SUCCESS The Results is processed successfully.
3308 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3309 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3315 SecureBootRouteConfig (
3316 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3317 IN CONST EFI_STRING Configuration
,
3318 OUT EFI_STRING
*Progress
3321 UINT8
*SecureBootEnable
;
3322 SECUREBOOT_CONFIGURATION IfrNvData
;
3326 if (Configuration
== NULL
|| Progress
== NULL
) {
3327 return EFI_INVALID_PARAMETER
;
3330 *Progress
= Configuration
;
3331 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3332 return EFI_NOT_FOUND
;
3336 // Get Configuration from Variable.
3338 SecureBootExtractConfigFromVariable (&IfrNvData
);
3341 // Map the Configuration to the configuration block.
3343 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3344 Status
= gHiiConfigRouting
->ConfigToBlock (
3347 (UINT8
*)&IfrNvData
,
3351 if (EFI_ERROR (Status
)) {
3356 // Store Buffer Storage back to EFI variable if needed
3358 SecureBootEnable
= NULL
;
3359 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3360 if (NULL
!= SecureBootEnable
) {
3361 FreePool (SecureBootEnable
);
3362 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3363 if (EFI_ERROR (Status
)) {
3368 *Progress
= Configuration
+ StrLen (Configuration
);
3373 This function is called to provide results data to the driver.
3375 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3376 @param[in] Action Specifies the type of action taken by the browser.
3377 @param[in] QuestionId A unique value which is sent to the original
3378 exporting driver so that it can identify the type
3380 @param[in] Type The type of value for the question.
3381 @param[in] Value A pointer to the data being sent to the original
3383 @param[out] ActionRequest On return, points to the action requested by the
3386 @retval EFI_SUCCESS The callback successfully handled the action.
3387 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3388 variable and its data.
3389 @retval EFI_DEVICE_ERROR The variable could not be saved.
3390 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3396 SecureBootCallback (
3397 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3398 IN EFI_BROWSER_ACTION Action
,
3399 IN EFI_QUESTION_ID QuestionId
,
3401 IN EFI_IFR_TYPE_VALUE
*Value
,
3402 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3407 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3409 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3411 UINT8
*SecureBootEnable
;
3412 UINT8
*SecureBootMode
;
3413 CHAR16 PromptString
[100];
3414 UINT8 CurSecureBootMode
;
3416 Status
= EFI_SUCCESS
;
3417 SecureBootEnable
= NULL
;
3418 SecureBootMode
= NULL
;
3420 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3421 return EFI_INVALID_PARAMETER
;
3423 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3426 // Retrieve uncommitted data from Browser
3428 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3429 IfrNvData
= AllocateZeroPool (BufferSize
);
3430 if (IfrNvData
== NULL
) {
3431 return EFI_OUT_OF_RESOURCES
;
3434 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3436 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3437 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3438 mIsEnterSecureBootForm
= TRUE
;
3439 } else if (QuestionId
== KEY_TRANS_SECURE_BOOT_MODE
){
3441 // Secure Boot Policy variable changes after tranistion. Re-sync CurSecureBootMode
3443 ExtractSecureBootModeFromVariable(&IfrNvData
->CurSecureBootMode
);
3444 mIsSelectedSecureBootModeForm
= TRUE
;
3445 mIsSecureBootModeChanged
= FALSE
;
3450 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3451 Status
= EFI_UNSUPPORTED
;
3452 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3453 if (mIsEnterSecureBootForm
) {
3454 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3455 Status
= EFI_SUCCESS
;
3457 } else if (QuestionId
== KEY_TRANS_SECURE_BOOT_MODE
) {
3458 if (mIsSelectedSecureBootModeForm
) {
3459 Value
->u8
= IfrNvData
->CurSecureBootMode
;
3460 Status
= EFI_SUCCESS
;
3466 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3467 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3468 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3469 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3470 Status
= EFI_UNSUPPORTED
;
3474 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3476 switch (QuestionId
) {
3477 case KEY_SECURE_BOOT_ENABLE
:
3478 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3479 if (NULL
!= SecureBootEnable
) {
3480 FreePool (SecureBootEnable
);
3481 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3483 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3485 L
"Only Physical Presence User could disable secure boot!",
3488 Status
= EFI_UNSUPPORTED
;
3491 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3493 L
"Configuration changed, please reset the platform to take effect!",
3500 case KEY_SECURE_BOOT_OPTION
:
3501 FreeMenu (&DirectoryMenu
);
3502 FreeMenu (&FsOptionMenu
);
3505 case KEY_SECURE_BOOT_KEK_OPTION
:
3506 case KEY_SECURE_BOOT_DB_OPTION
:
3507 case KEY_SECURE_BOOT_DBX_OPTION
:
3508 case KEY_SECURE_BOOT_DBT_OPTION
:
3510 // Clear Signature GUID.
3512 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3513 if (Private
->SignatureGUID
== NULL
) {
3514 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3515 if (Private
->SignatureGUID
== NULL
) {
3516 return EFI_OUT_OF_RESOURCES
;
3520 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3521 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3522 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3523 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3524 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3525 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3527 LabelId
= FORMID_ENROLL_KEK_FORM
;
3531 // Refresh selected file.
3533 CleanUpPage (LabelId
, Private
);
3536 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
3537 case FORMID_ENROLL_KEK_FORM
:
3538 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3539 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3540 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3541 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
3542 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
3543 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
3544 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
3545 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
3546 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
3547 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
) {
3548 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
3549 IfrNvData
->CertificateFormat
= HASHALG_SHA256
;
3551 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbt
;
3554 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
3555 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
3556 UpdateFileExplorer (Private
, 0);
3559 case KEY_SECURE_BOOT_DELETE_PK
:
3562 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3564 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3565 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3568 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3569 Status
= DeletePlatformKey ();
3570 if (EFI_ERROR (Status
)) {
3572 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3574 L
"Only Physical Presence User could delete PK in custom mode!",
3582 case KEY_DELETE_KEK
:
3585 EFI_KEY_EXCHANGE_KEY_NAME
,
3586 &gEfiGlobalVariableGuid
,
3588 FORMID_DELETE_KEK_FORM
,
3589 OPTION_DEL_KEK_QUESTION_ID
3593 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3596 EFI_IMAGE_SECURITY_DATABASE
,
3597 &gEfiImageSecurityDatabaseGuid
,
3599 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3600 OPTION_DEL_DB_QUESTION_ID
3604 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3607 EFI_IMAGE_SECURITY_DATABASE1
,
3608 &gEfiImageSecurityDatabaseGuid
,
3610 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3611 OPTION_DEL_DBX_QUESTION_ID
3616 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3619 EFI_IMAGE_SECURITY_DATABASE2
,
3620 &gEfiImageSecurityDatabaseGuid
,
3622 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3623 OPTION_DEL_DBT_QUESTION_ID
3628 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3629 Status
= EnrollKeyExchangeKey (Private
);
3630 if (EFI_ERROR (Status
)) {
3632 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3634 L
"ERROR: Unsupported file type!",
3635 L
"Only supports DER-encoded X509 certificate",
3641 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3642 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3643 if (EFI_ERROR (Status
)) {
3645 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3647 L
"ERROR: Unsupported file type!",
3648 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3654 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3655 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3657 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3659 L
"Enrollment failed! Same certificate had already been in the dbx!",
3665 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3666 Status
= EnrollX509HashtoSigDB (
3668 IfrNvData
->CertificateFormat
,
3669 &IfrNvData
->RevocationDate
,
3670 &IfrNvData
->RevocationTime
,
3671 IfrNvData
->AlwaysRevocation
3674 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3676 if (EFI_ERROR (Status
)) {
3678 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3680 L
"ERROR: Unsupported file type!",
3681 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3687 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3688 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3689 if (EFI_ERROR (Status
)) {
3691 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3693 L
"ERROR: Unsupported file type!",
3694 L
"Only supports DER-encoded X509 certificate.",
3699 case KEY_TRANS_SECURE_BOOT_MODE
:
3701 // Pop up to alert user want to change secure boot mode
3703 if ((IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
&&
3704 (Value
->u8
== SECURE_BOOT_MODE_AUDIT_MODE
|| Value
->u8
== SECURE_BOOT_MODE_DEPLOYED_MODE
))
3705 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
&&
3706 Value
->u8
== SECURE_BOOT_MODE_AUDIT_MODE
)
3707 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
&&
3708 Value
->u8
== SECURE_BOOT_MODE_USER_MODE
&& IfrNvData
->PhysicalPresent
== 1)){
3710 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3712 L
"Are you sure you want to switch secure boot mode?",
3713 L
"Press 'Y' to switch secure boot mode, 'N' to discard change and return",
3716 if (Key
.UnicodeChar
!= 'y' && Key
.UnicodeChar
!= 'Y') {
3718 // If not 'Y'/''y' restore to defualt secure boot mode
3720 Value
->u8
= IfrNvData
->CurSecureBootMode
;
3723 } else if ((IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
&& Value
->u8
== SECURE_BOOT_MODE_USER_MODE
)
3724 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
&& Value
->u8
== SECURE_BOOT_MODE_SETUP_MODE
)
3725 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
&& Value
->u8
== SECURE_BOOT_MODE_DEPLOYED_MODE
)
3726 ||(IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
&& Value
->u8
== SECURE_BOOT_MODE_SETUP_MODE
)) {
3728 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3730 L
"Secure boot mode tranistion requires PK change",
3731 L
"Please go to link below to update PK",
3735 Status
= EFI_INVALID_PARAMETER
;
3739 Status
= SecureBootModeTransition(IfrNvData
->CurSecureBootMode
, Value
->u8
);
3741 // Secure Boot Policy variable may change after tranistion. Re-sync CurSecureBootMode
3743 ExtractSecureBootModeFromVariable(&CurSecureBootMode
);
3744 if (IfrNvData
->CurSecureBootMode
!= CurSecureBootMode
) {
3745 IfrNvData
->CurSecureBootMode
= CurSecureBootMode
;
3746 mIsSecureBootModeChanged
= TRUE
;
3748 if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
) {
3749 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"UserMode", NULL
);
3750 } else if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
) {
3751 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"SetupMode", NULL
);
3752 } else if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3753 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"AuditMode", NULL
);
3754 } else if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3755 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"DeployedMode", NULL
);
3761 if (QuestionId
>= FILE_OPTION_GOTO_OFFSET
) {
3762 UpdateFileExplorer (Private
, QuestionId
);
3763 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3764 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3765 DeleteKeyExchangeKey (Private
, QuestionId
);
3766 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3767 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3770 EFI_IMAGE_SECURITY_DATABASE
,
3771 &gEfiImageSecurityDatabaseGuid
,
3773 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3774 OPTION_DEL_DB_QUESTION_ID
,
3775 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3777 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3778 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3781 EFI_IMAGE_SECURITY_DATABASE1
,
3782 &gEfiImageSecurityDatabaseGuid
,
3784 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3785 OPTION_DEL_DBX_QUESTION_ID
,
3786 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3788 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3789 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3792 EFI_IMAGE_SECURITY_DATABASE2
,
3793 &gEfiImageSecurityDatabaseGuid
,
3795 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3796 OPTION_DEL_DBT_QUESTION_ID
,
3797 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3802 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3803 switch (QuestionId
) {
3804 case KEY_SECURE_BOOT_ENABLE
:
3805 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3807 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3808 Status
= EnrollPlatformKey (Private
);
3809 if (EFI_ERROR (Status
)) {
3812 sizeof (PromptString
),
3813 L
"Only DER encoded certificate file (%s) is supported.",
3817 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3819 L
"ERROR: Unsupported file type!",
3824 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3828 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3829 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3830 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3831 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3832 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3833 if (Private
->FileContext
->FHandle
!= NULL
) {
3834 CloseFile (Private
->FileContext
->FHandle
);
3835 Private
->FileContext
->FHandle
= NULL
;
3836 Private
->FileContext
->FileName
= NULL
;
3839 if (Private
->SignatureGUID
!= NULL
) {
3840 FreePool (Private
->SignatureGUID
);
3841 Private
->SignatureGUID
= NULL
;
3843 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3846 case KEY_SECURE_BOOT_MODE
:
3847 mIsEnterSecureBootForm
= FALSE
;
3849 case KEY_TRANS_SECURE_BOOT_MODE
:
3850 mIsSelectedSecureBootModeForm
= FALSE
;
3851 if (mIsSecureBootModeChanged
) {
3852 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3854 mIsSecureBootModeChanged
= FALSE
;
3856 case KEY_SECURE_BOOT_KEK_GUID
:
3857 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3858 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3859 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3860 ASSERT (Private
->SignatureGUID
!= NULL
);
3861 Status
= StringToGuid (
3862 IfrNvData
->SignatureGuid
,
3863 StrLen (IfrNvData
->SignatureGuid
),
3864 Private
->SignatureGUID
3866 if (EFI_ERROR (Status
)) {
3870 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3873 case KEY_SECURE_BOOT_DELETE_PK
:
3874 if (IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
|| IfrNvData
->CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3875 IfrNvData
->DeletePk
= TRUE
;
3876 IfrNvData
->HasPk
= FALSE
;
3877 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3879 IfrNvData
->DeletePk
= FALSE
;
3880 IfrNvData
->HasPk
= TRUE
;
3881 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3885 if (QuestionId
>= FILE_OPTION_OFFSET
&& QuestionId
< FILE_OPTION_GOTO_OFFSET
) {
3886 if (UpdateFileExplorer (Private
, QuestionId
)) {
3887 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3892 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3893 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3894 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3895 if (SecureBootEnable
== NULL
) {
3896 IfrNvData
->HideSecureBoot
= TRUE
;
3898 FreePool (SecureBootEnable
);
3899 IfrNvData
->HideSecureBoot
= FALSE
;
3901 Value
->b
= IfrNvData
->HideSecureBoot
;
3903 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3905 // Force the platform back to Standard Mode once user leave the setup screen.
3907 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3908 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3909 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3910 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3912 if (SecureBootMode
!= NULL
) {
3913 FreePool (SecureBootMode
);
3919 if (!EFI_ERROR (Status
)) {
3920 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3921 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3924 FreePool (IfrNvData
);
3930 This function publish the SecureBoot configuration Form.
3932 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3934 @retval EFI_SUCCESS HII Form is installed successfully.
3935 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3936 @retval Others Other errors as indicated.
3940 InstallSecureBootConfigForm (
3941 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3945 EFI_HII_HANDLE HiiHandle
;
3946 EFI_HANDLE DriverHandle
;
3947 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3949 DriverHandle
= NULL
;
3950 ConfigAccess
= &PrivateData
->ConfigAccess
;
3951 Status
= gBS
->InstallMultipleProtocolInterfaces (
3953 &gEfiDevicePathProtocolGuid
,
3954 &mSecureBootHiiVendorDevicePath
,
3955 &gEfiHiiConfigAccessProtocolGuid
,
3959 if (EFI_ERROR (Status
)) {
3963 PrivateData
->DriverHandle
= DriverHandle
;
3966 // Publish the HII package list
3968 HiiHandle
= HiiAddPackages (
3969 &gSecureBootConfigFormSetGuid
,
3971 SecureBootConfigDxeStrings
,
3972 SecureBootConfigBin
,
3975 if (HiiHandle
== NULL
) {
3976 gBS
->UninstallMultipleProtocolInterfaces (
3978 &gEfiDevicePathProtocolGuid
,
3979 &mSecureBootHiiVendorDevicePath
,
3980 &gEfiHiiConfigAccessProtocolGuid
,
3984 return EFI_OUT_OF_RESOURCES
;
3987 PrivateData
->HiiHandle
= HiiHandle
;
3989 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
3990 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
3992 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
3993 UninstallSecureBootConfigForm (PrivateData
);
3994 return EFI_OUT_OF_RESOURCES
;
3997 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
3998 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
4000 InitializeListHead (&FsOptionMenu
.Head
);
4001 InitializeListHead (&DirectoryMenu
.Head
);
4004 // Init OpCode Handle and Allocate space for creation of Buffer
4006 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4007 if (mStartOpCodeHandle
== NULL
) {
4008 UninstallSecureBootConfigForm (PrivateData
);
4009 return EFI_OUT_OF_RESOURCES
;
4012 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4013 if (mEndOpCodeHandle
== NULL
) {
4014 UninstallSecureBootConfigForm (PrivateData
);
4015 return EFI_OUT_OF_RESOURCES
;
4019 // Create Hii Extend Label OpCode as the start opcode
4021 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4025 sizeof (EFI_IFR_GUID_LABEL
)
4027 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4030 // Create Hii Extend Label OpCode as the end opcode
4032 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4036 sizeof (EFI_IFR_GUID_LABEL
)
4038 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4039 mEndLabel
->Number
= LABEL_END
;
4045 This function removes SecureBoot configuration Form.
4047 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4051 UninstallSecureBootConfigForm (
4052 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4056 // Uninstall HII package list
4058 if (PrivateData
->HiiHandle
!= NULL
) {
4059 HiiRemovePackages (PrivateData
->HiiHandle
);
4060 PrivateData
->HiiHandle
= NULL
;
4064 // Uninstall HII Config Access Protocol
4066 if (PrivateData
->DriverHandle
!= NULL
) {
4067 gBS
->UninstallMultipleProtocolInterfaces (
4068 PrivateData
->DriverHandle
,
4069 &gEfiDevicePathProtocolGuid
,
4070 &mSecureBootHiiVendorDevicePath
,
4071 &gEfiHiiConfigAccessProtocolGuid
,
4072 &PrivateData
->ConfigAccess
,
4075 PrivateData
->DriverHandle
= NULL
;
4078 if (PrivateData
->SignatureGUID
!= NULL
) {
4079 FreePool (PrivateData
->SignatureGUID
);
4082 if (PrivateData
->MenuEntry
!= NULL
) {
4083 FreePool (PrivateData
->MenuEntry
);
4086 if (PrivateData
->FileContext
!= NULL
) {
4087 FreePool (PrivateData
->FileContext
);
4090 FreePool (PrivateData
);
4092 FreeMenu (&DirectoryMenu
);
4093 FreeMenu (&FsOptionMenu
);
4095 if (mStartOpCodeHandle
!= NULL
) {
4096 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
4099 if (mEndOpCodeHandle
!= NULL
) {
4100 HiiFreeOpCodeHandle (mEndOpCodeHandle
);