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 Copyright (c) Microsoft Corporation.
10 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Guid/GlobalVariable.h>
14 #include <Guid/AuthenticatedVariableFormat.h>
15 #include <Guid/ImageAuthentication.h>
16 #include <Library/BaseCryptLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/UefiLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiRuntimeServicesTableLib.h>
23 #include <Library/SecureBootVariableLib.h>
24 #include "Library/DxeServicesLib.h"
26 // This time can be used when deleting variables, as it should be greater than any variable time.
27 EFI_TIME mMaxTimestamp
= {
35 0x00000000, // Nanosecond
41 /** Creates EFI Signature List structure.
43 @param[in] Data A pointer to signature data.
44 @param[in] Size Size of signature data.
45 @param[out] SigList Created Signature List.
47 @retval EFI_SUCCESS Signature List was created successfully.
48 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
55 OUT EFI_SIGNATURE_LIST
**SigList
59 EFI_SIGNATURE_LIST
*TmpSigList
;
60 EFI_SIGNATURE_DATA
*SigData
;
63 // Allocate data for Signature Database
65 SigListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + Size
;
66 TmpSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (SigListSize
);
67 if (TmpSigList
== NULL
) {
68 return EFI_OUT_OF_RESOURCES
;
72 // Only gEfiCertX509Guid type is supported
74 TmpSigList
->SignatureListSize
= (UINT32
)SigListSize
;
75 TmpSigList
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + Size
);
76 TmpSigList
->SignatureHeaderSize
= 0;
77 CopyGuid (&TmpSigList
->SignatureType
, &gEfiCertX509Guid
);
82 SigData
= (EFI_SIGNATURE_DATA
*)(TmpSigList
+ 1);
83 CopyGuid (&SigData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
84 CopyMem (&SigData
->SignatureData
[0], Data
, Size
);
86 *SigList
= TmpSigList
;
91 /** Adds new signature list to signature database.
93 @param[in] SigLists A pointer to signature database.
94 @param[in] SigListAppend A signature list to be added.
95 @param[out] *SigListOut Created signature database.
96 @param[in, out] SigListsSize A size of created signature database.
98 @retval EFI_SUCCESS Signature List was added successfully.
99 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
104 IN EFI_SIGNATURE_LIST
*SigLists
,
105 IN EFI_SIGNATURE_LIST
*SigListAppend
,
106 OUT EFI_SIGNATURE_LIST
**SigListOut
,
107 IN OUT UINTN
*SigListsSize
110 EFI_SIGNATURE_LIST
*TmpSigList
;
112 UINTN NewSigListsSize
;
114 NewSigListsSize
= *SigListsSize
+ SigListAppend
->SignatureListSize
;
116 TmpSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (NewSigListsSize
);
117 if (TmpSigList
== NULL
) {
118 return EFI_OUT_OF_RESOURCES
;
121 CopyMem (TmpSigList
, SigLists
, *SigListsSize
);
123 Offset
= (UINT8
*)TmpSigList
;
124 Offset
+= *SigListsSize
;
125 CopyMem ((VOID
*)Offset
, SigListAppend
, SigListAppend
->SignatureListSize
);
127 *SigListsSize
= NewSigListsSize
;
128 *SigListOut
= TmpSigList
;
133 Create a EFI Signature List with data fetched from section specified as a argument.
134 Found keys are verified using RsaGetPublicKeyFromX509().
136 @param[in] KeyFileGuid A pointer to to the FFS filename GUID
137 @param[out] SigListsSize A pointer to size of signature list
138 @param[out] SigListsOut a pointer to a callee-allocated buffer with signature lists
140 @retval EFI_SUCCESS Create time based payload successfully.
141 @retval EFI_NOT_FOUND Section with key has not been found.
142 @retval EFI_INVALID_PARAMETER Embedded key has a wrong format.
143 @retval Others Unexpected error happens.
147 SecureBootFetchData (
148 IN EFI_GUID
*KeyFileGuid
,
149 OUT UINTN
*SigListsSize
,
150 OUT EFI_SIGNATURE_LIST
**SigListOut
153 EFI_SIGNATURE_LIST
*EfiSig
;
154 EFI_SIGNATURE_LIST
*TmpEfiSig
;
155 EFI_SIGNATURE_LIST
*TmpEfiSig2
;
166 Status
= GetSectionFromAnyFv (
174 if (Status
== EFI_SUCCESS
) {
176 if (RsaGetPublicKeyFromX509 (Buffer
, Size
, &RsaPubKey
) == FALSE
) {
177 DEBUG ((DEBUG_ERROR
, "%a: Invalid key format: %d\n", __FUNCTION__
, KeyIndex
));
178 if (EfiSig
!= NULL
) {
183 return EFI_INVALID_PARAMETER
;
186 Status
= CreateSigList (Buffer
, Size
, &TmpEfiSig
);
189 // Concatenate lists if more than one section found
193 *SigListsSize
= TmpEfiSig
->SignatureListSize
;
195 ConcatenateSigList (EfiSig
, TmpEfiSig
, &TmpEfiSig2
, SigListsSize
);
197 FreePool (TmpEfiSig
);
205 if (Status
== EFI_NOT_FOUND
) {
211 return EFI_NOT_FOUND
;
214 *SigListOut
= EfiSig
;
220 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
221 descriptor with the input data. NO authentication is required in this function.
223 @param[in, out] DataSize On input, the size of Data buffer in bytes.
224 On output, the size of data returned in Data
226 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
227 pointer to NULL to wrap an empty payload.
228 On output, Pointer to the new payload date buffer allocated from pool,
229 it's caller's responsibility to free the memory when finish using it.
230 @param[in] Time Pointer to time information to created time based payload.
232 @retval EFI_SUCCESS Create time based payload successfully.
233 @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.
234 @retval EFI_INVALID_PARAMETER The parameter is invalid.
235 @retval Others Unexpected error happens.
240 CreateTimeBasedPayload (
241 IN OUT UINTN
*DataSize
,
249 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
250 UINTN DescriptorSize
;
252 if ((Data
== NULL
) || (DataSize
== NULL
) || (Time
== NULL
)) {
253 DEBUG ((DEBUG_ERROR
, "%a(), invalid arg\n", __FUNCTION__
));
254 return EFI_INVALID_PARAMETER
;
258 // In Setup mode or Custom mode, the variable does not need to be signed but the
259 // parameters to the SetVariable() call still need to be prepared as authenticated
260 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
264 PayloadSize
= *DataSize
;
266 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
267 NewData
= (UINT8
*)AllocateZeroPool (DescriptorSize
+ PayloadSize
);
268 if (NewData
== NULL
) {
269 DEBUG ((DEBUG_ERROR
, "%a() Out of resources.\n", __FUNCTION__
));
270 return EFI_OUT_OF_RESOURCES
;
273 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
274 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
277 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*)(NewData
);
279 CopyMem (&DescriptorData
->TimeStamp
, Time
, sizeof (EFI_TIME
));
281 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
282 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
283 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
284 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
286 if (Payload
!= NULL
) {
291 *DataSize
= DescriptorSize
+ PayloadSize
;
297 Internal helper function to delete a Variable given its name and GUID, NO authentication
300 @param[in] VariableName Name of the Variable.
301 @param[in] VendorGuid GUID of the Variable.
303 @retval EFI_SUCCESS Variable deleted successfully.
304 @retval Others The driver failed to start the device.
310 IN CHAR16
*VariableName
,
311 IN EFI_GUID
*VendorGuid
320 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
321 if (Variable
== NULL
) {
329 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
330 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
332 Status
= CreateTimeBasedPayload (&DataSize
, &Data
, &mMaxTimestamp
);
333 if (EFI_ERROR (Status
)) {
334 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
338 Status
= gRT
->SetVariable (
354 Set the platform secure boot mode into "Custom" or "Standard" mode.
356 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
357 CUSTOM_SECURE_BOOT_MODE.
359 @return EFI_SUCCESS The platform has switched to the special mode successfully.
360 @return other Fail to operate the secure boot mode.
366 IN UINT8 SecureBootMode
369 return gRT
->SetVariable (
370 EFI_CUSTOM_MODE_NAME
,
371 &gEfiCustomModeEnableGuid
,
372 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
379 Fetches the value of SetupMode variable.
381 @param[out] SetupMode Pointer to UINT8 for SetupMode output
383 @retval other Retval from GetVariable.
394 Size
= sizeof (*SetupMode
);
395 Status
= gRT
->GetVariable (
397 &gEfiGlobalVariableGuid
,
402 if (EFI_ERROR (Status
)) {
410 Clears the content of the 'db' variable.
412 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
413 while VendorGuid is NULL.
414 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
424 Status
= DeleteVariable (
425 EFI_IMAGE_SECURITY_DATABASE
,
426 &gEfiImageSecurityDatabaseGuid
433 Clears the content of the 'dbx' variable.
435 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
436 while VendorGuid is NULL.
437 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
447 Status
= DeleteVariable (
448 EFI_IMAGE_SECURITY_DATABASE1
,
449 &gEfiImageSecurityDatabaseGuid
456 Clears the content of the 'dbt' variable.
458 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
459 while VendorGuid is NULL.
460 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
470 Status
= DeleteVariable (
471 EFI_IMAGE_SECURITY_DATABASE2
,
472 &gEfiImageSecurityDatabaseGuid
479 Clears the content of the 'KEK' variable.
481 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
482 while VendorGuid is NULL.
483 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
493 Status
= DeleteVariable (
494 EFI_KEY_EXCHANGE_KEY_NAME
,
495 &gEfiGlobalVariableGuid
502 Remove the PK variable.
504 @retval EFI_SUCCESS Delete PK successfully.
505 @retval Others Could not allow to delete PK.
516 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
517 if (EFI_ERROR (Status
)) {
521 Status
= DeleteVariable (
522 EFI_PLATFORM_KEY_NAME
,
523 &gEfiGlobalVariableGuid