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"));
184 KeyInfo
= (CPL_KEY_INFO
*)KeyBlob
;
185 if (KeyInfo
->KeyLengthInBits
/8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
186 Status
= EFI_UNSUPPORTED
;
191 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
193 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
194 KeyBuffer
= AllocateZeroPool(KeyLenInBytes
);
195 if (KeyBuffer
== NULL
) {
196 Status
= EFI_OUT_OF_RESOURCES
;
199 Status
= Int2OctStr (
200 (UINTN
*) ((UINTN
)KeyBlob
+ sizeof(CPL_KEY_INFO
)),
201 KeyLenInBytes
/ sizeof (UINTN
),
205 if (EFI_ERROR(Status
)) {
209 // Allocate space for PK certificate list and initialize the list.
210 // Create PK database entry with SignatureHeaderSize equals 0.
212 *PkCert
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool(
213 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
214 + WIN_CERT_UEFI_RSA2048_SIZE
217 if (*PkCert
== NULL
) {
218 Status
= EFI_OUT_OF_RESOURCES
;
222 (*PkCert
)->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
223 + sizeof(EFI_SIGNATURE_DATA
) - 1
224 + WIN_CERT_UEFI_RSA2048_SIZE
;
225 (*PkCert
)->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
226 (*PkCert
)->SignatureHeaderSize
= 0;
227 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertRsa2048Guid
);
229 PkCertData
= (EFI_SIGNATURE_DATA
*)((UINTN
)(*PkCert
)
230 + sizeof(EFI_SIGNATURE_LIST
)
231 + (*PkCert
)->SignatureHeaderSize
);
232 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
234 // Fill the PK database with PKpub data from PKKeyFile.
236 CopyMem (&(PkCertData
->SignatureData
[0]), KeyBuffer
, WIN_CERT_UEFI_RSA2048_SIZE
);
240 if (KeyBlob
!= NULL
) {
244 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
249 if (KeyBuffer
!= NULL
) {
250 FreePool (KeyBuffer
);
257 Generate the PK signature list from the X509 Certificate storing file (.cer)
259 @param[in] X509File FileHandle of X509 Certificate storing file.
260 @param[out] PkCert Point to the data buffer to store the signature list.
262 @return EFI_UNSUPPORTED Unsupported Key Length.
263 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
267 CreatePkX509SignatureList (
268 IN EFI_FILE_HANDLE X509File
,
269 OUT EFI_SIGNATURE_LIST
**PkCert
275 EFI_SIGNATURE_DATA
*PkCertData
;
281 Status
= ReadFileContent (X509File
, &X509Data
, &X509DataSize
, 0);
282 if (EFI_ERROR (Status
)) {
287 // Allocate space for PK certificate list and initialize it.
288 // Create PK database entry with SignatureHeaderSize equals 0.
290 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
291 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
294 if (*PkCert
== NULL
) {
295 Status
= EFI_OUT_OF_RESOURCES
;
299 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
300 + sizeof(EFI_SIGNATURE_DATA
) - 1
302 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
303 (*PkCert
)->SignatureHeaderSize
= 0;
304 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
305 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
306 + sizeof(EFI_SIGNATURE_LIST
)
307 + (*PkCert
)->SignatureHeaderSize
);
308 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
310 // Fill the PK database with PKpub data from X509 certificate file.
312 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
316 if (X509Data
!= NULL
) {
320 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
329 Enroll new PK into the System without original PK's authentication.
331 The SignatureOwner GUID will be the same with PK's vendorguid.
333 @param[in] PrivateData The module's private data.
335 @retval EFI_SUCCESS New PK enrolled successfully.
336 @retval EFI_INVALID_PARAMETER The parameter is invalid.
337 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
342 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
348 EFI_SIGNATURE_LIST
*PkCert
;
351 if (Private
->FileContext
->FileName
== NULL
) {
352 return EFI_INVALID_PARAMETER
;
358 // Parse the file's postfix. Only support *.pbk(RSA2048) and *.cer(X509) files.
360 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
361 if (CompareMem (FilePostFix
, L
".pbk",4) && CompareMem (FilePostFix
, L
".cer",4)) {
362 DEBUG ((EFI_D_ERROR
, "Don't support the file, only *.pbk or *.cer.\n is supported."));
363 return EFI_INVALID_PARAMETER
;
365 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
366 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
369 // Prase the selected PK file and generature PK certificate list.
371 if (!CompareMem (FilePostFix
, L
".pbk",4)) {
372 Status
= CreatePkRsaSignatureList (
373 Private
->FileContext
->FHandle
,
376 if (EFI_ERROR (Status
)) {
379 } else if (!CompareMem (FilePostFix
, L
".cer",4)) {
380 Status
= CreatePkX509SignatureList (
381 Private
->FileContext
->FHandle
,
384 if (EFI_ERROR (Status
)) {
390 // Set Platform Key variable.
392 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
393 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
394 DataSize
= PkCert
->SignatureListSize
;
395 Status
= gRT
->SetVariable(
396 EFI_PLATFORM_KEY_NAME
,
397 &gEfiGlobalVariableGuid
,
402 if (EFI_ERROR (Status
)) {
403 if (Status
== EFI_OUT_OF_RESOURCES
) {
404 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
411 if (PkCert
!= NULL
) {
415 if (Private
->FileContext
->FHandle
!= NULL
) {
416 CloseFile (Private
->FileContext
->FHandle
);
417 Private
->FileContext
->FHandle
= NULL
;
424 Remove the PK variable.
426 @retval EFI_SUCCESS Delete PK successfully.
427 @retval Others Could not allow to delete PK.
437 Status
= DeleteVariable (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
);
443 Enroll a new KEK item from public key storing file (*.pbk).
445 @param[in] PrivateData The module's private data.
447 @retval EFI_SUCCESS New KEK enrolled successfully.
448 @retval EFI_INVALID_PARAMETER The parameter is invalid.
449 @retval EFI_UNSUPPORTED Unsupported command.
450 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
455 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
461 EFI_SIGNATURE_LIST
*KekSigList
;
464 CPL_KEY_INFO
*KeyInfo
;
465 EFI_SIGNATURE_DATA
*KEKSigData
;
466 UINTN KekSigListSize
;
481 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
482 // First, We have to parse out public key data from the pbk key file.
484 Status
= ReadFileContent (
485 Private
->FileContext
->FHandle
,
490 if (EFI_ERROR (Status
)) {
493 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
494 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
495 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
496 Status
= EFI_UNSUPPORTED
;
501 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
503 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
504 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
505 if (KeyBuffer
== NULL
) {
506 Status
= EFI_OUT_OF_RESOURCES
;
510 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
511 KeyLenInBytes
/ sizeof (UINTN
),
515 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
518 // Form an new EFI_SIGNATURE_LIST.
520 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
521 + sizeof(EFI_SIGNATURE_DATA
) - 1
522 + WIN_CERT_UEFI_RSA2048_SIZE
;
524 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
525 if (KekSigList
== NULL
) {
526 Status
= EFI_OUT_OF_RESOURCES
;
530 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
531 + sizeof(EFI_SIGNATURE_DATA
) - 1
532 + WIN_CERT_UEFI_RSA2048_SIZE
;
533 KekSigList
->SignatureHeaderSize
= 0;
534 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
535 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
537 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
538 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
540 KEKSigData
->SignatureData
,
541 KeyBlob
+ sizeof(CPL_KEY_INFO
),
542 WIN_CERT_UEFI_RSA2048_SIZE
546 // Check if KEK entry has been already existed.
547 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
548 // new KEK to original variable.
550 Attr
|= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
;
552 Status
= gRT
->GetVariable(
553 EFI_KEY_EXCHANGE_KEY_NAME
,
554 &gEfiGlobalVariableGuid
,
559 if (Status
== EFI_BUFFER_TOO_SMALL
) {
560 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
561 } else if (Status
!= EFI_NOT_FOUND
) {
566 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
568 Status
= gRT
->SetVariable(
569 EFI_KEY_EXCHANGE_KEY_NAME
,
570 &gEfiGlobalVariableGuid
,
575 if (EFI_ERROR (Status
)) {
581 CloseFile (Private
->FileContext
->FHandle
);
582 Private
->FileContext
->FHandle
= NULL
;
583 Private
->FileContext
->FileName
= NULL
;
585 if (Private
->SignatureGUID
!= NULL
) {
586 FreePool (Private
->SignatureGUID
);
587 Private
->SignatureGUID
= NULL
;
590 if (KeyBlob
!= NULL
) {
593 if (KeyBuffer
!= NULL
) {
594 FreePool (KeyBuffer
);
596 if (KekSigList
!= NULL
) {
597 FreePool (KekSigList
);
604 Enroll a new KEK item from X509 certificate file.
606 @param[in] PrivateData The module's private data.
608 @retval EFI_SUCCESS New X509 is enrolled successfully.
609 @retval EFI_INVALID_PARAMETER The parameter is invalid.
610 @retval EFI_UNSUPPORTED Unsupported command.
611 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
616 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
622 EFI_SIGNATURE_DATA
*KEKSigData
;
623 EFI_SIGNATURE_LIST
*KekSigList
;
625 UINTN KekSigListSize
;
635 Status
= ReadFileContent (
636 Private
->FileContext
->FHandle
,
641 if (EFI_ERROR (Status
)) {
645 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
646 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
647 if (KekSigList
== NULL
) {
648 Status
= EFI_OUT_OF_RESOURCES
;
653 // Fill Certificate Database parameters.
655 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
656 KekSigList
->SignatureHeaderSize
= 0;
657 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
658 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
660 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
661 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
662 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
665 // Check if KEK been already existed.
666 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
667 // new kek to original variable
669 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
670 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
672 Status
= gRT
->GetVariable(
673 EFI_KEY_EXCHANGE_KEY_NAME
,
674 &gEfiGlobalVariableGuid
,
679 if (Status
== EFI_BUFFER_TOO_SMALL
) {
680 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
681 } else if (Status
!= EFI_NOT_FOUND
) {
685 Status
= gRT
->SetVariable(
686 EFI_KEY_EXCHANGE_KEY_NAME
,
687 &gEfiGlobalVariableGuid
,
692 if (EFI_ERROR (Status
)) {
698 CloseFile (Private
->FileContext
->FHandle
);
699 Private
->FileContext
->FileName
= NULL
;
700 Private
->FileContext
->FHandle
= NULL
;
702 if (Private
->SignatureGUID
!= NULL
) {
703 FreePool (Private
->SignatureGUID
);
704 Private
->SignatureGUID
= NULL
;
707 if (KekSigList
!= NULL
) {
708 FreePool (KekSigList
);
715 Enroll new KEK into the System without PK's authentication.
716 The SignatureOwner GUID will be Private->SignatureGUID.
718 @param[in] PrivateData The module's private data.
720 @retval EFI_SUCCESS New KEK enrolled successful.
721 @retval EFI_INVALID_PARAMETER The parameter is invalid.
722 @retval others Fail to enroll KEK data.
726 EnrollKeyExchangeKey (
727 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
732 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
733 return EFI_INVALID_PARAMETER
;
737 // Parse the file's postfix. Supports .cer and .der file as X509 certificate,
738 // and .pbk as RSA public key file.
740 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
741 if ((CompareMem (FilePostFix
, L
".cer",4) == 0) || (CompareMem (FilePostFix
, L
".der",4) == 0)) {
742 return EnrollX509ToKek (Private
);
743 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
744 return EnrollRsa2048ToKek (Private
);
746 return EFI_INVALID_PARAMETER
;
751 Enroll a new X509 certificate into Signature Database (DB or DBX) without
752 KEK's authentication.
754 @param[in] PrivateData The module's private data.
755 @param[in] VariableName Variable name of signature database, must be
756 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
758 @retval EFI_SUCCESS New X509 is enrolled successfully.
759 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
764 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
765 IN CHAR16
*VariableName
771 EFI_SIGNATURE_LIST
*SigDBCert
;
772 EFI_SIGNATURE_DATA
*SigDBCertData
;
783 SigDBCertData
= NULL
;
786 Status
= ReadFileContent (
787 Private
->FileContext
->FHandle
,
792 if (EFI_ERROR (Status
)) {
796 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
798 Data
= AllocateZeroPool (SigDBSize
);
800 Status
= EFI_OUT_OF_RESOURCES
;
805 // Fill Certificate Database parameters.
807 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
808 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
809 SigDBCert
->SignatureHeaderSize
= 0;
810 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
811 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
813 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
814 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
815 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
818 // Check if signature database entry has been already existed.
819 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
820 // new signature data to original variable
822 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
823 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
825 Status
= gRT
->GetVariable(
827 &gEfiImageSecurityDatabaseGuid
,
832 if (Status
== EFI_BUFFER_TOO_SMALL
) {
833 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
834 } else if (Status
!= EFI_NOT_FOUND
) {
838 Status
= gRT
->SetVariable(
840 &gEfiImageSecurityDatabaseGuid
,
845 if (EFI_ERROR (Status
)) {
851 CloseFile (Private
->FileContext
->FHandle
);
852 Private
->FileContext
->FileName
= NULL
;
853 Private
->FileContext
->FHandle
= NULL
;
855 if (Private
->SignatureGUID
!= NULL
) {
856 FreePool (Private
->SignatureGUID
);
857 Private
->SignatureGUID
= NULL
;
864 if (X509Data
!= NULL
) {
872 Load PE/COFF image information into internal buffer and check its validity.
874 @retval EFI_SUCCESS Successful
875 @retval EFI_UNSUPPORTED Invalid PE/COFF file
876 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
884 EFI_IMAGE_DOS_HEADER
*DosHdr
;
885 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
886 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
891 // Read the Dos header
893 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
894 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
897 // DOS image header is present,
898 // So read the PE header after the DOS image header
900 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
904 mPeCoffHeaderOffset
= 0;
908 // Read PE header and check the signature validity and machine compatibility
910 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
911 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
913 return EFI_UNSUPPORTED
;
916 mNtHeader
.Pe32
= NtHeader32
;
919 // Check the architecture field of PE header and get the Certificate Data Directory data
920 // Note the size of FileHeader field is constant for both IA32 and X64 arch
922 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
923 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
925 // IA-32 Architecture
927 mImageType
= ImageType_IA32
;
928 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
930 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
931 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
933 // 64-bits Architecture
935 mImageType
= ImageType_X64
;
936 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
937 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
939 return EFI_UNSUPPORTED
;
946 Calculate hash of Pe/Coff image based on the authenticode image hashing in
947 PE/COFF Specification 8.0 Appendix A
949 @param[in] HashAlg Hash algorithm type.
951 @retval TRUE Successfully hash image.
952 @retval FALSE Fail in hash image.
962 EFI_IMAGE_SECTION_HEADER
*Section
;
967 UINTN SumOfBytesHashed
;
968 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
973 SectionHeader
= NULL
;
976 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
981 // Initialize context of hash.
983 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
985 if (HashAlg
== HASHALG_SHA1
) {
986 mImageDigestSize
= SHA1_DIGEST_SIZE
;
987 mCertType
= gEfiCertSha1Guid
;
988 } else if (HashAlg
== HASHALG_SHA256
) {
989 mImageDigestSize
= SHA256_DIGEST_SIZE
;
990 mCertType
= gEfiCertSha256Guid
;
993 CtxSize
= mHash
[HashAlg
].GetContextSize();
995 HashCtx
= AllocatePool (CtxSize
);
996 ASSERT (HashCtx
!= NULL
);
998 // 1. Load the image header into memory.
1000 // 2. Initialize a SHA hash context.
1001 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1006 // Measuring PE/COFF Image Header;
1007 // But CheckSum field and SECURITY data directory (certificate) are excluded
1009 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1011 // 3. Calculate the distance from the base of the image header to the image checksum address.
1012 // 4. Hash the image header from its base to beginning of the image checksum.
1014 HashBase
= mImageBase
;
1015 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1019 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1022 // Use PE32+ offset.
1024 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1027 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1032 // 5. Skip over the image checksum (it occupies a single ULONG).
1033 // 6. Get the address of the beginning of the Cert Directory.
1034 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1036 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1040 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1041 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1044 // Use PE32+ offset.
1046 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1047 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1050 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1055 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1056 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1058 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1062 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1063 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1066 // Use PE32+ offset.
1068 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1069 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1072 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1077 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1079 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1083 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1088 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1092 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1093 // structures in the image. The 'NumberOfSections' field of the image
1094 // header indicates how big the table should be. Do not include any
1095 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1097 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1098 ASSERT (SectionHeader
!= NULL
);
1100 // 12. Using the 'PointerToRawData' in the referenced section headers as
1101 // a key, arrange the elements in the table in ascending order. In other
1102 // words, sort the section headers according to the disk-file offset of
1105 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1107 mPeCoffHeaderOffset
+
1109 sizeof (EFI_IMAGE_FILE_HEADER
) +
1110 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1112 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1114 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1115 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1118 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1123 // 13. Walk through the sorted table, bring the corresponding section
1124 // into memory, and hash the entire section (using the 'SizeOfRawData'
1125 // field in the section header to determine the amount of data to hash).
1126 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1127 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1129 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1130 Section
= &SectionHeader
[Index
];
1131 if (Section
->SizeOfRawData
== 0) {
1134 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1135 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1137 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1142 SumOfBytesHashed
+= HashSize
;
1146 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1147 // data in the file that needs to be added to the hash. This data begins
1148 // at file offset SUM_OF_BYTES_HASHED and its length is:
1149 // FileSize - (CertDirectory->Size)
1151 if (mImageSize
> SumOfBytesHashed
) {
1152 HashBase
= mImageBase
+ SumOfBytesHashed
;
1153 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1159 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1163 // Use PE32+ offset.
1167 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1171 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1177 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1180 if (HashCtx
!= NULL
) {
1183 if (SectionHeader
!= NULL
) {
1184 FreePool (SectionHeader
);
1190 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1191 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1194 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1195 @retval EFI_SUCCESS Hash successfully.
1204 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1206 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1208 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1210 // Check the Hash algorithm in PE/COFF Authenticode.
1211 // According to PKCS#7 Definition:
1212 // SignedData ::= SEQUENCE {
1214 // digestAlgorithms DigestAlgorithmIdentifiers,
1215 // contentInfo ContentInfo,
1217 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1218 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1219 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1221 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1223 // Only support two bytes of Long Form of Length Encoding.
1229 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1234 if (Index
== HASHALG_MAX
) {
1235 return EFI_UNSUPPORTED
;
1239 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1241 if (!HashPeImage(Index
)) {
1242 return EFI_UNSUPPORTED
;
1249 Enroll a new executable's signature into Signature Database.
1251 @param[in] PrivateData The module's private data.
1252 @param[in] VariableName Variable name of signature database, must be
1253 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1255 @retval EFI_SUCCESS New signature is enrolled successfully.
1256 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1257 @retval EFI_UNSUPPORTED Unsupported command.
1258 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1262 EnrollImageSignatureToSigDB (
1263 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1264 IN CHAR16
*VariableName
1268 EFI_SIGNATURE_LIST
*SigDBCert
;
1269 EFI_SIGNATURE_DATA
*SigDBCertData
;
1274 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
1277 GuidCertData
= NULL
;
1278 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1279 | EFI_VARIABLE_BOOTSERVICE_ACCESS
;
1282 // Form the SigDB certificate list.
1283 // Format the data item into EFI_SIGNATURE_LIST type.
1285 // We need to parse executable's signature data from specified signed executable file.
1286 // In current implementation, we simply trust the pass-in signed executable file.
1287 // In reality, it's OS's responsibility to verify the signed executable file.
1291 // Read the whole file content
1293 Status
= ReadFileContent(
1294 Private
->FileContext
->FHandle
,
1295 (VOID
**) &mImageBase
,
1299 if (EFI_ERROR (Status
)) {
1303 Status
= LoadPeImage ();
1304 if (EFI_ERROR (Status
)) {
1308 if (mSecDataDir
->SizeOfCert
== 0) {
1309 if (!HashPeImage (HASHALG_SHA256
)) {
1310 Status
= EFI_SECURITY_VIOLATION
;
1316 // Read the certificate data
1318 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
1320 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1321 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
1322 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
1323 Status
= EFI_ABORTED
;
1327 if (!HashPeImage (HASHALG_SHA256
)) {
1328 Status
= EFI_ABORTED
;
1332 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1334 Status
= HashPeImageByType ();
1335 if (EFI_ERROR (Status
)) {
1339 Status
= EFI_ABORTED
;
1345 // Create a new SigDB entry.
1347 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
1348 + sizeof(EFI_SIGNATURE_DATA
) - 1
1349 + (UINT32
) mImageDigestSize
;
1351 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
1353 Status
= EFI_OUT_OF_RESOURCES
;
1358 // Adjust the Certificate Database parameters.
1360 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1361 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1362 SigDBCert
->SignatureHeaderSize
= 0;
1363 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
1364 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
1366 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
1367 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1368 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
1371 // Check if SigDB variable has been already existed.
1372 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1373 // new signature data to original variable
1376 Status
= gRT
->GetVariable(
1378 &gEfiImageSecurityDatabaseGuid
,
1383 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1384 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1385 } else if (Status
!= EFI_NOT_FOUND
) {
1390 // Enroll the variable.
1392 Status
= gRT
->SetVariable(
1394 &gEfiImageSecurityDatabaseGuid
,
1399 if (EFI_ERROR (Status
)) {
1405 CloseFile (Private
->FileContext
->FHandle
);
1406 Private
->FileContext
->FHandle
= NULL
;
1407 Private
->FileContext
->FileName
= NULL
;
1409 if (Private
->SignatureGUID
!= NULL
) {
1410 FreePool (Private
->SignatureGUID
);
1411 Private
->SignatureGUID
= NULL
;
1418 if (mImageBase
!= NULL
) {
1419 FreePool (mImageBase
);
1427 Enroll signature into DB/DBX without KEK's authentication.
1428 The SignatureOwner GUID will be Private->SignatureGUID.
1430 @param[in] PrivateData The module's private data.
1431 @param[in] VariableName Variable name of signature database, must be
1432 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1434 @retval EFI_SUCCESS New signature enrolled successfully.
1435 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1436 @retval others Fail to enroll signature data.
1440 EnrollSignatureDatabase (
1441 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1442 IN CHAR16
*VariableName
1445 UINT16
* FilePostFix
;
1447 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1448 return EFI_INVALID_PARAMETER
;
1452 // Parse the file's postfix.
1454 FilePostFix
= Private
->FileContext
->FileName
+ StrLen (Private
->FileContext
->FileName
) - 4;
1455 if ((CompareMem (FilePostFix
, L
".cer",4) == 0) || (CompareMem (FilePostFix
, L
".der",4) == 0)) {
1457 // Supports .cer and .der file as X509 certificate.
1459 return EnrollX509toSigDB (Private
, VariableName
);
1462 return EnrollImageSignatureToSigDB (Private
, VariableName
);
1466 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1467 by GUID in the page for user to select and delete as needed.
1469 @param[in] PrivateData Module's private data.
1470 @param[in] VariableName The variable name of the vendor's signature database.
1471 @param[in] VendorGuid A unique identifier for the vendor.
1472 @param[in] LabelNumber Label number to insert opcodes.
1473 @param[in] FormId Form ID of current page.
1474 @param[in] QuestionIdBase Base question id of the signature list.
1476 @retval EFI_SUCCESS Success to update the signature list page
1477 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1482 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1483 IN CHAR16
*VariableName
,
1484 IN EFI_GUID
*VendorGuid
,
1485 IN UINT16 LabelNumber
,
1486 IN EFI_FORM_ID FormId
,
1487 IN EFI_QUESTION_ID QuestionIdBase
1494 VOID
*StartOpCodeHandle
;
1495 VOID
*EndOpCodeHandle
;
1496 EFI_IFR_GUID_LABEL
*StartLabel
;
1497 EFI_IFR_GUID_LABEL
*EndLabel
;
1500 EFI_SIGNATURE_LIST
*CertList
;
1501 EFI_SIGNATURE_DATA
*Cert
;
1502 UINT32 ItemDataSize
;
1504 EFI_STRING_ID GuidID
;
1511 StartOpCodeHandle
= NULL
;
1512 EndOpCodeHandle
= NULL
;
1515 // Initialize the container for dynamic opcodes.
1517 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1518 if (StartOpCodeHandle
== NULL
) {
1519 Status
= EFI_OUT_OF_RESOURCES
;
1523 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1524 if (EndOpCodeHandle
== NULL
) {
1525 Status
= EFI_OUT_OF_RESOURCES
;
1530 // Create Hii Extend Label OpCode.
1532 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1536 sizeof (EFI_IFR_GUID_LABEL
)
1538 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1539 StartLabel
->Number
= LabelNumber
;
1541 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1545 sizeof (EFI_IFR_GUID_LABEL
)
1547 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1548 EndLabel
->Number
= LABEL_END
;
1554 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1555 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1559 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1561 Status
= EFI_OUT_OF_RESOURCES
;
1565 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1566 if (EFI_ERROR (Status
)) {
1570 GuidStr
= AllocateZeroPool (100);
1571 if (GuidStr
== NULL
) {
1572 Status
= EFI_OUT_OF_RESOURCES
;
1577 // Enumerate all KEK pub data.
1579 ItemDataSize
= (UINT32
) DataSize
;
1580 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1583 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1585 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1586 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
1587 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1588 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
1589 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
1590 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
1591 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
1592 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
1595 // The signature type is not supported in current implementation.
1600 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1601 for (Index
= 0; Index
< CertCount
; Index
++) {
1602 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
1603 + sizeof (EFI_SIGNATURE_LIST
)
1604 + CertList
->SignatureHeaderSize
1605 + Index
* CertList
->SignatureSize
);
1607 // Display GUID and help
1609 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
1610 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
1611 HiiCreateCheckBoxOpCode (
1613 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
1618 EFI_IFR_FLAG_CALLBACK
,
1624 ItemDataSize
-= CertList
->SignatureListSize
;
1625 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1630 PrivateData
->HiiHandle
,
1631 &gSecureBootConfigFormSetGuid
,
1637 if (StartOpCodeHandle
!= NULL
) {
1638 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1641 if (EndOpCodeHandle
!= NULL
) {
1642 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1649 if (GuidStr
!= NULL
) {
1657 Delete a KEK entry from KEK database.
1659 @param[in] PrivateData Module's private data.
1660 @param[in] QuestionId Question id of the KEK item to delete.
1662 @retval EFI_SUCCESS Delete kek item successfully.
1663 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1667 DeleteKeyExchangeKey (
1668 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1669 IN EFI_QUESTION_ID QuestionId
1678 EFI_SIGNATURE_LIST
*CertList
;
1679 EFI_SIGNATURE_LIST
*NewCertList
;
1680 EFI_SIGNATURE_DATA
*Cert
;
1683 BOOLEAN IsKEKItemFound
;
1685 UINTN DeleteKekIndex
;
1693 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
1696 // Get original KEK variable.
1699 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
1700 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1704 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
1705 if (OldData
== NULL
) {
1706 Status
= EFI_OUT_OF_RESOURCES
;
1710 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
1711 if (EFI_ERROR(Status
)) {
1716 // Allocate space for new variable.
1718 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1720 Status
= EFI_OUT_OF_RESOURCES
;
1725 // Enumerate all KEK pub data and erasing the target item.
1727 IsKEKItemFound
= FALSE
;
1728 KekDataSize
= (UINT32
) DataSize
;
1729 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1732 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1733 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1734 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1735 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1736 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1737 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1738 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1739 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1740 for (Index
= 0; Index
< CertCount
; Index
++) {
1741 if (GuidIndex
== DeleteKekIndex
) {
1743 // Find it! Skip it!
1745 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1746 IsKEKItemFound
= TRUE
;
1749 // This item doesn't match. Copy it to the Data buffer.
1751 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
1752 Offset
+= CertList
->SignatureSize
;
1755 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1759 // This List doesn't match. Copy it to the Data buffer.
1761 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
1762 Offset
+= CertList
->SignatureListSize
;
1765 KekDataSize
-= CertList
->SignatureListSize
;
1766 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1769 if (!IsKEKItemFound
) {
1771 // Doesn't find the Kek Item!
1773 Status
= EFI_NOT_FOUND
;
1778 // Delete the Signature header if there is no signature in the list.
1780 KekDataSize
= Offset
;
1781 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1783 ZeroMem (OldData
, KekDataSize
);
1784 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1785 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1786 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1787 if (CertCount
!= 0) {
1788 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
1789 Offset
+= CertList
->SignatureListSize
;
1791 KekDataSize
-= CertList
->SignatureListSize
;
1792 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1795 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1798 Status
= gRT
->SetVariable(
1799 EFI_KEY_EXCHANGE_KEY_NAME
,
1800 &gEfiGlobalVariableGuid
,
1805 if (EFI_ERROR (Status
)) {
1806 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
1815 if (OldData
!= NULL
) {
1819 return UpdateDeletePage (
1821 EFI_KEY_EXCHANGE_KEY_NAME
,
1822 &gEfiGlobalVariableGuid
,
1824 FORMID_DELETE_KEK_FORM
,
1825 OPTION_DEL_KEK_QUESTION_ID
1830 Delete a signature entry from siganture database.
1832 @param[in] PrivateData Module's private data.
1833 @param[in] VariableName The variable name of the vendor's signature database.
1834 @param[in] VendorGuid A unique identifier for the vendor.
1835 @param[in] LabelNumber Label number to insert opcodes.
1836 @param[in] FormId Form ID of current page.
1837 @param[in] QuestionIdBase Base question id of the signature list.
1838 @param[in] DeleteIndex Signature index to delete.
1840 @retval EFI_SUCCESS Delete siganture successfully.
1841 @retval EFI_NOT_FOUND Can't find the signature item,
1842 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1846 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1847 IN CHAR16
*VariableName
,
1848 IN EFI_GUID
*VendorGuid
,
1849 IN UINT16 LabelNumber
,
1850 IN EFI_FORM_ID FormId
,
1851 IN EFI_QUESTION_ID QuestionIdBase
,
1852 IN UINTN DeleteIndex
1861 EFI_SIGNATURE_LIST
*CertList
;
1862 EFI_SIGNATURE_LIST
*NewCertList
;
1863 EFI_SIGNATURE_DATA
*Cert
;
1866 BOOLEAN IsItemFound
;
1867 UINT32 ItemDataSize
;
1877 // Get original signature list data.
1880 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
1881 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1885 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
1886 if (OldData
== NULL
) {
1887 Status
= EFI_OUT_OF_RESOURCES
;
1891 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
1892 if (EFI_ERROR(Status
)) {
1897 // Allocate space for new variable.
1899 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1901 Status
= EFI_OUT_OF_RESOURCES
;
1906 // Enumerate all signature data and erasing the target item.
1908 IsItemFound
= FALSE
;
1909 ItemDataSize
= (UINT32
) DataSize
;
1910 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1913 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1914 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1915 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
1916 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
1917 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)
1920 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
1922 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1923 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
1924 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1925 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1926 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1927 for (Index
= 0; Index
< CertCount
; Index
++) {
1928 if (GuidIndex
== DeleteIndex
) {
1930 // Find it! Skip it!
1932 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1936 // This item doesn't match. Copy it to the Data buffer.
1938 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
1939 Offset
+= CertList
->SignatureSize
;
1942 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1946 // This List doesn't match. Just copy it to the Data buffer.
1948 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
1949 Offset
+= CertList
->SignatureListSize
;
1952 ItemDataSize
-= CertList
->SignatureListSize
;
1953 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1958 // Doesn't find the signature Item!
1960 Status
= EFI_NOT_FOUND
;
1965 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
1967 ItemDataSize
= Offset
;
1968 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1970 ZeroMem (OldData
, ItemDataSize
);
1971 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1972 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1973 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1974 if (CertCount
!= 0) {
1975 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
1976 Offset
+= CertList
->SignatureListSize
;
1978 ItemDataSize
-= CertList
->SignatureListSize
;
1979 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1982 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1985 Status
= gRT
->SetVariable(
1992 if (EFI_ERROR (Status
)) {
1993 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2002 if (OldData
!= NULL
) {
2006 return UpdateDeletePage (
2017 This function extracts configuration from variable.
2019 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2023 SecureBootExtractConfigFromVariable (
2024 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2027 UINT8
*SecureBootEnable
;
2029 UINT8
*SecureBootMode
;
2031 SecureBootEnable
= NULL
;
2033 SecureBootMode
= NULL
;
2036 // Get the SecureBootEnable Variable
2038 SecureBootEnable
= GetVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
);
2041 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2044 if (SecureBootEnable
== NULL
) {
2045 ConfigData
->HideSecureBoot
= TRUE
;
2047 ConfigData
->HideSecureBoot
= FALSE
;
2048 ConfigData
->SecureBootState
= *SecureBootEnable
;
2051 // If it is Physical Presence User, set the PhysicalPresent to true.
2053 if (UserPhysicalPresent()) {
2054 ConfigData
->PhysicalPresent
= TRUE
;
2056 ConfigData
->PhysicalPresent
= FALSE
;
2060 // If there is no PK then the Delete Pk button will be gray.
2062 SetupMode
= GetVariable (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
);
2063 if (SetupMode
== NULL
|| (*SetupMode
) == 1) {
2064 ConfigData
->HasPk
= FALSE
;
2066 ConfigData
->HasPk
= TRUE
;
2070 // Get the SecureBootMode from CustomMode variable.
2072 SecureBootMode
= GetVariable (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
);
2073 if (SecureBootMode
== NULL
) {
2074 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2076 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2082 This function allows a caller to extract the current configuration for one
2083 or more named elements from the target driver.
2085 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2086 @param[in] Request A null-terminated Unicode string in
2087 <ConfigRequest> format.
2088 @param[out] Progress On return, points to a character in the Request
2089 string. Points to the string's null terminator if
2090 request was successful. Points to the most recent
2091 '&' before the first failing name/value pair (or
2092 the beginning of the string if the failure is in
2093 the first name/value pair) if the request was not
2095 @param[out] Results A null-terminated Unicode string in
2096 <ConfigAltResp> format which has all values filled
2097 in for the names in the Request string. String to
2098 be allocated by the called function.
2100 @retval EFI_SUCCESS The Results is filled with the requested values.
2101 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2102 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2103 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2109 SecureBootExtractConfig (
2110 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2111 IN CONST EFI_STRING Request
,
2112 OUT EFI_STRING
*Progress
,
2113 OUT EFI_STRING
*Results
2119 SECUREBOOT_CONFIGURATION Configuration
;
2120 EFI_STRING ConfigRequest
;
2121 EFI_STRING ConfigRequestHdr
;
2122 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2123 BOOLEAN AllocatedRequest
;
2125 if (Progress
== NULL
|| Results
== NULL
) {
2126 return EFI_INVALID_PARAMETER
;
2129 AllocatedRequest
= FALSE
;
2130 ConfigRequestHdr
= NULL
;
2131 ConfigRequest
= NULL
;
2134 ZeroMem (&Configuration
, sizeof (Configuration
));
2135 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2136 *Progress
= Request
;
2138 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2139 return EFI_NOT_FOUND
;
2143 // Get Configuration from Variable.
2145 SecureBootExtractConfigFromVariable (&Configuration
);
2147 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2148 ConfigRequest
= Request
;
2149 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2151 // Request is set to NULL or OFFSET is NULL, construct full request string.
2153 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2154 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2156 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2157 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2158 ConfigRequest
= AllocateZeroPool (Size
);
2159 ASSERT (ConfigRequest
!= NULL
);
2160 AllocatedRequest
= TRUE
;
2161 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2162 FreePool (ConfigRequestHdr
);
2163 ConfigRequestHdr
= NULL
;
2166 Status
= gHiiConfigRouting
->BlockToConfig (
2169 (UINT8
*) &Configuration
,
2176 // Free the allocated config request string.
2178 if (AllocatedRequest
) {
2179 FreePool (ConfigRequest
);
2183 // Set Progress string to the original request string.
2185 if (Request
== NULL
) {
2187 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2188 *Progress
= Request
+ StrLen (Request
);
2195 This function processes the results of changes in configuration.
2197 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2198 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2200 @param[out] Progress A pointer to a string filled in with the offset of
2201 the most recent '&' before the first failing
2202 name/value pair (or the beginning of the string if
2203 the failure is in the first name/value pair) or
2204 the terminating NULL if all was successful.
2206 @retval EFI_SUCCESS The Results is processed successfully.
2207 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2208 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2214 SecureBootRouteConfig (
2215 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2216 IN CONST EFI_STRING Configuration
,
2217 OUT EFI_STRING
*Progress
2220 if (Configuration
== NULL
|| Progress
== NULL
) {
2221 return EFI_INVALID_PARAMETER
;
2224 *Progress
= Configuration
;
2225 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2226 return EFI_NOT_FOUND
;
2229 *Progress
= Configuration
+ StrLen (Configuration
);
2234 This function is called to provide results data to the driver.
2236 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2237 @param[in] Action Specifies the type of action taken by the browser.
2238 @param[in] QuestionId A unique value which is sent to the original
2239 exporting driver so that it can identify the type
2241 @param[in] Type The type of value for the question.
2242 @param[in] Value A pointer to the data being sent to the original
2244 @param[out] ActionRequest On return, points to the action requested by the
2247 @retval EFI_SUCCESS The callback successfully handled the action.
2248 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2249 variable and its data.
2250 @retval EFI_DEVICE_ERROR The variable could not be saved.
2251 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2257 SecureBootCallback (
2258 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2259 IN EFI_BROWSER_ACTION Action
,
2260 IN EFI_QUESTION_ID QuestionId
,
2262 IN EFI_IFR_TYPE_VALUE
*Value
,
2263 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2268 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
2270 SECUREBOOT_CONFIGURATION
*IfrNvData
;
2273 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
2274 return EFI_INVALID_PARAMETER
;
2277 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) && (Action
!= EFI_BROWSER_ACTION_CHANGING
)) {
2278 return EFI_UNSUPPORTED
;
2281 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2284 // Retrieve uncommitted data from Browser
2286 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2287 IfrNvData
= AllocateZeroPool (BufferSize
);
2288 if (IfrNvData
== NULL
) {
2289 return EFI_OUT_OF_RESOURCES
;
2292 Status
= EFI_SUCCESS
;
2294 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2296 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2298 switch (QuestionId
) {
2299 case KEY_SECURE_BOOT_ENABLE
:
2300 if (NULL
!= GetVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
)) {
2301 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
2303 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2305 L
"Only Physical Presence User could disable secure boot!",
2308 Status
= EFI_UNSUPPORTED
;
2310 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2314 case KEY_SECURE_BOOT_OPTION
:
2315 FreeMenu (&DirectoryMenu
);
2316 FreeMenu (&FsOptionMenu
);
2319 case KEY_SECURE_BOOT_KEK_OPTION
:
2320 case KEY_SECURE_BOOT_DB_OPTION
:
2321 case KEY_SECURE_BOOT_DBX_OPTION
:
2323 // Clear Signature GUID.
2325 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
2326 if (Private
->SignatureGUID
== NULL
) {
2327 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
2328 if (Private
->SignatureGUID
== NULL
) {
2329 return EFI_OUT_OF_RESOURCES
;
2333 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
2334 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
2335 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
2336 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
2338 LabelId
= FORMID_ENROLL_KEK_FORM
;
2342 // Refresh selected file.
2344 CleanUpPage (LabelId
, Private
);
2347 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
2348 case FORMID_ENROLL_KEK_FORM
:
2349 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
2350 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
2351 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
2352 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
2353 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
2354 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
2355 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
2356 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
2358 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
2361 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2362 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
2363 UpdateFileExplorer (Private
, 0);
2366 case KEY_SECURE_BOOT_DELETE_PK
:
2368 Status
= DeletePlatformKey ();
2369 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2373 case KEY_DELETE_KEK
:
2376 EFI_KEY_EXCHANGE_KEY_NAME
,
2377 &gEfiGlobalVariableGuid
,
2379 FORMID_DELETE_KEK_FORM
,
2380 OPTION_DEL_KEK_QUESTION_ID
2384 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
2387 EFI_IMAGE_SECURITY_DATABASE
,
2388 &gEfiImageSecurityDatabaseGuid
,
2390 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2391 OPTION_DEL_DB_QUESTION_ID
2395 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
2398 EFI_IMAGE_SECURITY_DATABASE1
,
2399 &gEfiImageSecurityDatabaseGuid
,
2401 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2402 OPTION_DEL_DBX_QUESTION_ID
2407 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
2408 Status
= EnrollKeyExchangeKey (Private
);
2411 case KEY_VALUE_SAVE_AND_EXIT_DB
:
2412 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
2415 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
2416 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
2420 if (QuestionId
>= FILE_OPTION_OFFSET
) {
2421 UpdateFileExplorer (Private
, QuestionId
);
2422 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
2423 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2424 DeleteKeyExchangeKey (Private
, QuestionId
);
2425 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
2426 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2429 EFI_IMAGE_SECURITY_DATABASE
,
2430 &gEfiImageSecurityDatabaseGuid
,
2432 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2433 OPTION_DEL_DB_QUESTION_ID
,
2434 QuestionId
- OPTION_DEL_DB_QUESTION_ID
2436 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
2437 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2440 EFI_IMAGE_SECURITY_DATABASE1
,
2441 &gEfiImageSecurityDatabaseGuid
,
2443 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2444 OPTION_DEL_DBX_QUESTION_ID
,
2445 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
2450 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2451 switch (QuestionId
) {
2452 case KEY_SECURE_BOOT_ENABLE
:
2453 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2455 case KEY_VALUE_SAVE_AND_EXIT_PK
:
2456 Status
= EnrollPlatformKey (Private
);
2457 if (EFI_ERROR (Status
)) {
2459 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2461 L
"ERROR: The File Type is neither *.cer nor *.pbk!",
2465 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2469 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
2470 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
2471 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
2472 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
2473 if (Private
->FileContext
->FHandle
!= NULL
) {
2474 CloseFile (Private
->FileContext
->FHandle
);
2475 Private
->FileContext
->FHandle
= NULL
;
2476 Private
->FileContext
->FileName
= NULL
;
2479 if (Private
->SignatureGUID
!= NULL
) {
2480 FreePool (Private
->SignatureGUID
);
2481 Private
->SignatureGUID
= NULL
;
2483 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2486 case KEY_SECURE_BOOT_MODE
:
2487 if (NULL
!= GetVariable (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
)) {
2488 Status
= gRT
->SetVariable (
2489 EFI_CUSTOM_MODE_NAME
,
2490 &gEfiCustomModeEnableGuid
,
2491 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2495 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2496 IfrNvData
->SecureBootMode
= Value
->u8
;
2500 case KEY_SECURE_BOOT_KEK_GUID
:
2501 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
2502 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
2503 ASSERT (Private
->SignatureGUID
!= NULL
);
2504 Status
= StringToGuid (
2505 IfrNvData
->SignatureGuid
,
2506 StrLen (IfrNvData
->SignatureGuid
),
2507 Private
->SignatureGUID
2509 if (EFI_ERROR (Status
)) {
2513 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2516 case KEY_SECURE_BOOT_DELETE_PK
:
2518 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2524 if (!EFI_ERROR (Status
)) {
2525 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2526 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2528 FreePool (IfrNvData
);
2534 This function publish the SecureBoot configuration Form.
2536 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2538 @retval EFI_SUCCESS HII Form is installed successfully.
2539 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2540 @retval Others Other errors as indicated.
2544 InstallSecureBootConfigForm (
2545 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2549 EFI_HII_HANDLE HiiHandle
;
2550 EFI_HANDLE DriverHandle
;
2551 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2553 DriverHandle
= NULL
;
2554 ConfigAccess
= &PrivateData
->ConfigAccess
;
2555 Status
= gBS
->InstallMultipleProtocolInterfaces (
2557 &gEfiDevicePathProtocolGuid
,
2558 &mSecureBootHiiVendorDevicePath
,
2559 &gEfiHiiConfigAccessProtocolGuid
,
2563 if (EFI_ERROR (Status
)) {
2567 PrivateData
->DriverHandle
= DriverHandle
;
2570 // Publish the HII package list
2572 HiiHandle
= HiiAddPackages (
2573 &gSecureBootConfigFormSetGuid
,
2575 SecureBootConfigDxeStrings
,
2576 SecureBootConfigBin
,
2579 if (HiiHandle
== NULL
) {
2580 gBS
->UninstallMultipleProtocolInterfaces (
2582 &gEfiDevicePathProtocolGuid
,
2583 &mSecureBootHiiVendorDevicePath
,
2584 &gEfiHiiConfigAccessProtocolGuid
,
2588 return EFI_OUT_OF_RESOURCES
;
2591 PrivateData
->HiiHandle
= HiiHandle
;
2593 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
2594 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
2596 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
2597 UninstallSecureBootConfigForm (PrivateData
);
2598 return EFI_OUT_OF_RESOURCES
;
2601 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
2602 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2604 InitializeListHead (&FsOptionMenu
.Head
);
2605 InitializeListHead (&DirectoryMenu
.Head
);
2608 // Init OpCode Handle and Allocate space for creation of Buffer
2610 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2611 if (mStartOpCodeHandle
== NULL
) {
2612 UninstallSecureBootConfigForm (PrivateData
);
2613 return EFI_OUT_OF_RESOURCES
;
2616 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2617 if (mEndOpCodeHandle
== NULL
) {
2618 UninstallSecureBootConfigForm (PrivateData
);
2619 return EFI_OUT_OF_RESOURCES
;
2623 // Create Hii Extend Label OpCode as the start opcode
2625 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2629 sizeof (EFI_IFR_GUID_LABEL
)
2631 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2634 // Create Hii Extend Label OpCode as the end opcode
2636 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2640 sizeof (EFI_IFR_GUID_LABEL
)
2642 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2643 mEndLabel
->Number
= LABEL_END
;
2649 This function removes SecureBoot configuration Form.
2651 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2655 UninstallSecureBootConfigForm (
2656 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2660 // Uninstall HII package list
2662 if (PrivateData
->HiiHandle
!= NULL
) {
2663 HiiRemovePackages (PrivateData
->HiiHandle
);
2664 PrivateData
->HiiHandle
= NULL
;
2668 // Uninstall HII Config Access Protocol
2670 if (PrivateData
->DriverHandle
!= NULL
) {
2671 gBS
->UninstallMultipleProtocolInterfaces (
2672 PrivateData
->DriverHandle
,
2673 &gEfiDevicePathProtocolGuid
,
2674 &mSecureBootHiiVendorDevicePath
,
2675 &gEfiHiiConfigAccessProtocolGuid
,
2676 &PrivateData
->ConfigAccess
,
2679 PrivateData
->DriverHandle
= NULL
;
2682 if (PrivateData
->SignatureGUID
!= NULL
) {
2683 FreePool (PrivateData
->SignatureGUID
);
2686 if (PrivateData
->MenuEntry
!= NULL
) {
2687 FreePool (PrivateData
->MenuEntry
);
2690 if (PrivateData
->FileContext
!= NULL
) {
2691 FreePool (PrivateData
->FileContext
);
2694 FreePool (PrivateData
);
2696 FreeMenu (&DirectoryMenu
);
2697 FreeMenu (&FsOptionMenu
);
2699 if (mStartOpCodeHandle
!= NULL
) {
2700 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
2703 if (mEndOpCodeHandle
!= NULL
) {
2704 HiiFreeOpCodeHandle (mEndOpCodeHandle
);