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
73 UINT32 mPeCoffHeaderOffset
= 0;
74 WIN_CERTIFICATE
*mCertificate
= NULL
;
75 IMAGE_TYPE mImageType
;
76 UINT8
*mImageBase
= NULL
;
78 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
79 UINTN mImageDigestSize
;
81 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
82 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
86 Set Secure Boot option into variable space.
88 @param[in] VarValue The option of Secure Boot.
90 @retval EFI_SUCCESS The operation is finished successfully.
91 @retval Others Other errors as indicated.
95 SaveSecureBootVariable (
101 Status
= gRT
->SetVariable (
102 EFI_SECURE_BOOT_ENABLE_NAME
,
103 &gEfiSecureBootEnableDisableGuid
,
104 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
112 Internal helper function to delete a Variable given its name and GUID, NO authentication
115 @param[in] VariableName Name of the Variable.
116 @param[in] VendorGuid GUID of the Variable.
118 @retval EFI_SUCCESS Variable deleted successfully.
119 @retval Others The driver failed to start the device.
124 IN CHAR16
*VariableName
,
125 IN EFI_GUID
*VendorGuid
131 Variable
= GetVariable (VariableName
, VendorGuid
);
132 if (Variable
== NULL
) {
136 Status
= gRT
->SetVariable (
139 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
147 Generate a PK signature list from the public key storing file (*.pbk).
149 @param[in] PkKeyFile FileHandle of the public key storing file.
150 @param[out] PkCert Point to the data buffer to store the signature list.
152 @return EFI_UNSUPPORTED Unsupported Key Length.
153 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
157 CreatePkRsaSignatureList (
158 IN EFI_FILE_HANDLE PkKeyFile
,
159 OUT EFI_SIGNATURE_LIST
**PkCert
165 CPL_KEY_INFO
*KeyInfo
;
166 EFI_SIGNATURE_DATA
*PkCertData
;
173 Status
= EFI_SUCCESS
;
176 // Get key from PK key file
178 Status
= ReadFileContent (PkKeyFile
, &KeyBlob
, &KeyBlobSize
, 0);
179 if (EFI_ERROR(Status
)) {
180 DEBUG ((EFI_D_ERROR
, "Can't Open the file for PK enrolling.\n"));
183 ASSERT (KeyBlob
!= NULL
);
185 KeyInfo
= (CPL_KEY_INFO
*)KeyBlob
;
186 if (KeyInfo
->KeyLengthInBits
/8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
187 Status
= EFI_UNSUPPORTED
;
192 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
194 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
195 KeyBuffer
= AllocateZeroPool(KeyLenInBytes
);
196 if (KeyBuffer
== NULL
) {
197 Status
= EFI_OUT_OF_RESOURCES
;
200 Status
= Int2OctStr (
201 (UINTN
*) ((UINTN
)KeyBlob
+ sizeof(CPL_KEY_INFO
)),
202 KeyLenInBytes
/ sizeof (UINTN
),
206 if (EFI_ERROR(Status
)) {
210 // Allocate space for PK certificate list and initialize the list.
211 // Create PK database entry with SignatureHeaderSize equals 0.
213 *PkCert
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool(
214 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
215 + WIN_CERT_UEFI_RSA2048_SIZE
218 if (*PkCert
== NULL
) {
219 Status
= EFI_OUT_OF_RESOURCES
;
223 (*PkCert
)->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
224 + sizeof(EFI_SIGNATURE_DATA
) - 1
225 + WIN_CERT_UEFI_RSA2048_SIZE
;
226 (*PkCert
)->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
227 (*PkCert
)->SignatureHeaderSize
= 0;
228 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertRsa2048Guid
);
230 PkCertData
= (EFI_SIGNATURE_DATA
*)((UINTN
)(*PkCert
)
231 + sizeof(EFI_SIGNATURE_LIST
)
232 + (*PkCert
)->SignatureHeaderSize
);
233 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
235 // Fill the PK database with PKpub data from PKKeyFile.
237 CopyMem (&(PkCertData
->SignatureData
[0]), KeyBuffer
, WIN_CERT_UEFI_RSA2048_SIZE
);
241 if (KeyBlob
!= NULL
) {
245 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
250 if (KeyBuffer
!= NULL
) {
251 FreePool (KeyBuffer
);
258 Generate the PK signature list from the X509 Certificate storing file (.cer)
260 @param[in] X509File FileHandle of X509 Certificate storing file.
261 @param[out] PkCert Point to the data buffer to store the signature list.
263 @return EFI_UNSUPPORTED Unsupported Key Length.
264 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
268 CreatePkX509SignatureList (
269 IN EFI_FILE_HANDLE X509File
,
270 OUT EFI_SIGNATURE_LIST
**PkCert
276 EFI_SIGNATURE_DATA
*PkCertData
;
282 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
283 if (EFI_ERROR (Status
)) {
286 ASSERT (X509Data
!= NULL
);
289 // Allocate space for PK certificate list and initialize it.
290 // Create PK database entry with SignatureHeaderSize equals 0.
292 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
293 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
296 if (*PkCert
== NULL
) {
297 Status
= EFI_OUT_OF_RESOURCES
;
301 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
302 + sizeof(EFI_SIGNATURE_DATA
) - 1
304 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
305 (*PkCert
)->SignatureHeaderSize
= 0;
306 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
307 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
308 + sizeof(EFI_SIGNATURE_LIST
)
309 + (*PkCert
)->SignatureHeaderSize
);
310 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
312 // Fill the PK database with PKpub data from X509 certificate file.
314 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
318 if (X509Data
!= NULL
) {
322 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
331 Enroll new PK into the System without original PK's authentication.
333 The SignatureOwner GUID will be the same with PK's vendorguid.
335 @param[in] PrivateData The module's private data.
337 @retval EFI_SUCCESS New PK enrolled successfully.
338 @retval EFI_INVALID_PARAMETER The parameter is invalid.
339 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
344 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
350 EFI_SIGNATURE_LIST
*PkCert
;
353 if (Private
->FileContext
->FileName
== NULL
) {
354 return EFI_INVALID_PARAMETER
;
360 // Parse the file's postfix. Only support *.pbk(RSA2048) and *.cer(X509) files.
362 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
363 if (CompareMem (FilePostFix
, L
".pbk",4) && CompareMem (FilePostFix
, L
".cer",4)) {
364 DEBUG ((EFI_D_ERROR
, "Don't support the file, only *.pbk or *.cer.\n is supported."));
365 return EFI_INVALID_PARAMETER
;
367 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
368 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
371 // Prase the selected PK file and generature PK certificate list.
373 if (!CompareMem (FilePostFix
, L
".pbk",4)) {
374 Status
= CreatePkRsaSignatureList (
375 Private
->FileContext
->FHandle
,
378 if (EFI_ERROR (Status
)) {
381 } else if (!CompareMem (FilePostFix
, L
".cer",4)) {
382 Status
= CreatePkX509SignatureList (
383 Private
->FileContext
->FHandle
,
386 if (EFI_ERROR (Status
)) {
390 ASSERT (PkCert
!= NULL
);
393 // Set Platform Key variable.
395 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
396 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
397 DataSize
= PkCert
->SignatureListSize
;
398 Status
= gRT
->SetVariable(
399 EFI_PLATFORM_KEY_NAME
,
400 &gEfiGlobalVariableGuid
,
405 if (EFI_ERROR (Status
)) {
406 if (Status
== EFI_OUT_OF_RESOURCES
) {
407 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
414 if (PkCert
!= NULL
) {
418 if (Private
->FileContext
->FHandle
!= NULL
) {
419 CloseFile (Private
->FileContext
->FHandle
);
420 Private
->FileContext
->FHandle
= NULL
;
427 Remove the PK variable.
429 @retval EFI_SUCCESS Delete PK successfully.
430 @retval Others Could not allow to delete PK.
440 Status
= DeleteVariable (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
);
446 Enroll a new KEK item from public key storing file (*.pbk).
448 @param[in] PrivateData The module's private data.
450 @retval EFI_SUCCESS New KEK enrolled successfully.
451 @retval EFI_INVALID_PARAMETER The parameter is invalid.
452 @retval EFI_UNSUPPORTED Unsupported command.
453 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
458 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
464 EFI_SIGNATURE_LIST
*KekSigList
;
467 CPL_KEY_INFO
*KeyInfo
;
468 EFI_SIGNATURE_DATA
*KEKSigData
;
469 UINTN KekSigListSize
;
484 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
485 // First, We have to parse out public key data from the pbk key file.
487 Status
= ReadFileContent (
488 Private
->FileContext
->FHandle
,
493 if (EFI_ERROR (Status
)) {
496 ASSERT (KeyBlob
!= NULL
);
497 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
498 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
499 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
500 Status
= EFI_UNSUPPORTED
;
505 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
507 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
508 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
509 if (KeyBuffer
== NULL
) {
510 Status
= EFI_OUT_OF_RESOURCES
;
514 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
515 KeyLenInBytes
/ sizeof (UINTN
),
519 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
522 // Form an new EFI_SIGNATURE_LIST.
524 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
525 + sizeof(EFI_SIGNATURE_DATA
) - 1
526 + WIN_CERT_UEFI_RSA2048_SIZE
;
528 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
529 if (KekSigList
== NULL
) {
530 Status
= EFI_OUT_OF_RESOURCES
;
534 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
535 + sizeof(EFI_SIGNATURE_DATA
) - 1
536 + WIN_CERT_UEFI_RSA2048_SIZE
;
537 KekSigList
->SignatureHeaderSize
= 0;
538 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
539 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
541 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
542 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
544 KEKSigData
->SignatureData
,
545 KeyBlob
+ sizeof(CPL_KEY_INFO
),
546 WIN_CERT_UEFI_RSA2048_SIZE
550 // Check if KEK entry has been already existed.
551 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
552 // new KEK to original variable.
554 Attr
|= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
;
556 Status
= gRT
->GetVariable(
557 EFI_KEY_EXCHANGE_KEY_NAME
,
558 &gEfiGlobalVariableGuid
,
563 if (Status
== EFI_BUFFER_TOO_SMALL
) {
564 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
565 } else if (Status
!= EFI_NOT_FOUND
) {
570 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
572 Status
= gRT
->SetVariable(
573 EFI_KEY_EXCHANGE_KEY_NAME
,
574 &gEfiGlobalVariableGuid
,
579 if (EFI_ERROR (Status
)) {
585 CloseFile (Private
->FileContext
->FHandle
);
586 Private
->FileContext
->FHandle
= NULL
;
587 Private
->FileContext
->FileName
= NULL
;
589 if (Private
->SignatureGUID
!= NULL
) {
590 FreePool (Private
->SignatureGUID
);
591 Private
->SignatureGUID
= NULL
;
594 if (KeyBlob
!= NULL
) {
597 if (KeyBuffer
!= NULL
) {
598 FreePool (KeyBuffer
);
600 if (KekSigList
!= NULL
) {
601 FreePool (KekSigList
);
608 Enroll a new KEK item from X509 certificate file.
610 @param[in] PrivateData The module's private data.
612 @retval EFI_SUCCESS New X509 is enrolled successfully.
613 @retval EFI_INVALID_PARAMETER The parameter is invalid.
614 @retval EFI_UNSUPPORTED Unsupported command.
615 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
620 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
626 EFI_SIGNATURE_DATA
*KEKSigData
;
627 EFI_SIGNATURE_LIST
*KekSigList
;
629 UINTN KekSigListSize
;
639 Status
= ReadFileContent (
640 Private
->FileContext
->FHandle
,
645 if (EFI_ERROR (Status
)) {
648 ASSERT (X509Data
!= NULL
);
650 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
651 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
652 if (KekSigList
== NULL
) {
653 Status
= EFI_OUT_OF_RESOURCES
;
658 // Fill Certificate Database parameters.
660 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
661 KekSigList
->SignatureHeaderSize
= 0;
662 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
663 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
665 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
666 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
667 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
670 // Check if KEK been already existed.
671 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
672 // new kek to original variable
674 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
675 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
677 Status
= gRT
->GetVariable(
678 EFI_KEY_EXCHANGE_KEY_NAME
,
679 &gEfiGlobalVariableGuid
,
684 if (Status
== EFI_BUFFER_TOO_SMALL
) {
685 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
686 } else if (Status
!= EFI_NOT_FOUND
) {
690 Status
= gRT
->SetVariable(
691 EFI_KEY_EXCHANGE_KEY_NAME
,
692 &gEfiGlobalVariableGuid
,
697 if (EFI_ERROR (Status
)) {
703 CloseFile (Private
->FileContext
->FHandle
);
704 Private
->FileContext
->FileName
= NULL
;
705 Private
->FileContext
->FHandle
= NULL
;
707 if (Private
->SignatureGUID
!= NULL
) {
708 FreePool (Private
->SignatureGUID
);
709 Private
->SignatureGUID
= NULL
;
712 if (KekSigList
!= NULL
) {
713 FreePool (KekSigList
);
720 Enroll new KEK into the System without PK's authentication.
721 The SignatureOwner GUID will be Private->SignatureGUID.
723 @param[in] PrivateData The module's private data.
725 @retval EFI_SUCCESS New KEK enrolled successful.
726 @retval EFI_INVALID_PARAMETER The parameter is invalid.
727 @retval others Fail to enroll KEK data.
731 EnrollKeyExchangeKey (
732 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
737 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
738 return EFI_INVALID_PARAMETER
;
742 // Parse the file's postfix. Supports .cer and .der file as X509 certificate,
743 // and .pbk as RSA public key file.
745 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
746 if ((CompareMem (FilePostFix
, L
".cer",4) == 0) || (CompareMem (FilePostFix
, L
".der",4) == 0)) {
747 return EnrollX509ToKek (Private
);
748 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
749 return EnrollRsa2048ToKek (Private
);
751 return EFI_INVALID_PARAMETER
;
756 Enroll a new X509 certificate into Signature Database (DB or DBX) without
757 KEK's authentication.
759 @param[in] PrivateData The module's private data.
760 @param[in] VariableName Variable name of signature database, must be
761 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
763 @retval EFI_SUCCESS New X509 is enrolled successfully.
764 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
769 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
770 IN CHAR16
*VariableName
776 EFI_SIGNATURE_LIST
*SigDBCert
;
777 EFI_SIGNATURE_DATA
*SigDBCertData
;
788 SigDBCertData
= NULL
;
791 Status
= ReadFileContent (
792 Private
->FileContext
->FHandle
,
797 if (EFI_ERROR (Status
)) {
800 ASSERT (X509Data
!= NULL
);
802 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
804 Data
= AllocateZeroPool (SigDBSize
);
806 Status
= EFI_OUT_OF_RESOURCES
;
811 // Fill Certificate Database parameters.
813 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
814 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
815 SigDBCert
->SignatureHeaderSize
= 0;
816 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
817 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
819 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
820 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
821 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
824 // Check if signature database entry has been already existed.
825 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
826 // new signature data to original variable
828 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
829 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
831 Status
= gRT
->GetVariable(
833 &gEfiImageSecurityDatabaseGuid
,
838 if (Status
== EFI_BUFFER_TOO_SMALL
) {
839 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
840 } else if (Status
!= EFI_NOT_FOUND
) {
844 Status
= gRT
->SetVariable(
846 &gEfiImageSecurityDatabaseGuid
,
851 if (EFI_ERROR (Status
)) {
857 CloseFile (Private
->FileContext
->FHandle
);
858 Private
->FileContext
->FileName
= NULL
;
859 Private
->FileContext
->FHandle
= NULL
;
861 if (Private
->SignatureGUID
!= NULL
) {
862 FreePool (Private
->SignatureGUID
);
863 Private
->SignatureGUID
= NULL
;
870 if (X509Data
!= NULL
) {
878 Load PE/COFF image information into internal buffer and check its validity.
880 @retval EFI_SUCCESS Successful
881 @retval EFI_UNSUPPORTED Invalid PE/COFF file
882 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
890 EFI_IMAGE_DOS_HEADER
*DosHdr
;
891 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
892 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
897 // Read the Dos header
899 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
900 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
903 // DOS image header is present,
904 // So read the PE header after the DOS image header
906 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
910 mPeCoffHeaderOffset
= 0;
914 // Read PE header and check the signature validity and machine compatibility
916 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
917 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
919 return EFI_UNSUPPORTED
;
922 mNtHeader
.Pe32
= NtHeader32
;
925 // Check the architecture field of PE header and get the Certificate Data Directory data
926 // Note the size of FileHeader field is constant for both IA32 and X64 arch
928 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
929 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
931 // IA-32 Architecture
933 mImageType
= ImageType_IA32
;
934 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
936 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
937 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
939 // 64-bits Architecture
941 mImageType
= ImageType_X64
;
942 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
943 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
945 return EFI_UNSUPPORTED
;
952 Calculate hash of Pe/Coff image based on the authenticode image hashing in
953 PE/COFF Specification 8.0 Appendix A
955 @param[in] HashAlg Hash algorithm type.
957 @retval TRUE Successfully hash image.
958 @retval FALSE Fail in hash image.
968 EFI_IMAGE_SECTION_HEADER
*Section
;
973 UINTN SumOfBytesHashed
;
974 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
979 SectionHeader
= NULL
;
982 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
987 // Initialize context of hash.
989 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
991 if (HashAlg
== HASHALG_SHA1
) {
992 mImageDigestSize
= SHA1_DIGEST_SIZE
;
993 mCertType
= gEfiCertSha1Guid
;
994 } else if (HashAlg
== HASHALG_SHA256
) {
995 mImageDigestSize
= SHA256_DIGEST_SIZE
;
996 mCertType
= gEfiCertSha256Guid
;
999 CtxSize
= mHash
[HashAlg
].GetContextSize();
1001 HashCtx
= AllocatePool (CtxSize
);
1002 ASSERT (HashCtx
!= NULL
);
1004 // 1. Load the image header into memory.
1006 // 2. Initialize a SHA hash context.
1007 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1012 // Measuring PE/COFF Image Header;
1013 // But CheckSum field and SECURITY data directory (certificate) are excluded
1015 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1017 // 3. Calculate the distance from the base of the image header to the image checksum address.
1018 // 4. Hash the image header from its base to beginning of the image checksum.
1020 HashBase
= mImageBase
;
1021 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1025 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1028 // Use PE32+ offset.
1030 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1033 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1038 // 5. Skip over the image checksum (it occupies a single ULONG).
1039 // 6. Get the address of the beginning of the Cert Directory.
1040 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1042 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1046 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1047 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1050 // Use PE32+ offset.
1052 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1053 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1056 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1061 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1062 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1064 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1068 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1069 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1072 // Use PE32+ offset.
1074 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1075 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1078 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1083 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1085 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1089 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1094 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1098 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1099 // structures in the image. The 'NumberOfSections' field of the image
1100 // header indicates how big the table should be. Do not include any
1101 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1103 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1104 ASSERT (SectionHeader
!= NULL
);
1106 // 12. Using the 'PointerToRawData' in the referenced section headers as
1107 // a key, arrange the elements in the table in ascending order. In other
1108 // words, sort the section headers according to the disk-file offset of
1111 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1113 mPeCoffHeaderOffset
+
1115 sizeof (EFI_IMAGE_FILE_HEADER
) +
1116 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1118 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1120 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1121 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1124 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1129 // 13. Walk through the sorted table, bring the corresponding section
1130 // into memory, and hash the entire section (using the 'SizeOfRawData'
1131 // field in the section header to determine the amount of data to hash).
1132 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1133 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1135 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1136 Section
= &SectionHeader
[Index
];
1137 if (Section
->SizeOfRawData
== 0) {
1140 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1141 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1143 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1148 SumOfBytesHashed
+= HashSize
;
1152 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1153 // data in the file that needs to be added to the hash. This data begins
1154 // at file offset SUM_OF_BYTES_HASHED and its length is:
1155 // FileSize - (CertDirectory->Size)
1157 if (mImageSize
> SumOfBytesHashed
) {
1158 HashBase
= mImageBase
+ SumOfBytesHashed
;
1159 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1165 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1169 // Use PE32+ offset.
1173 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1177 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1183 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1186 if (HashCtx
!= NULL
) {
1189 if (SectionHeader
!= NULL
) {
1190 FreePool (SectionHeader
);
1196 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1197 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1200 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1201 @retval EFI_SUCCESS Hash successfully.
1210 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1212 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1214 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1216 // Check the Hash algorithm in PE/COFF Authenticode.
1217 // According to PKCS#7 Definition:
1218 // SignedData ::= SEQUENCE {
1220 // digestAlgorithms DigestAlgorithmIdentifiers,
1221 // contentInfo ContentInfo,
1223 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1224 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1225 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1227 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1229 // Only support two bytes of Long Form of Length Encoding.
1235 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1240 if (Index
== HASHALG_MAX
) {
1241 return EFI_UNSUPPORTED
;
1245 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1247 if (!HashPeImage(Index
)) {
1248 return EFI_UNSUPPORTED
;
1255 Enroll a new executable's signature into Signature Database.
1257 @param[in] PrivateData The module's private data.
1258 @param[in] VariableName Variable name of signature database, must be
1259 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1261 @retval EFI_SUCCESS New signature is enrolled successfully.
1262 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1263 @retval EFI_UNSUPPORTED Unsupported command.
1264 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1268 EnrollImageSignatureToSigDB (
1269 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1270 IN CHAR16
*VariableName
1274 EFI_SIGNATURE_LIST
*SigDBCert
;
1275 EFI_SIGNATURE_DATA
*SigDBCertData
;
1280 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
1283 GuidCertData
= NULL
;
1284 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1285 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
1288 // Form the SigDB certificate list.
1289 // Format the data item into EFI_SIGNATURE_LIST type.
1291 // We need to parse executable's signature data from specified signed executable file.
1292 // In current implementation, we simply trust the pass-in signed executable file.
1293 // In reality, it's OS's responsibility to verify the signed executable file.
1297 // Read the whole file content
1299 Status
= ReadFileContent(
1300 Private
->FileContext
->FHandle
,
1301 (VOID
**) &mImageBase
,
1305 if (EFI_ERROR (Status
)) {
1308 ASSERT (mImageBase
!= NULL
);
1310 Status
= LoadPeImage ();
1311 if (EFI_ERROR (Status
)) {
1315 if (mSecDataDir
->SizeOfCert
== 0) {
1316 if (!HashPeImage (HASHALG_SHA256
)) {
1317 Status
= EFI_SECURITY_VIOLATION
;
1323 // Read the certificate data
1325 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
1327 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1328 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
1329 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
1330 Status
= EFI_ABORTED
;
1334 if (!HashPeImage (HASHALG_SHA256
)) {
1335 Status
= EFI_ABORTED
;
1339 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1341 Status
= HashPeImageByType ();
1342 if (EFI_ERROR (Status
)) {
1346 Status
= EFI_ABORTED
;
1352 // Create a new SigDB entry.
1354 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
1355 + sizeof(EFI_SIGNATURE_DATA
) - 1
1356 + (UINT32
) mImageDigestSize
;
1358 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
1360 Status
= EFI_OUT_OF_RESOURCES
;
1365 // Adjust the Certificate Database parameters.
1367 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1368 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1369 SigDBCert
->SignatureHeaderSize
= 0;
1370 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
1371 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
1373 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
1374 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1375 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
1378 // Check if SigDB variable has been already existed.
1379 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1380 // new signature data to original variable
1383 Status
= gRT
->GetVariable(
1385 &gEfiImageSecurityDatabaseGuid
,
1390 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1391 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1392 } else if (Status
!= EFI_NOT_FOUND
) {
1397 // Enroll the variable.
1399 Status
= gRT
->SetVariable(
1401 &gEfiImageSecurityDatabaseGuid
,
1406 if (EFI_ERROR (Status
)) {
1412 CloseFile (Private
->FileContext
->FHandle
);
1413 Private
->FileContext
->FHandle
= NULL
;
1414 Private
->FileContext
->FileName
= NULL
;
1416 if (Private
->SignatureGUID
!= NULL
) {
1417 FreePool (Private
->SignatureGUID
);
1418 Private
->SignatureGUID
= NULL
;
1425 if (mImageBase
!= NULL
) {
1426 FreePool (mImageBase
);
1434 Enroll signature into DB/DBX without KEK's authentication.
1435 The SignatureOwner GUID will be Private->SignatureGUID.
1437 @param[in] PrivateData The module's private data.
1438 @param[in] VariableName Variable name of signature database, must be
1439 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1441 @retval EFI_SUCCESS New signature enrolled successfully.
1442 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1443 @retval others Fail to enroll signature data.
1447 EnrollSignatureDatabase (
1448 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1449 IN CHAR16
*VariableName
1452 UINT16
* FilePostFix
;
1454 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1455 return EFI_INVALID_PARAMETER
;
1459 // Parse the file's postfix.
1461 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
1462 if ((CompareMem (FilePostFix
, L
".cer",4) == 0) || (CompareMem (FilePostFix
, L
".der",4) == 0)) {
1464 // Supports .cer and .der file as X509 certificate.
1466 return EnrollX509toSigDB (Private
, VariableName
);
1469 return EnrollImageSignatureToSigDB (Private
, VariableName
);
1473 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1474 by GUID in the page for user to select and delete as needed.
1476 @param[in] PrivateData Module's private data.
1477 @param[in] VariableName The variable name of the vendor's signature database.
1478 @param[in] VendorGuid A unique identifier for the vendor.
1479 @param[in] LabelNumber Label number to insert opcodes.
1480 @param[in] FormId Form ID of current page.
1481 @param[in] QuestionIdBase Base question id of the signature list.
1483 @retval EFI_SUCCESS Success to update the signature list page
1484 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1489 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1490 IN CHAR16
*VariableName
,
1491 IN EFI_GUID
*VendorGuid
,
1492 IN UINT16 LabelNumber
,
1493 IN EFI_FORM_ID FormId
,
1494 IN EFI_QUESTION_ID QuestionIdBase
1501 VOID
*StartOpCodeHandle
;
1502 VOID
*EndOpCodeHandle
;
1503 EFI_IFR_GUID_LABEL
*StartLabel
;
1504 EFI_IFR_GUID_LABEL
*EndLabel
;
1507 EFI_SIGNATURE_LIST
*CertList
;
1508 EFI_SIGNATURE_DATA
*Cert
;
1509 UINT32 ItemDataSize
;
1511 EFI_STRING_ID GuidID
;
1518 StartOpCodeHandle
= NULL
;
1519 EndOpCodeHandle
= NULL
;
1522 // Initialize the container for dynamic opcodes.
1524 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1525 if (StartOpCodeHandle
== NULL
) {
1526 Status
= EFI_OUT_OF_RESOURCES
;
1530 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1531 if (EndOpCodeHandle
== NULL
) {
1532 Status
= EFI_OUT_OF_RESOURCES
;
1537 // Create Hii Extend Label OpCode.
1539 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1543 sizeof (EFI_IFR_GUID_LABEL
)
1545 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1546 StartLabel
->Number
= LabelNumber
;
1548 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1552 sizeof (EFI_IFR_GUID_LABEL
)
1554 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1555 EndLabel
->Number
= LABEL_END
;
1561 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1562 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1566 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1568 Status
= EFI_OUT_OF_RESOURCES
;
1572 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1573 if (EFI_ERROR (Status
)) {
1577 GuidStr
= AllocateZeroPool (100);
1578 if (GuidStr
== NULL
) {
1579 Status
= EFI_OUT_OF_RESOURCES
;
1584 // Enumerate all KEK pub data.
1586 ItemDataSize
= (UINT32
) DataSize
;
1587 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1590 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1592 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1593 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
1594 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1595 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
1596 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
1597 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
1598 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
1599 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
1602 // The signature type is not supported in current implementation.
1607 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1608 for (Index
= 0; Index
< CertCount
; Index
++) {
1609 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
1610 + sizeof (EFI_SIGNATURE_LIST
)
1611 + CertList
->SignatureHeaderSize
1612 + Index
* CertList
->SignatureSize
);
1614 // Display GUID and help
1616 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
1617 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
1618 HiiCreateCheckBoxOpCode (
1620 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
1625 EFI_IFR_FLAG_CALLBACK
,
1631 ItemDataSize
-= CertList
->SignatureListSize
;
1632 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1637 PrivateData
->HiiHandle
,
1638 &gSecureBootConfigFormSetGuid
,
1644 if (StartOpCodeHandle
!= NULL
) {
1645 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1648 if (EndOpCodeHandle
!= NULL
) {
1649 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1656 if (GuidStr
!= NULL
) {
1664 Delete a KEK entry from KEK database.
1666 @param[in] PrivateData Module's private data.
1667 @param[in] QuestionId Question id of the KEK item to delete.
1669 @retval EFI_SUCCESS Delete kek item successfully.
1670 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1674 DeleteKeyExchangeKey (
1675 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1676 IN EFI_QUESTION_ID QuestionId
1685 EFI_SIGNATURE_LIST
*CertList
;
1686 EFI_SIGNATURE_LIST
*NewCertList
;
1687 EFI_SIGNATURE_DATA
*Cert
;
1690 BOOLEAN IsKEKItemFound
;
1692 UINTN DeleteKekIndex
;
1700 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
1703 // Get original KEK variable.
1706 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
1707 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1711 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
1712 if (OldData
== NULL
) {
1713 Status
= EFI_OUT_OF_RESOURCES
;
1717 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
1718 if (EFI_ERROR(Status
)) {
1723 // Allocate space for new variable.
1725 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1727 Status
= EFI_OUT_OF_RESOURCES
;
1732 // Enumerate all KEK pub data and erasing the target item.
1734 IsKEKItemFound
= FALSE
;
1735 KekDataSize
= (UINT32
) DataSize
;
1736 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1739 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1740 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1741 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1742 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1743 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1744 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1745 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1746 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1747 for (Index
= 0; Index
< CertCount
; Index
++) {
1748 if (GuidIndex
== DeleteKekIndex
) {
1750 // Find it! Skip it!
1752 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1753 IsKEKItemFound
= TRUE
;
1756 // This item doesn't match. Copy it to the Data buffer.
1758 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
1759 Offset
+= CertList
->SignatureSize
;
1762 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1766 // This List doesn't match. Copy it to the Data buffer.
1768 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
1769 Offset
+= CertList
->SignatureListSize
;
1772 KekDataSize
-= CertList
->SignatureListSize
;
1773 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1776 if (!IsKEKItemFound
) {
1778 // Doesn't find the Kek Item!
1780 Status
= EFI_NOT_FOUND
;
1785 // Delete the Signature header if there is no signature in the list.
1787 KekDataSize
= Offset
;
1788 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1790 ZeroMem (OldData
, KekDataSize
);
1791 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1792 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1793 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1794 if (CertCount
!= 0) {
1795 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
1796 Offset
+= CertList
->SignatureListSize
;
1798 KekDataSize
-= CertList
->SignatureListSize
;
1799 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1802 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1805 Status
= gRT
->SetVariable(
1806 EFI_KEY_EXCHANGE_KEY_NAME
,
1807 &gEfiGlobalVariableGuid
,
1812 if (EFI_ERROR (Status
)) {
1813 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
1822 if (OldData
!= NULL
) {
1826 return UpdateDeletePage (
1828 EFI_KEY_EXCHANGE_KEY_NAME
,
1829 &gEfiGlobalVariableGuid
,
1831 FORMID_DELETE_KEK_FORM
,
1832 OPTION_DEL_KEK_QUESTION_ID
1837 Delete a signature entry from siganture database.
1839 @param[in] PrivateData Module's private data.
1840 @param[in] VariableName The variable name of the vendor's signature database.
1841 @param[in] VendorGuid A unique identifier for the vendor.
1842 @param[in] LabelNumber Label number to insert opcodes.
1843 @param[in] FormId Form ID of current page.
1844 @param[in] QuestionIdBase Base question id of the signature list.
1845 @param[in] DeleteIndex Signature index to delete.
1847 @retval EFI_SUCCESS Delete siganture successfully.
1848 @retval EFI_NOT_FOUND Can't find the signature item,
1849 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1853 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1854 IN CHAR16
*VariableName
,
1855 IN EFI_GUID
*VendorGuid
,
1856 IN UINT16 LabelNumber
,
1857 IN EFI_FORM_ID FormId
,
1858 IN EFI_QUESTION_ID QuestionIdBase
,
1859 IN UINTN DeleteIndex
1868 EFI_SIGNATURE_LIST
*CertList
;
1869 EFI_SIGNATURE_LIST
*NewCertList
;
1870 EFI_SIGNATURE_DATA
*Cert
;
1873 BOOLEAN IsItemFound
;
1874 UINT32 ItemDataSize
;
1884 // Get original signature list data.
1887 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
1888 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1892 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
1893 if (OldData
== NULL
) {
1894 Status
= EFI_OUT_OF_RESOURCES
;
1898 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
1899 if (EFI_ERROR(Status
)) {
1904 // Allocate space for new variable.
1906 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1908 Status
= EFI_OUT_OF_RESOURCES
;
1913 // Enumerate all signature data and erasing the target item.
1915 IsItemFound
= FALSE
;
1916 ItemDataSize
= (UINT32
) DataSize
;
1917 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1920 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1921 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1922 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
1923 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
1924 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)
1927 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
1929 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1930 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
1931 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1932 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1933 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1934 for (Index
= 0; Index
< CertCount
; Index
++) {
1935 if (GuidIndex
== DeleteIndex
) {
1937 // Find it! Skip it!
1939 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1943 // This item doesn't match. Copy it to the Data buffer.
1945 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
1946 Offset
+= CertList
->SignatureSize
;
1949 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1953 // This List doesn't match. Just copy it to the Data buffer.
1955 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
1956 Offset
+= CertList
->SignatureListSize
;
1959 ItemDataSize
-= CertList
->SignatureListSize
;
1960 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1965 // Doesn't find the signature Item!
1967 Status
= EFI_NOT_FOUND
;
1972 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
1974 ItemDataSize
= Offset
;
1975 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1977 ZeroMem (OldData
, ItemDataSize
);
1978 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1979 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1980 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1981 if (CertCount
!= 0) {
1982 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
1983 Offset
+= CertList
->SignatureListSize
;
1985 ItemDataSize
-= CertList
->SignatureListSize
;
1986 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1989 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1992 Status
= gRT
->SetVariable(
1999 if (EFI_ERROR (Status
)) {
2000 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2009 if (OldData
!= NULL
) {
2013 return UpdateDeletePage (
2024 This function extracts configuration from variable.
2026 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2030 SecureBootExtractConfigFromVariable (
2031 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2034 UINT8
*SecureBootEnable
;
2036 UINT8
*SecureBootMode
;
2038 SecureBootEnable
= NULL
;
2040 SecureBootMode
= NULL
;
2043 // Get the SecureBootEnable Variable
2045 SecureBootEnable
= GetVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
);
2048 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2051 if (SecureBootEnable
== NULL
) {
2052 ConfigData
->HideSecureBoot
= TRUE
;
2054 ConfigData
->HideSecureBoot
= FALSE
;
2055 ConfigData
->SecureBootState
= *SecureBootEnable
;
2058 // If it is Physical Presence User, set the PhysicalPresent to true.
2060 if (UserPhysicalPresent()) {
2061 ConfigData
->PhysicalPresent
= TRUE
;
2063 ConfigData
->PhysicalPresent
= FALSE
;
2067 // If there is no PK then the Delete Pk button will be gray.
2069 SetupMode
= GetVariable (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
);
2070 if (SetupMode
== NULL
|| (*SetupMode
) == 1) {
2071 ConfigData
->HasPk
= FALSE
;
2073 ConfigData
->HasPk
= TRUE
;
2077 // Get the SecureBootMode from CustomMode variable.
2079 SecureBootMode
= GetVariable (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
);
2080 if (SecureBootMode
== NULL
) {
2081 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2083 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2089 This function allows a caller to extract the current configuration for one
2090 or more named elements from the target driver.
2092 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2093 @param[in] Request A null-terminated Unicode string in
2094 <ConfigRequest> format.
2095 @param[out] Progress On return, points to a character in the Request
2096 string. Points to the string's null terminator if
2097 request was successful. Points to the most recent
2098 '&' before the first failing name/value pair (or
2099 the beginning of the string if the failure is in
2100 the first name/value pair) if the request was not
2102 @param[out] Results A null-terminated Unicode string in
2103 <ConfigAltResp> format which has all values filled
2104 in for the names in the Request string. String to
2105 be allocated by the called function.
2107 @retval EFI_SUCCESS The Results is filled with the requested values.
2108 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2109 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2110 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2116 SecureBootExtractConfig (
2117 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2118 IN CONST EFI_STRING Request
,
2119 OUT EFI_STRING
*Progress
,
2120 OUT EFI_STRING
*Results
2126 SECUREBOOT_CONFIGURATION Configuration
;
2127 EFI_STRING ConfigRequest
;
2128 EFI_STRING ConfigRequestHdr
;
2129 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2130 BOOLEAN AllocatedRequest
;
2132 if (Progress
== NULL
|| Results
== NULL
) {
2133 return EFI_INVALID_PARAMETER
;
2136 AllocatedRequest
= FALSE
;
2137 ConfigRequestHdr
= NULL
;
2138 ConfigRequest
= NULL
;
2141 ZeroMem (&Configuration
, sizeof (Configuration
));
2142 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2143 *Progress
= Request
;
2145 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2146 return EFI_NOT_FOUND
;
2150 // Get Configuration from Variable.
2152 SecureBootExtractConfigFromVariable (&Configuration
);
2154 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2155 ConfigRequest
= Request
;
2156 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2158 // Request is set to NULL or OFFSET is NULL, construct full request string.
2160 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2161 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2163 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2164 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2165 ConfigRequest
= AllocateZeroPool (Size
);
2166 ASSERT (ConfigRequest
!= NULL
);
2167 AllocatedRequest
= TRUE
;
2168 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2169 FreePool (ConfigRequestHdr
);
2170 ConfigRequestHdr
= NULL
;
2173 Status
= gHiiConfigRouting
->BlockToConfig (
2176 (UINT8
*) &Configuration
,
2183 // Free the allocated config request string.
2185 if (AllocatedRequest
) {
2186 FreePool (ConfigRequest
);
2190 // Set Progress string to the original request string.
2192 if (Request
== NULL
) {
2194 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2195 *Progress
= Request
+ StrLen (Request
);
2202 This function processes the results of changes in configuration.
2204 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2205 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2207 @param[out] Progress A pointer to a string filled in with the offset of
2208 the most recent '&' before the first failing
2209 name/value pair (or the beginning of the string if
2210 the failure is in the first name/value pair) or
2211 the terminating NULL if all was successful.
2213 @retval EFI_SUCCESS The Results is processed successfully.
2214 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2215 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2221 SecureBootRouteConfig (
2222 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2223 IN CONST EFI_STRING Configuration
,
2224 OUT EFI_STRING
*Progress
2227 if (Configuration
== NULL
|| Progress
== NULL
) {
2228 return EFI_INVALID_PARAMETER
;
2231 *Progress
= Configuration
;
2232 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2233 return EFI_NOT_FOUND
;
2236 *Progress
= Configuration
+ StrLen (Configuration
);
2241 This function is called to provide results data to the driver.
2243 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2244 @param[in] Action Specifies the type of action taken by the browser.
2245 @param[in] QuestionId A unique value which is sent to the original
2246 exporting driver so that it can identify the type
2248 @param[in] Type The type of value for the question.
2249 @param[in] Value A pointer to the data being sent to the original
2251 @param[out] ActionRequest On return, points to the action requested by the
2254 @retval EFI_SUCCESS The callback successfully handled the action.
2255 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2256 variable and its data.
2257 @retval EFI_DEVICE_ERROR The variable could not be saved.
2258 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2264 SecureBootCallback (
2265 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2266 IN EFI_BROWSER_ACTION Action
,
2267 IN EFI_QUESTION_ID QuestionId
,
2269 IN EFI_IFR_TYPE_VALUE
*Value
,
2270 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2275 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
2277 SECUREBOOT_CONFIGURATION
*IfrNvData
;
2280 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
2281 return EFI_INVALID_PARAMETER
;
2284 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) && (Action
!= EFI_BROWSER_ACTION_CHANGING
)) {
2285 return EFI_UNSUPPORTED
;
2288 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2291 // Retrieve uncommitted data from Browser
2293 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2294 IfrNvData
= AllocateZeroPool (BufferSize
);
2295 if (IfrNvData
== NULL
) {
2296 return EFI_OUT_OF_RESOURCES
;
2299 Status
= EFI_SUCCESS
;
2301 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2303 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2305 switch (QuestionId
) {
2306 case KEY_SECURE_BOOT_ENABLE
:
2307 if (NULL
!= GetVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
)) {
2308 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
2310 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2312 L
"Only Physical Presence User could disable secure boot!",
2315 Status
= EFI_UNSUPPORTED
;
2317 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2321 case KEY_SECURE_BOOT_OPTION
:
2322 FreeMenu (&DirectoryMenu
);
2323 FreeMenu (&FsOptionMenu
);
2326 case KEY_SECURE_BOOT_KEK_OPTION
:
2327 case KEY_SECURE_BOOT_DB_OPTION
:
2328 case KEY_SECURE_BOOT_DBX_OPTION
:
2330 // Clear Signature GUID.
2332 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
2333 if (Private
->SignatureGUID
== NULL
) {
2334 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
2335 if (Private
->SignatureGUID
== NULL
) {
2336 return EFI_OUT_OF_RESOURCES
;
2340 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
2341 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
2342 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
2343 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
2345 LabelId
= FORMID_ENROLL_KEK_FORM
;
2349 // Refresh selected file.
2351 CleanUpPage (LabelId
, Private
);
2354 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
2355 case FORMID_ENROLL_KEK_FORM
:
2356 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
2357 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
2358 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
2359 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
2360 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
2361 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
2362 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
2363 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
2365 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
2368 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2369 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
2370 UpdateFileExplorer (Private
, 0);
2373 case KEY_SECURE_BOOT_DELETE_PK
:
2375 Status
= DeletePlatformKey ();
2376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2380 case KEY_DELETE_KEK
:
2383 EFI_KEY_EXCHANGE_KEY_NAME
,
2384 &gEfiGlobalVariableGuid
,
2386 FORMID_DELETE_KEK_FORM
,
2387 OPTION_DEL_KEK_QUESTION_ID
2391 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
2394 EFI_IMAGE_SECURITY_DATABASE
,
2395 &gEfiImageSecurityDatabaseGuid
,
2397 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2398 OPTION_DEL_DB_QUESTION_ID
2402 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
2405 EFI_IMAGE_SECURITY_DATABASE1
,
2406 &gEfiImageSecurityDatabaseGuid
,
2408 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2409 OPTION_DEL_DBX_QUESTION_ID
2414 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
2415 Status
= EnrollKeyExchangeKey (Private
);
2418 case KEY_VALUE_SAVE_AND_EXIT_DB
:
2419 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
2422 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
2423 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
2427 if (QuestionId
>= FILE_OPTION_OFFSET
) {
2428 UpdateFileExplorer (Private
, QuestionId
);
2429 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
2430 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2431 DeleteKeyExchangeKey (Private
, QuestionId
);
2432 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
2433 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2436 EFI_IMAGE_SECURITY_DATABASE
,
2437 &gEfiImageSecurityDatabaseGuid
,
2439 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2440 OPTION_DEL_DB_QUESTION_ID
,
2441 QuestionId
- OPTION_DEL_DB_QUESTION_ID
2443 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
2444 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2447 EFI_IMAGE_SECURITY_DATABASE1
,
2448 &gEfiImageSecurityDatabaseGuid
,
2450 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2451 OPTION_DEL_DBX_QUESTION_ID
,
2452 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
2457 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2458 switch (QuestionId
) {
2459 case KEY_SECURE_BOOT_ENABLE
:
2460 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2462 case KEY_VALUE_SAVE_AND_EXIT_PK
:
2463 Status
= EnrollPlatformKey (Private
);
2464 if (EFI_ERROR (Status
)) {
2466 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2468 L
"ERROR: The File Type is neither *.cer nor *.pbk!",
2472 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2476 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
2477 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
2478 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
2479 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
2480 if (Private
->FileContext
->FHandle
!= NULL
) {
2481 CloseFile (Private
->FileContext
->FHandle
);
2482 Private
->FileContext
->FHandle
= NULL
;
2483 Private
->FileContext
->FileName
= NULL
;
2486 if (Private
->SignatureGUID
!= NULL
) {
2487 FreePool (Private
->SignatureGUID
);
2488 Private
->SignatureGUID
= NULL
;
2490 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2493 case KEY_SECURE_BOOT_MODE
:
2494 if (NULL
!= GetVariable (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
)) {
2495 Status
= gRT
->SetVariable (
2496 EFI_CUSTOM_MODE_NAME
,
2497 &gEfiCustomModeEnableGuid
,
2498 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2502 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2503 IfrNvData
->SecureBootMode
= Value
->u8
;
2507 case KEY_SECURE_BOOT_KEK_GUID
:
2508 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
2509 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
2510 ASSERT (Private
->SignatureGUID
!= NULL
);
2511 Status
= StringToGuid (
2512 IfrNvData
->SignatureGuid
,
2513 StrLen (IfrNvData
->SignatureGuid
),
2514 Private
->SignatureGUID
2516 if (EFI_ERROR (Status
)) {
2520 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2523 case KEY_SECURE_BOOT_DELETE_PK
:
2525 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2531 if (!EFI_ERROR (Status
)) {
2532 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2533 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2535 FreePool (IfrNvData
);
2541 This function publish the SecureBoot configuration Form.
2543 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2545 @retval EFI_SUCCESS HII Form is installed successfully.
2546 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2547 @retval Others Other errors as indicated.
2551 InstallSecureBootConfigForm (
2552 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2556 EFI_HII_HANDLE HiiHandle
;
2557 EFI_HANDLE DriverHandle
;
2558 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2560 DriverHandle
= NULL
;
2561 ConfigAccess
= &PrivateData
->ConfigAccess
;
2562 Status
= gBS
->InstallMultipleProtocolInterfaces (
2564 &gEfiDevicePathProtocolGuid
,
2565 &mSecureBootHiiVendorDevicePath
,
2566 &gEfiHiiConfigAccessProtocolGuid
,
2570 if (EFI_ERROR (Status
)) {
2574 PrivateData
->DriverHandle
= DriverHandle
;
2577 // Publish the HII package list
2579 HiiHandle
= HiiAddPackages (
2580 &gSecureBootConfigFormSetGuid
,
2582 SecureBootConfigDxeStrings
,
2583 SecureBootConfigBin
,
2586 if (HiiHandle
== NULL
) {
2587 gBS
->UninstallMultipleProtocolInterfaces (
2589 &gEfiDevicePathProtocolGuid
,
2590 &mSecureBootHiiVendorDevicePath
,
2591 &gEfiHiiConfigAccessProtocolGuid
,
2595 return EFI_OUT_OF_RESOURCES
;
2598 PrivateData
->HiiHandle
= HiiHandle
;
2600 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
2601 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
2603 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
2604 UninstallSecureBootConfigForm (PrivateData
);
2605 return EFI_OUT_OF_RESOURCES
;
2608 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
2609 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2611 InitializeListHead (&FsOptionMenu
.Head
);
2612 InitializeListHead (&DirectoryMenu
.Head
);
2615 // Init OpCode Handle and Allocate space for creation of Buffer
2617 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2618 if (mStartOpCodeHandle
== NULL
) {
2619 UninstallSecureBootConfigForm (PrivateData
);
2620 return EFI_OUT_OF_RESOURCES
;
2623 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2624 if (mEndOpCodeHandle
== NULL
) {
2625 UninstallSecureBootConfigForm (PrivateData
);
2626 return EFI_OUT_OF_RESOURCES
;
2630 // Create Hii Extend Label OpCode as the start opcode
2632 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2636 sizeof (EFI_IFR_GUID_LABEL
)
2638 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2641 // Create Hii Extend Label OpCode as the end opcode
2643 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2647 sizeof (EFI_IFR_GUID_LABEL
)
2649 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2650 mEndLabel
->Number
= LABEL_END
;
2656 This function removes SecureBoot configuration Form.
2658 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2662 UninstallSecureBootConfigForm (
2663 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2667 // Uninstall HII package list
2669 if (PrivateData
->HiiHandle
!= NULL
) {
2670 HiiRemovePackages (PrivateData
->HiiHandle
);
2671 PrivateData
->HiiHandle
= NULL
;
2675 // Uninstall HII Config Access Protocol
2677 if (PrivateData
->DriverHandle
!= NULL
) {
2678 gBS
->UninstallMultipleProtocolInterfaces (
2679 PrivateData
->DriverHandle
,
2680 &gEfiDevicePathProtocolGuid
,
2681 &mSecureBootHiiVendorDevicePath
,
2682 &gEfiHiiConfigAccessProtocolGuid
,
2683 &PrivateData
->ConfigAccess
,
2686 PrivateData
->DriverHandle
= NULL
;
2689 if (PrivateData
->SignatureGUID
!= NULL
) {
2690 FreePool (PrivateData
->SignatureGUID
);
2693 if (PrivateData
->MenuEntry
!= NULL
) {
2694 FreePool (PrivateData
->MenuEntry
);
2697 if (PrivateData
->FileContext
!= NULL
) {
2698 FreePool (PrivateData
->FileContext
);
2701 FreePool (PrivateData
);
2703 FreeMenu (&DirectoryMenu
);
2704 FreeMenu (&FsOptionMenu
);
2706 if (mStartOpCodeHandle
!= NULL
) {
2707 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
2710 if (mEndOpCodeHandle
!= NULL
) {
2711 HiiFreeOpCodeHandle (mEndOpCodeHandle
);