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 <UefiSecureBoot.h>
14 #include <Guid/GlobalVariable.h>
15 #include <Guid/AuthenticatedVariableFormat.h>
16 #include <Guid/ImageAuthentication.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>
25 // This time can be used when deleting variables, as it should be greater than any variable time.
26 EFI_TIME mMaxTimestamp
= {
34 0x00000000, // Nanosecond
40 /** Creates EFI Signature List structure.
42 @param[in] Data A pointer to signature data.
43 @param[in] Size Size of signature data.
44 @param[out] SigList Created Signature List.
46 @retval EFI_SUCCESS Signature List was created successfully.
47 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
54 OUT EFI_SIGNATURE_LIST
**SigList
58 EFI_SIGNATURE_LIST
*TmpSigList
;
59 EFI_SIGNATURE_DATA
*SigData
;
62 // Allocate data for Signature Database
64 SigListSize
= sizeof (EFI_SIGNATURE_LIST
) + sizeof (EFI_SIGNATURE_DATA
) - 1 + Size
;
65 TmpSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (SigListSize
);
66 if (TmpSigList
== NULL
) {
67 return EFI_OUT_OF_RESOURCES
;
71 // Only gEfiCertX509Guid type is supported
73 TmpSigList
->SignatureListSize
= (UINT32
)SigListSize
;
74 TmpSigList
->SignatureSize
= (UINT32
)(sizeof (EFI_SIGNATURE_DATA
) - 1 + Size
);
75 TmpSigList
->SignatureHeaderSize
= 0;
76 CopyGuid (&TmpSigList
->SignatureType
, &gEfiCertX509Guid
);
81 SigData
= (EFI_SIGNATURE_DATA
*)(TmpSigList
+ 1);
82 CopyGuid (&SigData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
83 CopyMem (&SigData
->SignatureData
[0], Data
, Size
);
85 *SigList
= TmpSigList
;
90 /** Adds new signature list to signature database.
92 @param[in] SigLists A pointer to signature database.
93 @param[in] SigListAppend A signature list to be added.
94 @param[out] *SigListOut Created signature database.
95 @param[in, out] SigListsSize A size of created signature database.
97 @retval EFI_SUCCESS Signature List was added successfully.
98 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
103 IN EFI_SIGNATURE_LIST
*SigLists
,
104 IN EFI_SIGNATURE_LIST
*SigListAppend
,
105 OUT EFI_SIGNATURE_LIST
**SigListOut
,
106 IN OUT UINTN
*SigListsSize
109 EFI_SIGNATURE_LIST
*TmpSigList
;
111 UINTN NewSigListsSize
;
113 NewSigListsSize
= *SigListsSize
+ SigListAppend
->SignatureListSize
;
115 TmpSigList
= (EFI_SIGNATURE_LIST
*)AllocateZeroPool (NewSigListsSize
);
116 if (TmpSigList
== NULL
) {
117 return EFI_OUT_OF_RESOURCES
;
120 CopyMem (TmpSigList
, SigLists
, *SigListsSize
);
122 Offset
= (UINT8
*)TmpSigList
;
123 Offset
+= *SigListsSize
;
124 CopyMem ((VOID
*)Offset
, SigListAppend
, SigListAppend
->SignatureListSize
);
126 *SigListsSize
= NewSigListsSize
;
127 *SigListOut
= TmpSigList
;
132 Create a EFI Signature List with data supplied from input argument.
133 The input certificates from KeyInfo parameter should be DER-encoded
136 @param[out] SigListsSize A pointer to size of signature list
137 @param[out] SigListOut A pointer to a callee-allocated buffer with signature lists
138 @param[in] KeyInfoCount The number of certificate pointer and size pairs inside KeyInfo.
139 @param[in] KeyInfo A pointer to all certificates, in the format of DER-encoded,
140 to be concatenated into signature lists.
142 @retval EFI_SUCCESS Created signature list from payload successfully.
143 @retval EFI_NOT_FOUND Section with key has not been found.
144 @retval EFI_INVALID_PARAMETER Embedded key has a wrong format or input pointers are NULL.
145 @retval Others Unexpected error happens.
150 SecureBootCreateDataFromInput (
151 OUT UINTN
*SigListsSize
,
152 OUT EFI_SIGNATURE_LIST
**SigListOut
,
153 IN UINTN KeyInfoCount
,
154 IN CONST SECURE_BOOT_CERTIFICATE_INFO
*KeyInfo
157 EFI_SIGNATURE_LIST
*EfiSig
;
158 EFI_SIGNATURE_LIST
*TmpEfiSig
;
159 EFI_SIGNATURE_LIST
*TmpEfiSig2
;
166 if ((SigListOut
== NULL
) || (SigListsSize
== NULL
)) {
167 return EFI_INVALID_PARAMETER
;
170 if ((KeyInfoCount
== 0) || (KeyInfo
== NULL
)) {
171 return EFI_INVALID_PARAMETER
;
178 while (InputIndex
< KeyInfoCount
) {
179 if (KeyInfo
[InputIndex
].Data
!= NULL
) {
180 Size
= KeyInfo
[InputIndex
].DataSize
;
181 Buffer
= AllocateCopyPool (Size
, KeyInfo
[InputIndex
].Data
);
182 if (Buffer
== NULL
) {
183 if (EfiSig
!= NULL
) {
187 return EFI_OUT_OF_RESOURCES
;
190 Status
= CreateSigList (Buffer
, Size
, &TmpEfiSig
);
192 if (EFI_ERROR (Status
)) {
198 // Concatenate lists if more than one section found
202 *SigListsSize
= TmpEfiSig
->SignatureListSize
;
204 ConcatenateSigList (EfiSig
, TmpEfiSig
, &TmpEfiSig2
, SigListsSize
);
206 FreePool (TmpEfiSig
);
218 return EFI_NOT_FOUND
;
221 *SigListOut
= EfiSig
;
227 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
228 descriptor with the input data. NO authentication is required in this function.
230 @param[in, out] DataSize On input, the size of Data buffer in bytes.
231 On output, the size of data returned in Data
233 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
234 pointer to NULL to wrap an empty payload.
235 On output, Pointer to the new payload date buffer allocated from pool,
236 it's caller's responsibility to free the memory when finish using it.
237 @param[in] Time Pointer to time information to created time based payload.
239 @retval EFI_SUCCESS Create time based payload successfully.
240 @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.
241 @retval EFI_INVALID_PARAMETER The parameter is invalid.
242 @retval Others Unexpected error happens.
247 CreateTimeBasedPayload (
248 IN OUT UINTN
*DataSize
,
256 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
257 UINTN DescriptorSize
;
259 if ((Data
== NULL
) || (DataSize
== NULL
) || (Time
== NULL
)) {
260 DEBUG ((DEBUG_ERROR
, "%a(), invalid arg\n", __FUNCTION__
));
261 return EFI_INVALID_PARAMETER
;
265 // In Setup mode or Custom mode, the variable does not need to be signed but the
266 // parameters to the SetVariable() call still need to be prepared as authenticated
267 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
271 PayloadSize
= *DataSize
;
273 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
274 NewData
= (UINT8
*)AllocateZeroPool (DescriptorSize
+ PayloadSize
);
275 if (NewData
== NULL
) {
276 DEBUG ((DEBUG_ERROR
, "%a() Out of resources.\n", __FUNCTION__
));
277 return EFI_OUT_OF_RESOURCES
;
280 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
281 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
284 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*)(NewData
);
286 CopyMem (&DescriptorData
->TimeStamp
, Time
, sizeof (EFI_TIME
));
288 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
289 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
290 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
291 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
293 if (Payload
!= NULL
) {
298 *DataSize
= DescriptorSize
+ PayloadSize
;
304 Internal helper function to delete a Variable given its name and GUID, NO authentication
307 @param[in] VariableName Name of the Variable.
308 @param[in] VendorGuid GUID of the Variable.
310 @retval EFI_SUCCESS Variable deleted successfully.
311 @retval Others The driver failed to start the device.
317 IN CHAR16
*VariableName
,
318 IN EFI_GUID
*VendorGuid
327 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
328 if (Variable
== NULL
) {
336 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
337 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
339 Status
= CreateTimeBasedPayload (&DataSize
, &Data
, &mMaxTimestamp
);
340 if (EFI_ERROR (Status
)) {
341 DEBUG ((DEBUG_ERROR
, "Fail to create time-based data payload: %r", Status
));
345 Status
= gRT
->SetVariable (
361 Set the platform secure boot mode into "Custom" or "Standard" mode.
363 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
364 CUSTOM_SECURE_BOOT_MODE.
366 @return EFI_SUCCESS The platform has switched to the special mode successfully.
367 @return other Fail to operate the secure boot mode.
373 IN UINT8 SecureBootMode
376 return gRT
->SetVariable (
377 EFI_CUSTOM_MODE_NAME
,
378 &gEfiCustomModeEnableGuid
,
379 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
386 Fetches the value of SetupMode variable.
388 @param[out] SetupMode Pointer to UINT8 for SetupMode output
390 @retval other Retval from GetVariable.
401 Size
= sizeof (*SetupMode
);
402 Status
= gRT
->GetVariable (
404 &gEfiGlobalVariableGuid
,
409 if (EFI_ERROR (Status
)) {
417 Clears the content of the 'db' 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_DATABASE
,
433 &gEfiImageSecurityDatabaseGuid
440 Clears the content of the 'dbx' 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_DATABASE1
,
456 &gEfiImageSecurityDatabaseGuid
463 Clears the content of the 'dbt' 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_IMAGE_SECURITY_DATABASE2
,
479 &gEfiImageSecurityDatabaseGuid
486 Clears the content of the 'KEK' variable.
488 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
489 while VendorGuid is NULL.
490 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
500 Status
= DeleteVariable (
501 EFI_KEY_EXCHANGE_KEY_NAME
,
502 &gEfiGlobalVariableGuid
509 Remove the PK variable.
511 @retval EFI_SUCCESS Delete PK successfully.
512 @retval Others Could not allow to delete PK.
523 Status
= SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE
);
524 if (EFI_ERROR (Status
)) {
528 Status
= DeleteVariable (
529 EFI_PLATFORM_KEY_NAME
,
530 &gEfiGlobalVariableGuid