2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "SecureBootConfigImpl.h"
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
) (END_DEVICE_PATH_LENGTH
),
45 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
51 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
54 // OID ASN.1 Value for Hash Algorithms
56 UINT8 mHashOidValue
[] = {
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
65 HASH_TABLE mHash
[] = {
66 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
67 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
68 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
69 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
70 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
74 // Variable Definitions
76 UINT32 mPeCoffHeaderOffset
= 0;
77 WIN_CERTIFICATE
*mCertificate
= NULL
;
78 IMAGE_TYPE mImageType
;
79 UINT8
*mImageBase
= NULL
;
81 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
82 UINTN mImageDigestSize
;
84 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
85 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
88 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
90 CHAR16
* mDerEncodedSuffix
[] = {
96 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
99 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
101 @param[in] FileSuffix The suffix of the input certificate file
103 @retval TRUE It's a DER-encoded certificate.
104 @retval FALSE It's NOT a DER-encoded certificate.
108 IsDerEncodeCertificate (
109 IN CONST CHAR16
*FileSuffix
113 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
114 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
122 Set Secure Boot option into variable space.
124 @param[in] VarValue The option of Secure Boot.
126 @retval EFI_SUCCESS The operation is finished successfully.
127 @retval Others Other errors as indicated.
131 SaveSecureBootVariable (
137 Status
= gRT
->SetVariable (
138 EFI_SECURE_BOOT_ENABLE_NAME
,
139 &gEfiSecureBootEnableDisableGuid
,
140 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
148 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
149 descriptor with the input data. NO authentication is required in this function.
151 @param[in, out] DataSize On input, the size of Data buffer in bytes.
152 On output, the size of data returned in Data
154 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
155 pointer to NULL to wrap an empty payload.
156 On output, Pointer to the new payload date buffer allocated from pool,
157 it's caller's responsibility to free the memory when finish using it.
159 @retval EFI_SUCCESS Create time based payload successfully.
160 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
161 @retval EFI_INVALID_PARAMETER The parameter is invalid.
162 @retval Others Unexpected error happens.
166 CreateTimeBasedPayload (
167 IN OUT UINTN
*DataSize
,
175 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
176 UINTN DescriptorSize
;
179 if (Data
== NULL
|| DataSize
== NULL
) {
180 return EFI_INVALID_PARAMETER
;
184 // In Setup mode or Custom mode, the variable does not need to be signed but the
185 // parameters to the SetVariable() call still need to be prepared as authenticated
186 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
190 PayloadSize
= *DataSize
;
192 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
193 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
194 if (NewData
== NULL
) {
195 return EFI_OUT_OF_RESOURCES
;
198 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
199 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
202 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
204 ZeroMem (&Time
, sizeof (EFI_TIME
));
205 Status
= gRT
->GetTime (&Time
, NULL
);
206 if (EFI_ERROR (Status
)) {
215 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
217 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
218 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
219 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
220 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
222 if (Payload
!= NULL
) {
226 *DataSize
= DescriptorSize
+ PayloadSize
;
232 Internal helper function to delete a Variable given its name and GUID, NO authentication
235 @param[in] VariableName Name of the Variable.
236 @param[in] VendorGuid GUID of the Variable.
238 @retval EFI_SUCCESS Variable deleted successfully.
239 @retval Others The driver failed to start the device.
244 IN CHAR16
*VariableName
,
245 IN EFI_GUID
*VendorGuid
254 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
255 if (Variable
== NULL
) {
262 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
263 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
265 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
266 if (EFI_ERROR (Status
)) {
267 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
271 Status
= gRT
->SetVariable (
286 Set the platform secure boot mode into "Custom" or "Standard" mode.
288 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
289 CUSTOM_SECURE_BOOT_MODE.
291 @return EFI_SUCCESS The platform has switched to the special mode successfully.
292 @return other Fail to operate the secure boot mode.
297 IN UINT8 SecureBootMode
300 return gRT
->SetVariable (
301 EFI_CUSTOM_MODE_NAME
,
302 &gEfiCustomModeEnableGuid
,
303 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
310 Generate the PK signature list from the X509 Certificate storing file (.cer)
312 @param[in] X509File FileHandle of X509 Certificate storing file.
313 @param[out] PkCert Point to the data buffer to store the signature list.
315 @return EFI_UNSUPPORTED Unsupported Key Length.
316 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
320 CreatePkX509SignatureList (
321 IN EFI_FILE_HANDLE X509File
,
322 OUT EFI_SIGNATURE_LIST
**PkCert
328 EFI_SIGNATURE_DATA
*PkCertData
;
334 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
335 if (EFI_ERROR (Status
)) {
338 ASSERT (X509Data
!= NULL
);
341 // Allocate space for PK certificate list and initialize it.
342 // Create PK database entry with SignatureHeaderSize equals 0.
344 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
345 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
348 if (*PkCert
== NULL
) {
349 Status
= EFI_OUT_OF_RESOURCES
;
353 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
354 + sizeof(EFI_SIGNATURE_DATA
) - 1
356 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
357 (*PkCert
)->SignatureHeaderSize
= 0;
358 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
359 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
360 + sizeof(EFI_SIGNATURE_LIST
)
361 + (*PkCert
)->SignatureHeaderSize
);
362 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
364 // Fill the PK database with PKpub data from X509 certificate file.
366 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
370 if (X509Data
!= NULL
) {
374 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
383 Enroll new PK into the System without original PK's authentication.
385 The SignatureOwner GUID will be the same with PK's vendorguid.
387 @param[in] PrivateData The module's private data.
389 @retval EFI_SUCCESS New PK enrolled successfully.
390 @retval EFI_INVALID_PARAMETER The parameter is invalid.
391 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
396 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
402 EFI_SIGNATURE_LIST
*PkCert
;
406 if (Private
->FileContext
->FileName
== NULL
) {
407 return EFI_INVALID_PARAMETER
;
412 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
413 if (EFI_ERROR (Status
)) {
418 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
420 NameLength
= StrLen (Private
->FileContext
->FileName
);
421 if (NameLength
<= 4) {
422 return EFI_INVALID_PARAMETER
;
424 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
425 if (!IsDerEncodeCertificate(FilePostFix
)) {
426 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
427 return EFI_INVALID_PARAMETER
;
429 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
430 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
433 // Prase the selected PK file and generature PK certificate list.
435 Status
= CreatePkX509SignatureList (
436 Private
->FileContext
->FHandle
,
439 if (EFI_ERROR (Status
)) {
442 ASSERT (PkCert
!= NULL
);
445 // Set Platform Key variable.
447 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
448 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
449 DataSize
= PkCert
->SignatureListSize
;
450 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
451 if (EFI_ERROR (Status
)) {
452 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
456 Status
= gRT
->SetVariable(
457 EFI_PLATFORM_KEY_NAME
,
458 &gEfiGlobalVariableGuid
,
463 if (EFI_ERROR (Status
)) {
464 if (Status
== EFI_OUT_OF_RESOURCES
) {
465 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
472 if (PkCert
!= NULL
) {
476 if (Private
->FileContext
->FHandle
!= NULL
) {
477 CloseFile (Private
->FileContext
->FHandle
);
478 Private
->FileContext
->FHandle
= NULL
;
485 Remove the PK variable.
487 @retval EFI_SUCCESS Delete PK successfully.
488 @retval Others Could not allow to delete PK.
498 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
499 if (EFI_ERROR (Status
)) {
503 Status
= DeleteVariable (
504 EFI_PLATFORM_KEY_NAME
,
505 &gEfiGlobalVariableGuid
511 Enroll a new KEK item from public key storing file (*.pbk).
513 @param[in] PrivateData The module's private data.
515 @retval EFI_SUCCESS New KEK enrolled successfully.
516 @retval EFI_INVALID_PARAMETER The parameter is invalid.
517 @retval EFI_UNSUPPORTED Unsupported command.
518 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
523 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
529 EFI_SIGNATURE_LIST
*KekSigList
;
532 CPL_KEY_INFO
*KeyInfo
;
533 EFI_SIGNATURE_DATA
*KEKSigData
;
534 UINTN KekSigListSize
;
549 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
550 // First, We have to parse out public key data from the pbk key file.
552 Status
= ReadFileContent (
553 Private
->FileContext
->FHandle
,
558 if (EFI_ERROR (Status
)) {
561 ASSERT (KeyBlob
!= NULL
);
562 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
563 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
564 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
565 Status
= EFI_UNSUPPORTED
;
570 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
572 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
573 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
574 if (KeyBuffer
== NULL
) {
575 Status
= EFI_OUT_OF_RESOURCES
;
579 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
580 KeyLenInBytes
/ sizeof (UINTN
),
584 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
587 // Form an new EFI_SIGNATURE_LIST.
589 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
590 + sizeof(EFI_SIGNATURE_DATA
) - 1
591 + WIN_CERT_UEFI_RSA2048_SIZE
;
593 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
594 if (KekSigList
== NULL
) {
595 Status
= EFI_OUT_OF_RESOURCES
;
599 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
600 + sizeof(EFI_SIGNATURE_DATA
) - 1
601 + WIN_CERT_UEFI_RSA2048_SIZE
;
602 KekSigList
->SignatureHeaderSize
= 0;
603 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
604 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
606 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
607 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
609 KEKSigData
->SignatureData
,
610 KeyBlob
+ sizeof(CPL_KEY_INFO
),
611 WIN_CERT_UEFI_RSA2048_SIZE
615 // Check if KEK entry has been already existed.
616 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
617 // new KEK to original variable.
619 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
620 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
621 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
622 if (EFI_ERROR (Status
)) {
623 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
627 Status
= gRT
->GetVariable(
628 EFI_KEY_EXCHANGE_KEY_NAME
,
629 &gEfiGlobalVariableGuid
,
634 if (Status
== EFI_BUFFER_TOO_SMALL
) {
635 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
636 } else if (Status
!= EFI_NOT_FOUND
) {
641 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
643 Status
= gRT
->SetVariable(
644 EFI_KEY_EXCHANGE_KEY_NAME
,
645 &gEfiGlobalVariableGuid
,
650 if (EFI_ERROR (Status
)) {
656 CloseFile (Private
->FileContext
->FHandle
);
657 Private
->FileContext
->FHandle
= NULL
;
658 Private
->FileContext
->FileName
= NULL
;
660 if (Private
->SignatureGUID
!= NULL
) {
661 FreePool (Private
->SignatureGUID
);
662 Private
->SignatureGUID
= NULL
;
665 if (KeyBlob
!= NULL
) {
668 if (KeyBuffer
!= NULL
) {
669 FreePool (KeyBuffer
);
671 if (KekSigList
!= NULL
) {
672 FreePool (KekSigList
);
679 Enroll a new KEK item from X509 certificate file.
681 @param[in] PrivateData The module's private data.
683 @retval EFI_SUCCESS New X509 is enrolled successfully.
684 @retval EFI_INVALID_PARAMETER The parameter is invalid.
685 @retval EFI_UNSUPPORTED Unsupported command.
686 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
691 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
697 EFI_SIGNATURE_DATA
*KEKSigData
;
698 EFI_SIGNATURE_LIST
*KekSigList
;
700 UINTN KekSigListSize
;
710 Status
= ReadFileContent (
711 Private
->FileContext
->FHandle
,
716 if (EFI_ERROR (Status
)) {
719 ASSERT (X509Data
!= NULL
);
721 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
722 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
723 if (KekSigList
== NULL
) {
724 Status
= EFI_OUT_OF_RESOURCES
;
729 // Fill Certificate Database parameters.
731 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
732 KekSigList
->SignatureHeaderSize
= 0;
733 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
734 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
736 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
737 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
738 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
741 // Check if KEK been already existed.
742 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
743 // new kek to original variable
745 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
746 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
747 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
748 if (EFI_ERROR (Status
)) {
749 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
753 Status
= gRT
->GetVariable(
754 EFI_KEY_EXCHANGE_KEY_NAME
,
755 &gEfiGlobalVariableGuid
,
760 if (Status
== EFI_BUFFER_TOO_SMALL
) {
761 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
762 } else if (Status
!= EFI_NOT_FOUND
) {
766 Status
= gRT
->SetVariable(
767 EFI_KEY_EXCHANGE_KEY_NAME
,
768 &gEfiGlobalVariableGuid
,
773 if (EFI_ERROR (Status
)) {
779 CloseFile (Private
->FileContext
->FHandle
);
780 Private
->FileContext
->FileName
= NULL
;
781 Private
->FileContext
->FHandle
= NULL
;
783 if (Private
->SignatureGUID
!= NULL
) {
784 FreePool (Private
->SignatureGUID
);
785 Private
->SignatureGUID
= NULL
;
788 if (KekSigList
!= NULL
) {
789 FreePool (KekSigList
);
796 Enroll new KEK into the System without PK's authentication.
797 The SignatureOwner GUID will be Private->SignatureGUID.
799 @param[in] PrivateData The module's private data.
801 @retval EFI_SUCCESS New KEK enrolled successful.
802 @retval EFI_INVALID_PARAMETER The parameter is invalid.
803 @retval others Fail to enroll KEK data.
807 EnrollKeyExchangeKey (
808 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
815 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
816 return EFI_INVALID_PARAMETER
;
819 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
820 if (EFI_ERROR (Status
)) {
825 // Parse the file's postfix. Supports DER-encoded X509 certificate,
826 // and .pbk as RSA public key file.
828 NameLength
= StrLen (Private
->FileContext
->FileName
);
829 if (NameLength
<= 4) {
830 return EFI_INVALID_PARAMETER
;
832 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
833 if (IsDerEncodeCertificate(FilePostFix
)) {
834 return EnrollX509ToKek (Private
);
835 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
836 return EnrollRsa2048ToKek (Private
);
838 return EFI_INVALID_PARAMETER
;
843 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
844 KEK's authentication.
846 @param[in] PrivateData The module's private data.
847 @param[in] VariableName Variable name of signature database, must be
848 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
850 @retval EFI_SUCCESS New X509 is enrolled successfully.
851 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
856 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
857 IN CHAR16
*VariableName
863 EFI_SIGNATURE_LIST
*SigDBCert
;
864 EFI_SIGNATURE_DATA
*SigDBCertData
;
875 SigDBCertData
= NULL
;
878 Status
= ReadFileContent (
879 Private
->FileContext
->FHandle
,
884 if (EFI_ERROR (Status
)) {
887 ASSERT (X509Data
!= NULL
);
889 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
891 Data
= AllocateZeroPool (SigDBSize
);
893 Status
= EFI_OUT_OF_RESOURCES
;
898 // Fill Certificate Database parameters.
900 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
901 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
902 SigDBCert
->SignatureHeaderSize
= 0;
903 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
904 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
906 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
907 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
908 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
911 // Check if signature database entry has been already existed.
912 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
913 // new signature data to original variable
915 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
916 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
917 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
918 if (EFI_ERROR (Status
)) {
919 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
923 Status
= gRT
->GetVariable(
925 &gEfiImageSecurityDatabaseGuid
,
930 if (Status
== EFI_BUFFER_TOO_SMALL
) {
931 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
932 } else if (Status
!= EFI_NOT_FOUND
) {
936 Status
= gRT
->SetVariable(
938 &gEfiImageSecurityDatabaseGuid
,
943 if (EFI_ERROR (Status
)) {
949 CloseFile (Private
->FileContext
->FHandle
);
950 Private
->FileContext
->FileName
= NULL
;
951 Private
->FileContext
->FHandle
= NULL
;
953 if (Private
->SignatureGUID
!= NULL
) {
954 FreePool (Private
->SignatureGUID
);
955 Private
->SignatureGUID
= NULL
;
962 if (X509Data
!= NULL
) {
970 Check whether signature is in specified database.
972 @param[in] VariableName Name of database variable that is searched in.
973 @param[in] Signature Pointer to signature that is searched for.
974 @param[in] SignatureSize Size of Signature.
976 @return TRUE Found the signature in the variable database.
977 @return FALSE Not found the signature in the variable database.
981 IsSignatureFoundInDatabase (
982 IN CHAR16
*VariableName
,
984 IN UINTN SignatureSize
988 EFI_SIGNATURE_LIST
*CertList
;
989 EFI_SIGNATURE_DATA
*Cert
;
997 // Read signature database variable.
1002 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1003 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1007 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1012 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1013 if (EFI_ERROR (Status
)) {
1018 // Enumerate all signature data in SigDB to check if executable's signature exists.
1020 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1021 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1022 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1023 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1024 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1025 for (Index
= 0; Index
< CertCount
; Index
++) {
1026 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1028 // Find the signature in database.
1033 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1041 DataSize
-= CertList
->SignatureListSize
;
1042 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1054 Calculate the hash of a certificate data with the specified hash algorithm.
1056 @param[in] CertData The certificate data to be hashed.
1057 @param[in] CertSize The certificate size in bytes.
1058 @param[in] HashAlg The specified hash algorithm.
1059 @param[out] CertHash The output digest of the certificate
1061 @retval TRUE Successfully got the hash of the CertData.
1062 @retval FALSE Failed to get the hash of CertData.
1082 if (HashAlg
>= HASHALG_MAX
) {
1087 // Retrieve the TBSCertificate for Hash Calculation.
1089 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1094 // 1. Initialize context of hash.
1096 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1097 HashCtx
= AllocatePool (CtxSize
);
1098 ASSERT (HashCtx
!= NULL
);
1101 // 2. Initialize a hash context.
1103 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1109 // 3. Calculate the hash.
1111 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1117 // 4. Get the hash result.
1119 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1120 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1123 if (HashCtx
!= NULL
) {
1131 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1133 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1134 @param[in] CertSize Size of X.509 Certificate.
1136 @return TRUE Found the certificate hash in the forbidden database.
1137 @return FALSE Certificate hash is Not found in the forbidden database.
1141 IsCertHashFoundInDbx (
1142 IN UINT8
*Certificate
,
1148 EFI_SIGNATURE_LIST
*DbxList
;
1149 EFI_SIGNATURE_DATA
*CertHash
;
1150 UINTN CertHashCount
;
1153 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1155 UINTN SiglistHeaderSize
;
1160 HashAlg
= HASHALG_MAX
;
1164 // Read signature database variable.
1167 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1168 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1172 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1177 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1178 if (EFI_ERROR (Status
)) {
1183 // Check whether the certificate hash exists in the forbidden database.
1185 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1186 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1188 // Determine Hash Algorithm of Certificate in the forbidden database.
1190 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1191 HashAlg
= HASHALG_SHA256
;
1192 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1193 HashAlg
= HASHALG_SHA384
;
1194 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1195 HashAlg
= HASHALG_SHA512
;
1197 DataSize
-= DbxList
->SignatureListSize
;
1198 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1203 // Calculate the hash value of current db certificate for comparision.
1205 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1209 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1210 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1211 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1212 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1214 // Iterate each Signature Data Node within this CertList for verify.
1216 DbxCertHash
= CertHash
->SignatureData
;
1217 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1219 // Hash of Certificate is found in forbidden database.
1224 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1227 DataSize
-= DbxList
->SignatureListSize
;
1228 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1240 Check whether the signature list exists in given variable data.
1242 It searches the signature list for the ceritificate hash by CertType.
1243 If the signature list is found, get the offset of Database for the
1244 next hash of a certificate.
1246 @param[in] Database Variable data to save signature list.
1247 @param[in] DatabaseSize Variable size.
1248 @param[in] SignatureType The type of the signature.
1249 @param[out] Offset The offset to save a new hash of certificate.
1251 @return TRUE The signature list is found in the forbidden database.
1252 @return FALSE The signature list is not found in the forbidden database.
1255 GetSignaturelistOffset (
1256 IN EFI_SIGNATURE_LIST
*Database
,
1257 IN UINTN DatabaseSize
,
1258 IN EFI_GUID
*SignatureType
,
1262 EFI_SIGNATURE_LIST
*SigList
;
1265 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1271 SiglistSize
= DatabaseSize
;
1272 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1273 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1274 *Offset
= DatabaseSize
- SiglistSize
;
1277 SiglistSize
-= SigList
->SignatureListSize
;
1278 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1285 Enroll a new X509 certificate hash into Signature Database (dbx) without
1286 KEK's authentication.
1288 @param[in] PrivateData The module's private data.
1289 @param[in] HashAlg The hash algorithm to enroll the certificate.
1290 @param[in] RevocationDate The revocation date of the certificate.
1291 @param[in] RevocationTime The revocation time of the certificate.
1292 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1294 @retval EFI_SUCCESS New X509 is enrolled successfully.
1295 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1296 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1300 EnrollX509HashtoSigDB (
1301 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1303 IN EFI_HII_DATE
*RevocationDate
,
1304 IN EFI_HII_TIME
*RevocationTime
,
1305 IN BOOLEAN AlwaysRevocation
1311 EFI_SIGNATURE_LIST
*SignatureList
;
1312 UINTN SignatureListSize
;
1318 EFI_SIGNATURE_DATA
*SignatureData
;
1319 UINTN SignatureSize
;
1320 EFI_GUID SignatureType
;
1322 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1323 UINT16
* FilePostFix
;
1330 SignatureData
= NULL
;
1331 SignatureList
= NULL
;
1335 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1336 return EFI_INVALID_PARAMETER
;
1339 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1340 if (EFI_ERROR (Status
)) {
1345 // Parse the file's postfix.
1347 NameLength
= StrLen (Private
->FileContext
->FileName
);
1348 if (NameLength
<= 4) {
1349 return EFI_INVALID_PARAMETER
;
1351 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1352 if (!IsDerEncodeCertificate(FilePostFix
)) {
1354 // Only supports DER-encoded X509 certificate.
1356 return EFI_INVALID_PARAMETER
;
1360 // Get the certificate from file and calculate its hash.
1362 Status
= ReadFileContent (
1363 Private
->FileContext
->FHandle
,
1368 if (EFI_ERROR (Status
)) {
1371 ASSERT (X509Data
!= NULL
);
1373 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1378 // Get the variable for enrollment.
1381 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1382 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1383 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1385 return EFI_OUT_OF_RESOURCES
;
1388 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1389 if (EFI_ERROR (Status
)) {
1395 // Allocate memory for Signature and fill the Signature
1397 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1398 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1399 if (SignatureData
== NULL
) {
1400 return EFI_OUT_OF_RESOURCES
;
1402 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1403 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1408 if (!AlwaysRevocation
) {
1409 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1410 Time
->Year
= RevocationDate
->Year
;
1411 Time
->Month
= RevocationDate
->Month
;
1412 Time
->Day
= RevocationDate
->Day
;
1413 Time
->Hour
= RevocationTime
->Hour
;
1414 Time
->Minute
= RevocationTime
->Minute
;
1415 Time
->Second
= RevocationTime
->Second
;
1419 // Determine the GUID for certificate hash.
1422 case HASHALG_SHA256
:
1423 SignatureType
= gEfiCertX509Sha256Guid
;
1425 case HASHALG_SHA384
:
1426 SignatureType
= gEfiCertX509Sha384Guid
;
1428 case HASHALG_SHA512
:
1429 SignatureType
= gEfiCertX509Sha512Guid
;
1436 // Add signature into the new variable data buffer
1438 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1440 // Add the signature to the found signaturelist.
1442 DbSize
= DataSize
+ SignatureSize
;
1443 NewData
= AllocateZeroPool (DbSize
);
1444 if (NewData
== NULL
) {
1445 Status
= EFI_OUT_OF_RESOURCES
;
1449 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1450 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1451 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1453 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1454 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1456 Offset
+= SignatureListSize
;
1457 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1458 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1465 // Create a new signaturelist, and add the signature into the signaturelist.
1467 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1468 NewData
= AllocateZeroPool (DbSize
);
1469 if (NewData
== NULL
) {
1470 Status
= EFI_OUT_OF_RESOURCES
;
1474 // Fill Certificate Database parameters.
1476 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1477 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1478 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1479 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1480 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1481 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1482 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1483 CopyMem (NewData
, Data
, DataSize
);
1490 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1491 if (EFI_ERROR (Status
)) {
1495 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1496 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1497 Status
= gRT
->SetVariable(
1498 EFI_IMAGE_SECURITY_DATABASE1
,
1499 &gEfiImageSecurityDatabaseGuid
,
1504 if (EFI_ERROR (Status
)) {
1509 CloseFile (Private
->FileContext
->FHandle
);
1510 Private
->FileContext
->FileName
= NULL
;
1511 Private
->FileContext
->FHandle
= NULL
;
1513 if (Private
->SignatureGUID
!= NULL
) {
1514 FreePool (Private
->SignatureGUID
);
1515 Private
->SignatureGUID
= NULL
;
1522 if (SignatureData
!= NULL
) {
1523 FreePool (SignatureData
);
1526 if (X509Data
!= NULL
) {
1527 FreePool (X509Data
);
1534 Check whether a certificate from a file exists in dbx.
1536 @param[in] PrivateData The module's private data.
1537 @param[in] VariableName Variable name of signature database, must be
1538 EFI_IMAGE_SECURITY_DATABASE1.
1540 @retval TRUE The X509 certificate is found in dbx successfully.
1541 @retval FALSE The X509 certificate is not found in dbx.
1545 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1546 IN CHAR16
*VariableName
1555 // Read the certificate from file
1559 Status
= ReadFileContent (
1560 Private
->FileContext
->FHandle
,
1565 if (EFI_ERROR (Status
)) {
1570 // Check the raw certificate.
1573 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1579 // Check the hash of certificate.
1581 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1587 if (X509Data
!= NULL
) {
1588 FreePool (X509Data
);
1595 Load PE/COFF image information into internal buffer and check its validity.
1597 @retval EFI_SUCCESS Successful
1598 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1599 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1607 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1608 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1609 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1614 // Read the Dos header
1616 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1617 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1620 // DOS image header is present,
1621 // So read the PE header after the DOS image header
1623 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1627 mPeCoffHeaderOffset
= 0;
1631 // Read PE header and check the signature validity and machine compatibility
1633 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1634 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1636 return EFI_UNSUPPORTED
;
1639 mNtHeader
.Pe32
= NtHeader32
;
1642 // Check the architecture field of PE header and get the Certificate Data Directory data
1643 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1645 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1646 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
1648 // IA-32 Architecture
1650 mImageType
= ImageType_IA32
;
1651 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1653 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1654 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
1656 // 64-bits Architecture
1658 mImageType
= ImageType_X64
;
1659 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1660 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1662 return EFI_UNSUPPORTED
;
1669 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1670 PE/COFF Specification 8.0 Appendix A
1672 @param[in] HashAlg Hash algorithm type.
1674 @retval TRUE Successfully hash image.
1675 @retval FALSE Fail in hash image.
1685 EFI_IMAGE_SECTION_HEADER
*Section
;
1690 UINTN SumOfBytesHashed
;
1691 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1696 SectionHeader
= NULL
;
1699 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1704 // Initialize context of hash.
1706 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1708 if (HashAlg
== HASHALG_SHA1
) {
1709 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1710 mCertType
= gEfiCertSha1Guid
;
1711 } else if (HashAlg
== HASHALG_SHA256
) {
1712 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1713 mCertType
= gEfiCertSha256Guid
;
1716 CtxSize
= mHash
[HashAlg
].GetContextSize();
1718 HashCtx
= AllocatePool (CtxSize
);
1719 ASSERT (HashCtx
!= NULL
);
1721 // 1. Load the image header into memory.
1723 // 2. Initialize a SHA hash context.
1724 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1729 // Measuring PE/COFF Image Header;
1730 // But CheckSum field and SECURITY data directory (certificate) are excluded
1732 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1734 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1735 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1736 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1737 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1739 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1742 // Get the magic value from the PE/COFF Optional Header
1744 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1748 // 3. Calculate the distance from the base of the image header to the image checksum address.
1749 // 4. Hash the image header from its base to beginning of the image checksum.
1751 HashBase
= mImageBase
;
1752 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1756 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1759 // Use PE32+ offset.
1761 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1764 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1769 // 5. Skip over the image checksum (it occupies a single ULONG).
1770 // 6. Get the address of the beginning of the Cert Directory.
1771 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1773 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1777 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1778 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1781 // Use PE32+ offset.
1783 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1784 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1787 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1792 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1793 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1795 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1799 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1800 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1803 // Use PE32+ offset.
1805 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1806 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1809 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1814 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1816 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1820 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1825 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1829 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1830 // structures in the image. The 'NumberOfSections' field of the image
1831 // header indicates how big the table should be. Do not include any
1832 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1834 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1835 ASSERT (SectionHeader
!= NULL
);
1837 // 12. Using the 'PointerToRawData' in the referenced section headers as
1838 // a key, arrange the elements in the table in ascending order. In other
1839 // words, sort the section headers according to the disk-file offset of
1842 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1844 mPeCoffHeaderOffset
+
1846 sizeof (EFI_IMAGE_FILE_HEADER
) +
1847 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1849 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1851 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1852 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1855 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1860 // 13. Walk through the sorted table, bring the corresponding section
1861 // into memory, and hash the entire section (using the 'SizeOfRawData'
1862 // field in the section header to determine the amount of data to hash).
1863 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1864 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1866 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1867 Section
= &SectionHeader
[Index
];
1868 if (Section
->SizeOfRawData
== 0) {
1871 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1872 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1874 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1879 SumOfBytesHashed
+= HashSize
;
1883 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1884 // data in the file that needs to be added to the hash. This data begins
1885 // at file offset SUM_OF_BYTES_HASHED and its length is:
1886 // FileSize - (CertDirectory->Size)
1888 if (mImageSize
> SumOfBytesHashed
) {
1889 HashBase
= mImageBase
+ SumOfBytesHashed
;
1890 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1896 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1900 // Use PE32+ offset.
1904 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1908 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1914 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1917 if (HashCtx
!= NULL
) {
1920 if (SectionHeader
!= NULL
) {
1921 FreePool (SectionHeader
);
1927 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1928 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1931 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1932 @retval EFI_SUCCESS Hash successfully.
1941 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1943 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1945 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1947 // Check the Hash algorithm in PE/COFF Authenticode.
1948 // According to PKCS#7 Definition:
1949 // SignedData ::= SEQUENCE {
1951 // digestAlgorithms DigestAlgorithmIdentifiers,
1952 // contentInfo ContentInfo,
1954 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1955 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1956 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1958 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1960 // Only support two bytes of Long Form of Length Encoding.
1966 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1971 if (Index
== HASHALG_MAX
) {
1972 return EFI_UNSUPPORTED
;
1976 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1978 if (!HashPeImage(Index
)) {
1979 return EFI_UNSUPPORTED
;
1986 Enroll a new executable's signature into Signature Database.
1988 @param[in] PrivateData The module's private data.
1989 @param[in] VariableName Variable name of signature database, must be
1990 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
1991 or EFI_IMAGE_SECURITY_DATABASE2.
1993 @retval EFI_SUCCESS New signature is enrolled successfully.
1994 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1995 @retval EFI_UNSUPPORTED Unsupported command.
1996 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2000 EnrollImageSignatureToSigDB (
2001 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2002 IN CHAR16
*VariableName
2006 EFI_SIGNATURE_LIST
*SigDBCert
;
2007 EFI_SIGNATURE_DATA
*SigDBCertData
;
2012 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2015 GuidCertData
= NULL
;
2017 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2018 return EFI_UNSUPPORTED
;
2022 // Form the SigDB certificate list.
2023 // Format the data item into EFI_SIGNATURE_LIST type.
2025 // We need to parse executable's signature data from specified signed executable file.
2026 // In current implementation, we simply trust the pass-in signed executable file.
2027 // In reality, it's OS's responsibility to verify the signed executable file.
2031 // Read the whole file content
2033 Status
= ReadFileContent(
2034 Private
->FileContext
->FHandle
,
2035 (VOID
**) &mImageBase
,
2039 if (EFI_ERROR (Status
)) {
2042 ASSERT (mImageBase
!= NULL
);
2044 Status
= LoadPeImage ();
2045 if (EFI_ERROR (Status
)) {
2049 if (mSecDataDir
->SizeOfCert
== 0) {
2050 if (!HashPeImage (HASHALG_SHA256
)) {
2051 Status
= EFI_SECURITY_VIOLATION
;
2057 // Read the certificate data
2059 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2061 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2062 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2063 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2064 Status
= EFI_ABORTED
;
2068 if (!HashPeImage (HASHALG_SHA256
)) {
2069 Status
= EFI_ABORTED
;
2073 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2075 Status
= HashPeImageByType ();
2076 if (EFI_ERROR (Status
)) {
2080 Status
= EFI_ABORTED
;
2086 // Create a new SigDB entry.
2088 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2089 + sizeof(EFI_SIGNATURE_DATA
) - 1
2090 + (UINT32
) mImageDigestSize
;
2092 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2094 Status
= EFI_OUT_OF_RESOURCES
;
2099 // Adjust the Certificate Database parameters.
2101 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2102 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2103 SigDBCert
->SignatureHeaderSize
= 0;
2104 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2105 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2107 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2108 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2109 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2111 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2112 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2113 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2114 if (EFI_ERROR (Status
)) {
2115 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2120 // Check if SigDB variable has been already existed.
2121 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2122 // new signature data to original variable
2125 Status
= gRT
->GetVariable(
2127 &gEfiImageSecurityDatabaseGuid
,
2132 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2133 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2134 } else if (Status
!= EFI_NOT_FOUND
) {
2139 // Enroll the variable.
2141 Status
= gRT
->SetVariable(
2143 &gEfiImageSecurityDatabaseGuid
,
2148 if (EFI_ERROR (Status
)) {
2154 CloseFile (Private
->FileContext
->FHandle
);
2155 Private
->FileContext
->FHandle
= NULL
;
2156 Private
->FileContext
->FileName
= NULL
;
2158 if (Private
->SignatureGUID
!= NULL
) {
2159 FreePool (Private
->SignatureGUID
);
2160 Private
->SignatureGUID
= NULL
;
2167 if (mImageBase
!= NULL
) {
2168 FreePool (mImageBase
);
2176 Enroll signature into DB/DBX/DBT without KEK's authentication.
2177 The SignatureOwner GUID will be Private->SignatureGUID.
2179 @param[in] PrivateData The module's private data.
2180 @param[in] VariableName Variable name of signature database, must be
2181 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2183 @retval EFI_SUCCESS New signature enrolled successfully.
2184 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2185 @retval others Fail to enroll signature data.
2189 EnrollSignatureDatabase (
2190 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2191 IN CHAR16
*VariableName
2194 UINT16
* FilePostFix
;
2198 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2199 return EFI_INVALID_PARAMETER
;
2202 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2203 if (EFI_ERROR (Status
)) {
2208 // Parse the file's postfix.
2210 NameLength
= StrLen (Private
->FileContext
->FileName
);
2211 if (NameLength
<= 4) {
2212 return EFI_INVALID_PARAMETER
;
2214 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2215 if (IsDerEncodeCertificate (FilePostFix
)) {
2217 // Supports DER-encoded X509 certificate.
2219 return EnrollX509toSigDB (Private
, VariableName
);
2222 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2226 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2227 by GUID in the page for user to select and delete as needed.
2229 @param[in] PrivateData Module's private data.
2230 @param[in] VariableName The variable name of the vendor's signature database.
2231 @param[in] VendorGuid A unique identifier for the vendor.
2232 @param[in] LabelNumber Label number to insert opcodes.
2233 @param[in] FormId Form ID of current page.
2234 @param[in] QuestionIdBase Base question id of the signature list.
2236 @retval EFI_SUCCESS Success to update the signature list page
2237 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2242 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2243 IN CHAR16
*VariableName
,
2244 IN EFI_GUID
*VendorGuid
,
2245 IN UINT16 LabelNumber
,
2246 IN EFI_FORM_ID FormId
,
2247 IN EFI_QUESTION_ID QuestionIdBase
2254 VOID
*StartOpCodeHandle
;
2255 VOID
*EndOpCodeHandle
;
2256 EFI_IFR_GUID_LABEL
*StartLabel
;
2257 EFI_IFR_GUID_LABEL
*EndLabel
;
2260 EFI_SIGNATURE_LIST
*CertList
;
2261 EFI_SIGNATURE_DATA
*Cert
;
2262 UINT32 ItemDataSize
;
2264 EFI_STRING_ID GuidID
;
2271 StartOpCodeHandle
= NULL
;
2272 EndOpCodeHandle
= NULL
;
2275 // Initialize the container for dynamic opcodes.
2277 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2278 if (StartOpCodeHandle
== NULL
) {
2279 Status
= EFI_OUT_OF_RESOURCES
;
2283 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2284 if (EndOpCodeHandle
== NULL
) {
2285 Status
= EFI_OUT_OF_RESOURCES
;
2290 // Create Hii Extend Label OpCode.
2292 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2296 sizeof (EFI_IFR_GUID_LABEL
)
2298 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2299 StartLabel
->Number
= LabelNumber
;
2301 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2305 sizeof (EFI_IFR_GUID_LABEL
)
2307 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2308 EndLabel
->Number
= LABEL_END
;
2314 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2315 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2319 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2321 Status
= EFI_OUT_OF_RESOURCES
;
2325 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2326 if (EFI_ERROR (Status
)) {
2330 GuidStr
= AllocateZeroPool (100);
2331 if (GuidStr
== NULL
) {
2332 Status
= EFI_OUT_OF_RESOURCES
;
2337 // Enumerate all KEK pub data.
2339 ItemDataSize
= (UINT32
) DataSize
;
2340 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2343 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2345 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2346 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2347 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2348 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2349 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2350 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2351 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2352 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2353 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2354 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2355 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2356 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2357 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2358 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2361 // The signature type is not supported in current implementation.
2363 ItemDataSize
-= CertList
->SignatureListSize
;
2364 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2368 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2369 for (Index
= 0; Index
< CertCount
; Index
++) {
2370 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2371 + sizeof (EFI_SIGNATURE_LIST
)
2372 + CertList
->SignatureHeaderSize
2373 + Index
* CertList
->SignatureSize
);
2375 // Display GUID and help
2377 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2378 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2379 HiiCreateCheckBoxOpCode (
2381 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2386 EFI_IFR_FLAG_CALLBACK
,
2392 ItemDataSize
-= CertList
->SignatureListSize
;
2393 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2398 PrivateData
->HiiHandle
,
2399 &gSecureBootConfigFormSetGuid
,
2405 if (StartOpCodeHandle
!= NULL
) {
2406 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2409 if (EndOpCodeHandle
!= NULL
) {
2410 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2417 if (GuidStr
!= NULL
) {
2425 Delete a KEK entry from KEK database.
2427 @param[in] PrivateData Module's private data.
2428 @param[in] QuestionId Question id of the KEK item to delete.
2430 @retval EFI_SUCCESS Delete kek item successfully.
2431 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2435 DeleteKeyExchangeKey (
2436 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2437 IN EFI_QUESTION_ID QuestionId
2446 EFI_SIGNATURE_LIST
*CertList
;
2447 EFI_SIGNATURE_LIST
*NewCertList
;
2448 EFI_SIGNATURE_DATA
*Cert
;
2451 BOOLEAN IsKEKItemFound
;
2453 UINTN DeleteKekIndex
;
2461 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2463 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2464 if (EFI_ERROR (Status
)) {
2469 // Get original KEK variable.
2472 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2473 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2477 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2478 if (OldData
== NULL
) {
2479 Status
= EFI_OUT_OF_RESOURCES
;
2483 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2484 if (EFI_ERROR(Status
)) {
2489 // Allocate space for new variable.
2491 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2493 Status
= EFI_OUT_OF_RESOURCES
;
2498 // Enumerate all KEK pub data and erasing the target item.
2500 IsKEKItemFound
= FALSE
;
2501 KekDataSize
= (UINT32
) DataSize
;
2502 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2505 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2506 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2507 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2508 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2509 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2510 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2511 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2512 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2513 for (Index
= 0; Index
< CertCount
; Index
++) {
2514 if (GuidIndex
== DeleteKekIndex
) {
2516 // Find it! Skip it!
2518 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2519 IsKEKItemFound
= TRUE
;
2522 // This item doesn't match. Copy it to the Data buffer.
2524 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2525 Offset
+= CertList
->SignatureSize
;
2528 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2532 // This List doesn't match. Copy it to the Data buffer.
2534 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2535 Offset
+= CertList
->SignatureListSize
;
2538 KekDataSize
-= CertList
->SignatureListSize
;
2539 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2542 if (!IsKEKItemFound
) {
2544 // Doesn't find the Kek Item!
2546 Status
= EFI_NOT_FOUND
;
2551 // Delete the Signature header if there is no signature in the list.
2553 KekDataSize
= Offset
;
2554 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2556 ZeroMem (OldData
, KekDataSize
);
2557 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2558 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2559 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2560 if (CertCount
!= 0) {
2561 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2562 Offset
+= CertList
->SignatureListSize
;
2564 KekDataSize
-= CertList
->SignatureListSize
;
2565 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2569 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2570 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2571 if (EFI_ERROR (Status
)) {
2572 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2577 Status
= gRT
->SetVariable(
2578 EFI_KEY_EXCHANGE_KEY_NAME
,
2579 &gEfiGlobalVariableGuid
,
2584 if (EFI_ERROR (Status
)) {
2585 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2594 if (OldData
!= NULL
) {
2598 return UpdateDeletePage (
2600 EFI_KEY_EXCHANGE_KEY_NAME
,
2601 &gEfiGlobalVariableGuid
,
2603 FORMID_DELETE_KEK_FORM
,
2604 OPTION_DEL_KEK_QUESTION_ID
2609 Delete a signature entry from siganture database.
2611 @param[in] PrivateData Module's private data.
2612 @param[in] VariableName The variable name of the vendor's signature database.
2613 @param[in] VendorGuid A unique identifier for the vendor.
2614 @param[in] LabelNumber Label number to insert opcodes.
2615 @param[in] FormId Form ID of current page.
2616 @param[in] QuestionIdBase Base question id of the signature list.
2617 @param[in] DeleteIndex Signature index to delete.
2619 @retval EFI_SUCCESS Delete siganture successfully.
2620 @retval EFI_NOT_FOUND Can't find the signature item,
2621 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2625 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2626 IN CHAR16
*VariableName
,
2627 IN EFI_GUID
*VendorGuid
,
2628 IN UINT16 LabelNumber
,
2629 IN EFI_FORM_ID FormId
,
2630 IN EFI_QUESTION_ID QuestionIdBase
,
2631 IN UINTN DeleteIndex
2640 EFI_SIGNATURE_LIST
*CertList
;
2641 EFI_SIGNATURE_LIST
*NewCertList
;
2642 EFI_SIGNATURE_DATA
*Cert
;
2645 BOOLEAN IsItemFound
;
2646 UINT32 ItemDataSize
;
2655 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2656 if (EFI_ERROR (Status
)) {
2661 // Get original signature list data.
2664 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2665 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2669 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2670 if (OldData
== NULL
) {
2671 Status
= EFI_OUT_OF_RESOURCES
;
2675 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2676 if (EFI_ERROR(Status
)) {
2681 // Allocate space for new variable.
2683 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2685 Status
= EFI_OUT_OF_RESOURCES
;
2690 // Enumerate all signature data and erasing the target item.
2692 IsItemFound
= FALSE
;
2693 ItemDataSize
= (UINT32
) DataSize
;
2694 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2697 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2698 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2699 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2700 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2701 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2702 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2703 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2704 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2707 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2709 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2710 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2711 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2712 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2713 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2714 for (Index
= 0; Index
< CertCount
; Index
++) {
2715 if (GuidIndex
== DeleteIndex
) {
2717 // Find it! Skip it!
2719 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2723 // This item doesn't match. Copy it to the Data buffer.
2725 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2726 Offset
+= CertList
->SignatureSize
;
2729 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2733 // This List doesn't match. Just copy it to the Data buffer.
2735 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2736 Offset
+= CertList
->SignatureListSize
;
2739 ItemDataSize
-= CertList
->SignatureListSize
;
2740 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2745 // Doesn't find the signature Item!
2747 Status
= EFI_NOT_FOUND
;
2752 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2754 ItemDataSize
= Offset
;
2755 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2757 ZeroMem (OldData
, ItemDataSize
);
2758 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2759 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2760 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2761 if (CertCount
!= 0) {
2762 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2763 Offset
+= CertList
->SignatureListSize
;
2765 ItemDataSize
-= CertList
->SignatureListSize
;
2766 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2770 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2771 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2772 if (EFI_ERROR (Status
)) {
2773 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2778 Status
= gRT
->SetVariable(
2785 if (EFI_ERROR (Status
)) {
2786 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2795 if (OldData
!= NULL
) {
2799 return UpdateDeletePage (
2810 This function extracts configuration from variable.
2812 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2816 SecureBootExtractConfigFromVariable (
2817 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2820 UINT8
*SecureBootEnable
;
2822 UINT8
*SecureBootMode
;
2825 SecureBootEnable
= NULL
;
2827 SecureBootMode
= NULL
;
2830 // Initilize the Date and Time using system time.
2832 ConfigData
->CertificateFormat
= HASHALG_RAW
;
2833 ConfigData
->AlwaysRevocation
= TRUE
;
2834 gRT
->GetTime (&CurrTime
, NULL
);
2835 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
2836 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
2837 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
2838 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
2839 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
2840 ConfigData
->RevocationTime
.Second
= 0;
2843 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2846 ConfigData
->AttemptSecureBoot
= FALSE
;
2847 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2848 if (SecureBootEnable
== NULL
) {
2849 ConfigData
->HideSecureBoot
= TRUE
;
2851 ConfigData
->HideSecureBoot
= FALSE
;
2852 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
2853 ConfigData
->AttemptSecureBoot
= TRUE
;
2858 // If it is Physical Presence User, set the PhysicalPresent to true.
2860 if (UserPhysicalPresent()) {
2861 ConfigData
->PhysicalPresent
= TRUE
;
2863 ConfigData
->PhysicalPresent
= FALSE
;
2867 // If there is no PK then the Delete Pk button will be gray.
2869 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2870 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2871 ConfigData
->HasPk
= FALSE
;
2873 ConfigData
->HasPk
= TRUE
;
2877 // Get the SecureBootMode from CustomMode variable.
2879 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2880 if (SecureBootMode
== NULL
) {
2881 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2883 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2886 if (SecureBootEnable
!= NULL
) {
2887 FreePool (SecureBootEnable
);
2889 if (SetupMode
!= NULL
) {
2890 FreePool (SetupMode
);
2892 if (SecureBootMode
!= NULL
) {
2893 FreePool (SecureBootMode
);
2898 This function allows a caller to extract the current configuration for one
2899 or more named elements from the target driver.
2901 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2902 @param[in] Request A null-terminated Unicode string in
2903 <ConfigRequest> format.
2904 @param[out] Progress On return, points to a character in the Request
2905 string. Points to the string's null terminator if
2906 request was successful. Points to the most recent
2907 '&' before the first failing name/value pair (or
2908 the beginning of the string if the failure is in
2909 the first name/value pair) if the request was not
2911 @param[out] Results A null-terminated Unicode string in
2912 <ConfigAltResp> format which has all values filled
2913 in for the names in the Request string. String to
2914 be allocated by the called function.
2916 @retval EFI_SUCCESS The Results is filled with the requested values.
2917 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2918 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2919 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2925 SecureBootExtractConfig (
2926 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2927 IN CONST EFI_STRING Request
,
2928 OUT EFI_STRING
*Progress
,
2929 OUT EFI_STRING
*Results
2935 SECUREBOOT_CONFIGURATION Configuration
;
2936 EFI_STRING ConfigRequest
;
2937 EFI_STRING ConfigRequestHdr
;
2938 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2939 BOOLEAN AllocatedRequest
;
2942 if (Progress
== NULL
|| Results
== NULL
) {
2943 return EFI_INVALID_PARAMETER
;
2946 AllocatedRequest
= FALSE
;
2947 ConfigRequestHdr
= NULL
;
2948 ConfigRequest
= NULL
;
2952 ZeroMem (&Configuration
, sizeof (Configuration
));
2953 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2954 *Progress
= Request
;
2956 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2957 return EFI_NOT_FOUND
;
2961 // Get Configuration from Variable.
2963 SecureBootExtractConfigFromVariable (&Configuration
);
2966 // Update current secure boot state.
2968 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2969 if (SecureBoot
!= NULL
&& *SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2970 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
2972 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
2974 if (SecureBoot
!= NULL
) {
2975 FreePool (SecureBoot
);
2978 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2979 ConfigRequest
= Request
;
2980 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2982 // Request is set to NULL or OFFSET is NULL, construct full request string.
2984 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2985 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2987 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2988 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2989 ConfigRequest
= AllocateZeroPool (Size
);
2990 ASSERT (ConfigRequest
!= NULL
);
2991 AllocatedRequest
= TRUE
;
2992 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2993 FreePool (ConfigRequestHdr
);
2994 ConfigRequestHdr
= NULL
;
2997 Status
= gHiiConfigRouting
->BlockToConfig (
3000 (UINT8
*) &Configuration
,
3007 // Free the allocated config request string.
3009 if (AllocatedRequest
) {
3010 FreePool (ConfigRequest
);
3014 // Set Progress string to the original request string.
3016 if (Request
== NULL
) {
3018 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3019 *Progress
= Request
+ StrLen (Request
);
3026 This function processes the results of changes in configuration.
3028 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3029 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3031 @param[out] Progress A pointer to a string filled in with the offset of
3032 the most recent '&' before the first failing
3033 name/value pair (or the beginning of the string if
3034 the failure is in the first name/value pair) or
3035 the terminating NULL if all was successful.
3037 @retval EFI_SUCCESS The Results is processed successfully.
3038 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3039 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3045 SecureBootRouteConfig (
3046 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3047 IN CONST EFI_STRING Configuration
,
3048 OUT EFI_STRING
*Progress
3051 UINT8
*SecureBootEnable
;
3052 SECUREBOOT_CONFIGURATION IfrNvData
;
3056 if (Configuration
== NULL
|| Progress
== NULL
) {
3057 return EFI_INVALID_PARAMETER
;
3060 *Progress
= Configuration
;
3061 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3062 return EFI_NOT_FOUND
;
3066 // Get Configuration from Variable.
3068 SecureBootExtractConfigFromVariable (&IfrNvData
);
3071 // Map the Configuration to the configuration block.
3073 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3074 Status
= gHiiConfigRouting
->ConfigToBlock (
3077 (UINT8
*)&IfrNvData
,
3081 if (EFI_ERROR (Status
)) {
3086 // Store Buffer Storage back to EFI variable if needed
3088 SecureBootEnable
= NULL
;
3089 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3090 if (NULL
!= SecureBootEnable
) {
3091 FreePool (SecureBootEnable
);
3092 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3093 if (EFI_ERROR (Status
)) {
3098 *Progress
= Configuration
+ StrLen (Configuration
);
3103 This function is called to provide results data to the driver.
3105 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3106 @param[in] Action Specifies the type of action taken by the browser.
3107 @param[in] QuestionId A unique value which is sent to the original
3108 exporting driver so that it can identify the type
3110 @param[in] Type The type of value for the question.
3111 @param[in] Value A pointer to the data being sent to the original
3113 @param[out] ActionRequest On return, points to the action requested by the
3116 @retval EFI_SUCCESS The callback successfully handled the action.
3117 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3118 variable and its data.
3119 @retval EFI_DEVICE_ERROR The variable could not be saved.
3120 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3126 SecureBootCallback (
3127 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3128 IN EFI_BROWSER_ACTION Action
,
3129 IN EFI_QUESTION_ID QuestionId
,
3131 IN EFI_IFR_TYPE_VALUE
*Value
,
3132 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3137 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
3139 SECUREBOOT_CONFIGURATION
*IfrNvData
;
3141 UINT8
*SecureBootEnable
;
3142 UINT8
*SecureBootMode
;
3144 CHAR16 PromptString
[100];
3146 SecureBootEnable
= NULL
;
3147 SecureBootMode
= NULL
;
3150 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
3151 return EFI_INVALID_PARAMETER
;
3154 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
3155 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3156 mIsEnterSecureBootForm
= TRUE
;
3162 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
3163 Status
= EFI_UNSUPPORTED
;
3164 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
3165 if (mIsEnterSecureBootForm
) {
3166 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
3167 Status
= EFI_SUCCESS
;
3173 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
3174 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
3175 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
3176 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
3177 return EFI_UNSUPPORTED
;
3180 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3183 // Retrieve uncommitted data from Browser
3185 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3186 IfrNvData
= AllocateZeroPool (BufferSize
);
3187 if (IfrNvData
== NULL
) {
3188 return EFI_OUT_OF_RESOURCES
;
3191 Status
= EFI_SUCCESS
;
3193 HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
3195 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3197 switch (QuestionId
) {
3198 case KEY_SECURE_BOOT_ENABLE
:
3199 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3200 if (NULL
!= SecureBootEnable
) {
3201 FreePool (SecureBootEnable
);
3202 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
3204 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3206 L
"Only Physical Presence User could disable secure boot!",
3209 Status
= EFI_UNSUPPORTED
;
3212 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3214 L
"Configuration changed, please reset the platform to take effect!",
3221 case KEY_SECURE_BOOT_OPTION
:
3222 FreeMenu (&DirectoryMenu
);
3223 FreeMenu (&FsOptionMenu
);
3226 case KEY_SECURE_BOOT_KEK_OPTION
:
3227 case KEY_SECURE_BOOT_DB_OPTION
:
3228 case KEY_SECURE_BOOT_DBX_OPTION
:
3229 case KEY_SECURE_BOOT_DBT_OPTION
:
3231 // Clear Signature GUID.
3233 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
3234 if (Private
->SignatureGUID
== NULL
) {
3235 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
3236 if (Private
->SignatureGUID
== NULL
) {
3237 return EFI_OUT_OF_RESOURCES
;
3241 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
3242 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
3243 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
3244 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
3245 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
3246 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
3248 LabelId
= FORMID_ENROLL_KEK_FORM
;
3252 // Refresh selected file.
3254 CleanUpPage (LabelId
, Private
);
3257 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
3258 case FORMID_ENROLL_KEK_FORM
:
3259 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
3260 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
3261 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
3262 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
3263 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
3264 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
3265 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
3266 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
3267 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
3268 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
) {
3269 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
3270 IfrNvData
->CertificateFormat
= HASHALG_SHA256
;
3272 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbt
;
3275 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
3276 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
3277 UpdateFileExplorer (Private
, 0);
3280 case KEY_SECURE_BOOT_DELETE_PK
:
3283 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3285 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
3286 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
3289 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
3290 Status
= DeletePlatformKey ();
3291 if (EFI_ERROR (Status
)) {
3293 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3295 L
"Only Physical Presence User could delete PK in custom mode!",
3303 case KEY_DELETE_KEK
:
3306 EFI_KEY_EXCHANGE_KEY_NAME
,
3307 &gEfiGlobalVariableGuid
,
3309 FORMID_DELETE_KEK_FORM
,
3310 OPTION_DEL_KEK_QUESTION_ID
3314 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
3317 EFI_IMAGE_SECURITY_DATABASE
,
3318 &gEfiImageSecurityDatabaseGuid
,
3320 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3321 OPTION_DEL_DB_QUESTION_ID
3325 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
3328 EFI_IMAGE_SECURITY_DATABASE1
,
3329 &gEfiImageSecurityDatabaseGuid
,
3331 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3332 OPTION_DEL_DBX_QUESTION_ID
3337 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
3340 EFI_IMAGE_SECURITY_DATABASE2
,
3341 &gEfiImageSecurityDatabaseGuid
,
3343 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3344 OPTION_DEL_DBT_QUESTION_ID
3349 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
3350 Status
= EnrollKeyExchangeKey (Private
);
3351 if (EFI_ERROR (Status
)) {
3353 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3355 L
"ERROR: Unsupported file type!",
3356 L
"Only supports DER-encoded X509 certificate",
3362 case KEY_VALUE_SAVE_AND_EXIT_DB
:
3363 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
3364 if (EFI_ERROR (Status
)) {
3366 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3368 L
"ERROR: Unsupported file type!",
3369 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3375 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
3376 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
3378 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3380 L
"Enrollment failed! Same certificate had already been in the dbx!",
3386 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
3387 Status
= EnrollX509HashtoSigDB (
3389 IfrNvData
->CertificateFormat
,
3390 &IfrNvData
->RevocationDate
,
3391 &IfrNvData
->RevocationTime
,
3392 IfrNvData
->AlwaysRevocation
3395 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
3397 if (EFI_ERROR (Status
)) {
3399 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3401 L
"ERROR: Unsupported file type!",
3402 L
"Only supports DER-encoded X509 certificate and executable EFI image",
3408 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
3409 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
3410 if (EFI_ERROR (Status
)) {
3412 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3414 L
"ERROR: Unsupported file type!",
3415 L
"Only supports DER-encoded X509 certificate.",
3422 if (QuestionId
>= FILE_OPTION_GOTO_OFFSET
) {
3423 UpdateFileExplorer (Private
, QuestionId
);
3424 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
3425 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3426 DeleteKeyExchangeKey (Private
, QuestionId
);
3427 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
3428 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3431 EFI_IMAGE_SECURITY_DATABASE
,
3432 &gEfiImageSecurityDatabaseGuid
,
3434 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
3435 OPTION_DEL_DB_QUESTION_ID
,
3436 QuestionId
- OPTION_DEL_DB_QUESTION_ID
3438 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
3439 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3442 EFI_IMAGE_SECURITY_DATABASE1
,
3443 &gEfiImageSecurityDatabaseGuid
,
3445 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
3446 OPTION_DEL_DBX_QUESTION_ID
,
3447 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
3449 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
3450 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
3453 EFI_IMAGE_SECURITY_DATABASE2
,
3454 &gEfiImageSecurityDatabaseGuid
,
3456 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
3457 OPTION_DEL_DBT_QUESTION_ID
,
3458 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
3463 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3464 switch (QuestionId
) {
3465 case KEY_SECURE_BOOT_ENABLE
:
3466 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3468 case KEY_VALUE_SAVE_AND_EXIT_PK
:
3469 Status
= EnrollPlatformKey (Private
);
3470 if (EFI_ERROR (Status
)) {
3473 sizeof (PromptString
),
3474 L
"Only DER encoded certificate file (%s) is supported.",
3478 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3480 L
"ERROR: Unsupported file type!",
3485 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
3489 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
3490 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
3491 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
3492 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
3493 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
3494 if (Private
->FileContext
->FHandle
!= NULL
) {
3495 CloseFile (Private
->FileContext
->FHandle
);
3496 Private
->FileContext
->FHandle
= NULL
;
3497 Private
->FileContext
->FileName
= NULL
;
3500 if (Private
->SignatureGUID
!= NULL
) {
3501 FreePool (Private
->SignatureGUID
);
3502 Private
->SignatureGUID
= NULL
;
3504 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3507 case KEY_SECURE_BOOT_MODE
:
3508 mIsEnterSecureBootForm
= FALSE
;
3511 case KEY_SECURE_BOOT_KEK_GUID
:
3512 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
3513 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
3514 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
3515 ASSERT (Private
->SignatureGUID
!= NULL
);
3516 Status
= StringToGuid (
3517 IfrNvData
->SignatureGuid
,
3518 StrLen (IfrNvData
->SignatureGuid
),
3519 Private
->SignatureGUID
3521 if (EFI_ERROR (Status
)) {
3525 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3528 case KEY_SECURE_BOOT_DELETE_PK
:
3529 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3530 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3531 IfrNvData
->DeletePk
= TRUE
;
3532 IfrNvData
->HasPk
= FALSE
;
3533 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
3535 IfrNvData
->DeletePk
= FALSE
;
3536 IfrNvData
->HasPk
= TRUE
;
3537 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3539 if (SetupMode
!= NULL
) {
3540 FreePool (SetupMode
);
3544 if (QuestionId
>= FILE_OPTION_OFFSET
&& QuestionId
< FILE_OPTION_GOTO_OFFSET
) {
3545 if (UpdateFileExplorer (Private
, QuestionId
)) {
3546 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
3551 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
3552 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
3553 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3554 if (SecureBootEnable
== NULL
) {
3555 IfrNvData
->HideSecureBoot
= TRUE
;
3557 FreePool (SecureBootEnable
);
3558 IfrNvData
->HideSecureBoot
= FALSE
;
3560 Value
->b
= IfrNvData
->HideSecureBoot
;
3562 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
3564 // Force the platform back to Standard Mode once user leave the setup screen.
3566 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3567 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
3568 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3569 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
3571 if (SecureBootMode
!= NULL
) {
3572 FreePool (SecureBootMode
);
3576 if (!EFI_ERROR (Status
)) {
3577 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3578 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3580 FreePool (IfrNvData
);
3586 This function publish the SecureBoot configuration Form.
3588 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3590 @retval EFI_SUCCESS HII Form is installed successfully.
3591 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
3592 @retval Others Other errors as indicated.
3596 InstallSecureBootConfigForm (
3597 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3601 EFI_HII_HANDLE HiiHandle
;
3602 EFI_HANDLE DriverHandle
;
3603 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3605 DriverHandle
= NULL
;
3606 ConfigAccess
= &PrivateData
->ConfigAccess
;
3607 Status
= gBS
->InstallMultipleProtocolInterfaces (
3609 &gEfiDevicePathProtocolGuid
,
3610 &mSecureBootHiiVendorDevicePath
,
3611 &gEfiHiiConfigAccessProtocolGuid
,
3615 if (EFI_ERROR (Status
)) {
3619 PrivateData
->DriverHandle
= DriverHandle
;
3622 // Publish the HII package list
3624 HiiHandle
= HiiAddPackages (
3625 &gSecureBootConfigFormSetGuid
,
3627 SecureBootConfigDxeStrings
,
3628 SecureBootConfigBin
,
3631 if (HiiHandle
== NULL
) {
3632 gBS
->UninstallMultipleProtocolInterfaces (
3634 &gEfiDevicePathProtocolGuid
,
3635 &mSecureBootHiiVendorDevicePath
,
3636 &gEfiHiiConfigAccessProtocolGuid
,
3640 return EFI_OUT_OF_RESOURCES
;
3643 PrivateData
->HiiHandle
= HiiHandle
;
3645 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
3646 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
3648 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
3649 UninstallSecureBootConfigForm (PrivateData
);
3650 return EFI_OUT_OF_RESOURCES
;
3653 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
3654 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
3656 InitializeListHead (&FsOptionMenu
.Head
);
3657 InitializeListHead (&DirectoryMenu
.Head
);
3660 // Init OpCode Handle and Allocate space for creation of Buffer
3662 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3663 if (mStartOpCodeHandle
== NULL
) {
3664 UninstallSecureBootConfigForm (PrivateData
);
3665 return EFI_OUT_OF_RESOURCES
;
3668 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3669 if (mEndOpCodeHandle
== NULL
) {
3670 UninstallSecureBootConfigForm (PrivateData
);
3671 return EFI_OUT_OF_RESOURCES
;
3675 // Create Hii Extend Label OpCode as the start opcode
3677 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
3681 sizeof (EFI_IFR_GUID_LABEL
)
3683 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3686 // Create Hii Extend Label OpCode as the end opcode
3688 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
3692 sizeof (EFI_IFR_GUID_LABEL
)
3694 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3695 mEndLabel
->Number
= LABEL_END
;
3701 This function removes SecureBoot configuration Form.
3703 @param[in, out] PrivateData Points to SecureBoot configuration private data.
3707 UninstallSecureBootConfigForm (
3708 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
3712 // Uninstall HII package list
3714 if (PrivateData
->HiiHandle
!= NULL
) {
3715 HiiRemovePackages (PrivateData
->HiiHandle
);
3716 PrivateData
->HiiHandle
= NULL
;
3720 // Uninstall HII Config Access Protocol
3722 if (PrivateData
->DriverHandle
!= NULL
) {
3723 gBS
->UninstallMultipleProtocolInterfaces (
3724 PrivateData
->DriverHandle
,
3725 &gEfiDevicePathProtocolGuid
,
3726 &mSecureBootHiiVendorDevicePath
,
3727 &gEfiHiiConfigAccessProtocolGuid
,
3728 &PrivateData
->ConfigAccess
,
3731 PrivateData
->DriverHandle
= NULL
;
3734 if (PrivateData
->SignatureGUID
!= NULL
) {
3735 FreePool (PrivateData
->SignatureGUID
);
3738 if (PrivateData
->MenuEntry
!= NULL
) {
3739 FreePool (PrivateData
->MenuEntry
);
3742 if (PrivateData
->FileContext
!= NULL
) {
3743 FreePool (PrivateData
->FileContext
);
3746 FreePool (PrivateData
);
3748 FreeMenu (&DirectoryMenu
);
3749 FreeMenu (&FsOptionMenu
);
3751 if (mStartOpCodeHandle
!= NULL
) {
3752 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
3755 if (mEndOpCodeHandle
!= NULL
) {
3756 HiiFreeOpCodeHandle (mEndOpCodeHandle
);