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
;
149 Status
= GetSectionFromAnyFv (
157 if (Status
== EFI_SUCCESS
) {
159 if (RsaGetPublicKeyFromX509 (Buffer
, Size
, &RsaPubKey
) == FALSE
) {
160 DEBUG ((DEBUG_ERROR
, "%a: Invalid key format: %d\n", __FUNCTION__
, KeyIndex
));
161 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
);
188 if (Status
== EFI_NOT_FOUND
) {
194 return EFI_NOT_FOUND
;
197 *SigListOut
= EfiSig
;
203 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
204 descriptor with the input data. NO authentication is required in this function.
206 @param[in, out] DataSize On input, the size of Data buffer in bytes.
207 On output, the size of data returned in Data
209 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
210 pointer to NULL to wrap an empty payload.
211 On output, Pointer to the new payload date buffer allocated from pool,
212 it's caller's responsibility to free the memory when finish using it.
214 @retval EFI_SUCCESS Create time based payload successfully.
215 @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.
216 @retval EFI_INVALID_PARAMETER The parameter is invalid.
217 @retval Others Unexpected error happens.
221 CreateTimeBasedPayload (
222 IN OUT UINTN
*DataSize
,
230 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
231 UINTN DescriptorSize
;
234 if ((Data
== NULL
) || (DataSize
== NULL
)) {
235 return EFI_INVALID_PARAMETER
;
239 // In Setup mode or Custom mode, the variable does not need to be signed but the
240 // parameters to the SetVariable() call still need to be prepared as authenticated
241 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
245 PayloadSize
= *DataSize
;
247 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
248 NewData
= (UINT8
*)AllocateZeroPool (DescriptorSize
+ PayloadSize
);
249 if (NewData
== NULL
) {
250 return EFI_OUT_OF_RESOURCES
;
253 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
254 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
257 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*)(NewData
);
259 ZeroMem (&Time
, sizeof (EFI_TIME
));
260 Status
= gRT
->GetTime (&Time
, NULL
);
261 if (EFI_ERROR (Status
)) {
271 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
273 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
274 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
275 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
276 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
278 if (Payload
!= NULL
) {
282 *DataSize
= DescriptorSize
+ PayloadSize
;
288 Internal helper function to delete a Variable given its name and GUID, NO authentication
291 @param[in] VariableName Name of the Variable.
292 @param[in] VendorGuid GUID of the Variable.
294 @retval EFI_SUCCESS Variable deleted successfully.
295 @retval Others The driver failed to start the device.
300 IN CHAR16
*VariableName
,
301 IN EFI_GUID
*VendorGuid
310 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
311 if (Variable
== NULL
) {
319 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
320 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
322 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
323 if (EFI_ERROR (Status
)) {
324 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
328 Status
= gRT
->SetVariable (
344 Set the platform secure boot mode into "Custom" or "Standard" mode.
346 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
347 CUSTOM_SECURE_BOOT_MODE.
349 @return EFI_SUCCESS The platform has switched to the special mode successfully.
350 @return other Fail to operate the secure boot mode.
355 IN UINT8 SecureBootMode
358 return gRT
->SetVariable (
359 EFI_CUSTOM_MODE_NAME
,
360 &gEfiCustomModeEnableGuid
,
361 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
368 Fetches the value of SetupMode variable.
370 @param[out] SetupMode Pointer to UINT8 for SetupMode output
372 @retval other Retval from GetVariable.
383 Size
= sizeof (*SetupMode
);
384 Status
= gRT
->GetVariable (
386 &gEfiGlobalVariableGuid
,
391 if (EFI_ERROR (Status
)) {
399 Clears the content of the 'db' variable.
401 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
402 while VendorGuid is NULL.
403 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
413 Status
= DeleteVariable (
414 EFI_IMAGE_SECURITY_DATABASE
,
415 &gEfiImageSecurityDatabaseGuid
422 Clears the content of the 'dbx' variable.
424 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
425 while VendorGuid is NULL.
426 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
436 Status
= DeleteVariable (
437 EFI_IMAGE_SECURITY_DATABASE1
,
438 &gEfiImageSecurityDatabaseGuid
445 Clears the content of the 'dbt' variable.
447 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
448 while VendorGuid is NULL.
449 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
459 Status
= DeleteVariable (
460 EFI_IMAGE_SECURITY_DATABASE2
,
461 &gEfiImageSecurityDatabaseGuid
468 Clears the content of the 'KEK' variable.
470 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
471 while VendorGuid is NULL.
472 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
482 Status
= DeleteVariable (
483 EFI_KEY_EXCHANGE_KEY_NAME
,
484 &gEfiGlobalVariableGuid
491 Remove the PK variable.
493 @retval EFI_SUCCESS Delete PK successfully.
494 @retval Others Could not allow to delete PK.
505 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
506 if (EFI_ERROR (Status
)) {
510 Status
= DeleteVariable (
511 EFI_PLATFORM_KEY_NAME
,
512 &gEfiGlobalVariableGuid