2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "SecureBootConfigImpl.h"
17 #include <Library/BaseCryptLib.h>
19 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
21 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
22 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
24 SecureBootExtractConfig
,
25 SecureBootRouteConfig
,
30 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
36 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
37 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
40 SECUREBOOT_CONFIG_FORM_SET_GUID
44 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
46 (UINT8
) (END_DEVICE_PATH_LENGTH
),
47 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
53 BOOLEAN mIsEnterSecureBootForm
= 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
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
69 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
, Sha256Init
, Sha256Update
, Sha256Final
},
70 { L
"SHA384", 48, &mHashOidValue
[31], 9, Sha384GetContextSize
, Sha384Init
, Sha384Update
, Sha384Final
},
71 { L
"SHA512", 64, &mHashOidValue
[40], 9, Sha512GetContextSize
, Sha512Init
, Sha512Update
, Sha512Final
}
75 // Variable Definitions
77 UINT32 mPeCoffHeaderOffset
= 0;
78 WIN_CERTIFICATE
*mCertificate
= NULL
;
79 IMAGE_TYPE mImageType
;
80 UINT8
*mImageBase
= NULL
;
82 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
83 UINTN mImageDigestSize
;
85 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
86 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
89 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
91 CHAR16
* mDerEncodedSuffix
[] = {
97 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
99 SECUREBOOT_CONFIG_PRIVATE_DATA
*gSecureBootPrivateData
= NULL
;
102 This code cleans up enrolled file by closing file & free related resources attached to
105 @param[in] FileContext FileContext cached in SecureBootConfig driver
110 IN SECUREBOOT_FILE_CONTEXT
*FileContext
113 if (FileContext
->FHandle
!= NULL
) {
114 CloseFile (FileContext
->FHandle
);
115 FileContext
->FHandle
= NULL
;
118 if (FileContext
->FileName
!= NULL
){
119 FreePool(FileContext
->FileName
);
120 FileContext
->FileName
= NULL
;
122 FileContext
->FileType
= UNKNOWN_FILE_TYPE
;
127 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
129 @param[in] FileSuffix The suffix of the input certificate file
131 @retval TRUE It's a DER-encoded certificate.
132 @retval FALSE It's NOT a DER-encoded certificate.
136 IsDerEncodeCertificate (
137 IN CONST CHAR16
*FileSuffix
141 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
142 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
150 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
151 The function reads file content but won't open/close given FileHandle.
153 @param[in] FileHandle The FileHandle to be checked
155 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
156 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
160 IsAuthentication2Format (
161 IN EFI_FILE_HANDLE FileHandle
165 EFI_VARIABLE_AUTHENTICATION_2
*Auth2
;
166 BOOLEAN IsAuth2Format
;
168 IsAuth2Format
= FALSE
;
171 // Read the whole file content
173 Status
= ReadFileContent(
175 (VOID
**) &mImageBase
,
179 if (EFI_ERROR (Status
)) {
183 Auth2
= (EFI_VARIABLE_AUTHENTICATION_2
*)mImageBase
;
184 if (Auth2
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) {
188 if (CompareGuid(&gEfiCertPkcs7Guid
, &Auth2
->AuthInfo
.CertType
)) {
189 IsAuth2Format
= TRUE
;
194 // Do not close File. simply check file content
196 if (mImageBase
!= NULL
) {
197 FreePool (mImageBase
);
201 return IsAuth2Format
;
205 Set Secure Boot option into variable space.
207 @param[in] VarValue The option of Secure Boot.
209 @retval EFI_SUCCESS The operation is finished successfully.
210 @retval Others Other errors as indicated.
214 SaveSecureBootVariable (
220 Status
= gRT
->SetVariable (
221 EFI_SECURE_BOOT_ENABLE_NAME
,
222 &gEfiSecureBootEnableDisableGuid
,
223 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
231 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
232 descriptor with the input data. NO authentication is required in this function.
234 @param[in, out] DataSize On input, the size of Data buffer in bytes.
235 On output, the size of data returned in Data
237 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
238 pointer to NULL to wrap an empty payload.
239 On output, Pointer to the new payload date buffer allocated from pool,
240 it's caller's responsibility to free the memory when finish using it.
242 @retval EFI_SUCCESS Create time based payload successfully.
243 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
244 @retval EFI_INVALID_PARAMETER The parameter is invalid.
245 @retval Others Unexpected error happens.
249 CreateTimeBasedPayload (
250 IN OUT UINTN
*DataSize
,
258 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
259 UINTN DescriptorSize
;
262 if (Data
== NULL
|| DataSize
== NULL
) {
263 return EFI_INVALID_PARAMETER
;
267 // In Setup mode or Custom mode, the variable does not need to be signed but the
268 // parameters to the SetVariable() call still need to be prepared as authenticated
269 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
273 PayloadSize
= *DataSize
;
275 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
276 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
277 if (NewData
== NULL
) {
278 return EFI_OUT_OF_RESOURCES
;
281 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
282 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
285 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
287 ZeroMem (&Time
, sizeof (EFI_TIME
));
288 Status
= gRT
->GetTime (&Time
, NULL
);
289 if (EFI_ERROR (Status
)) {
298 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
300 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
301 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
302 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
303 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
305 if (Payload
!= NULL
) {
309 *DataSize
= DescriptorSize
+ PayloadSize
;
315 Internal helper function to delete a Variable given its name and GUID, NO authentication
318 @param[in] VariableName Name of the Variable.
319 @param[in] VendorGuid GUID of the Variable.
321 @retval EFI_SUCCESS Variable deleted successfully.
322 @retval Others The driver failed to start the device.
327 IN CHAR16
*VariableName
,
328 IN EFI_GUID
*VendorGuid
337 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
338 if (Variable
== NULL
) {
345 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
346 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
348 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
349 if (EFI_ERROR (Status
)) {
350 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
354 Status
= gRT
->SetVariable (
369 Set the platform secure boot mode into "Custom" or "Standard" mode.
371 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
372 CUSTOM_SECURE_BOOT_MODE.
374 @return EFI_SUCCESS The platform has switched to the special mode successfully.
375 @return other Fail to operate the secure boot mode.
380 IN UINT8 SecureBootMode
383 return gRT
->SetVariable (
384 EFI_CUSTOM_MODE_NAME
,
385 &gEfiCustomModeEnableGuid
,
386 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
393 Generate the PK signature list from the X509 Certificate storing file (.cer)
395 @param[in] X509File FileHandle of X509 Certificate storing file.
396 @param[out] PkCert Point to the data buffer to store the signature list.
398 @return EFI_UNSUPPORTED Unsupported Key Length.
399 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
403 CreatePkX509SignatureList (
404 IN EFI_FILE_HANDLE X509File
,
405 OUT EFI_SIGNATURE_LIST
**PkCert
411 EFI_SIGNATURE_DATA
*PkCertData
;
417 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
418 if (EFI_ERROR (Status
)) {
421 ASSERT (X509Data
!= NULL
);
424 // Allocate space for PK certificate list and initialize it.
425 // Create PK database entry with SignatureHeaderSize equals 0.
427 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
428 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
431 if (*PkCert
== NULL
) {
432 Status
= EFI_OUT_OF_RESOURCES
;
436 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
437 + sizeof(EFI_SIGNATURE_DATA
) - 1
439 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
440 (*PkCert
)->SignatureHeaderSize
= 0;
441 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
442 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
443 + sizeof(EFI_SIGNATURE_LIST
)
444 + (*PkCert
)->SignatureHeaderSize
);
445 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
447 // Fill the PK database with PKpub data from X509 certificate file.
449 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
453 if (X509Data
!= NULL
) {
457 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
466 Enroll new PK into the System without original PK's authentication.
468 The SignatureOwner GUID will be the same with PK's vendorguid.
470 @param[in] PrivateData The module's private data.
472 @retval EFI_SUCCESS New PK enrolled successfully.
473 @retval EFI_INVALID_PARAMETER The parameter is invalid.
474 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
479 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
485 EFI_SIGNATURE_LIST
*PkCert
;
489 if (Private
->FileContext
->FileName
== NULL
) {
490 return EFI_INVALID_PARAMETER
;
495 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
496 if (EFI_ERROR (Status
)) {
501 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
503 NameLength
= StrLen (Private
->FileContext
->FileName
);
504 if (NameLength
<= 4) {
505 return EFI_INVALID_PARAMETER
;
507 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
508 if (!IsDerEncodeCertificate(FilePostFix
)) {
509 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
510 return EFI_INVALID_PARAMETER
;
512 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
513 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
516 // Prase the selected PK file and generature PK certificate list.
518 Status
= CreatePkX509SignatureList (
519 Private
->FileContext
->FHandle
,
522 if (EFI_ERROR (Status
)) {
525 ASSERT (PkCert
!= NULL
);
528 // Set Platform Key variable.
530 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
531 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
532 DataSize
= PkCert
->SignatureListSize
;
533 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
534 if (EFI_ERROR (Status
)) {
535 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
539 Status
= gRT
->SetVariable(
540 EFI_PLATFORM_KEY_NAME
,
541 &gEfiGlobalVariableGuid
,
546 if (EFI_ERROR (Status
)) {
547 if (Status
== EFI_OUT_OF_RESOURCES
) {
548 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
555 if (PkCert
!= NULL
) {
559 CloseEnrolledFile(Private
->FileContext
);
565 Remove the PK variable.
567 @retval EFI_SUCCESS Delete PK successfully.
568 @retval Others Could not allow to delete PK.
578 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
579 if (EFI_ERROR (Status
)) {
583 Status
= DeleteVariable (
584 EFI_PLATFORM_KEY_NAME
,
585 &gEfiGlobalVariableGuid
591 Enroll a new KEK item from public key storing file (*.pbk).
593 @param[in] PrivateData The module's private data.
595 @retval EFI_SUCCESS New KEK enrolled successfully.
596 @retval EFI_INVALID_PARAMETER The parameter is invalid.
597 @retval EFI_UNSUPPORTED Unsupported command.
598 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
603 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
609 EFI_SIGNATURE_LIST
*KekSigList
;
612 CPL_KEY_INFO
*KeyInfo
;
613 EFI_SIGNATURE_DATA
*KEKSigData
;
614 UINTN KekSigListSize
;
629 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
630 // First, We have to parse out public key data from the pbk key file.
632 Status
= ReadFileContent (
633 Private
->FileContext
->FHandle
,
638 if (EFI_ERROR (Status
)) {
641 ASSERT (KeyBlob
!= NULL
);
642 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
643 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
644 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
645 Status
= EFI_UNSUPPORTED
;
650 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
652 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
653 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
654 if (KeyBuffer
== NULL
) {
655 Status
= EFI_OUT_OF_RESOURCES
;
659 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
660 KeyLenInBytes
/ sizeof (UINTN
),
664 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
667 // Form an new EFI_SIGNATURE_LIST.
669 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
670 + sizeof(EFI_SIGNATURE_DATA
) - 1
671 + WIN_CERT_UEFI_RSA2048_SIZE
;
673 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
674 if (KekSigList
== NULL
) {
675 Status
= EFI_OUT_OF_RESOURCES
;
679 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
680 + sizeof(EFI_SIGNATURE_DATA
) - 1
681 + WIN_CERT_UEFI_RSA2048_SIZE
;
682 KekSigList
->SignatureHeaderSize
= 0;
683 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
684 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
686 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
687 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
689 KEKSigData
->SignatureData
,
690 KeyBlob
+ sizeof(CPL_KEY_INFO
),
691 WIN_CERT_UEFI_RSA2048_SIZE
695 // Check if KEK entry has been already existed.
696 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
697 // new KEK to original variable.
699 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
700 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
701 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
702 if (EFI_ERROR (Status
)) {
703 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
707 Status
= gRT
->GetVariable(
708 EFI_KEY_EXCHANGE_KEY_NAME
,
709 &gEfiGlobalVariableGuid
,
714 if (Status
== EFI_BUFFER_TOO_SMALL
) {
715 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
716 } else if (Status
!= EFI_NOT_FOUND
) {
721 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
723 Status
= gRT
->SetVariable(
724 EFI_KEY_EXCHANGE_KEY_NAME
,
725 &gEfiGlobalVariableGuid
,
730 if (EFI_ERROR (Status
)) {
736 CloseEnrolledFile(Private
->FileContext
);
738 if (Private
->SignatureGUID
!= NULL
) {
739 FreePool (Private
->SignatureGUID
);
740 Private
->SignatureGUID
= NULL
;
743 if (KeyBlob
!= NULL
) {
746 if (KeyBuffer
!= NULL
) {
747 FreePool (KeyBuffer
);
749 if (KekSigList
!= NULL
) {
750 FreePool (KekSigList
);
757 Enroll a new KEK item from X509 certificate file.
759 @param[in] PrivateData The module's private data.
761 @retval EFI_SUCCESS New X509 is enrolled successfully.
762 @retval EFI_INVALID_PARAMETER The parameter is invalid.
763 @retval EFI_UNSUPPORTED Unsupported command.
764 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
769 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
775 EFI_SIGNATURE_DATA
*KEKSigData
;
776 EFI_SIGNATURE_LIST
*KekSigList
;
778 UINTN KekSigListSize
;
788 Status
= ReadFileContent (
789 Private
->FileContext
->FHandle
,
794 if (EFI_ERROR (Status
)) {
797 ASSERT (X509Data
!= NULL
);
799 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
800 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
801 if (KekSigList
== NULL
) {
802 Status
= EFI_OUT_OF_RESOURCES
;
807 // Fill Certificate Database parameters.
809 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
810 KekSigList
->SignatureHeaderSize
= 0;
811 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
812 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
814 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
815 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
816 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
819 // Check if KEK been already existed.
820 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
821 // new kek to original variable
823 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
824 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
825 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
826 if (EFI_ERROR (Status
)) {
827 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
831 Status
= gRT
->GetVariable(
832 EFI_KEY_EXCHANGE_KEY_NAME
,
833 &gEfiGlobalVariableGuid
,
838 if (Status
== EFI_BUFFER_TOO_SMALL
) {
839 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
840 } else if (Status
!= EFI_NOT_FOUND
) {
844 Status
= gRT
->SetVariable(
845 EFI_KEY_EXCHANGE_KEY_NAME
,
846 &gEfiGlobalVariableGuid
,
851 if (EFI_ERROR (Status
)) {
857 CloseEnrolledFile(Private
->FileContext
);
859 if (Private
->SignatureGUID
!= NULL
) {
860 FreePool (Private
->SignatureGUID
);
861 Private
->SignatureGUID
= NULL
;
864 if (KekSigList
!= NULL
) {
865 FreePool (KekSigList
);
872 Enroll new KEK into the System without PK's authentication.
873 The SignatureOwner GUID will be Private->SignatureGUID.
875 @param[in] PrivateData The module's private data.
877 @retval EFI_SUCCESS New KEK enrolled successful.
878 @retval EFI_INVALID_PARAMETER The parameter is invalid.
879 @retval others Fail to enroll KEK data.
883 EnrollKeyExchangeKey (
884 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
891 if ((Private
->FileContext
->FHandle
== NULL
) || (Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
892 return EFI_INVALID_PARAMETER
;
895 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
896 if (EFI_ERROR (Status
)) {
901 // Parse the file's postfix. Supports DER-encoded X509 certificate,
902 // and .pbk as RSA public key file.
904 NameLength
= StrLen (Private
->FileContext
->FileName
);
905 if (NameLength
<= 4) {
906 return EFI_INVALID_PARAMETER
;
908 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
909 if (IsDerEncodeCertificate(FilePostFix
)) {
910 return EnrollX509ToKek (Private
);
911 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
912 return EnrollRsa2048ToKek (Private
);
915 // File type is wrong, simply close it
917 CloseEnrolledFile(Private
->FileContext
);
919 return EFI_INVALID_PARAMETER
;
924 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
925 KEK's authentication.
927 @param[in] PrivateData The module's private data.
928 @param[in] VariableName Variable name of signature database, must be
929 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
931 @retval EFI_SUCCESS New X509 is enrolled successfully.
932 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
937 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
938 IN CHAR16
*VariableName
944 EFI_SIGNATURE_LIST
*SigDBCert
;
945 EFI_SIGNATURE_DATA
*SigDBCertData
;
956 SigDBCertData
= NULL
;
959 Status
= ReadFileContent (
960 Private
->FileContext
->FHandle
,
965 if (EFI_ERROR (Status
)) {
968 ASSERT (X509Data
!= NULL
);
970 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
972 Data
= AllocateZeroPool (SigDBSize
);
974 Status
= EFI_OUT_OF_RESOURCES
;
979 // Fill Certificate Database parameters.
981 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
982 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
983 SigDBCert
->SignatureHeaderSize
= 0;
984 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
985 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
987 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
988 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
989 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
992 // Check if signature database entry has been already existed.
993 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
994 // new signature data to original variable
996 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
997 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
998 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
999 if (EFI_ERROR (Status
)) {
1000 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1004 Status
= gRT
->GetVariable(
1006 &gEfiImageSecurityDatabaseGuid
,
1011 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1012 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1013 } else if (Status
!= EFI_NOT_FOUND
) {
1017 Status
= gRT
->SetVariable(
1019 &gEfiImageSecurityDatabaseGuid
,
1024 if (EFI_ERROR (Status
)) {
1030 CloseEnrolledFile(Private
->FileContext
);
1032 if (Private
->SignatureGUID
!= NULL
) {
1033 FreePool (Private
->SignatureGUID
);
1034 Private
->SignatureGUID
= NULL
;
1041 if (X509Data
!= NULL
) {
1042 FreePool (X509Data
);
1049 Check whether signature is in specified database.
1051 @param[in] VariableName Name of database variable that is searched in.
1052 @param[in] Signature Pointer to signature that is searched for.
1053 @param[in] SignatureSize Size of Signature.
1055 @return TRUE Found the signature in the variable database.
1056 @return FALSE Not found the signature in the variable database.
1060 IsSignatureFoundInDatabase (
1061 IN CHAR16
*VariableName
,
1062 IN UINT8
*Signature
,
1063 IN UINTN SignatureSize
1067 EFI_SIGNATURE_LIST
*CertList
;
1068 EFI_SIGNATURE_DATA
*Cert
;
1076 // Read signature database variable.
1081 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1082 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1086 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1091 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1092 if (EFI_ERROR (Status
)) {
1097 // Enumerate all signature data in SigDB to check if executable's signature exists.
1099 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1100 while ((DataSize
> 0) && (DataSize
>= CertList
->SignatureListSize
)) {
1101 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1102 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1103 if ((CertList
->SignatureSize
== sizeof(EFI_SIGNATURE_DATA
) - 1 + SignatureSize
) && (CompareGuid(&CertList
->SignatureType
, &gEfiCertX509Guid
))) {
1104 for (Index
= 0; Index
< CertCount
; Index
++) {
1105 if (CompareMem (Cert
->SignatureData
, Signature
, SignatureSize
) == 0) {
1107 // Find the signature in database.
1112 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1120 DataSize
-= CertList
->SignatureListSize
;
1121 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1133 Calculate the hash of a certificate data with the specified hash algorithm.
1135 @param[in] CertData The certificate data to be hashed.
1136 @param[in] CertSize The certificate size in bytes.
1137 @param[in] HashAlg The specified hash algorithm.
1138 @param[out] CertHash The output digest of the certificate
1140 @retval TRUE Successfully got the hash of the CertData.
1141 @retval FALSE Failed to get the hash of CertData.
1161 if (HashAlg
>= HASHALG_MAX
) {
1166 // Retrieve the TBSCertificate for Hash Calculation.
1168 if (!X509GetTBSCert (CertData
, CertSize
, &TBSCert
, &TBSCertSize
)) {
1173 // 1. Initialize context of hash.
1175 CtxSize
= mHash
[HashAlg
].GetContextSize ();
1176 HashCtx
= AllocatePool (CtxSize
);
1177 ASSERT (HashCtx
!= NULL
);
1180 // 2. Initialize a hash context.
1182 Status
= mHash
[HashAlg
].HashInit (HashCtx
);
1188 // 3. Calculate the hash.
1190 Status
= mHash
[HashAlg
].HashUpdate (HashCtx
, TBSCert
, TBSCertSize
);
1196 // 4. Get the hash result.
1198 ZeroMem (CertHash
, mHash
[HashAlg
].DigestLength
);
1199 Status
= mHash
[HashAlg
].HashFinal (HashCtx
, CertHash
);
1202 if (HashCtx
!= NULL
) {
1210 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1212 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1213 @param[in] CertSize Size of X.509 Certificate.
1215 @return TRUE Found the certificate hash in the forbidden database.
1216 @return FALSE Certificate hash is Not found in the forbidden database.
1220 IsCertHashFoundInDbx (
1221 IN UINT8
*Certificate
,
1227 EFI_SIGNATURE_LIST
*DbxList
;
1228 EFI_SIGNATURE_DATA
*CertHash
;
1229 UINTN CertHashCount
;
1232 UINT8 CertDigest
[MAX_DIGEST_SIZE
];
1234 UINTN SiglistHeaderSize
;
1239 HashAlg
= HASHALG_MAX
;
1243 // Read signature database variable.
1246 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1247 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1251 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1256 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1257 if (EFI_ERROR (Status
)) {
1262 // Check whether the certificate hash exists in the forbidden database.
1264 DbxList
= (EFI_SIGNATURE_LIST
*) Data
;
1265 while ((DataSize
> 0) && (DataSize
>= DbxList
->SignatureListSize
)) {
1267 // Determine Hash Algorithm of Certificate in the forbidden database.
1269 if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
1270 HashAlg
= HASHALG_SHA256
;
1271 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
1272 HashAlg
= HASHALG_SHA384
;
1273 } else if (CompareGuid (&DbxList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
1274 HashAlg
= HASHALG_SHA512
;
1276 DataSize
-= DbxList
->SignatureListSize
;
1277 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1282 // Calculate the hash value of current db certificate for comparision.
1284 if (!CalculateCertHash (Certificate
, CertSize
, HashAlg
, CertDigest
)) {
1288 SiglistHeaderSize
= sizeof (EFI_SIGNATURE_LIST
) + DbxList
->SignatureHeaderSize
;
1289 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) DbxList
+ SiglistHeaderSize
);
1290 CertHashCount
= (DbxList
->SignatureListSize
- SiglistHeaderSize
) / DbxList
->SignatureSize
;
1291 for (Index
= 0; Index
< CertHashCount
; Index
++) {
1293 // Iterate each Signature Data Node within this CertList for verify.
1295 DbxCertHash
= CertHash
->SignatureData
;
1296 if (CompareMem (DbxCertHash
, CertDigest
, mHash
[HashAlg
].DigestLength
) == 0) {
1298 // Hash of Certificate is found in forbidden database.
1303 CertHash
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertHash
+ DbxList
->SignatureSize
);
1306 DataSize
-= DbxList
->SignatureListSize
;
1307 DbxList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) DbxList
+ DbxList
->SignatureListSize
);
1319 Check whether the signature list exists in given variable data.
1321 It searches the signature list for the ceritificate hash by CertType.
1322 If the signature list is found, get the offset of Database for the
1323 next hash of a certificate.
1325 @param[in] Database Variable data to save signature list.
1326 @param[in] DatabaseSize Variable size.
1327 @param[in] SignatureType The type of the signature.
1328 @param[out] Offset The offset to save a new hash of certificate.
1330 @return TRUE The signature list is found in the forbidden database.
1331 @return FALSE The signature list is not found in the forbidden database.
1334 GetSignaturelistOffset (
1335 IN EFI_SIGNATURE_LIST
*Database
,
1336 IN UINTN DatabaseSize
,
1337 IN EFI_GUID
*SignatureType
,
1341 EFI_SIGNATURE_LIST
*SigList
;
1344 if ((Database
== NULL
) || (DatabaseSize
== 0)) {
1350 SiglistSize
= DatabaseSize
;
1351 while ((SiglistSize
> 0) && (SiglistSize
>= SigList
->SignatureListSize
)) {
1352 if (CompareGuid (&SigList
->SignatureType
, SignatureType
)) {
1353 *Offset
= DatabaseSize
- SiglistSize
;
1356 SiglistSize
-= SigList
->SignatureListSize
;
1357 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
1364 Enroll a new X509 certificate hash into Signature Database (dbx) without
1365 KEK's authentication.
1367 @param[in] PrivateData The module's private data.
1368 @param[in] HashAlg The hash algorithm to enroll the certificate.
1369 @param[in] RevocationDate The revocation date of the certificate.
1370 @param[in] RevocationTime The revocation time of the certificate.
1371 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1373 @retval EFI_SUCCESS New X509 is enrolled successfully.
1374 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1375 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1379 EnrollX509HashtoSigDB (
1380 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1382 IN EFI_HII_DATE
*RevocationDate
,
1383 IN EFI_HII_TIME
*RevocationTime
,
1384 IN BOOLEAN AlwaysRevocation
1390 EFI_SIGNATURE_LIST
*SignatureList
;
1391 UINTN SignatureListSize
;
1397 EFI_SIGNATURE_DATA
*SignatureData
;
1398 UINTN SignatureSize
;
1399 EFI_GUID SignatureType
;
1401 UINT8 CertHash
[MAX_DIGEST_SIZE
];
1402 UINT16
* FilePostFix
;
1409 SignatureData
= NULL
;
1410 SignatureList
= NULL
;
1414 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1415 return EFI_INVALID_PARAMETER
;
1418 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
1419 if (EFI_ERROR (Status
)) {
1424 // Parse the file's postfix.
1426 NameLength
= StrLen (Private
->FileContext
->FileName
);
1427 if (NameLength
<= 4) {
1428 return EFI_INVALID_PARAMETER
;
1430 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1431 if (!IsDerEncodeCertificate(FilePostFix
)) {
1433 // Only supports DER-encoded X509 certificate.
1435 return EFI_INVALID_PARAMETER
;
1439 // Get the certificate from file and calculate its hash.
1441 Status
= ReadFileContent (
1442 Private
->FileContext
->FHandle
,
1447 if (EFI_ERROR (Status
)) {
1450 ASSERT (X509Data
!= NULL
);
1452 if (!CalculateCertHash (X509Data
, X509DataSize
, HashAlg
, CertHash
)) {
1457 // Get the variable for enrollment.
1460 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, NULL
);
1461 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1462 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1464 return EFI_OUT_OF_RESOURCES
;
1467 Status
= gRT
->GetVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, Data
);
1468 if (EFI_ERROR (Status
)) {
1474 // Allocate memory for Signature and fill the Signature
1476 SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + sizeof (EFI_TIME
) + mHash
[HashAlg
].DigestLength
;
1477 SignatureData
= (EFI_SIGNATURE_DATA
*) AllocateZeroPool (SignatureSize
);
1478 if (SignatureData
== NULL
) {
1479 return EFI_OUT_OF_RESOURCES
;
1481 CopyGuid (&SignatureData
->SignatureOwner
, Private
->SignatureGUID
);
1482 CopyMem (SignatureData
->SignatureData
, CertHash
, mHash
[HashAlg
].DigestLength
);
1487 if (!AlwaysRevocation
) {
1488 Time
= (EFI_TIME
*)(&SignatureData
->SignatureData
+ mHash
[HashAlg
].DigestLength
);
1489 Time
->Year
= RevocationDate
->Year
;
1490 Time
->Month
= RevocationDate
->Month
;
1491 Time
->Day
= RevocationDate
->Day
;
1492 Time
->Hour
= RevocationTime
->Hour
;
1493 Time
->Minute
= RevocationTime
->Minute
;
1494 Time
->Second
= RevocationTime
->Second
;
1498 // Determine the GUID for certificate hash.
1501 case HASHALG_SHA256
:
1502 SignatureType
= gEfiCertX509Sha256Guid
;
1504 case HASHALG_SHA384
:
1505 SignatureType
= gEfiCertX509Sha384Guid
;
1507 case HASHALG_SHA512
:
1508 SignatureType
= gEfiCertX509Sha512Guid
;
1515 // Add signature into the new variable data buffer
1517 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST
*)Data
, DataSize
, &SignatureType
, &Offset
)) {
1519 // Add the signature to the found signaturelist.
1521 DbSize
= DataSize
+ SignatureSize
;
1522 NewData
= AllocateZeroPool (DbSize
);
1523 if (NewData
== NULL
) {
1524 Status
= EFI_OUT_OF_RESOURCES
;
1528 SignatureList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1529 SignatureListSize
= (UINTN
) ReadUnaligned32 ((UINT32
*)&SignatureList
->SignatureListSize
);
1530 CopyMem (NewData
, Data
, Offset
+ SignatureListSize
);
1532 SignatureList
= (EFI_SIGNATURE_LIST
*)(NewData
+ Offset
);
1533 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
)(SignatureListSize
+ SignatureSize
));
1535 Offset
+= SignatureListSize
;
1536 CopyMem (NewData
+ Offset
, SignatureData
, SignatureSize
);
1537 CopyMem (NewData
+ Offset
+ SignatureSize
, Data
+ Offset
, DataSize
- Offset
);
1544 // Create a new signaturelist, and add the signature into the signaturelist.
1546 DbSize
= DataSize
+ sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1547 NewData
= AllocateZeroPool (DbSize
);
1548 if (NewData
== NULL
) {
1549 Status
= EFI_OUT_OF_RESOURCES
;
1553 // Fill Certificate Database parameters.
1555 SignatureList
= (EFI_SIGNATURE_LIST
*) (NewData
+ DataSize
);
1556 SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
) + SignatureSize
;
1557 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureListSize
, (UINT32
) SignatureListSize
);
1558 WriteUnaligned32 ((UINT32
*) &SignatureList
->SignatureSize
, (UINT32
) SignatureSize
);
1559 CopyGuid (&SignatureList
->SignatureType
, &SignatureType
);
1560 CopyMem ((UINT8
* ) SignatureList
+ sizeof (EFI_SIGNATURE_LIST
), SignatureData
, SignatureSize
);
1561 if ((DataSize
!= 0) && (Data
!= NULL
)) {
1562 CopyMem (NewData
, Data
, DataSize
);
1569 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &Data
);
1570 if (EFI_ERROR (Status
)) {
1574 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1575 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1576 Status
= gRT
->SetVariable(
1577 EFI_IMAGE_SECURITY_DATABASE1
,
1578 &gEfiImageSecurityDatabaseGuid
,
1583 if (EFI_ERROR (Status
)) {
1589 CloseEnrolledFile(Private
->FileContext
);
1591 if (Private
->SignatureGUID
!= NULL
) {
1592 FreePool (Private
->SignatureGUID
);
1593 Private
->SignatureGUID
= NULL
;
1600 if (SignatureData
!= NULL
) {
1601 FreePool (SignatureData
);
1604 if (X509Data
!= NULL
) {
1605 FreePool (X509Data
);
1612 Check whether a certificate from a file exists in dbx.
1614 @param[in] PrivateData The module's private data.
1615 @param[in] VariableName Variable name of signature database, must be
1616 EFI_IMAGE_SECURITY_DATABASE1.
1618 @retval TRUE The X509 certificate is found in dbx successfully.
1619 @retval FALSE The X509 certificate is not found in dbx.
1623 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1624 IN CHAR16
*VariableName
1633 // Read the certificate from file
1637 Status
= ReadFileContent (
1638 Private
->FileContext
->FHandle
,
1643 if (EFI_ERROR (Status
)) {
1648 // Check the raw certificate.
1651 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1
, X509Data
, X509DataSize
)) {
1657 // Check the hash of certificate.
1659 if (IsCertHashFoundInDbx (X509Data
, X509DataSize
)) {
1665 if (X509Data
!= NULL
) {
1666 FreePool (X509Data
);
1673 Reads contents of a PE/COFF image in memory buffer.
1675 Caution: This function may receive untrusted input.
1676 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1677 read is within the image buffer.
1679 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1680 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1681 @param ReadSize On input, the size in bytes of the requested read operation.
1682 On output, the number of bytes actually read.
1683 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1685 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1689 SecureBootConfigImageRead (
1690 IN VOID
*FileHandle
,
1691 IN UINTN FileOffset
,
1692 IN OUT UINTN
*ReadSize
,
1698 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
1699 return EFI_INVALID_PARAMETER
;
1702 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
1703 return EFI_INVALID_PARAMETER
;
1706 EndPosition
= FileOffset
+ *ReadSize
;
1707 if (EndPosition
> mImageSize
) {
1708 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
1711 if (FileOffset
>= mImageSize
) {
1715 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
1721 Load PE/COFF image information into internal buffer and check its validity.
1723 @retval EFI_SUCCESS Successful
1724 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1725 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1733 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1734 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
1735 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
1736 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1742 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1743 ImageContext
.Handle
= (VOID
*) mImageBase
;
1744 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecureBootConfigImageRead
;
1747 // Get information about the image being loaded
1749 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1750 if (EFI_ERROR (Status
)) {
1752 // The information can't be got from the invalid PeImage
1754 DEBUG ((DEBUG_INFO
, "SecureBootConfigDxe: PeImage invalid. \n"));
1759 // Read the Dos header
1761 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
1762 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
1765 // DOS image header is present,
1766 // So read the PE header after the DOS image header
1768 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1772 mPeCoffHeaderOffset
= 0;
1776 // Read PE header and check the signature validity and machine compatibility
1778 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1779 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1781 return EFI_UNSUPPORTED
;
1784 mNtHeader
.Pe32
= NtHeader32
;
1787 // Check the architecture field of PE header and get the Certificate Data Directory data
1788 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1790 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1791 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)
1792 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
)) {
1794 // 32-bits Architecture
1796 mImageType
= ImageType_IA32
;
1797 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1799 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1800 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)
1801 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_AARCH64
)) {
1803 // 64-bits Architecture
1805 mImageType
= ImageType_X64
;
1806 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1807 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1809 return EFI_UNSUPPORTED
;
1816 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1817 PE/COFF Specification 8.0 Appendix A
1819 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1820 the function LoadPeImage ().
1822 @param[in] HashAlg Hash algorithm type.
1824 @retval TRUE Successfully hash image.
1825 @retval FALSE Fail in hash image.
1834 EFI_IMAGE_SECTION_HEADER
*Section
;
1839 UINTN SumOfBytesHashed
;
1840 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1845 SectionHeader
= NULL
;
1848 if (HashAlg
!= HASHALG_SHA256
) {
1853 // Initialize context of hash.
1855 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1857 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1858 mCertType
= gEfiCertSha256Guid
;
1860 CtxSize
= mHash
[HashAlg
].GetContextSize();
1862 HashCtx
= AllocatePool (CtxSize
);
1863 ASSERT (HashCtx
!= NULL
);
1865 // 1. Load the image header into memory.
1867 // 2. Initialize a SHA hash context.
1868 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1873 // Measuring PE/COFF Image Header;
1874 // But CheckSum field and SECURITY data directory (certificate) are excluded
1878 // 3. Calculate the distance from the base of the image header to the image checksum address.
1879 // 4. Hash the image header from its base to beginning of the image checksum.
1881 HashBase
= mImageBase
;
1882 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1886 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1889 // Use PE32+ offset.
1891 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1894 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1899 // 5. Skip over the image checksum (it occupies a single ULONG).
1900 // 6. Get the address of the beginning of the Cert Directory.
1901 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1903 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1907 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1908 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1911 // Use PE32+ offset.
1913 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1914 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1917 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1922 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1923 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1925 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1929 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1930 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1933 // Use PE32+ offset.
1935 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1936 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1939 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1944 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1946 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1950 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1955 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1959 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1960 // structures in the image. The 'NumberOfSections' field of the image
1961 // header indicates how big the table should be. Do not include any
1962 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1964 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1965 ASSERT (SectionHeader
!= NULL
);
1967 // 12. Using the 'PointerToRawData' in the referenced section headers as
1968 // a key, arrange the elements in the table in ascending order. In other
1969 // words, sort the section headers according to the disk-file offset of
1972 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1974 mPeCoffHeaderOffset
+
1976 sizeof (EFI_IMAGE_FILE_HEADER
) +
1977 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1979 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1981 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1982 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1985 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1990 // 13. Walk through the sorted table, bring the corresponding section
1991 // into memory, and hash the entire section (using the 'SizeOfRawData'
1992 // field in the section header to determine the amount of data to hash).
1993 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1994 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1996 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1997 Section
= &SectionHeader
[Index
];
1998 if (Section
->SizeOfRawData
== 0) {
2001 HashBase
= mImageBase
+ Section
->PointerToRawData
;
2002 HashSize
= (UINTN
) Section
->SizeOfRawData
;
2004 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2009 SumOfBytesHashed
+= HashSize
;
2013 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2014 // data in the file that needs to be added to the hash. This data begins
2015 // at file offset SUM_OF_BYTES_HASHED and its length is:
2016 // FileSize - (CertDirectory->Size)
2018 if (mImageSize
> SumOfBytesHashed
) {
2019 HashBase
= mImageBase
+ SumOfBytesHashed
;
2020 if (mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2026 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2030 // Use PE32+ offset.
2034 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2038 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2044 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2047 if (HashCtx
!= NULL
) {
2050 if (SectionHeader
!= NULL
) {
2051 FreePool (SectionHeader
);
2057 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2058 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2061 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2062 @retval EFI_SUCCESS Hash successfully.
2071 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2073 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2075 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2077 // Check the Hash algorithm in PE/COFF Authenticode.
2078 // According to PKCS#7 Definition:
2079 // SignedData ::= SEQUENCE {
2081 // digestAlgorithms DigestAlgorithmIdentifiers,
2082 // contentInfo ContentInfo,
2084 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2085 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2086 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2088 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2090 // Only support two bytes of Long Form of Length Encoding.
2096 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2101 if (Index
== HASHALG_MAX
) {
2102 return EFI_UNSUPPORTED
;
2106 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2108 if (!HashPeImage(Index
)) {
2109 return EFI_UNSUPPORTED
;
2116 Enroll a new executable's signature into Signature Database.
2118 @param[in] PrivateData The module's private data.
2119 @param[in] VariableName Variable name of signature database, must be
2120 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2121 or EFI_IMAGE_SECURITY_DATABASE2.
2123 @retval EFI_SUCCESS New signature is enrolled successfully.
2124 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2125 @retval EFI_UNSUPPORTED Unsupported command.
2126 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2130 EnrollAuthentication2Descriptor (
2131 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2132 IN CHAR16
*VariableName
2143 // DBT only support DER-X509 Cert Enrollment
2145 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2146 return EFI_UNSUPPORTED
;
2150 // Read the whole file content
2152 Status
= ReadFileContent(
2153 Private
->FileContext
->FHandle
,
2154 (VOID
**) &mImageBase
,
2158 if (EFI_ERROR (Status
)) {
2161 ASSERT (mImageBase
!= NULL
);
2163 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2164 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2167 // Check if SigDB variable has been already existed.
2168 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2169 // new signature data to original variable
2172 Status
= gRT
->GetVariable(
2174 &gEfiImageSecurityDatabaseGuid
,
2179 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2180 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2181 } else if (Status
!= EFI_NOT_FOUND
) {
2186 // Diretly set AUTHENTICATION_2 data to SetVariable
2188 Status
= gRT
->SetVariable(
2190 &gEfiImageSecurityDatabaseGuid
,
2196 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2200 CloseEnrolledFile(Private
->FileContext
);
2206 if (mImageBase
!= NULL
) {
2207 FreePool (mImageBase
);
2217 Enroll a new executable's signature into Signature Database.
2219 @param[in] PrivateData The module's private data.
2220 @param[in] VariableName Variable name of signature database, must be
2221 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2222 or EFI_IMAGE_SECURITY_DATABASE2.
2224 @retval EFI_SUCCESS New signature is enrolled successfully.
2225 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2226 @retval EFI_UNSUPPORTED Unsupported command.
2227 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2231 EnrollImageSignatureToSigDB (
2232 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2233 IN CHAR16
*VariableName
2237 EFI_SIGNATURE_LIST
*SigDBCert
;
2238 EFI_SIGNATURE_DATA
*SigDBCertData
;
2243 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2246 GuidCertData
= NULL
;
2248 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2249 return EFI_UNSUPPORTED
;
2253 // Form the SigDB certificate list.
2254 // Format the data item into EFI_SIGNATURE_LIST type.
2256 // We need to parse executable's signature data from specified signed executable file.
2257 // In current implementation, we simply trust the pass-in signed executable file.
2258 // In reality, it's OS's responsibility to verify the signed executable file.
2262 // Read the whole file content
2264 Status
= ReadFileContent(
2265 Private
->FileContext
->FHandle
,
2266 (VOID
**) &mImageBase
,
2270 if (EFI_ERROR (Status
)) {
2273 ASSERT (mImageBase
!= NULL
);
2275 Status
= LoadPeImage ();
2276 if (EFI_ERROR (Status
)) {
2280 if (mSecDataDir
->SizeOfCert
== 0) {
2281 if (!HashPeImage (HASHALG_SHA256
)) {
2282 Status
= EFI_SECURITY_VIOLATION
;
2288 // Read the certificate data
2290 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2292 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2293 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2294 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2295 Status
= EFI_ABORTED
;
2299 if (!HashPeImage (HASHALG_SHA256
)) {
2300 Status
= EFI_ABORTED
;
2304 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2306 Status
= HashPeImageByType ();
2307 if (EFI_ERROR (Status
)) {
2311 Status
= EFI_ABORTED
;
2317 // Create a new SigDB entry.
2319 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2320 + sizeof(EFI_SIGNATURE_DATA
) - 1
2321 + (UINT32
) mImageDigestSize
;
2323 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2325 Status
= EFI_OUT_OF_RESOURCES
;
2330 // Adjust the Certificate Database parameters.
2332 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2333 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2334 SigDBCert
->SignatureHeaderSize
= 0;
2335 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2336 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2338 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2339 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2340 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2342 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2343 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2344 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2345 if (EFI_ERROR (Status
)) {
2346 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2351 // Check if SigDB variable has been already existed.
2352 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2353 // new signature data to original variable
2356 Status
= gRT
->GetVariable(
2358 &gEfiImageSecurityDatabaseGuid
,
2363 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2364 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2365 } else if (Status
!= EFI_NOT_FOUND
) {
2370 // Enroll the variable.
2372 Status
= gRT
->SetVariable(
2374 &gEfiImageSecurityDatabaseGuid
,
2379 if (EFI_ERROR (Status
)) {
2385 CloseEnrolledFile(Private
->FileContext
);
2387 if (Private
->SignatureGUID
!= NULL
) {
2388 FreePool (Private
->SignatureGUID
);
2389 Private
->SignatureGUID
= NULL
;
2396 if (mImageBase
!= NULL
) {
2397 FreePool (mImageBase
);
2405 Enroll signature into DB/DBX/DBT without KEK's authentication.
2406 The SignatureOwner GUID will be Private->SignatureGUID.
2408 @param[in] PrivateData The module's private data.
2409 @param[in] VariableName Variable name of signature database, must be
2410 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2412 @retval EFI_SUCCESS New signature enrolled successfully.
2413 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2414 @retval others Fail to enroll signature data.
2418 EnrollSignatureDatabase (
2419 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2420 IN CHAR16
*VariableName
2423 UINT16
* FilePostFix
;
2427 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2428 return EFI_INVALID_PARAMETER
;
2431 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2432 if (EFI_ERROR (Status
)) {
2437 // Parse the file's postfix.
2439 NameLength
= StrLen (Private
->FileContext
->FileName
);
2440 if (NameLength
<= 4) {
2441 return EFI_INVALID_PARAMETER
;
2443 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2444 if (IsDerEncodeCertificate (FilePostFix
)) {
2446 // Supports DER-encoded X509 certificate.
2448 return EnrollX509toSigDB (Private
, VariableName
);
2449 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2450 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2452 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2457 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2458 by GUID in the page for user to select and delete as needed.
2460 @param[in] PrivateData Module's private data.
2461 @param[in] VariableName The variable name of the vendor's signature database.
2462 @param[in] VendorGuid A unique identifier for the vendor.
2463 @param[in] LabelNumber Label number to insert opcodes.
2464 @param[in] FormId Form ID of current page.
2465 @param[in] QuestionIdBase Base question id of the signature list.
2467 @retval EFI_SUCCESS Success to update the signature list page
2468 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2473 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2474 IN CHAR16
*VariableName
,
2475 IN EFI_GUID
*VendorGuid
,
2476 IN UINT16 LabelNumber
,
2477 IN EFI_FORM_ID FormId
,
2478 IN EFI_QUESTION_ID QuestionIdBase
2485 VOID
*StartOpCodeHandle
;
2486 VOID
*EndOpCodeHandle
;
2487 EFI_IFR_GUID_LABEL
*StartLabel
;
2488 EFI_IFR_GUID_LABEL
*EndLabel
;
2491 EFI_SIGNATURE_LIST
*CertList
;
2492 EFI_SIGNATURE_DATA
*Cert
;
2493 UINT32 ItemDataSize
;
2495 EFI_STRING_ID GuidID
;
2502 StartOpCodeHandle
= NULL
;
2503 EndOpCodeHandle
= NULL
;
2506 // Initialize the container for dynamic opcodes.
2508 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2509 if (StartOpCodeHandle
== NULL
) {
2510 Status
= EFI_OUT_OF_RESOURCES
;
2514 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2515 if (EndOpCodeHandle
== NULL
) {
2516 Status
= EFI_OUT_OF_RESOURCES
;
2521 // Create Hii Extend Label OpCode.
2523 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2527 sizeof (EFI_IFR_GUID_LABEL
)
2529 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2530 StartLabel
->Number
= LabelNumber
;
2532 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2536 sizeof (EFI_IFR_GUID_LABEL
)
2538 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2539 EndLabel
->Number
= LABEL_END
;
2545 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2546 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2550 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2552 Status
= EFI_OUT_OF_RESOURCES
;
2556 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2557 if (EFI_ERROR (Status
)) {
2561 GuidStr
= AllocateZeroPool (100);
2562 if (GuidStr
== NULL
) {
2563 Status
= EFI_OUT_OF_RESOURCES
;
2568 // Enumerate all KEK pub data.
2570 ItemDataSize
= (UINT32
) DataSize
;
2571 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2574 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2576 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2577 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2578 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2579 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2580 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2581 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2582 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2583 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2584 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2585 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2586 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2587 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2588 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2589 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2592 // The signature type is not supported in current implementation.
2594 ItemDataSize
-= CertList
->SignatureListSize
;
2595 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2599 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2600 for (Index
= 0; Index
< CertCount
; Index
++) {
2601 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2602 + sizeof (EFI_SIGNATURE_LIST
)
2603 + CertList
->SignatureHeaderSize
2604 + Index
* CertList
->SignatureSize
);
2606 // Display GUID and help
2608 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2609 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2610 HiiCreateCheckBoxOpCode (
2612 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2617 EFI_IFR_FLAG_CALLBACK
,
2623 ItemDataSize
-= CertList
->SignatureListSize
;
2624 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2629 PrivateData
->HiiHandle
,
2630 &gSecureBootConfigFormSetGuid
,
2636 if (StartOpCodeHandle
!= NULL
) {
2637 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2640 if (EndOpCodeHandle
!= NULL
) {
2641 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2648 if (GuidStr
!= NULL
) {
2656 Delete a KEK entry from KEK database.
2658 @param[in] PrivateData Module's private data.
2659 @param[in] QuestionId Question id of the KEK item to delete.
2661 @retval EFI_SUCCESS Delete kek item successfully.
2662 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2666 DeleteKeyExchangeKey (
2667 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2668 IN EFI_QUESTION_ID QuestionId
2677 EFI_SIGNATURE_LIST
*CertList
;
2678 EFI_SIGNATURE_LIST
*NewCertList
;
2679 EFI_SIGNATURE_DATA
*Cert
;
2682 BOOLEAN IsKEKItemFound
;
2684 UINTN DeleteKekIndex
;
2692 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2694 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2695 if (EFI_ERROR (Status
)) {
2700 // Get original KEK variable.
2703 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2704 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2708 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2709 if (OldData
== NULL
) {
2710 Status
= EFI_OUT_OF_RESOURCES
;
2714 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2715 if (EFI_ERROR(Status
)) {
2720 // Allocate space for new variable.
2722 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2724 Status
= EFI_OUT_OF_RESOURCES
;
2729 // Enumerate all KEK pub data and erasing the target item.
2731 IsKEKItemFound
= FALSE
;
2732 KekDataSize
= (UINT32
) DataSize
;
2733 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2736 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2737 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2738 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2739 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2740 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2741 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2742 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2743 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2744 for (Index
= 0; Index
< CertCount
; Index
++) {
2745 if (GuidIndex
== DeleteKekIndex
) {
2747 // Find it! Skip it!
2749 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2750 IsKEKItemFound
= TRUE
;
2753 // This item doesn't match. Copy it to the Data buffer.
2755 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2756 Offset
+= CertList
->SignatureSize
;
2759 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2763 // This List doesn't match. Copy it to the Data buffer.
2765 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2766 Offset
+= CertList
->SignatureListSize
;
2769 KekDataSize
-= CertList
->SignatureListSize
;
2770 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2773 if (!IsKEKItemFound
) {
2775 // Doesn't find the Kek Item!
2777 Status
= EFI_NOT_FOUND
;
2782 // Delete the Signature header if there is no signature in the list.
2784 KekDataSize
= Offset
;
2785 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2787 ZeroMem (OldData
, KekDataSize
);
2788 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2789 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2790 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2791 if (CertCount
!= 0) {
2792 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2793 Offset
+= CertList
->SignatureListSize
;
2795 KekDataSize
-= CertList
->SignatureListSize
;
2796 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2800 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2801 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2802 if (EFI_ERROR (Status
)) {
2803 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2808 Status
= gRT
->SetVariable(
2809 EFI_KEY_EXCHANGE_KEY_NAME
,
2810 &gEfiGlobalVariableGuid
,
2815 if (EFI_ERROR (Status
)) {
2816 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2825 if (OldData
!= NULL
) {
2829 return UpdateDeletePage (
2831 EFI_KEY_EXCHANGE_KEY_NAME
,
2832 &gEfiGlobalVariableGuid
,
2834 FORMID_DELETE_KEK_FORM
,
2835 OPTION_DEL_KEK_QUESTION_ID
2840 Delete a signature entry from signature database.
2842 @param[in] PrivateData Module's private data.
2843 @param[in] VariableName The variable name of the vendor's signature database.
2844 @param[in] VendorGuid A unique identifier for the vendor.
2845 @param[in] LabelNumber Label number to insert opcodes.
2846 @param[in] FormId Form ID of current page.
2847 @param[in] QuestionIdBase Base question id of the signature list.
2848 @param[in] DeleteIndex Signature index to delete.
2850 @retval EFI_SUCCESS Delete signature successfully.
2851 @retval EFI_NOT_FOUND Can't find the signature item,
2852 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2856 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2857 IN CHAR16
*VariableName
,
2858 IN EFI_GUID
*VendorGuid
,
2859 IN UINT16 LabelNumber
,
2860 IN EFI_FORM_ID FormId
,
2861 IN EFI_QUESTION_ID QuestionIdBase
,
2862 IN UINTN DeleteIndex
2871 EFI_SIGNATURE_LIST
*CertList
;
2872 EFI_SIGNATURE_LIST
*NewCertList
;
2873 EFI_SIGNATURE_DATA
*Cert
;
2876 BOOLEAN IsItemFound
;
2877 UINT32 ItemDataSize
;
2886 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2887 if (EFI_ERROR (Status
)) {
2892 // Get original signature list data.
2895 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2896 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2900 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2901 if (OldData
== NULL
) {
2902 Status
= EFI_OUT_OF_RESOURCES
;
2906 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2907 if (EFI_ERROR(Status
)) {
2912 // Allocate space for new variable.
2914 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2916 Status
= EFI_OUT_OF_RESOURCES
;
2921 // Enumerate all signature data and erasing the target item.
2923 IsItemFound
= FALSE
;
2924 ItemDataSize
= (UINT32
) DataSize
;
2925 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2928 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2929 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2930 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2931 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2932 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2933 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2934 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2935 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2938 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2940 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2941 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2942 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2943 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2944 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2945 for (Index
= 0; Index
< CertCount
; Index
++) {
2946 if (GuidIndex
== DeleteIndex
) {
2948 // Find it! Skip it!
2950 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2954 // This item doesn't match. Copy it to the Data buffer.
2956 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2957 Offset
+= CertList
->SignatureSize
;
2960 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2964 // This List doesn't match. Just copy it to the Data buffer.
2966 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2967 Offset
+= CertList
->SignatureListSize
;
2970 ItemDataSize
-= CertList
->SignatureListSize
;
2971 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2976 // Doesn't find the signature Item!
2978 Status
= EFI_NOT_FOUND
;
2983 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2985 ItemDataSize
= Offset
;
2986 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2988 ZeroMem (OldData
, ItemDataSize
);
2989 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2990 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2991 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2992 if (CertCount
!= 0) {
2993 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2994 Offset
+= CertList
->SignatureListSize
;
2996 ItemDataSize
-= CertList
->SignatureListSize
;
2997 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
3001 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3002 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
3003 if (EFI_ERROR (Status
)) {
3004 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
3009 Status
= gRT
->SetVariable(
3016 if (EFI_ERROR (Status
)) {
3017 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
3026 if (OldData
!= NULL
) {
3030 return UpdateDeletePage (
3041 This function to delete signature list or data, according by DelType.
3043 @param[in] PrivateData Module's private data.
3044 @param[in] DelType Indicate delete signature list or data.
3045 @param[in] CheckedCount Indicate how many signature data have
3046 been checked in current signature list.
3048 @retval EFI_SUCCESS Success to update the signature list page
3049 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3053 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3054 IN SIGNATURE_DELETE_TYPE DelType
,
3055 IN UINT32 CheckedCount
3059 EFI_SIGNATURE_LIST
*ListWalker
;
3060 EFI_SIGNATURE_LIST
*NewCertList
;
3061 EFI_SIGNATURE_DATA
*DataWalker
;
3062 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3063 UINT32 VariableAttr
;
3064 UINTN VariableDataSize
;
3065 UINTN RemainingSize
;
3069 UINT8
*VariableData
;
3070 UINT8
*NewVariableData
;
3072 Status
= EFI_SUCCESS
;
3074 VariableDataSize
= 0;
3077 VariableData
= NULL
;
3078 NewVariableData
= NULL
;
3080 if (PrivateData
->VariableName
== Variable_DB
) {
3081 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3082 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3083 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3084 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3085 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3090 Status
= gRT
->GetVariable (
3092 &gEfiImageSecurityDatabaseGuid
,
3097 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3101 VariableData
= AllocateZeroPool (VariableDataSize
);
3102 if (VariableData
== NULL
) {
3103 Status
= EFI_OUT_OF_RESOURCES
;
3107 Status
= gRT
->GetVariable (
3109 &gEfiImageSecurityDatabaseGuid
,
3114 if (EFI_ERROR (Status
)) {
3118 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3119 if (EFI_ERROR (Status
)) {
3123 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3124 if (NewVariableData
== NULL
) {
3125 Status
= EFI_OUT_OF_RESOURCES
;
3129 RemainingSize
= VariableDataSize
;
3130 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3131 if (DelType
== Delete_Signature_List_All
) {
3132 VariableDataSize
= 0;
3135 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3137 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3138 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3139 Offset
+= ListWalker
->SignatureListSize
;
3141 RemainingSize
-= ListWalker
->SignatureListSize
;
3142 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3147 // Handle the target EFI_SIGNATURE_LIST.
3148 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3149 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3151 if (CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
) && DelType
== Delete_Signature_Data
) {
3152 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3156 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3157 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3159 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3160 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
3161 if (PrivateData
->CheckArray
[Index
]) {
3163 // Delete checked signature data, and update the size of whole signature list.
3165 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3168 // Remain the unchecked signature data.
3170 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3171 Offset
+= ListWalker
->SignatureSize
;
3173 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3177 RemainingSize
-= ListWalker
->SignatureListSize
;
3178 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3181 // Copy remaining data, maybe 0.
3183 CopyMem((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3184 Offset
+= RemainingSize
;
3186 VariableDataSize
= Offset
;
3189 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3190 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3191 if (EFI_ERROR (Status
)) {
3192 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3197 Status
= gRT
->SetVariable (
3199 &gEfiImageSecurityDatabaseGuid
,
3204 if (EFI_ERROR (Status
)) {
3205 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3210 SECUREBOOT_FREE_NON_NULL (VariableData
);
3211 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3218 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3219 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3221 @param[in] PrivateData Module's private data.
3223 @return EFI_SUCCESS Update secure boot strings successfully.
3224 @return other Fail to update secure boot strings.
3228 UpdateSecureBootString(
3229 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3237 // Get current secure boot state.
3239 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3240 if (SecureBoot
== NULL
) {
3241 return EFI_NOT_FOUND
;
3244 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3245 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3247 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3250 FreePool(SecureBoot
);
3256 This function extracts configuration from variable.
3258 @param[in] Private Point to SecureBoot configuration driver private data.
3259 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3263 SecureBootExtractConfigFromVariable (
3264 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3265 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3268 UINT8
*SecureBootEnable
;
3270 UINT8
*SecureBootMode
;
3273 SecureBootEnable
= NULL
;
3275 SecureBootMode
= NULL
;
3278 // Initilize the Date and Time using system time.
3280 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3281 ConfigData
->AlwaysRevocation
= TRUE
;
3282 gRT
->GetTime (&CurrTime
, NULL
);
3283 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3284 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3285 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3286 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3287 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3288 ConfigData
->RevocationTime
.Second
= 0;
3289 if (Private
->FileContext
->FHandle
!= NULL
) {
3290 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3292 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3296 // If it is Physical Presence User, set the PhysicalPresent to true.
3298 if (UserPhysicalPresent()) {
3299 ConfigData
->PhysicalPresent
= TRUE
;
3301 ConfigData
->PhysicalPresent
= FALSE
;
3305 // If there is no PK then the Delete Pk button will be gray.
3307 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3308 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3309 ConfigData
->HasPk
= FALSE
;
3311 ConfigData
->HasPk
= TRUE
;
3315 // Check SecureBootEnable & Pk status, fix the inconsistence.
3316 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3319 ConfigData
->AttemptSecureBoot
= FALSE
;
3320 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3323 // Fix Pk, SecureBootEnable inconsistence
3325 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3326 ConfigData
->HideSecureBoot
= FALSE
;
3327 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3328 ConfigData
->AttemptSecureBoot
= TRUE
;
3331 ConfigData
->HideSecureBoot
= TRUE
;
3335 // Get the SecureBootMode from CustomMode variable.
3337 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3338 if (SecureBootMode
== NULL
) {
3339 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3341 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3344 if (SecureBootEnable
!= NULL
) {
3345 FreePool (SecureBootEnable
);
3347 if (SetupMode
!= NULL
) {
3348 FreePool (SetupMode
);
3350 if (SecureBootMode
!= NULL
) {
3351 FreePool (SecureBootMode
);
3356 This function allows a caller to extract the current configuration for one
3357 or more named elements from the target driver.
3359 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3360 @param[in] Request A null-terminated Unicode string in
3361 <ConfigRequest> format.
3362 @param[out] Progress On return, points to a character in the Request
3363 string. Points to the string's null terminator if
3364 request was successful. Points to the most recent
3365 '&' before the first failing name/value pair (or
3366 the beginning of the string if the failure is in
3367 the first name/value pair) if the request was not
3369 @param[out] Results A null-terminated Unicode string in
3370 <ConfigAltResp> format which has all values filled
3371 in for the names in the Request string. String to
3372 be allocated by the called function.
3374 @retval EFI_SUCCESS The Results is filled with the requested values.
3375 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3376 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3377 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3383 SecureBootExtractConfig (
3384 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3385 IN CONST EFI_STRING Request
,
3386 OUT EFI_STRING
*Progress
,
3387 OUT EFI_STRING
*Results
3393 SECUREBOOT_CONFIGURATION Configuration
;
3394 EFI_STRING ConfigRequest
;
3395 EFI_STRING ConfigRequestHdr
;
3396 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3397 BOOLEAN AllocatedRequest
;
3399 if (Progress
== NULL
|| Results
== NULL
) {
3400 return EFI_INVALID_PARAMETER
;
3403 AllocatedRequest
= FALSE
;
3404 ConfigRequestHdr
= NULL
;
3405 ConfigRequest
= NULL
;
3408 ZeroMem (&Configuration
, sizeof (Configuration
));
3409 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3410 *Progress
= Request
;
3412 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3413 return EFI_NOT_FOUND
;
3416 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3419 // Get Configuration from Variable.
3421 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3423 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3424 ConfigRequest
= Request
;
3425 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3427 // Request is set to NULL or OFFSET is NULL, construct full request string.
3429 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3430 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3432 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3433 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3434 ConfigRequest
= AllocateZeroPool (Size
);
3435 ASSERT (ConfigRequest
!= NULL
);
3436 AllocatedRequest
= TRUE
;
3437 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3438 FreePool (ConfigRequestHdr
);
3439 ConfigRequestHdr
= NULL
;
3442 Status
= gHiiConfigRouting
->BlockToConfig (
3445 (UINT8
*) &Configuration
,
3452 // Free the allocated config request string.
3454 if (AllocatedRequest
) {
3455 FreePool (ConfigRequest
);
3459 // Set Progress string to the original request string.
3461 if (Request
== NULL
) {
3463 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3464 *Progress
= Request
+ StrLen (Request
);
3471 This function processes the results of changes in configuration.
3473 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3474 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3476 @param[out] Progress A pointer to a string filled in with the offset of
3477 the most recent '&' before the first failing
3478 name/value pair (or the beginning of the string if
3479 the failure is in the first name/value pair) or
3480 the terminating NULL if all was successful.
3482 @retval EFI_SUCCESS The Results is processed successfully.
3483 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3484 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3490 SecureBootRouteConfig (
3491 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3492 IN CONST EFI_STRING Configuration
,
3493 OUT EFI_STRING
*Progress
3496 SECUREBOOT_CONFIGURATION IfrNvData
;
3498 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3501 if (Configuration
== NULL
|| Progress
== NULL
) {
3502 return EFI_INVALID_PARAMETER
;
3505 *Progress
= Configuration
;
3506 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3507 return EFI_NOT_FOUND
;
3510 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3513 // Get Configuration from Variable.
3515 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3518 // Map the Configuration to the configuration block.
3520 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3521 Status
= gHiiConfigRouting
->ConfigToBlock (
3524 (UINT8
*)&IfrNvData
,
3528 if (EFI_ERROR (Status
)) {
3533 // Store Buffer Storage back to EFI variable if needed
3535 if (!IfrNvData
.HideSecureBoot
) {
3536 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3537 if (EFI_ERROR (Status
)) {
3542 *Progress
= Configuration
+ StrLen (Configuration
);
3547 This function to load signature list, the update the menu page.
3549 @param[in] PrivateData Module's private data.
3550 @param[in] LabelId Label number to insert opcodes.
3551 @param[in] FormId Form ID of current page.
3552 @param[in] QuestionIdBase Base question id of the signature list.
3554 @retval EFI_SUCCESS Success to update the signature list page
3555 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3559 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3561 IN EFI_FORM_ID FormId
,
3562 IN EFI_QUESTION_ID QuestionIdBase
3566 EFI_STRING_ID ListType
;
3567 EFI_STRING FormatNameString
;
3568 EFI_STRING FormatHelpString
;
3569 EFI_STRING FormatTypeString
;
3570 EFI_SIGNATURE_LIST
*ListWalker
;
3571 EFI_IFR_GUID_LABEL
*StartLabel
;
3572 EFI_IFR_GUID_LABEL
*EndLabel
;
3573 EFI_IFR_GUID_LABEL
*StartGoto
;
3574 EFI_IFR_GUID_LABEL
*EndGoto
;
3575 EFI_FORM_ID DstFormId
;
3576 VOID
*StartOpCodeHandle
;
3577 VOID
*EndOpCodeHandle
;
3578 VOID
*StartGotoHandle
;
3579 VOID
*EndGotoHandle
;
3581 UINTN RemainingSize
;
3583 UINT8
*VariableData
;
3584 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3585 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3586 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3588 Status
= EFI_SUCCESS
;
3589 FormatNameString
= NULL
;
3590 FormatHelpString
= NULL
;
3591 StartOpCodeHandle
= NULL
;
3592 EndOpCodeHandle
= NULL
;
3593 StartGotoHandle
= NULL
;
3594 EndGotoHandle
= NULL
;
3596 VariableData
= NULL
;
3599 // Initialize the container for dynamic opcodes.
3601 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3602 if (StartOpCodeHandle
== NULL
) {
3603 Status
= EFI_OUT_OF_RESOURCES
;
3607 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3608 if (EndOpCodeHandle
== NULL
) {
3609 Status
= EFI_OUT_OF_RESOURCES
;
3613 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3614 if (StartGotoHandle
== NULL
) {
3615 Status
= EFI_OUT_OF_RESOURCES
;
3619 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3620 if (EndGotoHandle
== NULL
) {
3621 Status
= EFI_OUT_OF_RESOURCES
;
3626 // Create Hii Extend Label OpCode.
3628 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3632 sizeof (EFI_IFR_GUID_LABEL
)
3634 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3635 StartLabel
->Number
= LabelId
;
3637 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3641 sizeof (EFI_IFR_GUID_LABEL
)
3643 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3644 EndLabel
->Number
= LABEL_END
;
3646 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3650 sizeof(EFI_IFR_GUID_LABEL
)
3652 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3653 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3655 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3659 sizeof(EFI_IFR_GUID_LABEL
)
3661 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3662 EndGoto
->Number
= LABEL_END
;
3664 if (PrivateData
->VariableName
== Variable_DB
) {
3665 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3666 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3667 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3668 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3669 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3670 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3671 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3672 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3677 HiiCreateGotoOpCode (
3680 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3681 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3682 EFI_IFR_FLAG_CALLBACK
,
3683 KEY_SECURE_BOOT_DELETE_ALL_LIST
3687 // Read Variable, the variable name save in the PrivateData->VariableName.
3690 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3691 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3695 VariableData
= AllocateZeroPool (DataSize
);
3696 if (VariableData
== NULL
) {
3697 Status
= EFI_OUT_OF_RESOURCES
;
3700 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3701 if (EFI_ERROR (Status
)) {
3705 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3706 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3707 if (FormatNameString
== NULL
|| FormatHelpString
== NULL
) {
3711 RemainingSize
= DataSize
;
3712 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3713 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3714 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3715 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3716 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3717 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3718 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3719 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3720 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3721 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3722 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3723 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3724 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3725 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3726 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3727 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3729 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3731 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3732 if (FormatTypeString
== NULL
) {
3736 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3737 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3739 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3740 UnicodeSPrint (HelpBuffer
,
3741 sizeof (HelpBuffer
),
3744 SIGNATURE_DATA_COUNTS (ListWalker
)
3746 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3747 FormatTypeString
= NULL
;
3749 HiiCreateGotoOpCode (
3751 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3752 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3753 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3754 EFI_IFR_FLAG_CALLBACK
,
3755 QuestionIdBase
+ Index
++
3758 RemainingSize
-= ListWalker
->SignatureListSize
;
3759 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3764 PrivateData
->HiiHandle
,
3765 &gSecureBootConfigFormSetGuid
,
3772 PrivateData
->HiiHandle
,
3773 &gSecureBootConfigFormSetGuid
,
3779 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3780 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3781 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3782 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3784 SECUREBOOT_FREE_NON_NULL (VariableData
);
3785 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3786 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3788 PrivateData
->ListCount
= Index
;
3794 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3795 The buffer is callee allocated and should be freed by the caller.
3797 @param[in] ListEntry The pointer point to the signature list.
3798 @param[in] DataEntry The signature data we are processing.
3799 @param[out] BufferToReturn Buffer to save the hash value.
3801 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3802 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3803 @retval EFI_SUCCESS Operation success.
3807 IN EFI_SIGNATURE_LIST
*ListEntry
,
3808 IN EFI_SIGNATURE_DATA
*DataEntry
,
3809 OUT CHAR16
**BufferToReturn
3820 // Assume that, display 8 bytes in one line.
3824 if (ListEntry
== NULL
|| DataEntry
== NULL
|| BufferToReturn
== NULL
) {
3825 return EFI_INVALID_PARAMETER
;
3828 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3829 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3832 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3834 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof(CHAR16
));
3836 *BufferToReturn
= AllocateZeroPool(TotalSize
);
3837 if (*BufferToReturn
== NULL
) {
3838 return EFI_OUT_OF_RESOURCES
;
3841 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3842 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3843 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3845 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3847 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3853 Function to get the common name from the X509 format certificate.
3854 The buffer is callee allocated and should be freed by the caller.
3856 @param[in] ListEntry The pointer point to the signature list.
3857 @param[in] DataEntry The signature data we are processing.
3858 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3860 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3861 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3862 @retval EFI_SUCCESS Operation success.
3863 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3866 GetCommonNameFromX509 (
3867 IN EFI_SIGNATURE_LIST
*ListEntry
,
3868 IN EFI_SIGNATURE_DATA
*DataEntry
,
3869 OUT CHAR16
**BufferToReturn
3876 Status
= EFI_SUCCESS
;
3879 CNBuffer
= AllocateZeroPool(256);
3880 if (CNBuffer
== NULL
) {
3881 Status
= EFI_OUT_OF_RESOURCES
;
3887 (UINT8
*)DataEntry
+ sizeof(EFI_GUID
),
3888 ListEntry
->SignatureSize
- sizeof(EFI_GUID
),
3893 *BufferToReturn
= AllocateZeroPool(256 * sizeof(CHAR16
));
3894 if (*BufferToReturn
== NULL
) {
3895 Status
= EFI_OUT_OF_RESOURCES
;
3899 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3902 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3908 Format the help info for the signature data, each help info contain 3 parts.
3910 2. Content, depends on the type of the signature list.
3913 @param[in] PrivateData Module's private data.
3914 @param[in] ListEntry Point to the signature list.
3915 @param[in] DataEntry Point to the signature data we are processing.
3916 @param[out] StringId Save the string id of help info.
3918 @retval EFI_SUCCESS Operation success.
3919 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3923 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3924 IN EFI_SIGNATURE_LIST
*ListEntry
,
3925 IN EFI_SIGNATURE_DATA
*DataEntry
,
3926 OUT EFI_STRING_ID
*StringId
3931 EFI_STRING_ID ListTypeId
;
3932 EFI_STRING FormatHelpString
;
3933 EFI_STRING FormatTypeString
;
3935 UINTN HelpInfoIndex
;
3937 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3938 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3940 CHAR16
*HelpInfoString
;
3943 Status
= EFI_SUCCESS
;
3945 FormatTypeString
= NULL
;
3948 HelpInfoString
= NULL
;
3951 if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3952 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256
);
3953 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3955 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
3956 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509
);
3957 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3959 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
3960 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA1
);
3962 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
3963 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA256
);
3965 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3966 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA256
);
3968 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3969 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3970 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA384
);
3972 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3973 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3974 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA512
);
3976 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3978 Status
= EFI_UNSUPPORTED
;
3982 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
3983 if (FormatTypeString
== NULL
) {
3988 HelpInfoString
= AllocateZeroPool (TotalSize
);
3989 if (HelpInfoString
== NULL
) {
3990 Status
= EFI_OUT_OF_RESOURCES
;
3995 // Format GUID part.
3997 ZeroMem (GuidString
, sizeof (GuidString
));
3998 GuidToString(&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
3999 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
4000 if (FormatHelpString
== NULL
) {
4003 HelpInfoIndex
+= UnicodeSPrint (
4004 &HelpInfoString
[HelpInfoIndex
],
4005 TotalSize
- sizeof(CHAR16
) * HelpInfoIndex
,
4009 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4010 FormatHelpString
= NULL
;
4013 // Format content part, it depends on the type of signature list, hash value or CN.
4016 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
4017 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
4020 // Format hash value for each signature data entry.
4022 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
4023 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
4025 if (FormatHelpString
== NULL
) {
4028 HelpInfoIndex
+= UnicodeSPrint (
4029 &HelpInfoString
[HelpInfoIndex
],
4030 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4036 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4037 FormatHelpString
= NULL
;
4040 // Format revocation time part.
4043 ZeroMem (TimeString
, sizeof (TimeString
));
4046 sizeof (TimeString
),
4047 L
"%d-%d-%d %d:%d:%d",
4055 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
4056 if (FormatHelpString
== NULL
) {
4060 &HelpInfoString
[HelpInfoIndex
],
4061 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4065 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4066 FormatHelpString
= NULL
;
4069 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
4071 SECUREBOOT_FREE_NON_NULL (DataString
);
4072 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
4074 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
4080 This functino to load signature data under the signature list.
4082 @param[in] PrivateData Module's private data.
4083 @param[in] LabelId Label number to insert opcodes.
4084 @param[in] FormId Form ID of current page.
4085 @param[in] QuestionIdBase Base question id of the signature list.
4086 @param[in] ListIndex Indicate to load which signature list.
4088 @retval EFI_SUCCESS Success to update the signature list page
4089 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4093 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4095 IN EFI_FORM_ID FormId
,
4096 IN EFI_QUESTION_ID QuestionIdBase
,
4101 EFI_SIGNATURE_LIST
*ListWalker
;
4102 EFI_SIGNATURE_DATA
*DataWalker
;
4103 EFI_IFR_GUID_LABEL
*StartLabel
;
4104 EFI_IFR_GUID_LABEL
*EndLabel
;
4105 EFI_STRING_ID HelpStringId
;
4106 EFI_STRING FormatNameString
;
4107 VOID
*StartOpCodeHandle
;
4108 VOID
*EndOpCodeHandle
;
4110 UINTN RemainingSize
;
4112 UINT8
*VariableData
;
4113 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4114 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4116 Status
= EFI_SUCCESS
;
4117 FormatNameString
= NULL
;
4118 StartOpCodeHandle
= NULL
;
4119 EndOpCodeHandle
= NULL
;
4121 VariableData
= NULL
;
4124 // Initialize the container for dynamic opcodes.
4126 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4127 if (StartOpCodeHandle
== NULL
) {
4128 Status
= EFI_OUT_OF_RESOURCES
;
4132 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4133 if (EndOpCodeHandle
== NULL
) {
4134 Status
= EFI_OUT_OF_RESOURCES
;
4139 // Create Hii Extend Label OpCode.
4141 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4145 sizeof (EFI_IFR_GUID_LABEL
)
4147 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4148 StartLabel
->Number
= LabelId
;
4150 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4154 sizeof (EFI_IFR_GUID_LABEL
)
4156 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4157 EndLabel
->Number
= LABEL_END
;
4159 if (PrivateData
->VariableName
== Variable_DB
) {
4160 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4161 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4162 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4163 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4164 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4170 // Read Variable, the variable name save in the PrivateData->VariableName.
4173 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4174 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
4178 VariableData
= AllocateZeroPool (DataSize
);
4179 if (VariableData
== NULL
) {
4180 Status
= EFI_OUT_OF_RESOURCES
;
4183 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4184 if (EFI_ERROR (Status
)) {
4188 RemainingSize
= DataSize
;
4189 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4192 // Skip signature list.
4194 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4195 RemainingSize
-= ListWalker
->SignatureListSize
;
4196 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4199 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4200 if (FormatNameString
== NULL
) {
4204 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4205 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
4207 // Format name buffer.
4209 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4210 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4213 // Format help info buffer.
4215 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4216 if (EFI_ERROR (Status
)) {
4220 HiiCreateCheckBoxOpCode (
4222 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4225 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4227 EFI_IFR_FLAG_CALLBACK
,
4232 ZeroMem(NameBuffer
, 100);
4233 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4237 // Allocate a buffer to record which signature data will be checked.
4238 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4240 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4243 PrivateData
->HiiHandle
,
4244 &gSecureBootConfigFormSetGuid
,
4250 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4251 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4253 SECUREBOOT_FREE_NON_NULL (VariableData
);
4254 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4260 This function is called to provide results data to the driver.
4262 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4263 @param[in] Action Specifies the type of action taken by the browser.
4264 @param[in] QuestionId A unique value which is sent to the original
4265 exporting driver so that it can identify the type
4267 @param[in] Type The type of value for the question.
4268 @param[in] Value A pointer to the data being sent to the original
4270 @param[out] ActionRequest On return, points to the action requested by the
4273 @retval EFI_SUCCESS The callback successfully handled the action.
4274 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4275 variable and its data.
4276 @retval EFI_DEVICE_ERROR The variable could not be saved.
4277 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4283 SecureBootCallback (
4284 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4285 IN EFI_BROWSER_ACTION Action
,
4286 IN EFI_QUESTION_ID QuestionId
,
4288 IN EFI_IFR_TYPE_VALUE
*Value
,
4289 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4294 RETURN_STATUS RStatus
;
4295 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4297 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4299 UINT8
*SecureBootEnable
;
4301 UINT8
*SecureBootMode
;
4303 CHAR16 PromptString
[100];
4304 EFI_DEVICE_PATH_PROTOCOL
*File
;
4306 UINT16
*FilePostFix
;
4307 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4308 BOOLEAN GetBrowserDataResult
;
4310 Status
= EFI_SUCCESS
;
4311 SecureBootEnable
= NULL
;
4312 SecureBootMode
= NULL
;
4316 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4317 return EFI_INVALID_PARAMETER
;
4320 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4322 gSecureBootPrivateData
= Private
;
4325 // Retrieve uncommitted data from Browser
4327 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4328 IfrNvData
= AllocateZeroPool (BufferSize
);
4329 if (IfrNvData
== NULL
) {
4330 return EFI_OUT_OF_RESOURCES
;
4333 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
4335 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4336 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4338 // Update secure boot strings when opening this form
4340 Status
= UpdateSecureBootString(Private
);
4341 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4342 mIsEnterSecureBootForm
= TRUE
;
4345 // When entering SecureBoot OPTION Form
4346 // always close opened file & free resource
4348 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4349 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4350 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4351 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4352 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
4353 CloseEnrolledFile(Private
->FileContext
);
4354 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4356 // Update ListCount field in varstore
4357 // Button "Delete All Signature List" is
4358 // enable when ListCount is greater than 0.
4360 IfrNvData
->ListCount
= Private
->ListCount
;
4366 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4367 Status
= EFI_UNSUPPORTED
;
4368 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4369 if (mIsEnterSecureBootForm
) {
4370 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4371 Status
= EFI_SUCCESS
;
4377 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4378 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4379 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4380 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
4381 Status
= EFI_UNSUPPORTED
;
4385 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4387 switch (QuestionId
) {
4388 case KEY_SECURE_BOOT_ENABLE
:
4389 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4390 if (NULL
!= SecureBootEnable
) {
4391 FreePool (SecureBootEnable
);
4392 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4394 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4396 L
"Only Physical Presence User could disable secure boot!",
4399 Status
= EFI_UNSUPPORTED
;
4402 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4404 L
"Configuration changed, please reset the platform to take effect!",
4411 case KEY_SECURE_BOOT_KEK_OPTION
:
4412 case KEY_SECURE_BOOT_DB_OPTION
:
4413 case KEY_SECURE_BOOT_DBX_OPTION
:
4414 case KEY_SECURE_BOOT_DBT_OPTION
:
4415 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4417 // Clear Signature GUID.
4419 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4420 if (Private
->SignatureGUID
== NULL
) {
4421 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
4422 if (Private
->SignatureGUID
== NULL
) {
4423 return EFI_OUT_OF_RESOURCES
;
4428 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4430 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4432 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4433 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4434 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4435 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4436 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4437 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4439 LabelId
= FORMID_ENROLL_KEK_FORM
;
4443 // Refresh selected file.
4445 CleanUpPage (LabelId
, Private
);
4447 case KEY_SECURE_BOOT_PK_OPTION
:
4448 LabelId
= FORMID_ENROLL_PK_FORM
;
4450 // Refresh selected file.
4452 CleanUpPage (LabelId
, Private
);
4455 case FORMID_ENROLL_PK_FORM
:
4456 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4459 case FORMID_ENROLL_KEK_FORM
:
4460 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4463 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4464 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4467 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4468 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4470 if (Private
->FileContext
->FHandle
!= NULL
) {
4472 // Parse the file's postfix.
4474 NameLength
= StrLen (Private
->FileContext
->FileName
);
4475 if (NameLength
<= 4) {
4478 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4480 if (IsDerEncodeCertificate (FilePostFix
)) {
4482 // Supports DER-encoded X509 certificate.
4484 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4485 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
4486 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4488 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4490 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4493 // Clean up Certificate Format if File type is not X509 DER
4495 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4496 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4498 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4503 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4504 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4507 case KEY_SECURE_BOOT_DELETE_PK
:
4510 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4512 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4513 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4516 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
4517 Status
= DeletePlatformKey ();
4518 if (EFI_ERROR (Status
)) {
4520 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4522 L
"Only Physical Presence User could delete PK in custom mode!",
4530 case KEY_DELETE_KEK
:
4533 EFI_KEY_EXCHANGE_KEY_NAME
,
4534 &gEfiGlobalVariableGuid
,
4536 FORMID_DELETE_KEK_FORM
,
4537 OPTION_DEL_KEK_QUESTION_ID
4541 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4544 EFI_IMAGE_SECURITY_DATABASE
,
4545 &gEfiImageSecurityDatabaseGuid
,
4547 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4548 OPTION_DEL_DB_QUESTION_ID
4553 // From DBX option to the level-1 form, display signature list.
4555 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4556 Private
->VariableName
= Variable_DBX
;
4559 LABEL_SIGNATURE_LIST_START
,
4560 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4561 OPTION_SIGNATURE_LIST_QUESTION_ID
4566 // Delete all signature list and reload.
4568 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4570 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4572 L
"Press 'Y' to delete signature list.",
4573 L
"Press other key to cancel and exit.",
4577 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4578 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4583 LABEL_SIGNATURE_LIST_START
,
4584 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4585 OPTION_SIGNATURE_LIST_QUESTION_ID
4590 // Delete one signature list and reload.
4592 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4594 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4596 L
"Press 'Y' to delete signature data.",
4597 L
"Press other key to cancel and exit.",
4601 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4602 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4607 LABEL_SIGNATURE_LIST_START
,
4608 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4609 OPTION_SIGNATURE_LIST_QUESTION_ID
4614 // Delete checked signature data and reload.
4616 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4618 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4620 L
"Press 'Y' to delete signature data.",
4621 L
"Press other key to cancel and exit.",
4625 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4626 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4631 LABEL_SIGNATURE_LIST_START
,
4632 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4633 OPTION_SIGNATURE_LIST_QUESTION_ID
4637 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4640 EFI_IMAGE_SECURITY_DATABASE2
,
4641 &gEfiImageSecurityDatabaseGuid
,
4643 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4644 OPTION_DEL_DBT_QUESTION_ID
4649 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4650 Status
= EnrollKeyExchangeKey (Private
);
4651 if (EFI_ERROR (Status
)) {
4653 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4655 L
"ERROR: Unsupported file type!",
4656 L
"Only supports DER-encoded X509 certificate",
4662 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4663 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4664 if (EFI_ERROR (Status
)) {
4666 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4668 L
"ERROR: Unsupported file type!",
4669 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4675 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4676 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4678 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4680 L
"Enrollment failed! Same certificate had already been in the dbx!",
4685 // Cert already exists in DBX. Close opened file before exit.
4687 CloseEnrolledFile(Private
->FileContext
);
4691 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4692 Status
= EnrollX509HashtoSigDB (
4694 IfrNvData
->CertificateFormat
,
4695 &IfrNvData
->RevocationDate
,
4696 &IfrNvData
->RevocationTime
,
4697 IfrNvData
->AlwaysRevocation
4699 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4701 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4703 if (EFI_ERROR (Status
)) {
4705 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4707 L
"ERROR: Unsupported file type!",
4708 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4714 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4715 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4716 if (EFI_ERROR (Status
)) {
4718 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4720 L
"ERROR: Unsupported file type!",
4721 L
"Only supports DER-encoded X509 certificate.",
4726 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4727 Status
= EnrollPlatformKey (Private
);
4728 if (EFI_ERROR (Status
)) {
4731 sizeof (PromptString
),
4732 L
"Only DER encoded certificate file (%s) is supported.",
4736 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4738 L
"ERROR: Unsupported file type!",
4745 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4746 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4747 DeleteKeyExchangeKey (Private
, QuestionId
);
4748 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4749 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4752 EFI_IMAGE_SECURITY_DATABASE
,
4753 &gEfiImageSecurityDatabaseGuid
,
4755 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4756 OPTION_DEL_DB_QUESTION_ID
,
4757 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4759 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4760 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4763 LABEL_SIGNATURE_DATA_START
,
4764 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4765 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4766 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4768 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4769 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4770 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4771 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4772 IfrNvData
->CheckedDataCount
--;
4773 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4775 IfrNvData
->CheckedDataCount
++;
4776 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4778 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4779 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4782 EFI_IMAGE_SECURITY_DATABASE2
,
4783 &gEfiImageSecurityDatabaseGuid
,
4785 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4786 OPTION_DEL_DBT_QUESTION_ID
,
4787 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4792 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4793 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4794 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4795 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4796 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4797 CloseEnrolledFile(Private
->FileContext
);
4799 if (Private
->SignatureGUID
!= NULL
) {
4800 FreePool (Private
->SignatureGUID
);
4801 Private
->SignatureGUID
= NULL
;
4805 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4806 switch (QuestionId
) {
4807 case KEY_SECURE_BOOT_ENABLE
:
4808 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4810 case KEY_SECURE_BOOT_MODE
:
4811 mIsEnterSecureBootForm
= FALSE
;
4813 case KEY_SECURE_BOOT_KEK_GUID
:
4814 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4815 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4816 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4817 ASSERT (Private
->SignatureGUID
!= NULL
);
4818 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4819 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4820 Status
= EFI_INVALID_PARAMETER
;
4824 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4826 case KEY_SECURE_BOOT_DELETE_PK
:
4827 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4828 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
4829 IfrNvData
->DeletePk
= TRUE
;
4830 IfrNvData
->HasPk
= FALSE
;
4831 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4833 IfrNvData
->DeletePk
= FALSE
;
4834 IfrNvData
->HasPk
= TRUE
;
4835 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4837 if (SetupMode
!= NULL
) {
4838 FreePool (SetupMode
);
4844 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4845 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4846 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
4848 IfrNvData
->HideSecureBoot
= TRUE
;
4851 IfrNvData
->HideSecureBoot
= FALSE
;
4853 Value
->b
= IfrNvData
->HideSecureBoot
;
4855 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
4857 // Force the platform back to Standard Mode once user leave the setup screen.
4859 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
4860 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
4861 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
4862 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
4864 if (SecureBootMode
!= NULL
) {
4865 FreePool (SecureBootMode
);
4868 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
4870 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4872 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
4873 IfrNvData
->CheckedDataCount
= 0;
4879 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
4880 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4881 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
4884 FreePool (IfrNvData
);
4895 This function publish the SecureBoot configuration Form.
4897 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4899 @retval EFI_SUCCESS HII Form is installed successfully.
4900 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
4901 @retval Others Other errors as indicated.
4905 InstallSecureBootConfigForm (
4906 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4910 EFI_HII_HANDLE HiiHandle
;
4911 EFI_HANDLE DriverHandle
;
4912 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4914 DriverHandle
= NULL
;
4915 ConfigAccess
= &PrivateData
->ConfigAccess
;
4916 Status
= gBS
->InstallMultipleProtocolInterfaces (
4918 &gEfiDevicePathProtocolGuid
,
4919 &mSecureBootHiiVendorDevicePath
,
4920 &gEfiHiiConfigAccessProtocolGuid
,
4924 if (EFI_ERROR (Status
)) {
4928 PrivateData
->DriverHandle
= DriverHandle
;
4931 // Publish the HII package list
4933 HiiHandle
= HiiAddPackages (
4934 &gSecureBootConfigFormSetGuid
,
4936 SecureBootConfigDxeStrings
,
4937 SecureBootConfigBin
,
4940 if (HiiHandle
== NULL
) {
4941 gBS
->UninstallMultipleProtocolInterfaces (
4943 &gEfiDevicePathProtocolGuid
,
4944 &mSecureBootHiiVendorDevicePath
,
4945 &gEfiHiiConfigAccessProtocolGuid
,
4949 return EFI_OUT_OF_RESOURCES
;
4952 PrivateData
->HiiHandle
= HiiHandle
;
4954 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
4956 if (PrivateData
->FileContext
== NULL
) {
4957 UninstallSecureBootConfigForm (PrivateData
);
4958 return EFI_OUT_OF_RESOURCES
;
4962 // Init OpCode Handle and Allocate space for creation of Buffer
4964 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4965 if (mStartOpCodeHandle
== NULL
) {
4966 UninstallSecureBootConfigForm (PrivateData
);
4967 return EFI_OUT_OF_RESOURCES
;
4970 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4971 if (mEndOpCodeHandle
== NULL
) {
4972 UninstallSecureBootConfigForm (PrivateData
);
4973 return EFI_OUT_OF_RESOURCES
;
4977 // Create Hii Extend Label OpCode as the start opcode
4979 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4983 sizeof (EFI_IFR_GUID_LABEL
)
4985 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4988 // Create Hii Extend Label OpCode as the end opcode
4990 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4994 sizeof (EFI_IFR_GUID_LABEL
)
4996 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4997 mEndLabel
->Number
= LABEL_END
;
5003 This function removes SecureBoot configuration Form.
5005 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5009 UninstallSecureBootConfigForm (
5010 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5014 // Uninstall HII package list
5016 if (PrivateData
->HiiHandle
!= NULL
) {
5017 HiiRemovePackages (PrivateData
->HiiHandle
);
5018 PrivateData
->HiiHandle
= NULL
;
5022 // Uninstall HII Config Access Protocol
5024 if (PrivateData
->DriverHandle
!= NULL
) {
5025 gBS
->UninstallMultipleProtocolInterfaces (
5026 PrivateData
->DriverHandle
,
5027 &gEfiDevicePathProtocolGuid
,
5028 &mSecureBootHiiVendorDevicePath
,
5029 &gEfiHiiConfigAccessProtocolGuid
,
5030 &PrivateData
->ConfigAccess
,
5033 PrivateData
->DriverHandle
= NULL
;
5036 if (PrivateData
->SignatureGUID
!= NULL
) {
5037 FreePool (PrivateData
->SignatureGUID
);
5040 if (PrivateData
->FileContext
!= NULL
) {
5041 FreePool (PrivateData
->FileContext
);
5044 FreePool (PrivateData
);
5046 if (mStartOpCodeHandle
!= NULL
) {
5047 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5050 if (mEndOpCodeHandle
!= NULL
) {
5051 HiiFreeOpCodeHandle (mEndOpCodeHandle
);