2 This library provides helper functions to set/clear Secure Boot
5 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
7 Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
8 Copyright (c) 2021, Semihalf All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Guid/GlobalVariable.h>
12 #include <Guid/AuthenticatedVariableFormat.h>
13 #include <Guid/ImageAuthentication.h>
14 #include <Library/BaseCryptLib.h>
15 #include <Library/BaseLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/UefiLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/UefiRuntimeServicesTableLib.h>
21 #include <Library/SecureBootVariableLib.h>
22 #include "Library/DxeServicesLib.h"
24 /** Creates EFI Signature List structure.
26 @param[in] Data A pointer to signature data.
27 @param[in] Size Size of signature data.
28 @param[out] SigList Created Signature List.
30 @retval EFI_SUCCESS Signature List was created successfully.
31 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
38 OUT EFI_SIGNATURE_LIST
**SigList
42 EFI_SIGNATURE_LIST
*TmpSigList
;
43 EFI_SIGNATURE_DATA
*SigData
;
46 // Allocate data for Signature Database
48 SigListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + Size
;
49 TmpSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (SigListSize
);
50 if (TmpSigList
== NULL
) {
51 return EFI_OUT_OF_RESOURCES
;
55 // Only gEfiCertX509Guid type is supported
57 TmpSigList
->SignatureListSize
= (UINT32
)SigListSize
;
58 TmpSigList
->SignatureSize
= (UINT32
) (sizeof (EFI_SIGNATURE_DATA
) - 1 + Size
);
59 TmpSigList
->SignatureHeaderSize
= 0;
60 CopyGuid (&TmpSigList
->SignatureType
, &gEfiCertX509Guid
);
65 SigData
= (EFI_SIGNATURE_DATA
*) (TmpSigList
+ 1);
66 CopyGuid (&SigData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
67 CopyMem (&SigData
->SignatureData
[0], Data
, Size
);
69 *SigList
= TmpSigList
;
74 /** Adds new signature list to signature database.
76 @param[in] SigLists A pointer to signature database.
77 @param[in] SigListAppend A signature list to be added.
78 @param[out] *SigListOut Created signature database.
79 @param[in, out] SigListsSize A size of created signature database.
81 @retval EFI_SUCCESS Signature List was added successfully.
82 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
87 IN EFI_SIGNATURE_LIST
*SigLists
,
88 IN EFI_SIGNATURE_LIST
*SigListAppend
,
89 OUT EFI_SIGNATURE_LIST
**SigListOut
,
90 IN OUT UINTN
*SigListsSize
93 EFI_SIGNATURE_LIST
*TmpSigList
;
95 UINTN NewSigListsSize
;
97 NewSigListsSize
= *SigListsSize
+ SigListAppend
->SignatureListSize
;
99 TmpSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (NewSigListsSize
);
100 if (TmpSigList
== NULL
) {
101 return EFI_OUT_OF_RESOURCES
;
104 CopyMem (TmpSigList
, SigLists
, *SigListsSize
);
106 Offset
= (UINT8
*)TmpSigList
;
107 Offset
+= *SigListsSize
;
108 CopyMem ((VOID
*)Offset
, SigListAppend
, SigListAppend
->SignatureListSize
);
110 *SigListsSize
= NewSigListsSize
;
111 *SigListOut
= TmpSigList
;
116 Create a EFI Signature List with data fetched from section specified as a argument.
117 Found keys are verified using RsaGetPublicKeyFromX509().
119 @param[in] KeyFileGuid A pointer to to the FFS filename GUID
120 @param[out] SigListsSize A pointer to size of signature list
121 @param[out] SigListOut a pointer to a callee-allocated buffer with signature lists
123 @retval EFI_SUCCESS Create time based payload successfully.
124 @retval EFI_NOT_FOUND Section with key has not been found.
125 @retval EFI_INVALID_PARAMETER Embedded key has a wrong format.
126 @retval Others Unexpected error happens.
130 SecureBootFetchData (
131 IN EFI_GUID
*KeyFileGuid
,
132 OUT UINTN
*SigListsSize
,
133 OUT EFI_SIGNATURE_LIST
**SigListOut
136 EFI_SIGNATURE_LIST
*EfiSig
;
137 EFI_SIGNATURE_LIST
*TmpEfiSig
;
138 EFI_SIGNATURE_LIST
*TmpEfiSig2
;
150 Status
= GetSectionFromAnyFv (
158 if (Status
== EFI_SUCCESS
) {
160 if (RsaGetPublicKeyFromX509 (Buffer
, Size
, &RsaPubKey
) == FALSE
) {
161 DEBUG ((DEBUG_ERROR
, "%a: Invalid key format: %d\n", __FUNCTION__
, KeyIndex
));
162 if (EfiSig
!= NULL
) {
166 return EFI_INVALID_PARAMETER
;
169 Status
= CreateSigList (Buffer
, Size
, &TmpEfiSig
);
172 // Concatenate lists if more than one section found
176 *SigListsSize
= TmpEfiSig
->SignatureListSize
;
178 ConcatenateSigList (EfiSig
, TmpEfiSig
, &TmpEfiSig2
, SigListsSize
);
180 FreePool (TmpEfiSig
);
186 } if (Status
== EFI_NOT_FOUND
) {
192 return EFI_NOT_FOUND
;
195 *SigListOut
= EfiSig
;
201 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
202 descriptor with the input data. NO authentication is required in this function.
204 @param[in, out] DataSize On input, the size of Data buffer in bytes.
205 On output, the size of data returned in Data
207 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
208 pointer to NULL to wrap an empty payload.
209 On output, Pointer to the new payload date buffer allocated from pool,
210 it's caller's responsibility to free the memory when finish using it.
212 @retval EFI_SUCCESS Create time based payload successfully.
213 @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.
214 @retval EFI_INVALID_PARAMETER The parameter is invalid.
215 @retval Others Unexpected error happens.
219 CreateTimeBasedPayload (
220 IN OUT UINTN
*DataSize
,
228 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
229 UINTN DescriptorSize
;
232 if (Data
== NULL
|| DataSize
== NULL
) {
233 return EFI_INVALID_PARAMETER
;
237 // In Setup mode or Custom mode, the variable does not need to be signed but the
238 // parameters to the SetVariable() call still need to be prepared as authenticated
239 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
243 PayloadSize
= *DataSize
;
245 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
246 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
247 if (NewData
== NULL
) {
248 return EFI_OUT_OF_RESOURCES
;
251 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
252 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
255 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
257 ZeroMem (&Time
, sizeof (EFI_TIME
));
258 Status
= gRT
->GetTime (&Time
, NULL
);
259 if (EFI_ERROR (Status
)) {
268 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
270 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
271 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
272 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
273 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
275 if (Payload
!= NULL
) {
279 *DataSize
= DescriptorSize
+ PayloadSize
;
285 Internal helper function to delete a Variable given its name and GUID, NO authentication
288 @param[in] VariableName Name of the Variable.
289 @param[in] VendorGuid GUID of the Variable.
291 @retval EFI_SUCCESS Variable deleted successfully.
292 @retval Others The driver failed to start the device.
297 IN CHAR16
*VariableName
,
298 IN EFI_GUID
*VendorGuid
307 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
308 if (Variable
== NULL
) {
315 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
316 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
318 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
319 if (EFI_ERROR (Status
)) {
320 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
324 Status
= gRT
->SetVariable (
339 Set the platform secure boot mode into "Custom" or "Standard" mode.
341 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
342 CUSTOM_SECURE_BOOT_MODE.
344 @return EFI_SUCCESS The platform has switched to the special mode successfully.
345 @return other Fail to operate the secure boot mode.
350 IN UINT8 SecureBootMode
353 return gRT
->SetVariable (
354 EFI_CUSTOM_MODE_NAME
,
355 &gEfiCustomModeEnableGuid
,
356 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
363 Fetches the value of SetupMode variable.
365 @param[out] SetupMode Pointer to UINT8 for SetupMode output
367 @retval other Retval from GetVariable.
378 Size
= sizeof (*SetupMode
);
379 Status
= gRT
->GetVariable (
381 &gEfiGlobalVariableGuid
,
386 if (EFI_ERROR (Status
)) {
394 Clears the content of the 'db' variable.
396 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
397 while VendorGuid is NULL.
398 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
408 Status
= DeleteVariable (
409 EFI_IMAGE_SECURITY_DATABASE
,
410 &gEfiImageSecurityDatabaseGuid
417 Clears the content of the 'dbx' variable.
419 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
420 while VendorGuid is NULL.
421 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
431 Status
= DeleteVariable (
432 EFI_IMAGE_SECURITY_DATABASE1
,
433 &gEfiImageSecurityDatabaseGuid
440 Clears the content of the 'dbt' variable.
442 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
443 while VendorGuid is NULL.
444 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
454 Status
= DeleteVariable (
455 EFI_IMAGE_SECURITY_DATABASE2
,
456 &gEfiImageSecurityDatabaseGuid
463 Clears the content of the 'KEK' variable.
465 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
466 while VendorGuid is NULL.
467 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
477 Status
= DeleteVariable (
478 EFI_KEY_EXCHANGE_KEY_NAME
,
479 &gEfiGlobalVariableGuid
486 Remove the PK variable.
488 @retval EFI_SUCCESS Delete PK successfully.
489 @retval Others Could not allow to delete PK.
500 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
501 if (EFI_ERROR (Status
)) {
505 Status
= DeleteVariable (
506 EFI_PLATFORM_KEY_NAME
,
507 &gEfiGlobalVariableGuid