2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "SecureBootConfigImpl.h"
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
) (END_DEVICE_PATH_LENGTH
),
45 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
52 // OID ASN.1 Value for Hash Algorithms
54 UINT8 mHashOidValue
[] = {
55 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
56 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
63 HASH_TABLE mHash
[] = {
64 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
65 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
66 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
67 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
68 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
72 // Variable Definitions
74 UINT32 mPeCoffHeaderOffset
= 0;
75 WIN_CERTIFICATE
*mCertificate
= NULL
;
76 IMAGE_TYPE mImageType
;
77 UINT8
*mImageBase
= NULL
;
79 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
80 UINTN mImageDigestSize
;
82 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
83 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
86 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
88 CHAR16
* mDerEncodedSuffix
[] = {
94 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
97 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
99 @param[in] FileSuffix The suffix of the input certificate file
101 @retval TRUE It's a DER-encoded certificate.
102 @retval FALSE It's NOT a DER-encoded certificate.
106 IsDerEncodeCertificate (
107 IN CONST CHAR16
*FileSuffix
111 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
112 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
120 Set Secure Boot option into variable space.
122 @param[in] VarValue The option of Secure Boot.
124 @retval EFI_SUCCESS The operation is finished successfully.
125 @retval Others Other errors as indicated.
129 SaveSecureBootVariable (
135 Status
= gRT
->SetVariable (
136 EFI_SECURE_BOOT_ENABLE_NAME
,
137 &gEfiSecureBootEnableDisableGuid
,
138 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
146 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
147 descriptor with the input data. NO authentication is required in this function.
149 @param[in, out] DataSize On input, the size of Data buffer in bytes.
150 On output, the size of data returned in Data
152 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
153 pointer to NULL to wrap an empty payload.
154 On output, Pointer to the new payload date buffer allocated from pool,
155 it's caller's responsibility to free the memory when finish using it.
157 @retval EFI_SUCCESS Create time based payload successfully.
158 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
159 @retval EFI_INVALID_PARAMETER The parameter is invalid.
160 @retval Others Unexpected error happens.
164 CreateTimeBasedPayload (
165 IN OUT UINTN
*DataSize
,
173 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
174 UINTN DescriptorSize
;
177 if (Data
== NULL
|| DataSize
== NULL
) {
178 return EFI_INVALID_PARAMETER
;
182 // In Setup mode or Custom mode, the variable does not need to be signed but the
183 // parameters to the SetVariable() call still need to be prepared as authenticated
184 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
188 PayloadSize
= *DataSize
;
190 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
191 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
192 if (NewData
== NULL
) {
193 return EFI_OUT_OF_RESOURCES
;
196 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
197 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
200 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
202 ZeroMem (&Time
, sizeof (EFI_TIME
));
203 Status
= gRT
->GetTime (&Time
, NULL
);
204 if (EFI_ERROR (Status
)) {
213 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
215 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
216 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
217 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
218 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
220 if (Payload
!= NULL
) {
224 *DataSize
= DescriptorSize
+ PayloadSize
;
230 Internal helper function to delete a Variable given its name and GUID, NO authentication
233 @param[in] VariableName Name of the Variable.
234 @param[in] VendorGuid GUID of the Variable.
236 @retval EFI_SUCCESS Variable deleted successfully.
237 @retval Others The driver failed to start the device.
242 IN CHAR16
*VariableName
,
243 IN EFI_GUID
*VendorGuid
252 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
253 if (Variable
== NULL
) {
259 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
260 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
262 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
263 if (EFI_ERROR (Status
)) {
264 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
268 Status
= gRT
->SetVariable (
282 Generate the PK signature list from the X509 Certificate storing file (.cer)
284 @param[in] X509File FileHandle of X509 Certificate storing file.
285 @param[out] PkCert Point to the data buffer to store the signature list.
287 @return EFI_UNSUPPORTED Unsupported Key Length.
288 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
292 CreatePkX509SignatureList (
293 IN EFI_FILE_HANDLE X509File
,
294 OUT EFI_SIGNATURE_LIST
**PkCert
300 EFI_SIGNATURE_DATA
*PkCertData
;
306 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
307 if (EFI_ERROR (Status
)) {
310 ASSERT (X509Data
!= NULL
);
313 // Allocate space for PK certificate list and initialize it.
314 // Create PK database entry with SignatureHeaderSize equals 0.
316 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
317 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
320 if (*PkCert
== NULL
) {
321 Status
= EFI_OUT_OF_RESOURCES
;
325 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
326 + sizeof(EFI_SIGNATURE_DATA
) - 1
328 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
329 (*PkCert
)->SignatureHeaderSize
= 0;
330 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
331 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
332 + sizeof(EFI_SIGNATURE_LIST
)
333 + (*PkCert
)->SignatureHeaderSize
);
334 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
336 // Fill the PK database with PKpub data from X509 certificate file.
338 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
342 if (X509Data
!= NULL
) {
346 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
355 Enroll new PK into the System without original PK's authentication.
357 The SignatureOwner GUID will be the same with PK's vendorguid.
359 @param[in] PrivateData The module's private data.
361 @retval EFI_SUCCESS New PK enrolled successfully.
362 @retval EFI_INVALID_PARAMETER The parameter is invalid.
363 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
368 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
374 EFI_SIGNATURE_LIST
*PkCert
;
377 if (Private
->FileContext
->FileName
== NULL
) {
378 return EFI_INVALID_PARAMETER
;
384 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
386 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
387 if (!IsDerEncodeCertificate(FilePostFix
)) {
388 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
389 return EFI_INVALID_PARAMETER
;
391 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
392 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
395 // Prase the selected PK file and generature PK certificate list.
397 Status
= CreatePkX509SignatureList (
398 Private
->FileContext
->FHandle
,
401 if (EFI_ERROR (Status
)) {
404 ASSERT (PkCert
!= NULL
);
407 // Set Platform Key variable.
409 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
410 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
411 DataSize
= PkCert
->SignatureListSize
;
412 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
413 if (EFI_ERROR (Status
)) {
414 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
418 Status
= gRT
->SetVariable(
419 EFI_PLATFORM_KEY_NAME
,
420 &gEfiGlobalVariableGuid
,
425 if (EFI_ERROR (Status
)) {
426 if (Status
== EFI_OUT_OF_RESOURCES
) {
427 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
434 if (PkCert
!= NULL
) {
438 if (Private
->FileContext
->FHandle
!= NULL
) {
439 CloseFile (Private
->FileContext
->FHandle
);
440 Private
->FileContext
->FHandle
= NULL
;
447 Remove the PK variable.
449 @retval EFI_SUCCESS Delete PK successfully.
450 @retval Others Could not allow to delete PK.
460 Status
= DeleteVariable (
461 EFI_PLATFORM_KEY_NAME
,
462 &gEfiGlobalVariableGuid
468 Enroll a new KEK item from public key storing file (*.pbk).
470 @param[in] PrivateData The module's private data.
472 @retval EFI_SUCCESS New KEK enrolled successfully.
473 @retval EFI_INVALID_PARAMETER The parameter is invalid.
474 @retval EFI_UNSUPPORTED Unsupported command.
475 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
480 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
486 EFI_SIGNATURE_LIST
*KekSigList
;
489 CPL_KEY_INFO
*KeyInfo
;
490 EFI_SIGNATURE_DATA
*KEKSigData
;
491 UINTN KekSigListSize
;
506 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
507 // First, We have to parse out public key data from the pbk key file.
509 Status
= ReadFileContent (
510 Private
->FileContext
->FHandle
,
515 if (EFI_ERROR (Status
)) {
518 ASSERT (KeyBlob
!= NULL
);
519 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
520 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
521 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
522 Status
= EFI_UNSUPPORTED
;
527 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
529 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
530 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
531 if (KeyBuffer
== NULL
) {
532 Status
= EFI_OUT_OF_RESOURCES
;
536 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
537 KeyLenInBytes
/ sizeof (UINTN
),
541 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
544 // Form an new EFI_SIGNATURE_LIST.
546 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
547 + sizeof(EFI_SIGNATURE_DATA
) - 1
548 + WIN_CERT_UEFI_RSA2048_SIZE
;
550 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
551 if (KekSigList
== NULL
) {
552 Status
= EFI_OUT_OF_RESOURCES
;
556 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
557 + sizeof(EFI_SIGNATURE_DATA
) - 1
558 + WIN_CERT_UEFI_RSA2048_SIZE
;
559 KekSigList
->SignatureHeaderSize
= 0;
560 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
561 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
563 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
564 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
566 KEKSigData
->SignatureData
,
567 KeyBlob
+ sizeof(CPL_KEY_INFO
),
568 WIN_CERT_UEFI_RSA2048_SIZE
572 // Check if KEK entry has been already existed.
573 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
574 // new KEK to original variable.
576 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
577 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
578 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
579 if (EFI_ERROR (Status
)) {
580 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
584 Status
= gRT
->GetVariable(
585 EFI_KEY_EXCHANGE_KEY_NAME
,
586 &gEfiGlobalVariableGuid
,
591 if (Status
== EFI_BUFFER_TOO_SMALL
) {
592 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
593 } else if (Status
!= EFI_NOT_FOUND
) {
598 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
600 Status
= gRT
->SetVariable(
601 EFI_KEY_EXCHANGE_KEY_NAME
,
602 &gEfiGlobalVariableGuid
,
607 if (EFI_ERROR (Status
)) {
613 CloseFile (Private
->FileContext
->FHandle
);
614 Private
->FileContext
->FHandle
= NULL
;
615 Private
->FileContext
->FileName
= NULL
;
617 if (Private
->SignatureGUID
!= NULL
) {
618 FreePool (Private
->SignatureGUID
);
619 Private
->SignatureGUID
= NULL
;
622 if (KeyBlob
!= NULL
) {
625 if (KeyBuffer
!= NULL
) {
626 FreePool (KeyBuffer
);
628 if (KekSigList
!= NULL
) {
629 FreePool (KekSigList
);
636 Enroll a new KEK item from X509 certificate file.
638 @param[in] PrivateData The module's private data.
640 @retval EFI_SUCCESS New X509 is enrolled successfully.
641 @retval EFI_INVALID_PARAMETER The parameter is invalid.
642 @retval EFI_UNSUPPORTED Unsupported command.
643 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
648 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
654 EFI_SIGNATURE_DATA
*KEKSigData
;
655 EFI_SIGNATURE_LIST
*KekSigList
;
657 UINTN KekSigListSize
;
667 Status
= ReadFileContent (
668 Private
->FileContext
->FHandle
,
673 if (EFI_ERROR (Status
)) {
676 ASSERT (X509Data
!= NULL
);
678 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
679 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
680 if (KekSigList
== NULL
) {
681 Status
= EFI_OUT_OF_RESOURCES
;
686 // Fill Certificate Database parameters.
688 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
689 KekSigList
->SignatureHeaderSize
= 0;
690 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
691 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
693 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
694 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
695 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
698 // Check if KEK been already existed.
699 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
700 // new kek to original variable
702 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
703 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
704 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
705 if (EFI_ERROR (Status
)) {
706 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
710 Status
= gRT
->GetVariable(
711 EFI_KEY_EXCHANGE_KEY_NAME
,
712 &gEfiGlobalVariableGuid
,
717 if (Status
== EFI_BUFFER_TOO_SMALL
) {
718 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
719 } else if (Status
!= EFI_NOT_FOUND
) {
723 Status
= gRT
->SetVariable(
724 EFI_KEY_EXCHANGE_KEY_NAME
,
725 &gEfiGlobalVariableGuid
,
730 if (EFI_ERROR (Status
)) {
736 CloseFile (Private
->FileContext
->FHandle
);
737 Private
->FileContext
->FileName
= NULL
;
738 Private
->FileContext
->FHandle
= NULL
;
740 if (Private
->SignatureGUID
!= NULL
) {
741 FreePool (Private
->SignatureGUID
);
742 Private
->SignatureGUID
= NULL
;
745 if (KekSigList
!= NULL
) {
746 FreePool (KekSigList
);
753 Enroll new KEK into the System without PK's authentication.
754 The SignatureOwner GUID will be Private->SignatureGUID.
756 @param[in] PrivateData The module's private data.
758 @retval EFI_SUCCESS New KEK enrolled successful.
759 @retval EFI_INVALID_PARAMETER The parameter is invalid.
760 @retval others Fail to enroll KEK data.
764 EnrollKeyExchangeKey (
765 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
770 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
771 return EFI_INVALID_PARAMETER
;
775 // Parse the file's postfix. Supports DER-encoded X509 certificate,
776 // and .pbk as RSA public key file.
778 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
779 if (IsDerEncodeCertificate(FilePostFix
)) {
780 return EnrollX509ToKek (Private
);
781 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
782 return EnrollRsa2048ToKek (Private
);
784 return EFI_INVALID_PARAMETER
;
789 Enroll a new X509 certificate into Signature Database (DB or DBX) without
790 KEK's authentication.
792 @param[in] PrivateData The module's private data.
793 @param[in] VariableName Variable name of signature database, must be
794 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
796 @retval EFI_SUCCESS New X509 is enrolled successfully.
797 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
802 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
803 IN CHAR16
*VariableName
809 EFI_SIGNATURE_LIST
*SigDBCert
;
810 EFI_SIGNATURE_DATA
*SigDBCertData
;
821 SigDBCertData
= NULL
;
824 Status
= ReadFileContent (
825 Private
->FileContext
->FHandle
,
830 if (EFI_ERROR (Status
)) {
833 ASSERT (X509Data
!= NULL
);
835 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
837 Data
= AllocateZeroPool (SigDBSize
);
839 Status
= EFI_OUT_OF_RESOURCES
;
844 // Fill Certificate Database parameters.
846 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
847 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
848 SigDBCert
->SignatureHeaderSize
= 0;
849 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
850 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
852 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
853 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
854 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
857 // Check if signature database entry has been already existed.
858 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
859 // new signature data to original variable
861 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
862 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
863 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
864 if (EFI_ERROR (Status
)) {
865 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
869 Status
= gRT
->GetVariable(
871 &gEfiImageSecurityDatabaseGuid
,
876 if (Status
== EFI_BUFFER_TOO_SMALL
) {
877 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
878 } else if (Status
!= EFI_NOT_FOUND
) {
882 Status
= gRT
->SetVariable(
884 &gEfiImageSecurityDatabaseGuid
,
889 if (EFI_ERROR (Status
)) {
895 CloseFile (Private
->FileContext
->FHandle
);
896 Private
->FileContext
->FileName
= NULL
;
897 Private
->FileContext
->FHandle
= NULL
;
899 if (Private
->SignatureGUID
!= NULL
) {
900 FreePool (Private
->SignatureGUID
);
901 Private
->SignatureGUID
= NULL
;
908 if (X509Data
!= NULL
) {
916 Load PE/COFF image information into internal buffer and check its validity.
918 @retval EFI_SUCCESS Successful
919 @retval EFI_UNSUPPORTED Invalid PE/COFF file
920 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
928 EFI_IMAGE_DOS_HEADER
*DosHdr
;
929 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
930 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
935 // Read the Dos header
937 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
938 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
941 // DOS image header is present,
942 // So read the PE header after the DOS image header
944 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
948 mPeCoffHeaderOffset
= 0;
952 // Read PE header and check the signature validity and machine compatibility
954 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
955 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
957 return EFI_UNSUPPORTED
;
960 mNtHeader
.Pe32
= NtHeader32
;
963 // Check the architecture field of PE header and get the Certificate Data Directory data
964 // Note the size of FileHeader field is constant for both IA32 and X64 arch
966 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
967 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
969 // IA-32 Architecture
971 mImageType
= ImageType_IA32
;
972 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
974 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
975 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
977 // 64-bits Architecture
979 mImageType
= ImageType_X64
;
980 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
981 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
983 return EFI_UNSUPPORTED
;
990 Calculate hash of Pe/Coff image based on the authenticode image hashing in
991 PE/COFF Specification 8.0 Appendix A
993 @param[in] HashAlg Hash algorithm type.
995 @retval TRUE Successfully hash image.
996 @retval FALSE Fail in hash image.
1006 EFI_IMAGE_SECTION_HEADER
*Section
;
1011 UINTN SumOfBytesHashed
;
1012 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1017 SectionHeader
= NULL
;
1020 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1025 // Initialize context of hash.
1027 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1029 if (HashAlg
== HASHALG_SHA1
) {
1030 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1031 mCertType
= gEfiCertSha1Guid
;
1032 } else if (HashAlg
== HASHALG_SHA256
) {
1033 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1034 mCertType
= gEfiCertSha256Guid
;
1037 CtxSize
= mHash
[HashAlg
].GetContextSize();
1039 HashCtx
= AllocatePool (CtxSize
);
1040 ASSERT (HashCtx
!= NULL
);
1042 // 1. Load the image header into memory.
1044 // 2. Initialize a SHA hash context.
1045 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1050 // Measuring PE/COFF Image Header;
1051 // But CheckSum field and SECURITY data directory (certificate) are excluded
1053 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1055 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1056 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1057 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1058 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1060 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1063 // Get the magic value from the PE/COFF Optional Header
1065 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1069 // 3. Calculate the distance from the base of the image header to the image checksum address.
1070 // 4. Hash the image header from its base to beginning of the image checksum.
1072 HashBase
= mImageBase
;
1073 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1077 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1080 // Use PE32+ offset.
1082 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1085 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1090 // 5. Skip over the image checksum (it occupies a single ULONG).
1091 // 6. Get the address of the beginning of the Cert Directory.
1092 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1094 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1098 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1099 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1102 // Use PE32+ offset.
1104 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1105 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1108 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1113 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1114 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1116 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1120 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1121 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1124 // Use PE32+ offset.
1126 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1127 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1130 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1135 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1137 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1141 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1146 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1150 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1151 // structures in the image. The 'NumberOfSections' field of the image
1152 // header indicates how big the table should be. Do not include any
1153 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1155 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1156 ASSERT (SectionHeader
!= NULL
);
1158 // 12. Using the 'PointerToRawData' in the referenced section headers as
1159 // a key, arrange the elements in the table in ascending order. In other
1160 // words, sort the section headers according to the disk-file offset of
1163 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1165 mPeCoffHeaderOffset
+
1167 sizeof (EFI_IMAGE_FILE_HEADER
) +
1168 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1170 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1172 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1173 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1176 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1181 // 13. Walk through the sorted table, bring the corresponding section
1182 // into memory, and hash the entire section (using the 'SizeOfRawData'
1183 // field in the section header to determine the amount of data to hash).
1184 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1185 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1187 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1188 Section
= &SectionHeader
[Index
];
1189 if (Section
->SizeOfRawData
== 0) {
1192 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1193 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1195 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1200 SumOfBytesHashed
+= HashSize
;
1204 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1205 // data in the file that needs to be added to the hash. This data begins
1206 // at file offset SUM_OF_BYTES_HASHED and its length is:
1207 // FileSize - (CertDirectory->Size)
1209 if (mImageSize
> SumOfBytesHashed
) {
1210 HashBase
= mImageBase
+ SumOfBytesHashed
;
1211 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1217 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1221 // Use PE32+ offset.
1225 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1229 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1235 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1238 if (HashCtx
!= NULL
) {
1241 if (SectionHeader
!= NULL
) {
1242 FreePool (SectionHeader
);
1248 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1249 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1252 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1253 @retval EFI_SUCCESS Hash successfully.
1262 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1264 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1266 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1268 // Check the Hash algorithm in PE/COFF Authenticode.
1269 // According to PKCS#7 Definition:
1270 // SignedData ::= SEQUENCE {
1272 // digestAlgorithms DigestAlgorithmIdentifiers,
1273 // contentInfo ContentInfo,
1275 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1276 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1277 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1279 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1281 // Only support two bytes of Long Form of Length Encoding.
1287 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1292 if (Index
== HASHALG_MAX
) {
1293 return EFI_UNSUPPORTED
;
1297 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1299 if (!HashPeImage(Index
)) {
1300 return EFI_UNSUPPORTED
;
1307 Enroll a new executable's signature into Signature Database.
1309 @param[in] PrivateData The module's private data.
1310 @param[in] VariableName Variable name of signature database, must be
1311 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1313 @retval EFI_SUCCESS New signature is enrolled successfully.
1314 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1315 @retval EFI_UNSUPPORTED Unsupported command.
1316 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1320 EnrollImageSignatureToSigDB (
1321 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1322 IN CHAR16
*VariableName
1326 EFI_SIGNATURE_LIST
*SigDBCert
;
1327 EFI_SIGNATURE_DATA
*SigDBCertData
;
1332 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
1335 GuidCertData
= NULL
;
1338 // Form the SigDB certificate list.
1339 // Format the data item into EFI_SIGNATURE_LIST type.
1341 // We need to parse executable's signature data from specified signed executable file.
1342 // In current implementation, we simply trust the pass-in signed executable file.
1343 // In reality, it's OS's responsibility to verify the signed executable file.
1347 // Read the whole file content
1349 Status
= ReadFileContent(
1350 Private
->FileContext
->FHandle
,
1351 (VOID
**) &mImageBase
,
1355 if (EFI_ERROR (Status
)) {
1358 ASSERT (mImageBase
!= NULL
);
1360 Status
= LoadPeImage ();
1361 if (EFI_ERROR (Status
)) {
1365 if (mSecDataDir
->SizeOfCert
== 0) {
1366 if (!HashPeImage (HASHALG_SHA256
)) {
1367 Status
= EFI_SECURITY_VIOLATION
;
1373 // Read the certificate data
1375 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
1377 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1378 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
1379 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
1380 Status
= EFI_ABORTED
;
1384 if (!HashPeImage (HASHALG_SHA256
)) {
1385 Status
= EFI_ABORTED
;
1389 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1391 Status
= HashPeImageByType ();
1392 if (EFI_ERROR (Status
)) {
1396 Status
= EFI_ABORTED
;
1402 // Create a new SigDB entry.
1404 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
1405 + sizeof(EFI_SIGNATURE_DATA
) - 1
1406 + (UINT32
) mImageDigestSize
;
1408 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
1410 Status
= EFI_OUT_OF_RESOURCES
;
1415 // Adjust the Certificate Database parameters.
1417 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1418 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1419 SigDBCert
->SignatureHeaderSize
= 0;
1420 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
1421 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
1423 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
1424 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1425 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
1427 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1428 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1429 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
1430 if (EFI_ERROR (Status
)) {
1431 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1436 // Check if SigDB variable has been already existed.
1437 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1438 // new signature data to original variable
1441 Status
= gRT
->GetVariable(
1443 &gEfiImageSecurityDatabaseGuid
,
1448 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1449 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1450 } else if (Status
!= EFI_NOT_FOUND
) {
1455 // Enroll the variable.
1457 Status
= gRT
->SetVariable(
1459 &gEfiImageSecurityDatabaseGuid
,
1464 if (EFI_ERROR (Status
)) {
1470 CloseFile (Private
->FileContext
->FHandle
);
1471 Private
->FileContext
->FHandle
= NULL
;
1472 Private
->FileContext
->FileName
= NULL
;
1474 if (Private
->SignatureGUID
!= NULL
) {
1475 FreePool (Private
->SignatureGUID
);
1476 Private
->SignatureGUID
= NULL
;
1483 if (mImageBase
!= NULL
) {
1484 FreePool (mImageBase
);
1492 Enroll signature into DB/DBX without KEK's authentication.
1493 The SignatureOwner GUID will be Private->SignatureGUID.
1495 @param[in] PrivateData The module's private data.
1496 @param[in] VariableName Variable name of signature database, must be
1497 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1499 @retval EFI_SUCCESS New signature enrolled successfully.
1500 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1501 @retval others Fail to enroll signature data.
1505 EnrollSignatureDatabase (
1506 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1507 IN CHAR16
*VariableName
1510 UINT16
* FilePostFix
;
1512 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1513 return EFI_INVALID_PARAMETER
;
1517 // Parse the file's postfix.
1519 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
1520 if (IsDerEncodeCertificate(FilePostFix
)) {
1522 // Supports DER-encoded X509 certificate.
1524 return EnrollX509toSigDB (Private
, VariableName
);
1527 return EnrollImageSignatureToSigDB (Private
, VariableName
);
1531 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1532 by GUID in the page for user to select and delete as needed.
1534 @param[in] PrivateData Module's private data.
1535 @param[in] VariableName The variable name of the vendor's signature database.
1536 @param[in] VendorGuid A unique identifier for the vendor.
1537 @param[in] LabelNumber Label number to insert opcodes.
1538 @param[in] FormId Form ID of current page.
1539 @param[in] QuestionIdBase Base question id of the signature list.
1541 @retval EFI_SUCCESS Success to update the signature list page
1542 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1547 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1548 IN CHAR16
*VariableName
,
1549 IN EFI_GUID
*VendorGuid
,
1550 IN UINT16 LabelNumber
,
1551 IN EFI_FORM_ID FormId
,
1552 IN EFI_QUESTION_ID QuestionIdBase
1559 VOID
*StartOpCodeHandle
;
1560 VOID
*EndOpCodeHandle
;
1561 EFI_IFR_GUID_LABEL
*StartLabel
;
1562 EFI_IFR_GUID_LABEL
*EndLabel
;
1565 EFI_SIGNATURE_LIST
*CertList
;
1566 EFI_SIGNATURE_DATA
*Cert
;
1567 UINT32 ItemDataSize
;
1569 EFI_STRING_ID GuidID
;
1576 StartOpCodeHandle
= NULL
;
1577 EndOpCodeHandle
= NULL
;
1580 // Initialize the container for dynamic opcodes.
1582 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1583 if (StartOpCodeHandle
== NULL
) {
1584 Status
= EFI_OUT_OF_RESOURCES
;
1588 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1589 if (EndOpCodeHandle
== NULL
) {
1590 Status
= EFI_OUT_OF_RESOURCES
;
1595 // Create Hii Extend Label OpCode.
1597 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1601 sizeof (EFI_IFR_GUID_LABEL
)
1603 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1604 StartLabel
->Number
= LabelNumber
;
1606 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1610 sizeof (EFI_IFR_GUID_LABEL
)
1612 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1613 EndLabel
->Number
= LABEL_END
;
1619 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1620 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1624 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1626 Status
= EFI_OUT_OF_RESOURCES
;
1630 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1631 if (EFI_ERROR (Status
)) {
1635 GuidStr
= AllocateZeroPool (100);
1636 if (GuidStr
== NULL
) {
1637 Status
= EFI_OUT_OF_RESOURCES
;
1642 // Enumerate all KEK pub data.
1644 ItemDataSize
= (UINT32
) DataSize
;
1645 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1648 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1650 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1651 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
1652 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1653 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
1654 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
1655 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
1656 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
1657 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
1660 // The signature type is not supported in current implementation.
1665 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1666 for (Index
= 0; Index
< CertCount
; Index
++) {
1667 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
1668 + sizeof (EFI_SIGNATURE_LIST
)
1669 + CertList
->SignatureHeaderSize
1670 + Index
* CertList
->SignatureSize
);
1672 // Display GUID and help
1674 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
1675 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
1676 HiiCreateCheckBoxOpCode (
1678 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
1683 EFI_IFR_FLAG_CALLBACK
,
1689 ItemDataSize
-= CertList
->SignatureListSize
;
1690 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1695 PrivateData
->HiiHandle
,
1696 &gSecureBootConfigFormSetGuid
,
1702 if (StartOpCodeHandle
!= NULL
) {
1703 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1706 if (EndOpCodeHandle
!= NULL
) {
1707 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1714 if (GuidStr
!= NULL
) {
1722 Delete a KEK entry from KEK database.
1724 @param[in] PrivateData Module's private data.
1725 @param[in] QuestionId Question id of the KEK item to delete.
1727 @retval EFI_SUCCESS Delete kek item successfully.
1728 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1732 DeleteKeyExchangeKey (
1733 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1734 IN EFI_QUESTION_ID QuestionId
1743 EFI_SIGNATURE_LIST
*CertList
;
1744 EFI_SIGNATURE_LIST
*NewCertList
;
1745 EFI_SIGNATURE_DATA
*Cert
;
1748 BOOLEAN IsKEKItemFound
;
1750 UINTN DeleteKekIndex
;
1758 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
1761 // Get original KEK variable.
1764 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
1765 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1769 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
1770 if (OldData
== NULL
) {
1771 Status
= EFI_OUT_OF_RESOURCES
;
1775 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
1776 if (EFI_ERROR(Status
)) {
1781 // Allocate space for new variable.
1783 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1785 Status
= EFI_OUT_OF_RESOURCES
;
1790 // Enumerate all KEK pub data and erasing the target item.
1792 IsKEKItemFound
= FALSE
;
1793 KekDataSize
= (UINT32
) DataSize
;
1794 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1797 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1798 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1799 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1800 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1801 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1802 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1803 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1804 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1805 for (Index
= 0; Index
< CertCount
; Index
++) {
1806 if (GuidIndex
== DeleteKekIndex
) {
1808 // Find it! Skip it!
1810 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1811 IsKEKItemFound
= TRUE
;
1814 // This item doesn't match. Copy it to the Data buffer.
1816 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
1817 Offset
+= CertList
->SignatureSize
;
1820 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1824 // This List doesn't match. Copy it to the Data buffer.
1826 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
1827 Offset
+= CertList
->SignatureListSize
;
1830 KekDataSize
-= CertList
->SignatureListSize
;
1831 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1834 if (!IsKEKItemFound
) {
1836 // Doesn't find the Kek Item!
1838 Status
= EFI_NOT_FOUND
;
1843 // Delete the Signature header if there is no signature in the list.
1845 KekDataSize
= Offset
;
1846 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1848 ZeroMem (OldData
, KekDataSize
);
1849 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1850 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1851 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1852 if (CertCount
!= 0) {
1853 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
1854 Offset
+= CertList
->SignatureListSize
;
1856 KekDataSize
-= CertList
->SignatureListSize
;
1857 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1861 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1862 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
1863 if (EFI_ERROR (Status
)) {
1864 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1869 Status
= gRT
->SetVariable(
1870 EFI_KEY_EXCHANGE_KEY_NAME
,
1871 &gEfiGlobalVariableGuid
,
1876 if (EFI_ERROR (Status
)) {
1877 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
1886 if (OldData
!= NULL
) {
1890 return UpdateDeletePage (
1892 EFI_KEY_EXCHANGE_KEY_NAME
,
1893 &gEfiGlobalVariableGuid
,
1895 FORMID_DELETE_KEK_FORM
,
1896 OPTION_DEL_KEK_QUESTION_ID
1901 Delete a signature entry from siganture database.
1903 @param[in] PrivateData Module's private data.
1904 @param[in] VariableName The variable name of the vendor's signature database.
1905 @param[in] VendorGuid A unique identifier for the vendor.
1906 @param[in] LabelNumber Label number to insert opcodes.
1907 @param[in] FormId Form ID of current page.
1908 @param[in] QuestionIdBase Base question id of the signature list.
1909 @param[in] DeleteIndex Signature index to delete.
1911 @retval EFI_SUCCESS Delete siganture successfully.
1912 @retval EFI_NOT_FOUND Can't find the signature item,
1913 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1917 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1918 IN CHAR16
*VariableName
,
1919 IN EFI_GUID
*VendorGuid
,
1920 IN UINT16 LabelNumber
,
1921 IN EFI_FORM_ID FormId
,
1922 IN EFI_QUESTION_ID QuestionIdBase
,
1923 IN UINTN DeleteIndex
1932 EFI_SIGNATURE_LIST
*CertList
;
1933 EFI_SIGNATURE_LIST
*NewCertList
;
1934 EFI_SIGNATURE_DATA
*Cert
;
1937 BOOLEAN IsItemFound
;
1938 UINT32 ItemDataSize
;
1948 // Get original signature list data.
1951 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
1952 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1956 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
1957 if (OldData
== NULL
) {
1958 Status
= EFI_OUT_OF_RESOURCES
;
1962 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
1963 if (EFI_ERROR(Status
)) {
1968 // Allocate space for new variable.
1970 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1972 Status
= EFI_OUT_OF_RESOURCES
;
1977 // Enumerate all signature data and erasing the target item.
1979 IsItemFound
= FALSE
;
1980 ItemDataSize
= (UINT32
) DataSize
;
1981 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1984 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1985 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1986 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
1987 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
1988 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)
1991 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
1993 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1994 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
1995 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1996 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1997 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1998 for (Index
= 0; Index
< CertCount
; Index
++) {
1999 if (GuidIndex
== DeleteIndex
) {
2001 // Find it! Skip it!
2003 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2007 // This item doesn't match. Copy it to the Data buffer.
2009 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2010 Offset
+= CertList
->SignatureSize
;
2013 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2017 // This List doesn't match. Just copy it to the Data buffer.
2019 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2020 Offset
+= CertList
->SignatureListSize
;
2023 ItemDataSize
-= CertList
->SignatureListSize
;
2024 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2029 // Doesn't find the signature Item!
2031 Status
= EFI_NOT_FOUND
;
2036 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2038 ItemDataSize
= Offset
;
2039 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2041 ZeroMem (OldData
, ItemDataSize
);
2042 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2043 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2044 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
2045 if (CertCount
!= 0) {
2046 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2047 Offset
+= CertList
->SignatureListSize
;
2049 ItemDataSize
-= CertList
->SignatureListSize
;
2050 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2054 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2055 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2056 if (EFI_ERROR (Status
)) {
2057 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2062 Status
= gRT
->SetVariable(
2069 if (EFI_ERROR (Status
)) {
2070 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2079 if (OldData
!= NULL
) {
2083 return UpdateDeletePage (
2094 This function extracts configuration from variable.
2096 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2100 SecureBootExtractConfigFromVariable (
2101 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2104 UINT8
*SecureBootEnable
;
2107 UINT8
*SecureBootMode
;
2109 SecureBootEnable
= NULL
;
2112 SecureBootMode
= NULL
;
2115 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2118 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2119 if (SecureBootEnable
== NULL
) {
2120 ConfigData
->HideSecureBoot
= TRUE
;
2122 ConfigData
->HideSecureBoot
= FALSE
;
2126 // If it is Physical Presence User, set the PhysicalPresent to true.
2128 if (UserPhysicalPresent()) {
2129 ConfigData
->PhysicalPresent
= TRUE
;
2131 ConfigData
->PhysicalPresent
= FALSE
;
2135 // If there is no PK then the Delete Pk button will be gray.
2137 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2138 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2139 ConfigData
->HasPk
= FALSE
;
2141 ConfigData
->HasPk
= TRUE
;
2145 // If the value of SecureBoot variable is 1, the platform is operating in secure boot mode.
2147 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2148 if (SecureBoot
!= NULL
&& *SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2149 ConfigData
->SecureBootState
= TRUE
;
2151 ConfigData
->SecureBootState
= FALSE
;
2155 // Get the SecureBootMode from CustomMode variable.
2157 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2158 if (SecureBootMode
== NULL
) {
2159 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2161 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2167 This function allows a caller to extract the current configuration for one
2168 or more named elements from the target driver.
2170 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2171 @param[in] Request A null-terminated Unicode string in
2172 <ConfigRequest> format.
2173 @param[out] Progress On return, points to a character in the Request
2174 string. Points to the string's null terminator if
2175 request was successful. Points to the most recent
2176 '&' before the first failing name/value pair (or
2177 the beginning of the string if the failure is in
2178 the first name/value pair) if the request was not
2180 @param[out] Results A null-terminated Unicode string in
2181 <ConfigAltResp> format which has all values filled
2182 in for the names in the Request string. String to
2183 be allocated by the called function.
2185 @retval EFI_SUCCESS The Results is filled with the requested values.
2186 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2187 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2188 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2194 SecureBootExtractConfig (
2195 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2196 IN CONST EFI_STRING Request
,
2197 OUT EFI_STRING
*Progress
,
2198 OUT EFI_STRING
*Results
2204 SECUREBOOT_CONFIGURATION Configuration
;
2205 EFI_STRING ConfigRequest
;
2206 EFI_STRING ConfigRequestHdr
;
2207 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2208 BOOLEAN AllocatedRequest
;
2210 if (Progress
== NULL
|| Results
== NULL
) {
2211 return EFI_INVALID_PARAMETER
;
2214 AllocatedRequest
= FALSE
;
2215 ConfigRequestHdr
= NULL
;
2216 ConfigRequest
= NULL
;
2219 ZeroMem (&Configuration
, sizeof (Configuration
));
2220 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2221 *Progress
= Request
;
2223 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2224 return EFI_NOT_FOUND
;
2228 // Get Configuration from Variable.
2230 SecureBootExtractConfigFromVariable (&Configuration
);
2232 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2233 ConfigRequest
= Request
;
2234 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2236 // Request is set to NULL or OFFSET is NULL, construct full request string.
2238 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2239 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2241 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2242 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2243 ConfigRequest
= AllocateZeroPool (Size
);
2244 ASSERT (ConfigRequest
!= NULL
);
2245 AllocatedRequest
= TRUE
;
2246 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2247 FreePool (ConfigRequestHdr
);
2248 ConfigRequestHdr
= NULL
;
2251 Status
= gHiiConfigRouting
->BlockToConfig (
2254 (UINT8
*) &Configuration
,
2261 // Free the allocated config request string.
2263 if (AllocatedRequest
) {
2264 FreePool (ConfigRequest
);
2268 // Set Progress string to the original request string.
2270 if (Request
== NULL
) {
2272 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2273 *Progress
= Request
+ StrLen (Request
);
2280 This function processes the results of changes in configuration.
2282 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2283 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2285 @param[out] Progress A pointer to a string filled in with the offset of
2286 the most recent '&' before the first failing
2287 name/value pair (or the beginning of the string if
2288 the failure is in the first name/value pair) or
2289 the terminating NULL if all was successful.
2291 @retval EFI_SUCCESS The Results is processed successfully.
2292 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2293 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2299 SecureBootRouteConfig (
2300 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2301 IN CONST EFI_STRING Configuration
,
2302 OUT EFI_STRING
*Progress
2305 if (Configuration
== NULL
|| Progress
== NULL
) {
2306 return EFI_INVALID_PARAMETER
;
2309 *Progress
= Configuration
;
2310 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2311 return EFI_NOT_FOUND
;
2314 *Progress
= Configuration
+ StrLen (Configuration
);
2319 This function is called to provide results data to the driver.
2321 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2322 @param[in] Action Specifies the type of action taken by the browser.
2323 @param[in] QuestionId A unique value which is sent to the original
2324 exporting driver so that it can identify the type
2326 @param[in] Type The type of value for the question.
2327 @param[in] Value A pointer to the data being sent to the original
2329 @param[out] ActionRequest On return, points to the action requested by the
2332 @retval EFI_SUCCESS The callback successfully handled the action.
2333 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2334 variable and its data.
2335 @retval EFI_DEVICE_ERROR The variable could not be saved.
2336 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2342 SecureBootCallback (
2343 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2344 IN EFI_BROWSER_ACTION Action
,
2345 IN EFI_QUESTION_ID QuestionId
,
2347 IN EFI_IFR_TYPE_VALUE
*Value
,
2348 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2353 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
2355 SECUREBOOT_CONFIGURATION
*IfrNvData
;
2357 UINT8
*SecureBootEnable
;
2358 CHAR16 PromptString
[100];
2360 SecureBootEnable
= NULL
;
2362 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
2363 return EFI_INVALID_PARAMETER
;
2366 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) && (Action
!= EFI_BROWSER_ACTION_CHANGING
)) {
2367 return EFI_UNSUPPORTED
;
2370 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2373 // Retrieve uncommitted data from Browser
2375 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2376 IfrNvData
= AllocateZeroPool (BufferSize
);
2377 if (IfrNvData
== NULL
) {
2378 return EFI_OUT_OF_RESOURCES
;
2381 Status
= EFI_SUCCESS
;
2383 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2385 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2387 switch (QuestionId
) {
2388 case KEY_SECURE_BOOT_ENABLE
:
2389 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2390 if (NULL
!= SecureBootEnable
) {
2391 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
2393 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2395 L
"Only Physical Presence User could disable secure boot!",
2398 Status
= EFI_UNSUPPORTED
;
2400 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2404 case KEY_SECURE_BOOT_OPTION
:
2405 FreeMenu (&DirectoryMenu
);
2406 FreeMenu (&FsOptionMenu
);
2409 case KEY_SECURE_BOOT_KEK_OPTION
:
2410 case KEY_SECURE_BOOT_DB_OPTION
:
2411 case KEY_SECURE_BOOT_DBX_OPTION
:
2413 // Clear Signature GUID.
2415 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
2416 if (Private
->SignatureGUID
== NULL
) {
2417 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
2418 if (Private
->SignatureGUID
== NULL
) {
2419 return EFI_OUT_OF_RESOURCES
;
2423 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
2424 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
2425 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
2426 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
2428 LabelId
= FORMID_ENROLL_KEK_FORM
;
2432 // Refresh selected file.
2434 CleanUpPage (LabelId
, Private
);
2437 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
2438 case FORMID_ENROLL_KEK_FORM
:
2439 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
2440 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
2441 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
2442 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
2443 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
2444 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
2445 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
2446 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
2448 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
2451 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2452 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
2453 UpdateFileExplorer (Private
, 0);
2456 case KEY_SECURE_BOOT_DELETE_PK
:
2458 Status
= DeletePlatformKey ();
2459 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2463 case KEY_DELETE_KEK
:
2466 EFI_KEY_EXCHANGE_KEY_NAME
,
2467 &gEfiGlobalVariableGuid
,
2469 FORMID_DELETE_KEK_FORM
,
2470 OPTION_DEL_KEK_QUESTION_ID
2474 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
2477 EFI_IMAGE_SECURITY_DATABASE
,
2478 &gEfiImageSecurityDatabaseGuid
,
2480 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2481 OPTION_DEL_DB_QUESTION_ID
2485 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
2488 EFI_IMAGE_SECURITY_DATABASE1
,
2489 &gEfiImageSecurityDatabaseGuid
,
2491 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2492 OPTION_DEL_DBX_QUESTION_ID
2497 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
2498 Status
= EnrollKeyExchangeKey (Private
);
2501 case KEY_VALUE_SAVE_AND_EXIT_DB
:
2502 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
2505 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
2506 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
2510 if (QuestionId
>= FILE_OPTION_OFFSET
) {
2511 UpdateFileExplorer (Private
, QuestionId
);
2512 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
2513 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2514 DeleteKeyExchangeKey (Private
, QuestionId
);
2515 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
2516 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2519 EFI_IMAGE_SECURITY_DATABASE
,
2520 &gEfiImageSecurityDatabaseGuid
,
2522 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2523 OPTION_DEL_DB_QUESTION_ID
,
2524 QuestionId
- OPTION_DEL_DB_QUESTION_ID
2526 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
2527 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2530 EFI_IMAGE_SECURITY_DATABASE1
,
2531 &gEfiImageSecurityDatabaseGuid
,
2533 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2534 OPTION_DEL_DBX_QUESTION_ID
,
2535 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
2540 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2541 switch (QuestionId
) {
2542 case KEY_SECURE_BOOT_ENABLE
:
2543 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2545 case KEY_VALUE_SAVE_AND_EXIT_PK
:
2546 Status
= EnrollPlatformKey (Private
);
2549 sizeof (PromptString
),
2550 L
"Only DER encoded certificate file (%s) is supported.",
2553 if (EFI_ERROR (Status
)) {
2555 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2557 L
"ERROR: Unsupported file type!",
2562 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2566 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
2567 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
2568 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
2569 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
2570 if (Private
->FileContext
->FHandle
!= NULL
) {
2571 CloseFile (Private
->FileContext
->FHandle
);
2572 Private
->FileContext
->FHandle
= NULL
;
2573 Private
->FileContext
->FileName
= NULL
;
2576 if (Private
->SignatureGUID
!= NULL
) {
2577 FreePool (Private
->SignatureGUID
);
2578 Private
->SignatureGUID
= NULL
;
2580 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2583 case KEY_SECURE_BOOT_MODE
:
2584 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2585 if (NULL
!= SecureBootEnable
) {
2586 Status
= gRT
->SetVariable (
2587 EFI_CUSTOM_MODE_NAME
,
2588 &gEfiCustomModeEnableGuid
,
2589 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2593 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2594 IfrNvData
->SecureBootMode
= Value
->u8
;
2598 case KEY_SECURE_BOOT_KEK_GUID
:
2599 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
2600 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
2601 ASSERT (Private
->SignatureGUID
!= NULL
);
2602 Status
= StringToGuid (
2603 IfrNvData
->SignatureGuid
,
2604 StrLen (IfrNvData
->SignatureGuid
),
2605 Private
->SignatureGUID
2607 if (EFI_ERROR (Status
)) {
2611 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2614 case KEY_SECURE_BOOT_DELETE_PK
:
2616 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2622 if (!EFI_ERROR (Status
)) {
2623 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2624 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2626 FreePool (IfrNvData
);
2632 This function publish the SecureBoot configuration Form.
2634 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2636 @retval EFI_SUCCESS HII Form is installed successfully.
2637 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2638 @retval Others Other errors as indicated.
2642 InstallSecureBootConfigForm (
2643 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2647 EFI_HII_HANDLE HiiHandle
;
2648 EFI_HANDLE DriverHandle
;
2649 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2651 DriverHandle
= NULL
;
2652 ConfigAccess
= &PrivateData
->ConfigAccess
;
2653 Status
= gBS
->InstallMultipleProtocolInterfaces (
2655 &gEfiDevicePathProtocolGuid
,
2656 &mSecureBootHiiVendorDevicePath
,
2657 &gEfiHiiConfigAccessProtocolGuid
,
2661 if (EFI_ERROR (Status
)) {
2665 PrivateData
->DriverHandle
= DriverHandle
;
2668 // Publish the HII package list
2670 HiiHandle
= HiiAddPackages (
2671 &gSecureBootConfigFormSetGuid
,
2673 SecureBootConfigDxeStrings
,
2674 SecureBootConfigBin
,
2677 if (HiiHandle
== NULL
) {
2678 gBS
->UninstallMultipleProtocolInterfaces (
2680 &gEfiDevicePathProtocolGuid
,
2681 &mSecureBootHiiVendorDevicePath
,
2682 &gEfiHiiConfigAccessProtocolGuid
,
2686 return EFI_OUT_OF_RESOURCES
;
2689 PrivateData
->HiiHandle
= HiiHandle
;
2691 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
2692 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
2694 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
2695 UninstallSecureBootConfigForm (PrivateData
);
2696 return EFI_OUT_OF_RESOURCES
;
2699 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
2700 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2702 InitializeListHead (&FsOptionMenu
.Head
);
2703 InitializeListHead (&DirectoryMenu
.Head
);
2706 // Init OpCode Handle and Allocate space for creation of Buffer
2708 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2709 if (mStartOpCodeHandle
== NULL
) {
2710 UninstallSecureBootConfigForm (PrivateData
);
2711 return EFI_OUT_OF_RESOURCES
;
2714 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2715 if (mEndOpCodeHandle
== NULL
) {
2716 UninstallSecureBootConfigForm (PrivateData
);
2717 return EFI_OUT_OF_RESOURCES
;
2721 // Create Hii Extend Label OpCode as the start opcode
2723 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2727 sizeof (EFI_IFR_GUID_LABEL
)
2729 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2732 // Create Hii Extend Label OpCode as the end opcode
2734 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2738 sizeof (EFI_IFR_GUID_LABEL
)
2740 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2741 mEndLabel
->Number
= LABEL_END
;
2747 This function removes SecureBoot configuration Form.
2749 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2753 UninstallSecureBootConfigForm (
2754 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2758 // Uninstall HII package list
2760 if (PrivateData
->HiiHandle
!= NULL
) {
2761 HiiRemovePackages (PrivateData
->HiiHandle
);
2762 PrivateData
->HiiHandle
= NULL
;
2766 // Uninstall HII Config Access Protocol
2768 if (PrivateData
->DriverHandle
!= NULL
) {
2769 gBS
->UninstallMultipleProtocolInterfaces (
2770 PrivateData
->DriverHandle
,
2771 &gEfiDevicePathProtocolGuid
,
2772 &mSecureBootHiiVendorDevicePath
,
2773 &gEfiHiiConfigAccessProtocolGuid
,
2774 &PrivateData
->ConfigAccess
,
2777 PrivateData
->DriverHandle
= NULL
;
2780 if (PrivateData
->SignatureGUID
!= NULL
) {
2781 FreePool (PrivateData
->SignatureGUID
);
2784 if (PrivateData
->MenuEntry
!= NULL
) {
2785 FreePool (PrivateData
->MenuEntry
);
2788 if (PrivateData
->FileContext
!= NULL
) {
2789 FreePool (PrivateData
->FileContext
);
2792 FreePool (PrivateData
);
2794 FreeMenu (&DirectoryMenu
);
2795 FreeMenu (&FsOptionMenu
);
2797 if (mStartOpCodeHandle
!= NULL
) {
2798 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
2801 if (mEndOpCodeHandle
!= NULL
) {
2802 HiiFreeOpCodeHandle (mEndOpCodeHandle
);