2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "SecureBootConfigImpl.h"
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
) (END_DEVICE_PATH_LENGTH
),
45 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
51 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
52 BOOLEAN mIsSelectedSecureBootModeForm
= FALSE
;
53 BOOLEAN mIsSecureBootModeChanged
= FALSE
;
56 // OID ASN.1 Value for Hash Algorithms
58 UINT8 mHashOidValue
[] = {
59 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
60 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
64 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
67 HASH_TABLE mHash
[] = {
68 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
69 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
70 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
71 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
72 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
76 // Variable Definitions
78 UINT32 mPeCoffHeaderOffset
= 0;
79 WIN_CERTIFICATE
*mCertificate
= NULL
;
80 IMAGE_TYPE mImageType
;
81 UINT8
*mImageBase
= NULL
;
83 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
84 UINTN mImageDigestSize
;
86 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
87 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
90 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
92 CHAR16
* mDerEncodedSuffix
[] = {
98 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
100 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
103 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
105 @param[in] FileSuffix The suffix of the input certificate file
107 @retval TRUE It's a DER-encoded certificate.
108 @retval FALSE It's NOT a DER-encoded certificate.
112 IsDerEncodeCertificate (
113 IN CONST CHAR16
*FileSuffix
117 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
118 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
126 Set Secure Boot option into variable space.
128 @param[in] VarValue The option of Secure Boot.
130 @retval EFI_SUCCESS The operation is finished successfully.
131 @retval Others Other errors as indicated.
135 SaveSecureBootVariable (
141 Status
= gRT
->SetVariable (
142 EFI_SECURE_BOOT_ENABLE_NAME
,
143 &gEfiSecureBootEnableDisableGuid
,
144 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
152 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
153 descriptor with the input data. NO authentication is required in this function.
155 @param[in, out] DataSize On input, the size of Data buffer in bytes.
156 On output, the size of data returned in Data
158 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
159 pointer to NULL to wrap an empty payload.
160 On output, Pointer to the new payload date buffer allocated from pool,
161 it's caller's responsibility to free the memory when finish using it.
163 @retval EFI_SUCCESS Create time based payload successfully.
164 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
165 @retval EFI_INVALID_PARAMETER The parameter is invalid.
166 @retval Others Unexpected error happens.
170 CreateTimeBasedPayload (
171 IN OUT UINTN
*DataSize
,
179 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
180 UINTN DescriptorSize
;
183 if (Data
== NULL
|| DataSize
== NULL
) {
184 return EFI_INVALID_PARAMETER
;
188 // In Setup mode or Custom mode, the variable does not need to be signed but the
189 // parameters to the SetVariable() call still need to be prepared as authenticated
190 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
194 PayloadSize
= *DataSize
;
196 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
197 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
198 if (NewData
== NULL
) {
199 return EFI_OUT_OF_RESOURCES
;
202 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
203 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
206 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
208 ZeroMem (&Time
, sizeof (EFI_TIME
));
209 Status
= gRT
->GetTime (&Time
, NULL
);
210 if (EFI_ERROR (Status
)) {
219 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
221 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
222 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
223 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
224 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
226 if (Payload
!= NULL
) {
230 *DataSize
= DescriptorSize
+ PayloadSize
;
236 Internal helper function to delete a Variable given its name and GUID, NO authentication
239 @param[in] VariableName Name of the Variable.
240 @param[in] VendorGuid GUID of the Variable.
242 @retval EFI_SUCCESS Variable deleted successfully.
243 @retval Others The driver failed to start the device.
248 IN CHAR16
*VariableName
,
249 IN EFI_GUID
*VendorGuid
258 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
259 if (Variable
== NULL
) {
266 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
267 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
269 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
270 if (EFI_ERROR (Status
)) {
271 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
275 Status
= gRT
->SetVariable (
290 Set the platform secure boot mode into "Custom" or "Standard" mode.
292 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
293 CUSTOM_SECURE_BOOT_MODE.
295 @return EFI_SUCCESS The platform has switched to the special mode successfully.
296 @return other Fail to operate the secure boot mode.
301 IN UINT8 SecureBootMode
304 return gRT
->SetVariable (
305 EFI_CUSTOM_MODE_NAME
,
306 &gEfiCustomModeEnableGuid
,
307 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
314 Generate the PK signature list from the X509 Certificate storing file (.cer)
316 @param[in] X509File FileHandle of X509 Certificate storing file.
317 @param[out] PkCert Point to the data buffer to store the signature list.
319 @return EFI_UNSUPPORTED Unsupported Key Length.
320 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
324 CreatePkX509SignatureList (
325 IN EFI_FILE_HANDLE X509File
,
326 OUT EFI_SIGNATURE_LIST
**PkCert
332 EFI_SIGNATURE_DATA
*PkCertData
;
338 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
339 if (EFI_ERROR (Status
)) {
342 ASSERT (X509Data
!= NULL
);
345 // Allocate space for PK certificate list and initialize it.
346 // Create PK database entry with SignatureHeaderSize equals 0.
348 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
349 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
352 if (*PkCert
== NULL
) {
353 Status
= EFI_OUT_OF_RESOURCES
;
357 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
358 + sizeof(EFI_SIGNATURE_DATA
) - 1
360 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
361 (*PkCert
)->SignatureHeaderSize
= 0;
362 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
363 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
364 + sizeof(EFI_SIGNATURE_LIST
)
365 + (*PkCert
)->SignatureHeaderSize
);
366 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
368 // Fill the PK database with PKpub data from X509 certificate file.
370 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
374 if (X509Data
!= NULL
) {
378 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
387 Enroll new PK into the System without original PK's authentication.
389 The SignatureOwner GUID will be the same with PK's vendorguid.
391 @param[in] PrivateData The module's private data.
393 @retval EFI_SUCCESS New PK enrolled successfully.
394 @retval EFI_INVALID_PARAMETER The parameter is invalid.
395 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
400 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
406 EFI_SIGNATURE_LIST
*PkCert
;
410 if (Private
->FileContext
->FileName
== NULL
) {
411 return EFI_INVALID_PARAMETER
;
416 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
417 if (EFI_ERROR (Status
)) {
422 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
424 NameLength
= StrLen (Private
->FileContext
->FileName
);
425 if (NameLength
<= 4) {
426 return EFI_INVALID_PARAMETER
;
428 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
429 if (!IsDerEncodeCertificate(FilePostFix
)) {
430 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
431 return EFI_INVALID_PARAMETER
;
433 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
434 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
437 // Prase the selected PK file and generature PK certificate list.
439 Status
= CreatePkX509SignatureList (
440 Private
->FileContext
->FHandle
,
443 if (EFI_ERROR (Status
)) {
446 ASSERT (PkCert
!= NULL
);
449 // Set Platform Key variable.
451 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
452 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
453 DataSize
= PkCert
->SignatureListSize
;
454 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
455 if (EFI_ERROR (Status
)) {
456 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
460 Status
= gRT
->SetVariable(
461 EFI_PLATFORM_KEY_NAME
,
462 &gEfiGlobalVariableGuid
,
467 if (EFI_ERROR (Status
)) {
468 if (Status
== EFI_OUT_OF_RESOURCES
) {
469 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
476 if (PkCert
!= NULL
) {
480 if (Private
->FileContext
->FHandle
!= NULL
) {
481 CloseFile (Private
->FileContext
->FHandle
);
482 Private
->FileContext
->FHandle
= NULL
;
489 Remove the PK variable.
491 @retval EFI_SUCCESS Delete PK successfully.
492 @retval Others Could not allow to delete PK.
502 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
503 if (EFI_ERROR (Status
)) {
507 Status
= DeleteVariable (
508 EFI_PLATFORM_KEY_NAME
,
509 &gEfiGlobalVariableGuid
515 Enroll a new KEK item from public key storing file (*.pbk).
517 @param[in] PrivateData The module's private data.
519 @retval EFI_SUCCESS New KEK enrolled successfully.
520 @retval EFI_INVALID_PARAMETER The parameter is invalid.
521 @retval EFI_UNSUPPORTED Unsupported command.
522 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
527 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
533 EFI_SIGNATURE_LIST
*KekSigList
;
536 CPL_KEY_INFO
*KeyInfo
;
537 EFI_SIGNATURE_DATA
*KEKSigData
;
538 UINTN KekSigListSize
;
553 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
554 // First, We have to parse out public key data from the pbk key file.
556 Status
= ReadFileContent (
557 Private
->FileContext
->FHandle
,
562 if (EFI_ERROR (Status
)) {
565 ASSERT (KeyBlob
!= NULL
);
566 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
567 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
568 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
569 Status
= EFI_UNSUPPORTED
;
574 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
576 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
577 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
578 if (KeyBuffer
== NULL
) {
579 Status
= EFI_OUT_OF_RESOURCES
;
583 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
584 KeyLenInBytes
/ sizeof (UINTN
),
588 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
591 // Form an new EFI_SIGNATURE_LIST.
593 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
594 + sizeof(EFI_SIGNATURE_DATA
) - 1
595 + WIN_CERT_UEFI_RSA2048_SIZE
;
597 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
598 if (KekSigList
== NULL
) {
599 Status
= EFI_OUT_OF_RESOURCES
;
603 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
604 + sizeof(EFI_SIGNATURE_DATA
) - 1
605 + WIN_CERT_UEFI_RSA2048_SIZE
;
606 KekSigList
->SignatureHeaderSize
= 0;
607 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
608 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
610 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
611 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
613 KEKSigData
->SignatureData
,
614 KeyBlob
+ sizeof(CPL_KEY_INFO
),
615 WIN_CERT_UEFI_RSA2048_SIZE
619 // Check if KEK entry has been already existed.
620 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
621 // new KEK to original variable.
623 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
624 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
625 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
626 if (EFI_ERROR (Status
)) {
627 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
631 Status
= gRT
->GetVariable(
632 EFI_KEY_EXCHANGE_KEY_NAME
,
633 &gEfiGlobalVariableGuid
,
638 if (Status
== EFI_BUFFER_TOO_SMALL
) {
639 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
640 } else if (Status
!= EFI_NOT_FOUND
) {
645 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
647 Status
= gRT
->SetVariable(
648 EFI_KEY_EXCHANGE_KEY_NAME
,
649 &gEfiGlobalVariableGuid
,
654 if (EFI_ERROR (Status
)) {
660 CloseFile (Private
->FileContext
->FHandle
);
661 Private
->FileContext
->FHandle
= NULL
;
663 if (Private
->FileContext
->FileName
!= NULL
){
664 FreePool(Private
->FileContext
->FileName
);
665 Private
->FileContext
->FileName
= NULL
;
668 if (Private
->SignatureGUID
!= NULL
) {
669 FreePool (Private
->SignatureGUID
);
670 Private
->SignatureGUID
= NULL
;
673 if (KeyBlob
!= NULL
) {
676 if (KeyBuffer
!= NULL
) {
677 FreePool (KeyBuffer
);
679 if (KekSigList
!= NULL
) {
680 FreePool (KekSigList
);
687 Enroll a new KEK item from X509 certificate file.
689 @param[in] PrivateData The module's private data.
691 @retval EFI_SUCCESS New X509 is enrolled successfully.
692 @retval EFI_INVALID_PARAMETER The parameter is invalid.
693 @retval EFI_UNSUPPORTED Unsupported command.
694 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
699 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
705 EFI_SIGNATURE_DATA
*KEKSigData
;
706 EFI_SIGNATURE_LIST
*KekSigList
;
708 UINTN KekSigListSize
;
718 Status
= ReadFileContent (
719 Private
->FileContext
->FHandle
,
724 if (EFI_ERROR (Status
)) {
727 ASSERT (X509Data
!= NULL
);
729 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
730 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
731 if (KekSigList
== NULL
) {
732 Status
= EFI_OUT_OF_RESOURCES
;
737 // Fill Certificate Database parameters.
739 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
740 KekSigList
->SignatureHeaderSize
= 0;
741 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
742 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
744 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
745 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
746 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
749 // Check if KEK been already existed.
750 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
751 // new kek to original variable
753 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
754 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
755 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
756 if (EFI_ERROR (Status
)) {
757 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
761 Status
= gRT
->GetVariable(
762 EFI_KEY_EXCHANGE_KEY_NAME
,
763 &gEfiGlobalVariableGuid
,
768 if (Status
== EFI_BUFFER_TOO_SMALL
) {
769 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
770 } else if (Status
!= EFI_NOT_FOUND
) {
774 Status
= gRT
->SetVariable(
775 EFI_KEY_EXCHANGE_KEY_NAME
,
776 &gEfiGlobalVariableGuid
,
781 if (EFI_ERROR (Status
)) {
787 CloseFile (Private
->FileContext
->FHandle
);
788 if (Private
->FileContext
->FileName
!= NULL
){
789 FreePool(Private
->FileContext
->FileName
);
790 Private
->FileContext
->FileName
= NULL
;
793 Private
->FileContext
->FHandle
= NULL
;
795 if (Private
->SignatureGUID
!= NULL
) {
796 FreePool (Private
->SignatureGUID
);
797 Private
->SignatureGUID
= NULL
;
800 if (KekSigList
!= NULL
) {
801 FreePool (KekSigList
);
808 Enroll new KEK into the System without PK's authentication.
809 The SignatureOwner GUID will be Private->SignatureGUID.
811 @param[in] PrivateData The module's private data.
813 @retval EFI_SUCCESS New KEK enrolled successful.
814 @retval EFI_INVALID_PARAMETER The parameter is invalid.
815 @retval others Fail to enroll KEK data.
819 EnrollKeyExchangeKey (
820 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
827 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
828 return EFI_INVALID_PARAMETER
;
831 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
832 if (EFI_ERROR (Status
)) {
837 // Parse the file's postfix. Supports DER-encoded X509 certificate,
838 // and .pbk as RSA public key file.
840 NameLength
= StrLen (Private
->FileContext
->FileName
);
841 if (NameLength
<= 4) {
842 return EFI_INVALID_PARAMETER
;
844 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
845 if (IsDerEncodeCertificate(FilePostFix
)) {
846 return EnrollX509ToKek (Private
);
847 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
848 return EnrollRsa2048ToKek (Private
);
850 return EFI_INVALID_PARAMETER
;
855 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
856 KEK's authentication.
858 @param[in] PrivateData The module's private data.
859 @param[in] VariableName Variable name of signature database, must be
860 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
862 @retval EFI_SUCCESS New X509 is enrolled successfully.
863 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
868 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
869 IN CHAR16
*VariableName
875 EFI_SIGNATURE_LIST
*SigDBCert
;
876 EFI_SIGNATURE_DATA
*SigDBCertData
;
887 SigDBCertData
= NULL
;
890 Status
= ReadFileContent (
891 Private
->FileContext
->FHandle
,
896 if (EFI_ERROR (Status
)) {
899 ASSERT (X509Data
!= NULL
);
901 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
903 Data
= AllocateZeroPool (SigDBSize
);
905 Status
= EFI_OUT_OF_RESOURCES
;
910 // Fill Certificate Database parameters.
912 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
913 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
914 SigDBCert
->SignatureHeaderSize
= 0;
915 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
916 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
918 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
919 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
920 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
923 // Check if signature database entry has been already existed.
924 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
925 // new signature data to original variable
927 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
928 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
929 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
930 if (EFI_ERROR (Status
)) {
931 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
935 Status
= gRT
->GetVariable(
937 &gEfiImageSecurityDatabaseGuid
,
942 if (Status
== EFI_BUFFER_TOO_SMALL
) {
943 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
944 } else if (Status
!= EFI_NOT_FOUND
) {
948 Status
= gRT
->SetVariable(
950 &gEfiImageSecurityDatabaseGuid
,
955 if (EFI_ERROR (Status
)) {
961 CloseFile (Private
->FileContext
->FHandle
);
962 if (Private
->FileContext
->FileName
!= NULL
){
963 FreePool(Private
->FileContext
->FileName
);
964 Private
->FileContext
->FileName
= NULL
;
967 Private
->FileContext
->FHandle
= NULL
;
969 if (Private
->SignatureGUID
!= NULL
) {
970 FreePool (Private
->SignatureGUID
);
971 Private
->SignatureGUID
= NULL
;
978 if (X509Data
!= NULL
) {
986 Check whether signature is in specified database.
988 @param[in] VariableName Name of database variable that is searched in.
989 @param[in] Signature Pointer to signature that is searched for.
990 @param[in] SignatureSize Size of Signature.
992 @return TRUE Found the signature in the variable database.
993 @return FALSE Not found the signature in the variable database.
997 IsSignatureFoundInDatabase (
998 IN CHAR16
*VariableName
,
1000 IN UINTN SignatureSize
1004 EFI_SIGNATURE_LIST
*CertList
;
1005 EFI_SIGNATURE_DATA
*Cert
;
1013 // Read signature database variable.
1018 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1019 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1023 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1028 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1029 if (EFI_ERROR (Status
)) {
1034 // Enumerate all signature data in SigDB to check if executable's signature exists.
1036 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1037 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1038 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1039 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1040 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1041 for (Index
= 0; Index
< CertCount
; Index
++) {
1042 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1044 // Find the signature in database.
1049 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1057 DataSize
-= CertList
->SignatureListSize
;
1058 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1070 Calculate the hash of a certificate data with the specified hash algorithm.
1072 @param[in] CertData The certificate data to be hashed.
1073 @param[in] CertSize The certificate size in bytes.
1074 @param[in] HashAlg The specified hash algorithm.
1075 @param[out] CertHash The output digest of the certificate
1077 @retval TRUE Successfully got the hash of the CertData.
1078 @retval FALSE Failed to get the hash of CertData.
1098 if (HashAlg
>= HASHALG_MAX
) {
1103 // Retrieve the TBSCertificate for Hash Calculation.
1105 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1110 // 1. Initialize context of hash.
1112 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1113 HashCtx
= AllocatePool (CtxSize
);
1114 ASSERT (HashCtx
!= NULL
);
1117 // 2. Initialize a hash context.
1119 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1125 // 3. Calculate the hash.
1127 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1133 // 4. Get the hash result.
1135 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1136 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1139 if (HashCtx
!= NULL
) {
1147 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1149 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1150 @param[in] CertSize Size of X.509 Certificate.
1152 @return TRUE Found the certificate hash in the forbidden database.
1153 @return FALSE Certificate hash is Not found in the forbidden database.
1157 IsCertHashFoundInDbx (
1158 IN UINT8
*Certificate
,
1164 EFI_SIGNATURE_LIST
*DbxList
;
1165 EFI_SIGNATURE_DATA
*CertHash
;
1166 UINTN CertHashCount
;
1169 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1171 UINTN SiglistHeaderSize
;
1176 HashAlg
= HASHALG_MAX
;
1180 // Read signature database variable.
1183 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1184 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1188 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1193 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1194 if (EFI_ERROR (Status
)) {
1199 // Check whether the certificate hash exists in the forbidden database.
1201 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1202 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1204 // Determine Hash Algorithm of Certificate in the forbidden database.
1206 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1207 HashAlg
= HASHALG_SHA256
;
1208 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1209 HashAlg
= HASHALG_SHA384
;
1210 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1211 HashAlg
= HASHALG_SHA512
;
1213 DataSize
-= DbxList
->SignatureListSize
;
1214 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1219 // Calculate the hash value of current db certificate for comparision.
1221 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1225 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1226 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1227 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1228 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1230 // Iterate each Signature Data Node within this CertList for verify.
1232 DbxCertHash
= CertHash
->SignatureData
;
1233 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1235 // Hash of Certificate is found in forbidden database.
1240 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1243 DataSize
-= DbxList
->SignatureListSize
;
1244 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1256 Check whether the signature list exists in given variable data.
1258 It searches the signature list for the ceritificate hash by CertType.
1259 If the signature list is found, get the offset of Database for the
1260 next hash of a certificate.
1262 @param[in] Database Variable data to save signature list.
1263 @param[in] DatabaseSize Variable size.
1264 @param[in] SignatureType The type of the signature.
1265 @param[out] Offset The offset to save a new hash of certificate.
1267 @return TRUE The signature list is found in the forbidden database.
1268 @return FALSE The signature list is not found in the forbidden database.
1271 GetSignaturelistOffset (
1272 IN EFI_SIGNATURE_LIST
*Database
,
1273 IN UINTN DatabaseSize
,
1274 IN EFI_GUID
*SignatureType
,
1278 EFI_SIGNATURE_LIST
*SigList
;
1281 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1287 SiglistSize
= DatabaseSize
;
1288 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1289 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1290 *Offset
= DatabaseSize
- SiglistSize
;
1293 SiglistSize
-= SigList
->SignatureListSize
;
1294 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1301 Enroll a new X509 certificate hash into Signature Database (dbx) without
1302 KEK's authentication.
1304 @param[in] PrivateData The module's private data.
1305 @param[in] HashAlg The hash algorithm to enroll the certificate.
1306 @param[in] RevocationDate The revocation date of the certificate.
1307 @param[in] RevocationTime The revocation time of the certificate.
1308 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1310 @retval EFI_SUCCESS New X509 is enrolled successfully.
1311 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1312 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1316 EnrollX509HashtoSigDB (
1317 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1319 IN EFI_HII_DATE
*RevocationDate
,
1320 IN EFI_HII_TIME
*RevocationTime
,
1321 IN BOOLEAN AlwaysRevocation
1327 EFI_SIGNATURE_LIST
*SignatureList
;
1328 UINTN SignatureListSize
;
1334 EFI_SIGNATURE_DATA
*SignatureData
;
1335 UINTN SignatureSize
;
1336 EFI_GUID SignatureType
;
1338 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1339 UINT16
* FilePostFix
;
1346 SignatureData
= NULL
;
1347 SignatureList
= NULL
;
1351 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1352 return EFI_INVALID_PARAMETER
;
1355 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1356 if (EFI_ERROR (Status
)) {
1361 // Parse the file's postfix.
1363 NameLength
= StrLen (Private
->FileContext
->FileName
);
1364 if (NameLength
<= 4) {
1365 return EFI_INVALID_PARAMETER
;
1367 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1368 if (!IsDerEncodeCertificate(FilePostFix
)) {
1370 // Only supports DER-encoded X509 certificate.
1372 return EFI_INVALID_PARAMETER
;
1376 // Get the certificate from file and calculate its hash.
1378 Status
= ReadFileContent (
1379 Private
->FileContext
->FHandle
,
1384 if (EFI_ERROR (Status
)) {
1387 ASSERT (X509Data
!= NULL
);
1389 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1394 // Get the variable for enrollment.
1397 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1398 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1399 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1401 return EFI_OUT_OF_RESOURCES
;
1404 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1405 if (EFI_ERROR (Status
)) {
1411 // Allocate memory for Signature and fill the Signature
1413 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1414 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1415 if (SignatureData
== NULL
) {
1416 return EFI_OUT_OF_RESOURCES
;
1418 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1419 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1424 if (!AlwaysRevocation
) {
1425 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1426 Time
->Year
= RevocationDate
->Year
;
1427 Time
->Month
= RevocationDate
->Month
;
1428 Time
->Day
= RevocationDate
->Day
;
1429 Time
->Hour
= RevocationTime
->Hour
;
1430 Time
->Minute
= RevocationTime
->Minute
;
1431 Time
->Second
= RevocationTime
->Second
;
1435 // Determine the GUID for certificate hash.
1438 case HASHALG_SHA256
:
1439 SignatureType
= gEfiCertX509Sha256Guid
;
1441 case HASHALG_SHA384
:
1442 SignatureType
= gEfiCertX509Sha384Guid
;
1444 case HASHALG_SHA512
:
1445 SignatureType
= gEfiCertX509Sha512Guid
;
1452 // Add signature into the new variable data buffer
1454 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1456 // Add the signature to the found signaturelist.
1458 DbSize
= DataSize
+ SignatureSize
;
1459 NewData
= AllocateZeroPool (DbSize
);
1460 if (NewData
== NULL
) {
1461 Status
= EFI_OUT_OF_RESOURCES
;
1465 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1466 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1467 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1469 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1470 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1472 Offset
+= SignatureListSize
;
1473 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1474 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1481 // Create a new signaturelist, and add the signature into the signaturelist.
1483 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1484 NewData
= AllocateZeroPool (DbSize
);
1485 if (NewData
== NULL
) {
1486 Status
= EFI_OUT_OF_RESOURCES
;
1490 // Fill Certificate Database parameters.
1492 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1493 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1494 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1495 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1496 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1497 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1498 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1499 CopyMem (NewData
, Data
, DataSize
);
1506 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1507 if (EFI_ERROR (Status
)) {
1511 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1512 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1513 Status
= gRT
->SetVariable(
1514 EFI_IMAGE_SECURITY_DATABASE1
,
1515 &gEfiImageSecurityDatabaseGuid
,
1520 if (EFI_ERROR (Status
)) {
1525 CloseFile (Private
->FileContext
->FHandle
);
1526 if (Private
->FileContext
->FileName
!= NULL
){
1527 FreePool(Private
->FileContext
->FileName
);
1528 Private
->FileContext
->FileName
= NULL
;
1531 Private
->FileContext
->FHandle
= NULL
;
1533 if (Private
->SignatureGUID
!= NULL
) {
1534 FreePool (Private
->SignatureGUID
);
1535 Private
->SignatureGUID
= NULL
;
1542 if (SignatureData
!= NULL
) {
1543 FreePool (SignatureData
);
1546 if (X509Data
!= NULL
) {
1547 FreePool (X509Data
);
1554 Check whether a certificate from a file exists in dbx.
1556 @param[in] PrivateData The module's private data.
1557 @param[in] VariableName Variable name of signature database, must be
1558 EFI_IMAGE_SECURITY_DATABASE1.
1560 @retval TRUE The X509 certificate is found in dbx successfully.
1561 @retval FALSE The X509 certificate is not found in dbx.
1565 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1566 IN CHAR16
*VariableName
1575 // Read the certificate from file
1579 Status
= ReadFileContent (
1580 Private
->FileContext
->FHandle
,
1585 if (EFI_ERROR (Status
)) {
1590 // Check the raw certificate.
1593 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1599 // Check the hash of certificate.
1601 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1607 if (X509Data
!= NULL
) {
1608 FreePool (X509Data
);
1615 Load PE/COFF image information into internal buffer and check its validity.
1617 @retval EFI_SUCCESS Successful
1618 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1619 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1627 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1628 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1629 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1634 // Read the Dos header
1636 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1637 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1640 // DOS image header is present,
1641 // So read the PE header after the DOS image header
1643 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1647 mPeCoffHeaderOffset
= 0;
1651 // Read PE header and check the signature validity and machine compatibility
1653 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1654 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1656 return EFI_UNSUPPORTED
;
1659 mNtHeader
.Pe32
= NtHeader32
;
1662 // Check the architecture field of PE header and get the Certificate Data Directory data
1663 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1665 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1666 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1667 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1669 // 32-bits Architecture
1671 mImageType
= ImageType_IA32
;
1672 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1674 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1675 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1676 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1678 // 64-bits Architecture
1680 mImageType
= ImageType_X64
;
1681 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1682 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1684 return EFI_UNSUPPORTED
;
1691 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1692 PE/COFF Specification 8.0 Appendix A
1694 @param[in] HashAlg Hash algorithm type.
1696 @retval TRUE Successfully hash image.
1697 @retval FALSE Fail in hash image.
1707 EFI_IMAGE_SECTION_HEADER
*Section
;
1712 UINTN SumOfBytesHashed
;
1713 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1718 SectionHeader
= NULL
;
1721 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1726 // Initialize context of hash.
1728 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1730 if (HashAlg
== HASHALG_SHA1
) {
1731 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1732 mCertType
= gEfiCertSha1Guid
;
1733 } else if (HashAlg
== HASHALG_SHA256
) {
1734 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1735 mCertType
= gEfiCertSha256Guid
;
1738 CtxSize
= mHash
[HashAlg
].GetContextSize();
1740 HashCtx
= AllocatePool (CtxSize
);
1741 ASSERT (HashCtx
!= NULL
);
1743 // 1. Load the image header into memory.
1745 // 2. Initialize a SHA hash context.
1746 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1751 // Measuring PE/COFF Image Header;
1752 // But CheckSum field and SECURITY data directory (certificate) are excluded
1754 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1756 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1757 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1758 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1759 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1761 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1764 // Get the magic value from the PE/COFF Optional Header
1766 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1770 // 3. Calculate the distance from the base of the image header to the image checksum address.
1771 // 4. Hash the image header from its base to beginning of the image checksum.
1773 HashBase
= mImageBase
;
1774 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1778 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1781 // Use PE32+ offset.
1783 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1786 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1791 // 5. Skip over the image checksum (it occupies a single ULONG).
1792 // 6. Get the address of the beginning of the Cert Directory.
1793 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1795 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1799 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1800 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1803 // Use PE32+ offset.
1805 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1806 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1809 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1814 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1815 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1817 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1821 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1822 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1825 // Use PE32+ offset.
1827 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1828 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1831 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1836 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1838 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1842 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1847 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1851 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1852 // structures in the image. The 'NumberOfSections' field of the image
1853 // header indicates how big the table should be. Do not include any
1854 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1856 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1857 ASSERT (SectionHeader
!= NULL
);
1859 // 12. Using the 'PointerToRawData' in the referenced section headers as
1860 // a key, arrange the elements in the table in ascending order. In other
1861 // words, sort the section headers according to the disk-file offset of
1864 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1866 mPeCoffHeaderOffset
+
1868 sizeof (EFI_IMAGE_FILE_HEADER
) +
1869 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1871 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1873 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1874 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1877 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1882 // 13. Walk through the sorted table, bring the corresponding section
1883 // into memory, and hash the entire section (using the 'SizeOfRawData'
1884 // field in the section header to determine the amount of data to hash).
1885 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1886 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1888 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1889 Section
= &SectionHeader
[Index
];
1890 if (Section
->SizeOfRawData
== 0) {
1893 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1894 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1896 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1901 SumOfBytesHashed
+= HashSize
;
1905 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1906 // data in the file that needs to be added to the hash. This data begins
1907 // at file offset SUM_OF_BYTES_HASHED and its length is:
1908 // FileSize - (CertDirectory->Size)
1910 if (mImageSize
> SumOfBytesHashed
) {
1911 HashBase
= mImageBase
+ SumOfBytesHashed
;
1912 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1918 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1922 // Use PE32+ offset.
1926 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1930 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1936 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1939 if (HashCtx
!= NULL
) {
1942 if (SectionHeader
!= NULL
) {
1943 FreePool (SectionHeader
);
1949 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
1950 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1953 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1954 @retval EFI_SUCCESS Hash successfully.
1963 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1965 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1967 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1969 // Check the Hash algorithm in PE/COFF Authenticode.
1970 // According to PKCS#7 Definition:
1971 // SignedData ::= SEQUENCE {
1973 // digestAlgorithms DigestAlgorithmIdentifiers,
1974 // contentInfo ContentInfo,
1976 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1977 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1978 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1980 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1982 // Only support two bytes of Long Form of Length Encoding.
1988 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1993 if (Index
== HASHALG_MAX
) {
1994 return EFI_UNSUPPORTED
;
1998 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2000 if (!HashPeImage(Index
)) {
2001 return EFI_UNSUPPORTED
;
2008 Enroll a new executable's signature into Signature Database.
2010 @param[in] PrivateData The module's private data.
2011 @param[in] VariableName Variable name of signature database, must be
2012 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2013 or EFI_IMAGE_SECURITY_DATABASE2.
2015 @retval EFI_SUCCESS New signature is enrolled successfully.
2016 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2017 @retval EFI_UNSUPPORTED Unsupported command.
2018 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2022 EnrollImageSignatureToSigDB (
2023 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2024 IN CHAR16
*VariableName
2028 EFI_SIGNATURE_LIST
*SigDBCert
;
2029 EFI_SIGNATURE_DATA
*SigDBCertData
;
2034 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2037 GuidCertData
= NULL
;
2039 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2040 return EFI_UNSUPPORTED
;
2044 // Form the SigDB certificate list.
2045 // Format the data item into EFI_SIGNATURE_LIST type.
2047 // We need to parse executable's signature data from specified signed executable file.
2048 // In current implementation, we simply trust the pass-in signed executable file.
2049 // In reality, it's OS's responsibility to verify the signed executable file.
2053 // Read the whole file content
2055 Status
= ReadFileContent(
2056 Private
->FileContext
->FHandle
,
2057 (VOID
**) &mImageBase
,
2061 if (EFI_ERROR (Status
)) {
2064 ASSERT (mImageBase
!= NULL
);
2066 Status
= LoadPeImage ();
2067 if (EFI_ERROR (Status
)) {
2071 if (mSecDataDir
->SizeOfCert
== 0) {
2072 if (!HashPeImage (HASHALG_SHA256
)) {
2073 Status
= EFI_SECURITY_VIOLATION
;
2079 // Read the certificate data
2081 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2083 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2084 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2085 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2086 Status
= EFI_ABORTED
;
2090 if (!HashPeImage (HASHALG_SHA256
)) {
2091 Status
= EFI_ABORTED
;
2095 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2097 Status
= HashPeImageByType ();
2098 if (EFI_ERROR (Status
)) {
2102 Status
= EFI_ABORTED
;
2108 // Create a new SigDB entry.
2110 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2111 + sizeof(EFI_SIGNATURE_DATA
) - 1
2112 + (UINT32
) mImageDigestSize
;
2114 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2116 Status
= EFI_OUT_OF_RESOURCES
;
2121 // Adjust the Certificate Database parameters.
2123 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2124 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2125 SigDBCert
->SignatureHeaderSize
= 0;
2126 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2127 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2129 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2130 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2131 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2133 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2134 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2135 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2136 if (EFI_ERROR (Status
)) {
2137 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2142 // Check if SigDB variable has been already existed.
2143 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2144 // new signature data to original variable
2147 Status
= gRT
->GetVariable(
2149 &gEfiImageSecurityDatabaseGuid
,
2154 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2155 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2156 } else if (Status
!= EFI_NOT_FOUND
) {
2161 // Enroll the variable.
2163 Status
= gRT
->SetVariable(
2165 &gEfiImageSecurityDatabaseGuid
,
2170 if (EFI_ERROR (Status
)) {
2176 CloseFile (Private
->FileContext
->FHandle
);
2177 Private
->FileContext
->FHandle
= NULL
;
2179 if (Private
->FileContext
->FileName
!= NULL
){
2180 FreePool(Private
->FileContext
->FileName
);
2181 Private
->FileContext
->FileName
= NULL
;
2184 if (Private
->SignatureGUID
!= NULL
) {
2185 FreePool (Private
->SignatureGUID
);
2186 Private
->SignatureGUID
= NULL
;
2193 if (mImageBase
!= NULL
) {
2194 FreePool (mImageBase
);
2202 Enroll signature into DB/DBX/DBT without KEK's authentication.
2203 The SignatureOwner GUID will be Private->SignatureGUID.
2205 @param[in] PrivateData The module's private data.
2206 @param[in] VariableName Variable name of signature database, must be
2207 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2209 @retval EFI_SUCCESS New signature enrolled successfully.
2210 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2211 @retval others Fail to enroll signature data.
2215 EnrollSignatureDatabase (
2216 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2217 IN CHAR16
*VariableName
2220 UINT16
* FilePostFix
;
2224 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2225 return EFI_INVALID_PARAMETER
;
2228 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2229 if (EFI_ERROR (Status
)) {
2234 // Parse the file's postfix.
2236 NameLength
= StrLen (Private
->FileContext
->FileName
);
2237 if (NameLength
<= 4) {
2238 return EFI_INVALID_PARAMETER
;
2240 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2241 if (IsDerEncodeCertificate (FilePostFix
)) {
2243 // Supports DER-encoded X509 certificate.
2245 return EnrollX509toSigDB (Private
, VariableName
);
2248 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2252 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2253 by GUID in the page for user to select and delete as needed.
2255 @param[in] PrivateData Module's private data.
2256 @param[in] VariableName The variable name of the vendor's signature database.
2257 @param[in] VendorGuid A unique identifier for the vendor.
2258 @param[in] LabelNumber Label number to insert opcodes.
2259 @param[in] FormId Form ID of current page.
2260 @param[in] QuestionIdBase Base question id of the signature list.
2262 @retval EFI_SUCCESS Success to update the signature list page
2263 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2268 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2269 IN CHAR16
*VariableName
,
2270 IN EFI_GUID
*VendorGuid
,
2271 IN UINT16 LabelNumber
,
2272 IN EFI_FORM_ID FormId
,
2273 IN EFI_QUESTION_ID QuestionIdBase
2280 VOID
*StartOpCodeHandle
;
2281 VOID
*EndOpCodeHandle
;
2282 EFI_IFR_GUID_LABEL
*StartLabel
;
2283 EFI_IFR_GUID_LABEL
*EndLabel
;
2286 EFI_SIGNATURE_LIST
*CertList
;
2287 EFI_SIGNATURE_DATA
*Cert
;
2288 UINT32 ItemDataSize
;
2290 EFI_STRING_ID GuidID
;
2297 StartOpCodeHandle
= NULL
;
2298 EndOpCodeHandle
= NULL
;
2301 // Initialize the container for dynamic opcodes.
2303 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2304 if (StartOpCodeHandle
== NULL
) {
2305 Status
= EFI_OUT_OF_RESOURCES
;
2309 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2310 if (EndOpCodeHandle
== NULL
) {
2311 Status
= EFI_OUT_OF_RESOURCES
;
2316 // Create Hii Extend Label OpCode.
2318 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2322 sizeof (EFI_IFR_GUID_LABEL
)
2324 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2325 StartLabel
->Number
= LabelNumber
;
2327 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2331 sizeof (EFI_IFR_GUID_LABEL
)
2333 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2334 EndLabel
->Number
= LABEL_END
;
2340 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2341 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2345 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2347 Status
= EFI_OUT_OF_RESOURCES
;
2351 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2352 if (EFI_ERROR (Status
)) {
2356 GuidStr
= AllocateZeroPool (100);
2357 if (GuidStr
== NULL
) {
2358 Status
= EFI_OUT_OF_RESOURCES
;
2363 // Enumerate all KEK pub data.
2365 ItemDataSize
= (UINT32
) DataSize
;
2366 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2369 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2371 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2372 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2373 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2374 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2375 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2376 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2377 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2378 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2379 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2380 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2381 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2382 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2383 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2384 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2387 // The signature type is not supported in current implementation.
2389 ItemDataSize
-= CertList
->SignatureListSize
;
2390 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2394 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2395 for (Index
= 0; Index
< CertCount
; Index
++) {
2396 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2397 + sizeof (EFI_SIGNATURE_LIST
)
2398 + CertList
->SignatureHeaderSize
2399 + Index
* CertList
->SignatureSize
);
2401 // Display GUID and help
2403 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2404 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2405 HiiCreateCheckBoxOpCode (
2407 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2412 EFI_IFR_FLAG_CALLBACK
,
2418 ItemDataSize
-= CertList
->SignatureListSize
;
2419 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2424 PrivateData
->HiiHandle
,
2425 &gSecureBootConfigFormSetGuid
,
2431 if (StartOpCodeHandle
!= NULL
) {
2432 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2435 if (EndOpCodeHandle
!= NULL
) {
2436 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2443 if (GuidStr
!= NULL
) {
2451 Delete a KEK entry from KEK database.
2453 @param[in] PrivateData Module's private data.
2454 @param[in] QuestionId Question id of the KEK item to delete.
2456 @retval EFI_SUCCESS Delete kek item successfully.
2457 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2461 DeleteKeyExchangeKey (
2462 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2463 IN EFI_QUESTION_ID QuestionId
2472 EFI_SIGNATURE_LIST
*CertList
;
2473 EFI_SIGNATURE_LIST
*NewCertList
;
2474 EFI_SIGNATURE_DATA
*Cert
;
2477 BOOLEAN IsKEKItemFound
;
2479 UINTN DeleteKekIndex
;
2487 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2489 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2490 if (EFI_ERROR (Status
)) {
2495 // Get original KEK variable.
2498 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2499 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2503 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2504 if (OldData
== NULL
) {
2505 Status
= EFI_OUT_OF_RESOURCES
;
2509 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2510 if (EFI_ERROR(Status
)) {
2515 // Allocate space for new variable.
2517 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2519 Status
= EFI_OUT_OF_RESOURCES
;
2524 // Enumerate all KEK pub data and erasing the target item.
2526 IsKEKItemFound
= FALSE
;
2527 KekDataSize
= (UINT32
) DataSize
;
2528 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2531 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2532 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2533 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2534 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2535 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2536 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2537 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2538 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2539 for (Index
= 0; Index
< CertCount
; Index
++) {
2540 if (GuidIndex
== DeleteKekIndex
) {
2542 // Find it! Skip it!
2544 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2545 IsKEKItemFound
= TRUE
;
2548 // This item doesn't match. Copy it to the Data buffer.
2550 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2551 Offset
+= CertList
->SignatureSize
;
2554 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2558 // This List doesn't match. Copy it to the Data buffer.
2560 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2561 Offset
+= CertList
->SignatureListSize
;
2564 KekDataSize
-= CertList
->SignatureListSize
;
2565 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2568 if (!IsKEKItemFound
) {
2570 // Doesn't find the Kek Item!
2572 Status
= EFI_NOT_FOUND
;
2577 // Delete the Signature header if there is no signature in the list.
2579 KekDataSize
= Offset
;
2580 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2582 ZeroMem (OldData
, KekDataSize
);
2583 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2584 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2585 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2586 if (CertCount
!= 0) {
2587 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2588 Offset
+= CertList
->SignatureListSize
;
2590 KekDataSize
-= CertList
->SignatureListSize
;
2591 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2595 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2596 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2597 if (EFI_ERROR (Status
)) {
2598 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2603 Status
= gRT
->SetVariable(
2604 EFI_KEY_EXCHANGE_KEY_NAME
,
2605 &gEfiGlobalVariableGuid
,
2610 if (EFI_ERROR (Status
)) {
2611 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2620 if (OldData
!= NULL
) {
2624 return UpdateDeletePage (
2626 EFI_KEY_EXCHANGE_KEY_NAME
,
2627 &gEfiGlobalVariableGuid
,
2629 FORMID_DELETE_KEK_FORM
,
2630 OPTION_DEL_KEK_QUESTION_ID
2635 Delete a signature entry from siganture database.
2637 @param[in] PrivateData Module's private data.
2638 @param[in] VariableName The variable name of the vendor's signature database.
2639 @param[in] VendorGuid A unique identifier for the vendor.
2640 @param[in] LabelNumber Label number to insert opcodes.
2641 @param[in] FormId Form ID of current page.
2642 @param[in] QuestionIdBase Base question id of the signature list.
2643 @param[in] DeleteIndex Signature index to delete.
2645 @retval EFI_SUCCESS Delete siganture successfully.
2646 @retval EFI_NOT_FOUND Can't find the signature item,
2647 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2651 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2652 IN CHAR16
*VariableName
,
2653 IN EFI_GUID
*VendorGuid
,
2654 IN UINT16 LabelNumber
,
2655 IN EFI_FORM_ID FormId
,
2656 IN EFI_QUESTION_ID QuestionIdBase
,
2657 IN UINTN DeleteIndex
2666 EFI_SIGNATURE_LIST
*CertList
;
2667 EFI_SIGNATURE_LIST
*NewCertList
;
2668 EFI_SIGNATURE_DATA
*Cert
;
2671 BOOLEAN IsItemFound
;
2672 UINT32 ItemDataSize
;
2681 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2682 if (EFI_ERROR (Status
)) {
2687 // Get original signature list data.
2690 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2691 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2695 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2696 if (OldData
== NULL
) {
2697 Status
= EFI_OUT_OF_RESOURCES
;
2701 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2702 if (EFI_ERROR(Status
)) {
2707 // Allocate space for new variable.
2709 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2711 Status
= EFI_OUT_OF_RESOURCES
;
2716 // Enumerate all signature data and erasing the target item.
2718 IsItemFound
= FALSE
;
2719 ItemDataSize
= (UINT32
) DataSize
;
2720 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2723 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2724 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2725 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2726 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2727 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2728 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2729 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2730 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2733 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2735 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2736 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2737 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2738 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2739 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2740 for (Index
= 0; Index
< CertCount
; Index
++) {
2741 if (GuidIndex
== DeleteIndex
) {
2743 // Find it! Skip it!
2745 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2749 // This item doesn't match. Copy it to the Data buffer.
2751 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2752 Offset
+= CertList
->SignatureSize
;
2755 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2759 // This List doesn't match. Just copy it to the Data buffer.
2761 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2762 Offset
+= CertList
->SignatureListSize
;
2765 ItemDataSize
-= CertList
->SignatureListSize
;
2766 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2771 // Doesn't find the signature Item!
2773 Status
= EFI_NOT_FOUND
;
2778 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2780 ItemDataSize
= Offset
;
2781 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2783 ZeroMem (OldData
, ItemDataSize
);
2784 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2785 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2786 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2787 if (CertCount
!= 0) {
2788 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2789 Offset
+= CertList
->SignatureListSize
;
2791 ItemDataSize
-= CertList
->SignatureListSize
;
2792 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2796 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2797 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2798 if (EFI_ERROR (Status
)) {
2799 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2804 Status
= gRT
->SetVariable(
2811 if (EFI_ERROR (Status
)) {
2812 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2821 if (OldData
!= NULL
) {
2825 return UpdateDeletePage (
2836 Perform secure boot mode transition from User Mode by setting AuditMode
2837 or DeployedMode variable.
2839 @param[in] NewMode New secure boot mode.
2841 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2844 TransitionFromUserMode(
2851 if (NewMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
2853 Status
= gRT
->SetVariable(
2854 EFI_AUDIT_MODE_NAME
,
2855 &gEfiGlobalVariableGuid
,
2856 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2861 } else if (NewMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
2863 Status
= gRT
->SetVariable(
2864 EFI_DEPLOYED_MODE_NAME
,
2865 &gEfiGlobalVariableGuid
,
2866 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2874 // Other case do nothing here. May Goto enroll PK page.
2880 Perform secure boot mode transition from Setup Mode by setting AuditMode
2883 @param[in] NewMode New secure boot mode.
2885 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2888 TransitionFromSetupMode(
2895 Status
= EFI_INVALID_PARAMETER
;
2897 if (NewMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
2899 Status
= gRT
->SetVariable(
2900 EFI_AUDIT_MODE_NAME
,
2901 &gEfiGlobalVariableGuid
,
2902 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2910 // Other case do nothing here. May Goto enroll PK page.
2916 Perform secure boot mode transition from Audit Mode. Nothing is done here,
2917 should goto enroll PK page.
2919 @param[in] NewMode New secure boot mode.
2921 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2924 TransitionFromAuditMode(
2929 // Other case do nothing here. Should Goto enroll PK page.
2935 Perform secure boot mode transition from Deployed Mode by setting Deployed Mode
2938 @param[in] NewMode New secure boot mode.
2940 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2943 TransitionFromDeployedMode(
2951 // Platform specific logic. when physical presence, Allow to set DeployedMode =:0
2952 // to switch back to UserMode
2954 if (NewMode
== SECURE_BOOT_MODE_USER_MODE
) {
2956 Status
= gRT
->SetVariable(
2957 EFI_DEPLOYED_MODE_NAME
,
2958 &gEfiGlobalVariableGuid
,
2959 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2963 DEBUG((EFI_D_INFO
, "DeployedMode Status %x\n", Status
));
2970 Perform main secure boot mode transition.
2972 @param[in] CurMode New secure boot mode.
2973 @param[in] NewMode New secure boot mode.
2975 @retval EFI_SUCCESS Secure Boot mode transition is successful.
2978 SecureBootModeTransition(
2986 // Set platform to be customized mode to ensure platform specific mode switch sucess
2988 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2989 if (EFI_ERROR (Status
)) {
2994 // SecureBootMode transition
2997 case SECURE_BOOT_MODE_USER_MODE
:
2998 Status
= TransitionFromUserMode(NewMode
);
3001 case SECURE_BOOT_MODE_SETUP_MODE
:
3002 Status
= TransitionFromSetupMode(NewMode
);
3005 case SECURE_BOOT_MODE_AUDIT_MODE
:
3006 Status
= TransitionFromAuditMode(NewMode
);
3009 case SECURE_BOOT_MODE_DEPLOYED_MODE
:
3010 Status
= TransitionFromDeployedMode(NewMode
);
3014 Status
= EFI_INVALID_PARAMETER
;
3022 Get current secure boot mode by retrieve data from SetupMode/AuditMode/DeployedMode.
3024 @param[out] SecureBootMode Current secure boot mode.
3028 ExtractSecureBootModeFromVariable(
3029 OUT UINT8
*SecureBootMode
3034 UINT8
*DeployedMode
;
3038 DeployedMode
= NULL
;
3041 // Get AuditMode/DeployedMode from variable
3043 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3044 GetVariable2 (EFI_AUDIT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&AuditMode
, NULL
);
3045 GetVariable2 (EFI_DEPLOYED_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&DeployedMode
, NULL
);
3046 if (SetupMode
!= NULL
&& AuditMode
!= NULL
&& DeployedMode
!= NULL
) {
3047 if (*SetupMode
== 0 && *AuditMode
== 0 && *DeployedMode
== 0) {
3051 *SecureBootMode
= SECURE_BOOT_MODE_USER_MODE
;
3052 } else if (*SetupMode
== 1 && *AuditMode
== 0 && *DeployedMode
== 0) {
3056 *SecureBootMode
= SECURE_BOOT_MODE_SETUP_MODE
;
3057 } else if (*SetupMode
== 1 && *AuditMode
== 1 && *DeployedMode
== 0) {
3061 *SecureBootMode
= SECURE_BOOT_MODE_AUDIT_MODE
;
3062 } else if (*SetupMode
== 0 && *AuditMode
== 0 && *DeployedMode
== 1) {
3066 *SecureBootMode
= SECURE_BOOT_MODE_DEPLOYED_MODE
;
3074 if (SetupMode
!= NULL
) {
3075 FreePool (SetupMode
);
3077 if (DeployedMode
!= NULL
) {
3078 FreePool (DeployedMode
);
3080 if (AuditMode
!= NULL
) {
3081 FreePool (AuditMode
);
3087 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3088 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3090 @param[in] PrivateData Module's private data.
3092 @return EFI_SUCCESS Update secure boot strings successfully.
3093 @return other Fail to update secure boot strings.
3097 UpdateSecureBootString(
3098 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3101 UINT8 CurSecureBootMode
;
3107 // Get current secure boot state.
3109 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3110 if (SecureBoot
== NULL
) {
3111 return EFI_NOT_FOUND
;
3114 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3115 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3117 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3120 // Get current secure boot mode.
3122 ExtractSecureBootModeFromVariable(&CurSecureBootMode
);
3124 if (CurSecureBootMode
== SECURE_BOOT_MODE_USER_MODE
) {
3125 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"UserMode", NULL
);
3126 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
) {
3127 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"SetupMode", NULL
);
3128 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3129 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"AuditMode", NULL
);
3130 } else if (CurSecureBootMode
== SECURE_BOOT_MODE_DEPLOYED_MODE
) {
3131 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT
), L
"DeployedMode", NULL
);
3134 FreePool(SecureBoot
);
3140 This function extracts configuration from variable.
3142 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3146 SecureBootExtractConfigFromVariable (
3147 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3150 UINT8
*SecureBootEnable
;
3151 UINT8
*SecureBootMode
;
3154 SecureBootEnable
= NULL
;
3155 SecureBootMode
= NULL
;
3158 // Initilize the Date and Time using system time.
3160 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3161 ConfigData
->AlwaysRevocation
= TRUE
;
3162 gRT
->GetTime (&CurrTime
, NULL
);
3163 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3164 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3165 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3166 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3167 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3168 ConfigData
->RevocationTime
.Second
= 0;
3171 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3174 ConfigData
->AttemptSecureBoot
= FALSE
;
3175 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3176 if (SecureBootEnable
== NULL
) {
3177 ConfigData
->HideSecureBoot
= TRUE
;
3179 ConfigData
->HideSecureBoot
= FALSE
;
3180 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
3181 ConfigData
->AttemptSecureBoot
= TRUE
;
3186 // If it is Physical Presence User, set the PhysicalPresent to true.
3188 if (UserPhysicalPresent()) {
3189 ConfigData
->PhysicalPresent
= TRUE
;
3191 ConfigData
->PhysicalPresent
= FALSE
;
3195 // Get the SecureBootMode from CustomMode variable.
3197 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3198 if (SecureBootMode
== NULL
) {
3199 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3201 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3205 // Extact current Secure Boot Mode
3207 ExtractSecureBootModeFromVariable(&ConfigData
->CurSecureBootMode
);
3210 // If there is no PK then the Delete Pk button will be gray.
3212 if (ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_SETUP_MODE
|| ConfigData
->CurSecureBootMode
== SECURE_BOOT_MODE_AUDIT_MODE
) {
3213 ConfigData
->HasPk
= FALSE
;
3215 ConfigData
->HasPk
= TRUE
;
3218 if (SecureBootEnable
!= NULL
) {
3219 FreePool (SecureBootEnable
);
3222 if (SecureBootMode
!= NULL
) {
3223 FreePool (SecureBootMode
);
3228 This function allows a caller to extract the current configuration for one
3229 or more named elements from the target driver.
3231 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3232 @param[in] Request A null-terminated Unicode string in
3233 <ConfigRequest> format.
3234 @param[out] Progress On return, points to a character in the Request
3235 string. Points to the string's null terminator if
3236 request was successful. Points to the most recent
3237 '&' before the first failing name/value pair (or
3238 the beginning of the string if the failure is in
3239 the first name/value pair) if the request was not
3241 @param[out] Results A null-terminated Unicode string in
3242 <ConfigAltResp> format which has all values filled
3243 in for the names in the Request string. String to
3244 be allocated by the called function.
3246 @retval EFI_SUCCESS The Results is filled with the requested values.
3247 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3248 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3249 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3255 SecureBootExtractConfig (
3256 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3257 IN CONST EFI_STRING Request
,
3258 OUT EFI_STRING
*Progress
,
3259 OUT EFI_STRING
*Results
3265 SECUREBOOT_CONFIGURATION Configuration
;
3266 EFI_STRING ConfigRequest
;
3267 EFI_STRING ConfigRequestHdr
;
3268 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3269 BOOLEAN AllocatedRequest
;
3271 if (Progress
== NULL
|| Results
== NULL
) {
3272 return EFI_INVALID_PARAMETER
;
3275 AllocatedRequest
= FALSE
;
3276 ConfigRequestHdr
= NULL
;
3277 ConfigRequest
= NULL
;
3280 ZeroMem (&Configuration
, sizeof (Configuration
));
3281 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3282 *Progress
= Request
;
3284 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3285 return EFI_NOT_FOUND
;
3289 // Get Configuration from Variable.
3291 SecureBootExtractConfigFromVariable (&Configuration
);
3293 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3294 ConfigRequest
= Request
;
3295 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3297 // Request is set to NULL or OFFSET is NULL, construct full request string.
3299 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3300 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3302 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3303 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3304 ConfigRequest
= AllocateZeroPool (Size
);
3305 ASSERT (ConfigRequest
!= NULL
);
3306 AllocatedRequest
= TRUE
;
3307 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3308 FreePool (ConfigRequestHdr
);
3309 ConfigRequestHdr
= NULL
;
3312 Status
= gHiiConfigRouting
->BlockToConfig (
3315 (UINT8
*) &Configuration
,
3322 // Free the allocated config request string.
3324 if (AllocatedRequest
) {
3325 FreePool (ConfigRequest
);
3329 // Set Progress string to the original request string.
3331 if (Request
== NULL
) {
3333 } else if (StrStr (Request
, L
"OFFSET"