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.
1835 EFI_IMAGE_SECTION_HEADER
*Section
;
1840 UINTN SumOfBytesHashed
;
1841 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1846 SectionHeader
= NULL
;
1849 if (HashAlg
!= HASHALG_SHA256
) {
1854 // Initialize context of hash.
1856 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1858 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1859 mCertType
= gEfiCertSha256Guid
;
1861 CtxSize
= mHash
[HashAlg
].GetContextSize();
1863 HashCtx
= AllocatePool (CtxSize
);
1864 ASSERT (HashCtx
!= NULL
);
1866 // 1. Load the image header into memory.
1868 // 2. Initialize a SHA hash context.
1869 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1874 // Measuring PE/COFF Image Header;
1875 // But CheckSum field and SECURITY data directory (certificate) are excluded
1877 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1879 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1880 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1881 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1882 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1884 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1887 // Get the magic value from the PE/COFF Optional Header
1889 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1893 // 3. Calculate the distance from the base of the image header to the image checksum address.
1894 // 4. Hash the image header from its base to beginning of the image checksum.
1896 HashBase
= mImageBase
;
1897 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1901 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1904 // Use PE32+ offset.
1906 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - (UINTN
) HashBase
;
1909 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1914 // 5. Skip over the image checksum (it occupies a single ULONG).
1915 // 6. Get the address of the beginning of the Cert Directory.
1916 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1918 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1922 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1923 HashSize
= (UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1926 // Use PE32+ offset.
1928 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1929 HashSize
= (UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - (UINTN
) HashBase
;
1932 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1937 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1938 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1940 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1944 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1945 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1948 // Use PE32+ offset.
1950 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1951 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- ((UINTN
) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINTN
) mImageBase
);
1954 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1959 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1961 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1965 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1970 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1974 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1975 // structures in the image. The 'NumberOfSections' field of the image
1976 // header indicates how big the table should be. Do not include any
1977 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1979 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1980 ASSERT (SectionHeader
!= NULL
);
1982 // 12. Using the 'PointerToRawData' in the referenced section headers as
1983 // a key, arrange the elements in the table in ascending order. In other
1984 // words, sort the section headers according to the disk-file offset of
1987 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1989 mPeCoffHeaderOffset
+
1991 sizeof (EFI_IMAGE_FILE_HEADER
) +
1992 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1994 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1996 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1997 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
2000 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
2005 // 13. Walk through the sorted table, bring the corresponding section
2006 // into memory, and hash the entire section (using the 'SizeOfRawData'
2007 // field in the section header to determine the amount of data to hash).
2008 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2009 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
2011 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
2012 Section
= &SectionHeader
[Index
];
2013 if (Section
->SizeOfRawData
== 0) {
2016 HashBase
= mImageBase
+ Section
->PointerToRawData
;
2017 HashSize
= (UINTN
) Section
->SizeOfRawData
;
2019 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2024 SumOfBytesHashed
+= HashSize
;
2028 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2029 // data in the file that needs to be added to the hash. This data begins
2030 // at file offset SUM_OF_BYTES_HASHED and its length is:
2031 // FileSize - (CertDirectory->Size)
2033 if (mImageSize
> SumOfBytesHashed
) {
2034 HashBase
= mImageBase
+ SumOfBytesHashed
;
2035 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2041 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2045 // Use PE32+ offset.
2049 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
2053 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
2059 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
2062 if (HashCtx
!= NULL
) {
2065 if (SectionHeader
!= NULL
) {
2066 FreePool (SectionHeader
);
2072 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2073 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2076 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2077 @retval EFI_SUCCESS Hash successfully.
2086 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
2088 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
2090 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
2092 // Check the Hash algorithm in PE/COFF Authenticode.
2093 // According to PKCS#7 Definition:
2094 // SignedData ::= SEQUENCE {
2096 // digestAlgorithms DigestAlgorithmIdentifiers,
2097 // contentInfo ContentInfo,
2099 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2100 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2101 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2103 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
2105 // Only support two bytes of Long Form of Length Encoding.
2111 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
2116 if (Index
== HASHALG_MAX
) {
2117 return EFI_UNSUPPORTED
;
2121 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2123 if (!HashPeImage(Index
)) {
2124 return EFI_UNSUPPORTED
;
2131 Enroll a new executable's signature into Signature Database.
2133 @param[in] PrivateData The module's private data.
2134 @param[in] VariableName Variable name of signature database, must be
2135 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2136 or EFI_IMAGE_SECURITY_DATABASE2.
2138 @retval EFI_SUCCESS New signature is enrolled successfully.
2139 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2140 @retval EFI_UNSUPPORTED Unsupported command.
2141 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2145 EnrollAuthentication2Descriptor (
2146 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2147 IN CHAR16
*VariableName
2158 // DBT only support DER-X509 Cert Enrollment
2160 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2161 return EFI_UNSUPPORTED
;
2165 // Read the whole file content
2167 Status
= ReadFileContent(
2168 Private
->FileContext
->FHandle
,
2169 (VOID
**) &mImageBase
,
2173 if (EFI_ERROR (Status
)) {
2176 ASSERT (mImageBase
!= NULL
);
2178 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2179 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2182 // Check if SigDB variable has been already existed.
2183 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2184 // new signature data to original variable
2187 Status
= gRT
->GetVariable(
2189 &gEfiImageSecurityDatabaseGuid
,
2194 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2195 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2196 } else if (Status
!= EFI_NOT_FOUND
) {
2201 // Diretly set AUTHENTICATION_2 data to SetVariable
2203 Status
= gRT
->SetVariable(
2205 &gEfiImageSecurityDatabaseGuid
,
2211 DEBUG((DEBUG_INFO
, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName
, Status
));
2215 CloseEnrolledFile(Private
->FileContext
);
2221 if (mImageBase
!= NULL
) {
2222 FreePool (mImageBase
);
2232 Enroll a new executable's signature into Signature Database.
2234 @param[in] PrivateData The module's private data.
2235 @param[in] VariableName Variable name of signature database, must be
2236 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2237 or EFI_IMAGE_SECURITY_DATABASE2.
2239 @retval EFI_SUCCESS New signature is enrolled successfully.
2240 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2241 @retval EFI_UNSUPPORTED Unsupported command.
2242 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2246 EnrollImageSignatureToSigDB (
2247 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2248 IN CHAR16
*VariableName
2252 EFI_SIGNATURE_LIST
*SigDBCert
;
2253 EFI_SIGNATURE_DATA
*SigDBCertData
;
2258 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
2261 GuidCertData
= NULL
;
2263 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0) {
2264 return EFI_UNSUPPORTED
;
2268 // Form the SigDB certificate list.
2269 // Format the data item into EFI_SIGNATURE_LIST type.
2271 // We need to parse executable's signature data from specified signed executable file.
2272 // In current implementation, we simply trust the pass-in signed executable file.
2273 // In reality, it's OS's responsibility to verify the signed executable file.
2277 // Read the whole file content
2279 Status
= ReadFileContent(
2280 Private
->FileContext
->FHandle
,
2281 (VOID
**) &mImageBase
,
2285 if (EFI_ERROR (Status
)) {
2288 ASSERT (mImageBase
!= NULL
);
2290 Status
= LoadPeImage ();
2291 if (EFI_ERROR (Status
)) {
2295 if (mSecDataDir
->SizeOfCert
== 0) {
2296 if (!HashPeImage (HASHALG_SHA256
)) {
2297 Status
= EFI_SECURITY_VIOLATION
;
2303 // Read the certificate data
2305 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
2307 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
2308 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
2309 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
2310 Status
= EFI_ABORTED
;
2314 if (!HashPeImage (HASHALG_SHA256
)) {
2315 Status
= EFI_ABORTED
;
2319 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
2321 Status
= HashPeImageByType ();
2322 if (EFI_ERROR (Status
)) {
2326 Status
= EFI_ABORTED
;
2332 // Create a new SigDB entry.
2334 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
2335 + sizeof(EFI_SIGNATURE_DATA
) - 1
2336 + (UINT32
) mImageDigestSize
;
2338 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
2340 Status
= EFI_OUT_OF_RESOURCES
;
2345 // Adjust the Certificate Database parameters.
2347 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
2348 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
2349 SigDBCert
->SignatureHeaderSize
= 0;
2350 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
2351 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
2353 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
2354 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
2355 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
2357 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
2358 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
2359 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
2360 if (EFI_ERROR (Status
)) {
2361 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2366 // Check if SigDB variable has been already existed.
2367 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2368 // new signature data to original variable
2371 Status
= gRT
->GetVariable(
2373 &gEfiImageSecurityDatabaseGuid
,
2378 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2379 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
2380 } else if (Status
!= EFI_NOT_FOUND
) {
2385 // Enroll the variable.
2387 Status
= gRT
->SetVariable(
2389 &gEfiImageSecurityDatabaseGuid
,
2394 if (EFI_ERROR (Status
)) {
2400 CloseEnrolledFile(Private
->FileContext
);
2402 if (Private
->SignatureGUID
!= NULL
) {
2403 FreePool (Private
->SignatureGUID
);
2404 Private
->SignatureGUID
= NULL
;
2411 if (mImageBase
!= NULL
) {
2412 FreePool (mImageBase
);
2420 Enroll signature into DB/DBX/DBT without KEK's authentication.
2421 The SignatureOwner GUID will be Private->SignatureGUID.
2423 @param[in] PrivateData The module's private data.
2424 @param[in] VariableName Variable name of signature database, must be
2425 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2427 @retval EFI_SUCCESS New signature enrolled successfully.
2428 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2429 @retval others Fail to enroll signature data.
2433 EnrollSignatureDatabase (
2434 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
2435 IN CHAR16
*VariableName
2438 UINT16
* FilePostFix
;
2442 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
2443 return EFI_INVALID_PARAMETER
;
2446 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
2447 if (EFI_ERROR (Status
)) {
2452 // Parse the file's postfix.
2454 NameLength
= StrLen (Private
->FileContext
->FileName
);
2455 if (NameLength
<= 4) {
2456 return EFI_INVALID_PARAMETER
;
2458 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
2459 if (IsDerEncodeCertificate (FilePostFix
)) {
2461 // Supports DER-encoded X509 certificate.
2463 return EnrollX509toSigDB (Private
, VariableName
);
2464 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
2465 return EnrollAuthentication2Descriptor(Private
, VariableName
);
2467 return EnrollImageSignatureToSigDB (Private
, VariableName
);
2472 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2473 by GUID in the page for user to select and delete as needed.
2475 @param[in] PrivateData Module's private data.
2476 @param[in] VariableName The variable name of the vendor's signature database.
2477 @param[in] VendorGuid A unique identifier for the vendor.
2478 @param[in] LabelNumber Label number to insert opcodes.
2479 @param[in] FormId Form ID of current page.
2480 @param[in] QuestionIdBase Base question id of the signature list.
2482 @retval EFI_SUCCESS Success to update the signature list page
2483 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2488 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2489 IN CHAR16
*VariableName
,
2490 IN EFI_GUID
*VendorGuid
,
2491 IN UINT16 LabelNumber
,
2492 IN EFI_FORM_ID FormId
,
2493 IN EFI_QUESTION_ID QuestionIdBase
2500 VOID
*StartOpCodeHandle
;
2501 VOID
*EndOpCodeHandle
;
2502 EFI_IFR_GUID_LABEL
*StartLabel
;
2503 EFI_IFR_GUID_LABEL
*EndLabel
;
2506 EFI_SIGNATURE_LIST
*CertList
;
2507 EFI_SIGNATURE_DATA
*Cert
;
2508 UINT32 ItemDataSize
;
2510 EFI_STRING_ID GuidID
;
2517 StartOpCodeHandle
= NULL
;
2518 EndOpCodeHandle
= NULL
;
2521 // Initialize the container for dynamic opcodes.
2523 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2524 if (StartOpCodeHandle
== NULL
) {
2525 Status
= EFI_OUT_OF_RESOURCES
;
2529 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2530 if (EndOpCodeHandle
== NULL
) {
2531 Status
= EFI_OUT_OF_RESOURCES
;
2536 // Create Hii Extend Label OpCode.
2538 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2542 sizeof (EFI_IFR_GUID_LABEL
)
2544 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2545 StartLabel
->Number
= LabelNumber
;
2547 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2551 sizeof (EFI_IFR_GUID_LABEL
)
2553 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2554 EndLabel
->Number
= LABEL_END
;
2560 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2561 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2565 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2567 Status
= EFI_OUT_OF_RESOURCES
;
2571 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
2572 if (EFI_ERROR (Status
)) {
2576 GuidStr
= AllocateZeroPool (100);
2577 if (GuidStr
== NULL
) {
2578 Status
= EFI_OUT_OF_RESOURCES
;
2583 // Enumerate all KEK pub data.
2585 ItemDataSize
= (UINT32
) DataSize
;
2586 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2589 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2591 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
2592 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
2593 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2594 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
2595 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
2596 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
2597 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
2598 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
2599 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
2600 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID
);
2601 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
2602 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID
);
2603 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
2604 Help
= STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID
);
2607 // The signature type is not supported in current implementation.
2609 ItemDataSize
-= CertList
->SignatureListSize
;
2610 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2614 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2615 for (Index
= 0; Index
< CertCount
; Index
++) {
2616 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
2617 + sizeof (EFI_SIGNATURE_LIST
)
2618 + CertList
->SignatureHeaderSize
2619 + Index
* CertList
->SignatureSize
);
2621 // Display GUID and help
2623 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
2624 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
2625 HiiCreateCheckBoxOpCode (
2627 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
2632 EFI_IFR_FLAG_CALLBACK
,
2638 ItemDataSize
-= CertList
->SignatureListSize
;
2639 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2644 PrivateData
->HiiHandle
,
2645 &gSecureBootConfigFormSetGuid
,
2651 if (StartOpCodeHandle
!= NULL
) {
2652 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2655 if (EndOpCodeHandle
!= NULL
) {
2656 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2663 if (GuidStr
!= NULL
) {
2671 Delete a KEK entry from KEK database.
2673 @param[in] PrivateData Module's private data.
2674 @param[in] QuestionId Question id of the KEK item to delete.
2676 @retval EFI_SUCCESS Delete kek item successfully.
2677 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2681 DeleteKeyExchangeKey (
2682 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2683 IN EFI_QUESTION_ID QuestionId
2692 EFI_SIGNATURE_LIST
*CertList
;
2693 EFI_SIGNATURE_LIST
*NewCertList
;
2694 EFI_SIGNATURE_DATA
*Cert
;
2697 BOOLEAN IsKEKItemFound
;
2699 UINTN DeleteKekIndex
;
2707 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
2709 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2710 if (EFI_ERROR (Status
)) {
2715 // Get original KEK variable.
2718 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
2719 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2723 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
2724 if (OldData
== NULL
) {
2725 Status
= EFI_OUT_OF_RESOURCES
;
2729 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
2730 if (EFI_ERROR(Status
)) {
2735 // Allocate space for new variable.
2737 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2739 Status
= EFI_OUT_OF_RESOURCES
;
2744 // Enumerate all KEK pub data and erasing the target item.
2746 IsKEKItemFound
= FALSE
;
2747 KekDataSize
= (UINT32
) DataSize
;
2748 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2751 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2752 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2753 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
2754 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2755 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
2756 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2757 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2758 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2759 for (Index
= 0; Index
< CertCount
; Index
++) {
2760 if (GuidIndex
== DeleteKekIndex
) {
2762 // Find it! Skip it!
2764 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2765 IsKEKItemFound
= TRUE
;
2768 // This item doesn't match. Copy it to the Data buffer.
2770 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
2771 Offset
+= CertList
->SignatureSize
;
2774 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2778 // This List doesn't match. Copy it to the Data buffer.
2780 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
2781 Offset
+= CertList
->SignatureListSize
;
2784 KekDataSize
-= CertList
->SignatureListSize
;
2785 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2788 if (!IsKEKItemFound
) {
2790 // Doesn't find the Kek Item!
2792 Status
= EFI_NOT_FOUND
;
2797 // Delete the Signature header if there is no signature in the list.
2799 KekDataSize
= Offset
;
2800 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2802 ZeroMem (OldData
, KekDataSize
);
2803 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
2804 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2805 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
2806 if (CertCount
!= 0) {
2807 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
2808 Offset
+= CertList
->SignatureListSize
;
2810 KekDataSize
-= CertList
->SignatureListSize
;
2811 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2815 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2816 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2817 if (EFI_ERROR (Status
)) {
2818 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2823 Status
= gRT
->SetVariable(
2824 EFI_KEY_EXCHANGE_KEY_NAME
,
2825 &gEfiGlobalVariableGuid
,
2830 if (EFI_ERROR (Status
)) {
2831 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2840 if (OldData
!= NULL
) {
2844 return UpdateDeletePage (
2846 EFI_KEY_EXCHANGE_KEY_NAME
,
2847 &gEfiGlobalVariableGuid
,
2849 FORMID_DELETE_KEK_FORM
,
2850 OPTION_DEL_KEK_QUESTION_ID
2855 Delete a signature entry from signature database.
2857 @param[in] PrivateData Module's private data.
2858 @param[in] VariableName The variable name of the vendor's signature database.
2859 @param[in] VendorGuid A unique identifier for the vendor.
2860 @param[in] LabelNumber Label number to insert opcodes.
2861 @param[in] FormId Form ID of current page.
2862 @param[in] QuestionIdBase Base question id of the signature list.
2863 @param[in] DeleteIndex Signature index to delete.
2865 @retval EFI_SUCCESS Delete signature successfully.
2866 @retval EFI_NOT_FOUND Can't find the signature item,
2867 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2871 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
2872 IN CHAR16
*VariableName
,
2873 IN EFI_GUID
*VendorGuid
,
2874 IN UINT16 LabelNumber
,
2875 IN EFI_FORM_ID FormId
,
2876 IN EFI_QUESTION_ID QuestionIdBase
,
2877 IN UINTN DeleteIndex
2886 EFI_SIGNATURE_LIST
*CertList
;
2887 EFI_SIGNATURE_LIST
*NewCertList
;
2888 EFI_SIGNATURE_DATA
*Cert
;
2891 BOOLEAN IsItemFound
;
2892 UINT32 ItemDataSize
;
2901 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2902 if (EFI_ERROR (Status
)) {
2907 // Get original signature list data.
2910 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2911 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2915 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2916 if (OldData
== NULL
) {
2917 Status
= EFI_OUT_OF_RESOURCES
;
2921 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2922 if (EFI_ERROR(Status
)) {
2927 // Allocate space for new variable.
2929 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2931 Status
= EFI_OUT_OF_RESOURCES
;
2936 // Enumerate all signature data and erasing the target item.
2938 IsItemFound
= FALSE
;
2939 ItemDataSize
= (UINT32
) DataSize
;
2940 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2943 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2944 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2945 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2946 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2947 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
) ||
2948 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha256Guid
) ||
2949 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha384Guid
) ||
2950 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Sha512Guid
)
2953 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2955 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2956 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2957 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2958 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2959 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2960 for (Index
= 0; Index
< CertCount
; Index
++) {
2961 if (GuidIndex
== DeleteIndex
) {
2963 // Find it! Skip it!
2965 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2969 // This item doesn't match. Copy it to the Data buffer.
2971 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2972 Offset
+= CertList
->SignatureSize
;
2975 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2979 // This List doesn't match. Just copy it to the Data buffer.
2981 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2982 Offset
+= CertList
->SignatureListSize
;
2985 ItemDataSize
-= CertList
->SignatureListSize
;
2986 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2991 // Doesn't find the signature Item!
2993 Status
= EFI_NOT_FOUND
;
2998 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
3000 ItemDataSize
= Offset
;
3001 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
3003 ZeroMem (OldData
, ItemDataSize
);
3004 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
3005 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
3006 DEBUG ((DEBUG_INFO
, " CertCount = %x\n", CertCount
));
3007 if (CertCount
!= 0) {
3008 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
3009 Offset
+= CertList
->SignatureListSize
;
3011 ItemDataSize
-= CertList
->SignatureListSize
;
3012 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
3016 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3017 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
3018 if (EFI_ERROR (Status
)) {
3019 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
3024 Status
= gRT
->SetVariable(
3031 if (EFI_ERROR (Status
)) {
3032 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
3041 if (OldData
!= NULL
) {
3045 return UpdateDeletePage (
3056 This function to delete signature list or data, according by DelType.
3058 @param[in] PrivateData Module's private data.
3059 @param[in] DelType Indicate delete signature list or data.
3060 @param[in] CheckedCount Indicate how many signature data have
3061 been checked in current signature list.
3063 @retval EFI_SUCCESS Success to update the signature list page
3064 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3068 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3069 IN SIGNATURE_DELETE_TYPE DelType
,
3070 IN UINT32 CheckedCount
3074 EFI_SIGNATURE_LIST
*ListWalker
;
3075 EFI_SIGNATURE_LIST
*NewCertList
;
3076 EFI_SIGNATURE_DATA
*DataWalker
;
3077 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3078 UINT32 VariableAttr
;
3079 UINTN VariableDataSize
;
3080 UINTN RemainingSize
;
3084 UINT8
*VariableData
;
3085 UINT8
*NewVariableData
;
3087 Status
= EFI_SUCCESS
;
3089 VariableDataSize
= 0;
3092 VariableData
= NULL
;
3093 NewVariableData
= NULL
;
3095 if (PrivateData
->VariableName
== Variable_DB
) {
3096 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3097 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3098 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3099 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3100 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3105 Status
= gRT
->GetVariable (
3107 &gEfiImageSecurityDatabaseGuid
,
3112 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3116 VariableData
= AllocateZeroPool (VariableDataSize
);
3117 if (VariableData
== NULL
) {
3118 Status
= EFI_OUT_OF_RESOURCES
;
3122 Status
= gRT
->GetVariable (
3124 &gEfiImageSecurityDatabaseGuid
,
3129 if (EFI_ERROR (Status
)) {
3133 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
3134 if (EFI_ERROR (Status
)) {
3138 NewVariableData
= AllocateZeroPool (VariableDataSize
);
3139 if (NewVariableData
== NULL
) {
3140 Status
= EFI_OUT_OF_RESOURCES
;
3144 RemainingSize
= VariableDataSize
;
3145 ListWalker
= (EFI_SIGNATURE_LIST
*)(VariableData
);
3146 if (DelType
== Delete_Signature_List_All
) {
3147 VariableDataSize
= 0;
3150 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3152 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
< PrivateData
->ListIndex
) {
3153 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, ListWalker
->SignatureListSize
);
3154 Offset
+= ListWalker
->SignatureListSize
;
3156 RemainingSize
-= ListWalker
->SignatureListSize
;
3157 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3162 // Handle the target EFI_SIGNATURE_LIST.
3163 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3164 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3166 if (CheckedCount
< SIGNATURE_DATA_COUNTS (ListWalker
) && DelType
== Delete_Signature_Data
) {
3167 NewCertList
= (EFI_SIGNATURE_LIST
*)(NewVariableData
+ Offset
);
3171 CopyMem ((UINT8
*)NewVariableData
+ Offset
, ListWalker
, sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3172 Offset
+= sizeof (EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
;
3174 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
3175 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
3176 if (PrivateData
->CheckArray
[Index
]) {
3178 // Delete checked signature data, and update the size of whole signature list.
3180 NewCertList
->SignatureListSize
-= NewCertList
->SignatureSize
;
3183 // Remain the unchecked signature data.
3185 CopyMem ((UINT8
*)NewVariableData
+ Offset
, DataWalker
, ListWalker
->SignatureSize
);
3186 Offset
+= ListWalker
->SignatureSize
;
3188 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
3192 RemainingSize
-= ListWalker
->SignatureListSize
;
3193 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3196 // Copy remaining data, maybe 0.
3198 CopyMem((UINT8
*)NewVariableData
+ Offset
, ListWalker
, RemainingSize
);
3199 Offset
+= RemainingSize
;
3201 VariableDataSize
= Offset
;
3204 if ((VariableAttr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
3205 Status
= CreateTimeBasedPayload (&VariableDataSize
, &NewVariableData
);
3206 if (EFI_ERROR (Status
)) {
3207 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
3212 Status
= gRT
->SetVariable (
3214 &gEfiImageSecurityDatabaseGuid
,
3219 if (EFI_ERROR (Status
)) {
3220 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r", Status
));
3225 SECUREBOOT_FREE_NON_NULL (VariableData
);
3226 SECUREBOOT_FREE_NON_NULL (NewVariableData
);
3233 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3234 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3236 @param[in] PrivateData Module's private data.
3238 @return EFI_SUCCESS Update secure boot strings successfully.
3239 @return other Fail to update secure boot strings.
3243 UpdateSecureBootString(
3244 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
3252 // Get current secure boot state.
3254 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
3255 if (SecureBoot
== NULL
) {
3256 return EFI_NOT_FOUND
;
3259 if (*SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
3260 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
3262 HiiSetString (Private
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
3265 FreePool(SecureBoot
);
3271 This function extracts configuration from variable.
3273 @param[in] Private Point to SecureBoot configuration driver private data.
3274 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3278 SecureBootExtractConfigFromVariable (
3279 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
3280 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
3283 UINT8
*SecureBootEnable
;
3285 UINT8
*SecureBootMode
;
3288 SecureBootEnable
= NULL
;
3290 SecureBootMode
= NULL
;
3293 // Initilize the Date and Time using system time.
3295 ConfigData
->CertificateFormat
= HASHALG_RAW
;
3296 ConfigData
->AlwaysRevocation
= TRUE
;
3297 gRT
->GetTime (&CurrTime
, NULL
);
3298 ConfigData
->RevocationDate
.Year
= CurrTime
.Year
;
3299 ConfigData
->RevocationDate
.Month
= CurrTime
.Month
;
3300 ConfigData
->RevocationDate
.Day
= CurrTime
.Day
;
3301 ConfigData
->RevocationTime
.Hour
= CurrTime
.Hour
;
3302 ConfigData
->RevocationTime
.Minute
= CurrTime
.Minute
;
3303 ConfigData
->RevocationTime
.Second
= 0;
3304 if (Private
->FileContext
->FHandle
!= NULL
) {
3305 ConfigData
->FileEnrollType
= Private
->FileContext
->FileType
;
3307 ConfigData
->FileEnrollType
= UNKNOWN_FILE_TYPE
;
3311 // If it is Physical Presence User, set the PhysicalPresent to true.
3313 if (UserPhysicalPresent()) {
3314 ConfigData
->PhysicalPresent
= TRUE
;
3316 ConfigData
->PhysicalPresent
= FALSE
;
3320 // If there is no PK then the Delete Pk button will be gray.
3322 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
3323 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
3324 ConfigData
->HasPk
= FALSE
;
3326 ConfigData
->HasPk
= TRUE
;
3330 // Check SecureBootEnable & Pk status, fix the inconsistence.
3331 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3334 ConfigData
->AttemptSecureBoot
= FALSE
;
3335 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
3338 // Fix Pk, SecureBootEnable inconsistence
3340 if ((SetupMode
!= NULL
) && (*SetupMode
) == USER_MODE
) {
3341 ConfigData
->HideSecureBoot
= FALSE
;
3342 if ((SecureBootEnable
!= NULL
) && (*SecureBootEnable
== SECURE_BOOT_ENABLE
)) {
3343 ConfigData
->AttemptSecureBoot
= TRUE
;
3346 ConfigData
->HideSecureBoot
= TRUE
;
3350 // Get the SecureBootMode from CustomMode variable.
3352 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
3353 if (SecureBootMode
== NULL
) {
3354 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
3356 ConfigData
->SecureBootMode
= *(SecureBootMode
);
3359 if (SecureBootEnable
!= NULL
) {
3360 FreePool (SecureBootEnable
);
3362 if (SetupMode
!= NULL
) {
3363 FreePool (SetupMode
);
3365 if (SecureBootMode
!= NULL
) {
3366 FreePool (SecureBootMode
);
3371 This function allows a caller to extract the current configuration for one
3372 or more named elements from the target driver.
3374 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3375 @param[in] Request A null-terminated Unicode string in
3376 <ConfigRequest> format.
3377 @param[out] Progress On return, points to a character in the Request
3378 string. Points to the string's null terminator if
3379 request was successful. Points to the most recent
3380 '&' before the first failing name/value pair (or
3381 the beginning of the string if the failure is in
3382 the first name/value pair) if the request was not
3384 @param[out] Results A null-terminated Unicode string in
3385 <ConfigAltResp> format which has all values filled
3386 in for the names in the Request string. String to
3387 be allocated by the called function.
3389 @retval EFI_SUCCESS The Results is filled with the requested values.
3390 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3391 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3392 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3398 SecureBootExtractConfig (
3399 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3400 IN CONST EFI_STRING Request
,
3401 OUT EFI_STRING
*Progress
,
3402 OUT EFI_STRING
*Results
3408 SECUREBOOT_CONFIGURATION Configuration
;
3409 EFI_STRING ConfigRequest
;
3410 EFI_STRING ConfigRequestHdr
;
3411 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3412 BOOLEAN AllocatedRequest
;
3414 if (Progress
== NULL
|| Results
== NULL
) {
3415 return EFI_INVALID_PARAMETER
;
3418 AllocatedRequest
= FALSE
;
3419 ConfigRequestHdr
= NULL
;
3420 ConfigRequest
= NULL
;
3423 ZeroMem (&Configuration
, sizeof (Configuration
));
3424 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3425 *Progress
= Request
;
3427 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3428 return EFI_NOT_FOUND
;
3431 ZeroMem(&Configuration
, sizeof(SECUREBOOT_CONFIGURATION
));
3434 // Get Configuration from Variable.
3436 SecureBootExtractConfigFromVariable (PrivateData
, &Configuration
);
3438 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3439 ConfigRequest
= Request
;
3440 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3442 // Request is set to NULL or OFFSET is NULL, construct full request string.
3444 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3445 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3447 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
3448 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3449 ConfigRequest
= AllocateZeroPool (Size
);
3450 ASSERT (ConfigRequest
!= NULL
);
3451 AllocatedRequest
= TRUE
;
3452 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3453 FreePool (ConfigRequestHdr
);
3454 ConfigRequestHdr
= NULL
;
3457 Status
= gHiiConfigRouting
->BlockToConfig (
3460 (UINT8
*) &Configuration
,
3467 // Free the allocated config request string.
3469 if (AllocatedRequest
) {
3470 FreePool (ConfigRequest
);
3474 // Set Progress string to the original request string.
3476 if (Request
== NULL
) {
3478 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3479 *Progress
= Request
+ StrLen (Request
);
3486 This function processes the results of changes in configuration.
3488 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3489 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3491 @param[out] Progress A pointer to a string filled in with the offset of
3492 the most recent '&' before the first failing
3493 name/value pair (or the beginning of the string if
3494 the failure is in the first name/value pair) or
3495 the terminating NULL if all was successful.
3497 @retval EFI_SUCCESS The Results is processed successfully.
3498 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3499 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3505 SecureBootRouteConfig (
3506 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3507 IN CONST EFI_STRING Configuration
,
3508 OUT EFI_STRING
*Progress
3511 SECUREBOOT_CONFIGURATION IfrNvData
;
3513 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
3516 if (Configuration
== NULL
|| Progress
== NULL
) {
3517 return EFI_INVALID_PARAMETER
;
3520 *Progress
= Configuration
;
3521 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
3522 return EFI_NOT_FOUND
;
3525 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
3528 // Get Configuration from Variable.
3530 SecureBootExtractConfigFromVariable (PrivateData
, &IfrNvData
);
3533 // Map the Configuration to the configuration block.
3535 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
3536 Status
= gHiiConfigRouting
->ConfigToBlock (
3539 (UINT8
*)&IfrNvData
,
3543 if (EFI_ERROR (Status
)) {
3548 // Store Buffer Storage back to EFI variable if needed
3550 if (!IfrNvData
.HideSecureBoot
) {
3551 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
3552 if (EFI_ERROR (Status
)) {
3557 *Progress
= Configuration
+ StrLen (Configuration
);
3562 This function to load signature list, the update the menu page.
3564 @param[in] PrivateData Module's private data.
3565 @param[in] LabelId Label number to insert opcodes.
3566 @param[in] FormId Form ID of current page.
3567 @param[in] QuestionIdBase Base question id of the signature list.
3569 @retval EFI_SUCCESS Success to update the signature list page
3570 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3574 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3576 IN EFI_FORM_ID FormId
,
3577 IN EFI_QUESTION_ID QuestionIdBase
3581 EFI_STRING_ID ListType
;
3582 EFI_STRING FormatNameString
;
3583 EFI_STRING FormatHelpString
;
3584 EFI_STRING FormatTypeString
;
3585 EFI_SIGNATURE_LIST
*ListWalker
;
3586 EFI_IFR_GUID_LABEL
*StartLabel
;
3587 EFI_IFR_GUID_LABEL
*EndLabel
;
3588 EFI_IFR_GUID_LABEL
*StartGoto
;
3589 EFI_IFR_GUID_LABEL
*EndGoto
;
3590 EFI_FORM_ID DstFormId
;
3591 VOID
*StartOpCodeHandle
;
3592 VOID
*EndOpCodeHandle
;
3593 VOID
*StartGotoHandle
;
3594 VOID
*EndGotoHandle
;
3596 UINTN RemainingSize
;
3598 UINT8
*VariableData
;
3599 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
3600 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
3601 CHAR16 HelpBuffer
[BUFFER_MAX_SIZE
];
3603 Status
= EFI_SUCCESS
;
3604 FormatNameString
= NULL
;
3605 FormatHelpString
= NULL
;
3606 StartOpCodeHandle
= NULL
;
3607 EndOpCodeHandle
= NULL
;
3608 StartGotoHandle
= NULL
;
3609 EndGotoHandle
= NULL
;
3611 VariableData
= NULL
;
3614 // Initialize the container for dynamic opcodes.
3616 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
3617 if (StartOpCodeHandle
== NULL
) {
3618 Status
= EFI_OUT_OF_RESOURCES
;
3622 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
3623 if (EndOpCodeHandle
== NULL
) {
3624 Status
= EFI_OUT_OF_RESOURCES
;
3628 StartGotoHandle
= HiiAllocateOpCodeHandle ();
3629 if (StartGotoHandle
== NULL
) {
3630 Status
= EFI_OUT_OF_RESOURCES
;
3634 EndGotoHandle
= HiiAllocateOpCodeHandle ();
3635 if (EndGotoHandle
== NULL
) {
3636 Status
= EFI_OUT_OF_RESOURCES
;
3641 // Create Hii Extend Label OpCode.
3643 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3647 sizeof (EFI_IFR_GUID_LABEL
)
3649 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3650 StartLabel
->Number
= LabelId
;
3652 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
3656 sizeof (EFI_IFR_GUID_LABEL
)
3658 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3659 EndLabel
->Number
= LABEL_END
;
3661 StartGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3665 sizeof(EFI_IFR_GUID_LABEL
)
3667 StartGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3668 StartGoto
->Number
= LABEL_DELETE_ALL_LIST_BUTTON
;
3670 EndGoto
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode(
3674 sizeof(EFI_IFR_GUID_LABEL
)
3676 EndGoto
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
3677 EndGoto
->Number
= LABEL_END
;
3679 if (PrivateData
->VariableName
== Variable_DB
) {
3680 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
3681 DstFormId
= FORMID_SECURE_BOOT_DB_OPTION_FORM
;
3682 } else if (PrivateData
->VariableName
== Variable_DBX
) {
3683 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
3684 DstFormId
= FORMID_SECURE_BOOT_DBX_OPTION_FORM
;
3685 } else if (PrivateData
->VariableName
== Variable_DBT
) {
3686 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
3687 DstFormId
= FORMID_SECURE_BOOT_DBT_OPTION_FORM
;
3692 HiiCreateGotoOpCode (
3695 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3696 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST
),
3697 EFI_IFR_FLAG_CALLBACK
,
3698 KEY_SECURE_BOOT_DELETE_ALL_LIST
3702 // Read Variable, the variable name save in the PrivateData->VariableName.
3705 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3706 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
3710 VariableData
= AllocateZeroPool (DataSize
);
3711 if (VariableData
== NULL
) {
3712 Status
= EFI_OUT_OF_RESOURCES
;
3715 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
3716 if (EFI_ERROR (Status
)) {
3720 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT
), NULL
);
3721 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT
), NULL
);
3722 if (FormatNameString
== NULL
|| FormatHelpString
== NULL
) {
3726 RemainingSize
= DataSize
;
3727 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
3728 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
)) {
3729 if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3730 ListType
= STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256
);
3731 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Guid
)) {
3732 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509
);
3733 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha1Guid
)) {
3734 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA1
);
3735 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertSha256Guid
)) {
3736 ListType
= STRING_TOKEN (STR_LIST_TYPE_SHA256
);
3737 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3738 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA256
);
3739 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3740 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA384
);
3741 } else if (CompareGuid (&ListWalker
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3742 ListType
= STRING_TOKEN (STR_LIST_TYPE_X509_SHA512
);
3744 ListType
= STRING_TOKEN (STR_LIST_TYPE_UNKNOWN
);
3746 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListType
, NULL
);
3747 if (FormatTypeString
== NULL
) {
3751 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
3752 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
3754 ZeroMem (HelpBuffer
, sizeof (HelpBuffer
));
3755 UnicodeSPrint (HelpBuffer
,
3756 sizeof (HelpBuffer
),
3759 SIGNATURE_DATA_COUNTS (ListWalker
)
3761 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
3762 FormatTypeString
= NULL
;
3764 HiiCreateGotoOpCode (
3766 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
3767 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
3768 HiiSetString (PrivateData
->HiiHandle
, 0, HelpBuffer
, NULL
),
3769 EFI_IFR_FLAG_CALLBACK
,
3770 QuestionIdBase
+ Index
++
3773 RemainingSize
-= ListWalker
->SignatureListSize
;
3774 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
3779 PrivateData
->HiiHandle
,
3780 &gSecureBootConfigFormSetGuid
,
3787 PrivateData
->HiiHandle
,
3788 &gSecureBootConfigFormSetGuid
,
3794 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
3795 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
3796 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle
);
3797 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle
);
3799 SECUREBOOT_FREE_NON_NULL (VariableData
);
3800 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
3801 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
3803 PrivateData
->ListCount
= Index
;
3809 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3810 The buffer is callee allocated and should be freed by the caller.
3812 @param[in] ListEntry The pointer point to the signature list.
3813 @param[in] DataEntry The signature data we are processing.
3814 @param[out] BufferToReturn Buffer to save the hash value.
3816 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3817 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3818 @retval EFI_SUCCESS Operation success.
3822 IN EFI_SIGNATURE_LIST
*ListEntry
,
3823 IN EFI_SIGNATURE_DATA
*DataEntry
,
3824 OUT CHAR16
**BufferToReturn
3835 // Assume that, display 8 bytes in one line.
3839 if (ListEntry
== NULL
|| DataEntry
== NULL
|| BufferToReturn
== NULL
) {
3840 return EFI_INVALID_PARAMETER
;
3843 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3844 Line
= (DataSize
+ OneLineBytes
- 1) / OneLineBytes
;
3847 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3849 TotalSize
= ((DataSize
+ Line
) * 2 * sizeof(CHAR16
));
3851 *BufferToReturn
= AllocateZeroPool(TotalSize
);
3852 if (*BufferToReturn
== NULL
) {
3853 return EFI_OUT_OF_RESOURCES
;
3856 for (Index
= 0, BufferIndex
= 0; Index
< DataSize
; Index
= Index
+ 1) {
3857 if ((Index
> 0) && (Index
% OneLineBytes
== 0)) {
3858 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3860 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"%02x", DataEntry
->SignatureData
[Index
]);
3862 BufferIndex
+= UnicodeSPrint(&(*BufferToReturn
)[BufferIndex
], TotalSize
- sizeof(CHAR16
) * BufferIndex
, L
"\n");
3868 Function to get the common name from the X509 format certificate.
3869 The buffer is callee allocated and should be freed by the caller.
3871 @param[in] ListEntry The pointer point to the signature list.
3872 @param[in] DataEntry The signature data we are processing.
3873 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3875 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3876 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3877 @retval EFI_SUCCESS Operation success.
3878 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3881 GetCommonNameFromX509 (
3882 IN EFI_SIGNATURE_LIST
*ListEntry
,
3883 IN EFI_SIGNATURE_DATA
*DataEntry
,
3884 OUT CHAR16
**BufferToReturn
3891 Status
= EFI_SUCCESS
;
3894 CNBuffer
= AllocateZeroPool(256);
3895 if (CNBuffer
== NULL
) {
3896 Status
= EFI_OUT_OF_RESOURCES
;
3902 (UINT8
*)DataEntry
+ sizeof(EFI_GUID
),
3903 ListEntry
->SignatureSize
- sizeof(EFI_GUID
),
3908 *BufferToReturn
= AllocateZeroPool(256 * sizeof(CHAR16
));
3909 if (*BufferToReturn
== NULL
) {
3910 Status
= EFI_OUT_OF_RESOURCES
;
3914 AsciiStrToUnicodeStrS (CNBuffer
, *BufferToReturn
, 256);
3917 SECUREBOOT_FREE_NON_NULL (CNBuffer
);
3923 Format the help info for the signature data, each help info contain 3 parts.
3925 2. Content, depends on the type of the signature list.
3928 @param[in] PrivateData Module's private data.
3929 @param[in] ListEntry Point to the signature list.
3930 @param[in] DataEntry Point to the signature data we are processing.
3931 @param[out] StringId Save the string id of help info.
3933 @retval EFI_SUCCESS Operation success.
3934 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3938 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
3939 IN EFI_SIGNATURE_LIST
*ListEntry
,
3940 IN EFI_SIGNATURE_DATA
*DataEntry
,
3941 OUT EFI_STRING_ID
*StringId
3946 EFI_STRING_ID ListTypeId
;
3947 EFI_STRING FormatHelpString
;
3948 EFI_STRING FormatTypeString
;
3950 UINTN HelpInfoIndex
;
3952 CHAR16 GuidString
[BUFFER_MAX_SIZE
];
3953 CHAR16 TimeString
[BUFFER_MAX_SIZE
];
3955 CHAR16
*HelpInfoString
;
3958 Status
= EFI_SUCCESS
;
3960 FormatTypeString
= NULL
;
3963 HelpInfoString
= NULL
;
3966 if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertRsa2048Guid
)) {
3967 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256
);
3968 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3970 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Guid
)) {
3971 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509
);
3972 DataSize
= ListEntry
->SignatureSize
- sizeof(EFI_GUID
);
3974 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha1Guid
)) {
3975 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA1
);
3977 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertSha256Guid
)) {
3978 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_SHA256
);
3980 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
3981 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA256
);
3983 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3984 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
3985 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA384
);
3987 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3988 } else if (CompareGuid(&ListEntry
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
3989 ListTypeId
= STRING_TOKEN(STR_LIST_TYPE_X509_SHA512
);
3991 Time
= (EFI_TIME
*)(DataEntry
->SignatureData
+ DataSize
);
3993 Status
= EFI_UNSUPPORTED
;
3997 FormatTypeString
= HiiGetString (PrivateData
->HiiHandle
, ListTypeId
, NULL
);
3998 if (FormatTypeString
== NULL
) {
4003 HelpInfoString
= AllocateZeroPool (TotalSize
);
4004 if (HelpInfoString
== NULL
) {
4005 Status
= EFI_OUT_OF_RESOURCES
;
4010 // Format GUID part.
4012 ZeroMem (GuidString
, sizeof (GuidString
));
4013 GuidToString(&DataEntry
->SignatureOwner
, GuidString
, BUFFER_MAX_SIZE
);
4014 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID
), NULL
);
4015 if (FormatHelpString
== NULL
) {
4018 HelpInfoIndex
+= UnicodeSPrint (
4019 &HelpInfoString
[HelpInfoIndex
],
4020 TotalSize
- sizeof(CHAR16
) * HelpInfoIndex
,
4024 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4025 FormatHelpString
= NULL
;
4028 // Format content part, it depends on the type of signature list, hash value or CN.
4031 GetCommonNameFromX509 (ListEntry
, DataEntry
, &DataString
);
4032 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN
), NULL
);
4035 // Format hash value for each signature data entry.
4037 ParseHashValue (ListEntry
, DataEntry
, &DataString
);
4038 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH
), NULL
);
4040 if (FormatHelpString
== NULL
) {
4043 HelpInfoIndex
+= UnicodeSPrint (
4044 &HelpInfoString
[HelpInfoIndex
],
4045 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4051 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4052 FormatHelpString
= NULL
;
4055 // Format revocation time part.
4058 ZeroMem (TimeString
, sizeof (TimeString
));
4061 sizeof (TimeString
),
4062 L
"%d-%d-%d %d:%d:%d",
4070 FormatHelpString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME
), NULL
);
4071 if (FormatHelpString
== NULL
) {
4075 &HelpInfoString
[HelpInfoIndex
],
4076 TotalSize
- sizeof (CHAR16
) * HelpInfoIndex
,
4080 SECUREBOOT_FREE_NON_NULL (FormatHelpString
);
4081 FormatHelpString
= NULL
;
4084 *StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, HelpInfoString
, NULL
);
4086 SECUREBOOT_FREE_NON_NULL (DataString
);
4087 SECUREBOOT_FREE_NON_NULL (HelpInfoString
);
4089 SECUREBOOT_FREE_NON_NULL (FormatTypeString
);
4095 This functino to load signature data under the signature list.
4097 @param[in] PrivateData Module's private data.
4098 @param[in] LabelId Label number to insert opcodes.
4099 @param[in] FormId Form ID of current page.
4100 @param[in] QuestionIdBase Base question id of the signature list.
4101 @param[in] ListIndex Indicate to load which signature list.
4103 @retval EFI_SUCCESS Success to update the signature list page
4104 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4108 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
4110 IN EFI_FORM_ID FormId
,
4111 IN EFI_QUESTION_ID QuestionIdBase
,
4116 EFI_SIGNATURE_LIST
*ListWalker
;
4117 EFI_SIGNATURE_DATA
*DataWalker
;
4118 EFI_IFR_GUID_LABEL
*StartLabel
;
4119 EFI_IFR_GUID_LABEL
*EndLabel
;
4120 EFI_STRING_ID HelpStringId
;
4121 EFI_STRING FormatNameString
;
4122 VOID
*StartOpCodeHandle
;
4123 VOID
*EndOpCodeHandle
;
4125 UINTN RemainingSize
;
4127 UINT8
*VariableData
;
4128 CHAR16 VariableName
[BUFFER_MAX_SIZE
];
4129 CHAR16 NameBuffer
[BUFFER_MAX_SIZE
];
4131 Status
= EFI_SUCCESS
;
4132 FormatNameString
= NULL
;
4133 StartOpCodeHandle
= NULL
;
4134 EndOpCodeHandle
= NULL
;
4136 VariableData
= NULL
;
4139 // Initialize the container for dynamic opcodes.
4141 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4142 if (StartOpCodeHandle
== NULL
) {
4143 Status
= EFI_OUT_OF_RESOURCES
;
4147 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4148 if (EndOpCodeHandle
== NULL
) {
4149 Status
= EFI_OUT_OF_RESOURCES
;
4154 // Create Hii Extend Label OpCode.
4156 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4160 sizeof (EFI_IFR_GUID_LABEL
)
4162 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4163 StartLabel
->Number
= LabelId
;
4165 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
4169 sizeof (EFI_IFR_GUID_LABEL
)
4171 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
4172 EndLabel
->Number
= LABEL_END
;
4174 if (PrivateData
->VariableName
== Variable_DB
) {
4175 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE
);
4176 } else if (PrivateData
->VariableName
== Variable_DBX
) {
4177 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE1
);
4178 } else if (PrivateData
->VariableName
== Variable_DBT
) {
4179 UnicodeSPrint (VariableName
, sizeof (VariableName
), EFI_IMAGE_SECURITY_DATABASE2
);
4185 // Read Variable, the variable name save in the PrivateData->VariableName.
4188 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4189 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
4193 VariableData
= AllocateZeroPool (DataSize
);
4194 if (VariableData
== NULL
) {
4195 Status
= EFI_OUT_OF_RESOURCES
;
4198 Status
= gRT
->GetVariable (VariableName
, &gEfiImageSecurityDatabaseGuid
, NULL
, &DataSize
, VariableData
);
4199 if (EFI_ERROR (Status
)) {
4203 RemainingSize
= DataSize
;
4204 ListWalker
= (EFI_SIGNATURE_LIST
*)VariableData
;
4207 // Skip signature list.
4209 while ((RemainingSize
> 0) && (RemainingSize
>= ListWalker
->SignatureListSize
) && ListIndex
-- > 0) {
4210 RemainingSize
-= ListWalker
->SignatureListSize
;
4211 ListWalker
= (EFI_SIGNATURE_LIST
*)((UINT8
*)ListWalker
+ ListWalker
->SignatureListSize
);
4214 FormatNameString
= HiiGetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT
), NULL
);
4215 if (FormatNameString
== NULL
) {
4219 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)ListWalker
+ sizeof(EFI_SIGNATURE_LIST
) + ListWalker
->SignatureHeaderSize
);
4220 for (Index
= 0; Index
< SIGNATURE_DATA_COUNTS(ListWalker
); Index
= Index
+ 1) {
4222 // Format name buffer.
4224 ZeroMem (NameBuffer
, sizeof (NameBuffer
));
4225 UnicodeSPrint (NameBuffer
, sizeof (NameBuffer
), FormatNameString
, Index
+ 1);
4228 // Format help info buffer.
4230 Status
= FormatHelpInfo (PrivateData
, ListWalker
, DataWalker
, &HelpStringId
);
4231 if (EFI_ERROR (Status
)) {
4235 HiiCreateCheckBoxOpCode (
4237 (EFI_QUESTION_ID
)(QuestionIdBase
+ Index
),
4240 HiiSetString (PrivateData
->HiiHandle
, 0, NameBuffer
, NULL
),
4242 EFI_IFR_FLAG_CALLBACK
,
4247 ZeroMem(NameBuffer
, 100);
4248 DataWalker
= (EFI_SIGNATURE_DATA
*)((UINT8
*)DataWalker
+ ListWalker
->SignatureSize
);
4252 // Allocate a buffer to record which signature data will be checked.
4253 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4255 PrivateData
->CheckArray
= AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker
) * sizeof (BOOLEAN
));
4258 PrivateData
->HiiHandle
,
4259 &gSecureBootConfigFormSetGuid
,
4265 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle
);
4266 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle
);
4268 SECUREBOOT_FREE_NON_NULL (VariableData
);
4269 SECUREBOOT_FREE_NON_NULL (FormatNameString
);
4275 This function is called to provide results data to the driver.
4277 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4278 @param[in] Action Specifies the type of action taken by the browser.
4279 @param[in] QuestionId A unique value which is sent to the original
4280 exporting driver so that it can identify the type
4282 @param[in] Type The type of value for the question.
4283 @param[in] Value A pointer to the data being sent to the original
4285 @param[out] ActionRequest On return, points to the action requested by the
4288 @retval EFI_SUCCESS The callback successfully handled the action.
4289 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4290 variable and its data.
4291 @retval EFI_DEVICE_ERROR The variable could not be saved.
4292 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4298 SecureBootCallback (
4299 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
4300 IN EFI_BROWSER_ACTION Action
,
4301 IN EFI_QUESTION_ID QuestionId
,
4303 IN EFI_IFR_TYPE_VALUE
*Value
,
4304 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
4309 RETURN_STATUS RStatus
;
4310 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
4312 SECUREBOOT_CONFIGURATION
*IfrNvData
;
4314 UINT8
*SecureBootEnable
;
4316 UINT8
*SecureBootMode
;
4318 CHAR16 PromptString
[100];
4319 EFI_DEVICE_PATH_PROTOCOL
*File
;
4321 UINT16
*FilePostFix
;
4322 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
4323 BOOLEAN GetBrowserDataResult
;
4325 Status
= EFI_SUCCESS
;
4326 SecureBootEnable
= NULL
;
4327 SecureBootMode
= NULL
;
4331 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
4332 return EFI_INVALID_PARAMETER
;
4335 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4337 gSecureBootPrivateData
= Private
;
4340 // Retrieve uncommitted data from Browser
4342 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4343 IfrNvData
= AllocateZeroPool (BufferSize
);
4344 if (IfrNvData
== NULL
) {
4345 return EFI_OUT_OF_RESOURCES
;
4348 GetBrowserDataResult
= HiiGetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
);
4350 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
4351 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4353 // Update secure boot strings when opening this form
4355 Status
= UpdateSecureBootString(Private
);
4356 SecureBootExtractConfigFromVariable (Private
, IfrNvData
);
4357 mIsEnterSecureBootForm
= TRUE
;
4360 // When entering SecureBoot OPTION Form
4361 // always close opened file & free resource
4363 if ((QuestionId
== KEY_SECURE_BOOT_PK_OPTION
) ||
4364 (QuestionId
== KEY_SECURE_BOOT_KEK_OPTION
) ||
4365 (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) ||
4366 (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) ||
4367 (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
)) {
4368 CloseEnrolledFile(Private
->FileContext
);
4369 } else if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_LIST
) {
4371 // Update ListCount field in varstore
4372 // Button "Delete All Signature List" is
4373 // enable when ListCount is greater than 0.
4375 IfrNvData
->ListCount
= Private
->ListCount
;
4381 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
4382 Status
= EFI_UNSUPPORTED
;
4383 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
4384 if (mIsEnterSecureBootForm
) {
4385 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
4386 Status
= EFI_SUCCESS
;
4392 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
4393 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
4394 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
4395 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
4396 Status
= EFI_UNSUPPORTED
;
4400 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
4402 switch (QuestionId
) {
4403 case KEY_SECURE_BOOT_ENABLE
:
4404 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
4405 if (NULL
!= SecureBootEnable
) {
4406 FreePool (SecureBootEnable
);
4407 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
4409 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4411 L
"Only Physical Presence User could disable secure boot!",
4414 Status
= EFI_UNSUPPORTED
;
4417 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4419 L
"Configuration changed, please reset the platform to take effect!",
4426 case KEY_SECURE_BOOT_KEK_OPTION
:
4427 case KEY_SECURE_BOOT_DB_OPTION
:
4428 case KEY_SECURE_BOOT_DBX_OPTION
:
4429 case KEY_SECURE_BOOT_DBT_OPTION
:
4430 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
4432 // Clear Signature GUID.
4434 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
4435 if (Private
->SignatureGUID
== NULL
) {
4436 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
4437 if (Private
->SignatureGUID
== NULL
) {
4438 return EFI_OUT_OF_RESOURCES
;
4443 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4445 SecureBootExtractConfigFromVariable (PrivateData
, IfrNvData
);
4447 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
4448 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
4449 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
4450 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
4451 } else if (QuestionId
== KEY_SECURE_BOOT_DBT_OPTION
) {
4452 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
;
4454 LabelId
= FORMID_ENROLL_KEK_FORM
;
4458 // Refresh selected file.
4460 CleanUpPage (LabelId
, Private
);
4462 case KEY_SECURE_BOOT_PK_OPTION
:
4463 LabelId
= FORMID_ENROLL_PK_FORM
;
4465 // Refresh selected file.
4467 CleanUpPage (LabelId
, Private
);
4470 case FORMID_ENROLL_PK_FORM
:
4471 ChooseFile (NULL
, NULL
, UpdatePKFromFile
, &File
);
4474 case FORMID_ENROLL_KEK_FORM
:
4475 ChooseFile (NULL
, NULL
, UpdateKEKFromFile
, &File
);
4478 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
4479 ChooseFile (NULL
, NULL
, UpdateDBFromFile
, &File
);
4482 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
4483 ChooseFile (NULL
, NULL
, UpdateDBXFromFile
, &File
);
4485 if (Private
->FileContext
->FHandle
!= NULL
) {
4487 // Parse the file's postfix.
4489 NameLength
= StrLen (Private
->FileContext
->FileName
);
4490 if (NameLength
<= 4) {
4493 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
4495 if (IsDerEncodeCertificate (FilePostFix
)) {
4497 // Supports DER-encoded X509 certificate.
4499 IfrNvData
->FileEnrollType
= X509_CERT_FILE_TYPE
;
4500 } else if (IsAuthentication2Format(Private
->FileContext
->FHandle
)){
4501 IfrNvData
->FileEnrollType
= AUTHENTICATION_2_FILE_TYPE
;
4503 IfrNvData
->FileEnrollType
= PE_IMAGE_FILE_TYPE
;
4505 Private
->FileContext
->FileType
= IfrNvData
->FileEnrollType
;
4508 // Clean up Certificate Format if File type is not X509 DER
4510 if (IfrNvData
->FileEnrollType
!= X509_CERT_FILE_TYPE
) {
4511 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4513 DEBUG((DEBUG_ERROR
, "IfrNvData->FileEnrollType %d\n", Private
->FileContext
->FileType
));
4518 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT
:
4519 ChooseFile (NULL
, NULL
, UpdateDBTFromFile
, &File
);
4522 case KEY_SECURE_BOOT_DELETE_PK
:
4525 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4527 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
4528 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4531 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
4532 Status
= DeletePlatformKey ();
4533 if (EFI_ERROR (Status
)) {
4535 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4537 L
"Only Physical Presence User could delete PK in custom mode!",
4545 case KEY_DELETE_KEK
:
4548 EFI_KEY_EXCHANGE_KEY_NAME
,
4549 &gEfiGlobalVariableGuid
,
4551 FORMID_DELETE_KEK_FORM
,
4552 OPTION_DEL_KEK_QUESTION_ID
4556 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
4559 EFI_IMAGE_SECURITY_DATABASE
,
4560 &gEfiImageSecurityDatabaseGuid
,
4562 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4563 OPTION_DEL_DB_QUESTION_ID
4568 // From DBX option to the level-1 form, display signature list.
4570 case KEY_VALUE_FROM_DBX_TO_LIST_FORM
:
4571 Private
->VariableName
= Variable_DBX
;
4574 LABEL_SIGNATURE_LIST_START
,
4575 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4576 OPTION_SIGNATURE_LIST_QUESTION_ID
4581 // Delete all signature list and reload.
4583 case KEY_SECURE_BOOT_DELETE_ALL_LIST
:
4585 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4587 L
"Press 'Y' to delete signature list.",
4588 L
"Press other key to cancel and exit.",
4592 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4593 DeleteSignatureEx (Private
, Delete_Signature_List_All
, IfrNvData
->CheckedDataCount
);
4598 LABEL_SIGNATURE_LIST_START
,
4599 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4600 OPTION_SIGNATURE_LIST_QUESTION_ID
4605 // Delete one signature list and reload.
4607 case KEY_SECURE_BOOT_DELETE_ALL_DATA
:
4609 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4611 L
"Press 'Y' to delete signature data.",
4612 L
"Press other key to cancel and exit.",
4616 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4617 DeleteSignatureEx (Private
, Delete_Signature_List_One
, IfrNvData
->CheckedDataCount
);
4622 LABEL_SIGNATURE_LIST_START
,
4623 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4624 OPTION_SIGNATURE_LIST_QUESTION_ID
4629 // Delete checked signature data and reload.
4631 case KEY_SECURE_BOOT_DELETE_CHECK_DATA
:
4633 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4635 L
"Press 'Y' to delete signature data.",
4636 L
"Press other key to cancel and exit.",
4640 if (Key
.UnicodeChar
== L
'Y' || Key
.UnicodeChar
== L
'y') {
4641 DeleteSignatureEx (Private
, Delete_Signature_Data
, IfrNvData
->CheckedDataCount
);
4646 LABEL_SIGNATURE_LIST_START
,
4647 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM
,
4648 OPTION_SIGNATURE_LIST_QUESTION_ID
4652 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
:
4655 EFI_IMAGE_SECURITY_DATABASE2
,
4656 &gEfiImageSecurityDatabaseGuid
,
4658 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4659 OPTION_DEL_DBT_QUESTION_ID
4664 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
4665 Status
= EnrollKeyExchangeKey (Private
);
4666 if (EFI_ERROR (Status
)) {
4668 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4670 L
"ERROR: Unsupported file type!",
4671 L
"Only supports DER-encoded X509 certificate",
4677 case KEY_VALUE_SAVE_AND_EXIT_DB
:
4678 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
4679 if (EFI_ERROR (Status
)) {
4681 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4683 L
"ERROR: Unsupported file type!",
4684 L
"Only supports DER-encoded X509 certificate and executable EFI image",
4690 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
4691 if (IsX509CertInDbx (Private
, EFI_IMAGE_SECURITY_DATABASE1
)) {
4693 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4695 L
"Enrollment failed! Same certificate had already been in the dbx!",
4700 // Cert already exists in DBX. Close opened file before exit.
4702 CloseEnrolledFile(Private
->FileContext
);
4706 if ((IfrNvData
!= NULL
) && (IfrNvData
->CertificateFormat
< HASHALG_MAX
)) {
4707 Status
= EnrollX509HashtoSigDB (
4709 IfrNvData
->CertificateFormat
,
4710 &IfrNvData
->RevocationDate
,
4711 &IfrNvData
->RevocationTime
,
4712 IfrNvData
->AlwaysRevocation
4714 IfrNvData
->CertificateFormat
= HASHALG_RAW
;
4716 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
4718 if (EFI_ERROR (Status
)) {
4720 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4722 L
"ERROR: Unsupported file type!",
4723 L
"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4729 case KEY_VALUE_SAVE_AND_EXIT_DBT
:
4730 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE2
);
4731 if (EFI_ERROR (Status
)) {
4733 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4735 L
"ERROR: Unsupported file type!",
4736 L
"Only supports DER-encoded X509 certificate.",
4741 case KEY_VALUE_SAVE_AND_EXIT_PK
:
4742 Status
= EnrollPlatformKey (Private
);
4743 if (EFI_ERROR (Status
)) {
4746 sizeof (PromptString
),
4747 L
"Only DER encoded certificate file (%s) is supported.",
4751 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
4753 L
"ERROR: Unsupported file type!",
4760 if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
4761 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4762 DeleteKeyExchangeKey (Private
, QuestionId
);
4763 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
4764 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4767 EFI_IMAGE_SECURITY_DATABASE
,
4768 &gEfiImageSecurityDatabaseGuid
,
4770 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
4771 OPTION_DEL_DB_QUESTION_ID
,
4772 QuestionId
- OPTION_DEL_DB_QUESTION_ID
4774 } else if ((QuestionId
>= OPTION_SIGNATURE_LIST_QUESTION_ID
) &&
4775 (QuestionId
< (OPTION_SIGNATURE_LIST_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4778 LABEL_SIGNATURE_DATA_START
,
4779 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM
,
4780 OPTION_SIGNATURE_DATA_QUESTION_ID
,
4781 QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
4783 Private
->ListIndex
= QuestionId
- OPTION_SIGNATURE_LIST_QUESTION_ID
;
4784 } else if ((QuestionId
>= OPTION_SIGNATURE_DATA_QUESTION_ID
) &&
4785 (QuestionId
< (OPTION_SIGNATURE_DATA_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4786 if (Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
]) {
4787 IfrNvData
->CheckedDataCount
--;
4788 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = FALSE
;
4790 IfrNvData
->CheckedDataCount
++;
4791 Private
->CheckArray
[QuestionId
- OPTION_SIGNATURE_DATA_QUESTION_ID
] = TRUE
;
4793 } else if ((QuestionId
>= OPTION_DEL_DBT_QUESTION_ID
) &&
4794 (QuestionId
< (OPTION_DEL_DBT_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
4797 EFI_IMAGE_SECURITY_DATABASE2
,
4798 &gEfiImageSecurityDatabaseGuid
,
4800 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT
,
4801 OPTION_DEL_DBT_QUESTION_ID
,
4802 QuestionId
- OPTION_DEL_DBT_QUESTION_ID
4807 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
4808 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
4809 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
4810 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
4811 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT
:
4812 CloseEnrolledFile(Private
->FileContext
);
4814 if (Private
->SignatureGUID
!= NULL
) {
4815 FreePool (Private
->SignatureGUID
);
4816 Private
->SignatureGUID
= NULL
;
4820 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
4821 switch (QuestionId
) {
4822 case KEY_SECURE_BOOT_ENABLE
:
4823 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4825 case KEY_SECURE_BOOT_MODE
:
4826 mIsEnterSecureBootForm
= FALSE
;
4828 case KEY_SECURE_BOOT_KEK_GUID
:
4829 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
4830 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
4831 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT
:
4832 ASSERT (Private
->SignatureGUID
!= NULL
);
4833 RStatus
= StrToGuid (IfrNvData
->SignatureGuid
, Private
->SignatureGUID
);
4834 if (RETURN_ERROR (RStatus
) || (IfrNvData
->SignatureGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
4835 Status
= EFI_INVALID_PARAMETER
;
4839 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4841 case KEY_SECURE_BOOT_DELETE_PK
:
4842 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
4843 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
4844 IfrNvData
->DeletePk
= TRUE
;
4845 IfrNvData
->HasPk
= FALSE
;
4846 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
4848 IfrNvData
->DeletePk
= FALSE
;
4849 IfrNvData
->HasPk
= TRUE
;
4850 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
4852 if (SetupMode
!= NULL
) {
4853 FreePool (SetupMode
);
4859 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
4860 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
4861 GetVariable2 (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&Pk
, NULL
);
4863 IfrNvData
->HideSecureBoot
= TRUE
;
4866 IfrNvData
->HideSecureBoot
= FALSE
;
4868 Value
->b
= IfrNvData
->HideSecureBoot
;
4870 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
4872 // Force the platform back to Standard Mode once user leave the setup screen.
4874 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
4875 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
4876 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
4877 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
4879 if (SecureBootMode
!= NULL
) {
4880 FreePool (SecureBootMode
);
4883 if (QuestionId
== KEY_SECURE_BOOT_DELETE_ALL_DATA
) {
4885 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4887 SECUREBOOT_FREE_NON_NULL (Private
->CheckArray
);
4888 IfrNvData
->CheckedDataCount
= 0;
4894 if (!EFI_ERROR (Status
) && GetBrowserDataResult
) {
4895 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
4896 HiiSetBrowserData (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
4899 FreePool (IfrNvData
);
4910 This function publish the SecureBoot configuration Form.
4912 @param[in, out] PrivateData Points to SecureBoot configuration private data.
4914 @retval EFI_SUCCESS HII Form is installed successfully.
4915 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
4916 @retval Others Other errors as indicated.
4920 InstallSecureBootConfigForm (
4921 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
4925 EFI_HII_HANDLE HiiHandle
;
4926 EFI_HANDLE DriverHandle
;
4927 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4929 DriverHandle
= NULL
;
4930 ConfigAccess
= &PrivateData
->ConfigAccess
;
4931 Status
= gBS
->InstallMultipleProtocolInterfaces (
4933 &gEfiDevicePathProtocolGuid
,
4934 &mSecureBootHiiVendorDevicePath
,
4935 &gEfiHiiConfigAccessProtocolGuid
,
4939 if (EFI_ERROR (Status
)) {
4943 PrivateData
->DriverHandle
= DriverHandle
;
4946 // Publish the HII package list
4948 HiiHandle
= HiiAddPackages (
4949 &gSecureBootConfigFormSetGuid
,
4951 SecureBootConfigDxeStrings
,
4952 SecureBootConfigBin
,
4955 if (HiiHandle
== NULL
) {
4956 gBS
->UninstallMultipleProtocolInterfaces (
4958 &gEfiDevicePathProtocolGuid
,
4959 &mSecureBootHiiVendorDevicePath
,
4960 &gEfiHiiConfigAccessProtocolGuid
,
4964 return EFI_OUT_OF_RESOURCES
;
4967 PrivateData
->HiiHandle
= HiiHandle
;
4969 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
4971 if (PrivateData
->FileContext
== NULL
) {
4972 UninstallSecureBootConfigForm (PrivateData
);
4973 return EFI_OUT_OF_RESOURCES
;
4977 // Init OpCode Handle and Allocate space for creation of Buffer
4979 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
4980 if (mStartOpCodeHandle
== NULL
) {
4981 UninstallSecureBootConfigForm (PrivateData
);
4982 return EFI_OUT_OF_RESOURCES
;
4985 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
4986 if (mEndOpCodeHandle
== NULL
) {
4987 UninstallSecureBootConfigForm (PrivateData
);
4988 return EFI_OUT_OF_RESOURCES
;
4992 // Create Hii Extend Label OpCode as the start opcode
4994 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
4998 sizeof (EFI_IFR_GUID_LABEL
)
5000 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5003 // Create Hii Extend Label OpCode as the end opcode
5005 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
5009 sizeof (EFI_IFR_GUID_LABEL
)
5011 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
5012 mEndLabel
->Number
= LABEL_END
;
5018 This function removes SecureBoot configuration Form.
5020 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5024 UninstallSecureBootConfigForm (
5025 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
5029 // Uninstall HII package list
5031 if (PrivateData
->HiiHandle
!= NULL
) {
5032 HiiRemovePackages (PrivateData
->HiiHandle
);
5033 PrivateData
->HiiHandle
= NULL
;
5037 // Uninstall HII Config Access Protocol
5039 if (PrivateData
->DriverHandle
!= NULL
) {
5040 gBS
->UninstallMultipleProtocolInterfaces (
5041 PrivateData
->DriverHandle
,
5042 &gEfiDevicePathProtocolGuid
,
5043 &mSecureBootHiiVendorDevicePath
,
5044 &gEfiHiiConfigAccessProtocolGuid
,
5045 &PrivateData
->ConfigAccess
,
5048 PrivateData
->DriverHandle
= NULL
;
5051 if (PrivateData
->SignatureGUID
!= NULL
) {
5052 FreePool (PrivateData
->SignatureGUID
);
5055 if (PrivateData
->FileContext
!= NULL
) {
5056 FreePool (PrivateData
->FileContext
);
5059 FreePool (PrivateData
);
5061 if (mStartOpCodeHandle
!= NULL
) {
5062 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
5065 if (mEndOpCodeHandle
!= NULL
) {
5066 HiiFreeOpCodeHandle (mEndOpCodeHandle
);