]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c
SecurityPkg: Apply uncrustify changes
[mirror_edk2.git] / SecurityPkg / Library / SecureBootVariableLib / SecureBootVariableLib.c
CommitLineData
bb806a6e
GB
1/** @file\r
2 This library provides helper functions to set/clear Secure Boot\r
3 keys and databases.\r
4\r
5 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
6 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>\r
7 Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>\r
8 Copyright (c) 2021, Semihalf All rights reserved.<BR>\r
9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
10**/\r
11#include <Guid/GlobalVariable.h>\r
12#include <Guid/AuthenticatedVariableFormat.h>\r
13#include <Guid/ImageAuthentication.h>\r
14#include <Library/BaseCryptLib.h>\r
15#include <Library/BaseLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/UefiRuntimeServicesTableLib.h>\r
21#include <Library/SecureBootVariableLib.h>\r
22#include "Library/DxeServicesLib.h"\r
23\r
24/** Creates EFI Signature List structure.\r
25\r
26 @param[in] Data A pointer to signature data.\r
27 @param[in] Size Size of signature data.\r
28 @param[out] SigList Created Signature List.\r
29\r
30 @retval EFI_SUCCESS Signature List was created successfully.\r
31 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
32**/\r
33STATIC\r
34EFI_STATUS\r
35CreateSigList (\r
c411b485
MK
36 IN VOID *Data,\r
37 IN UINTN Size,\r
38 OUT EFI_SIGNATURE_LIST **SigList\r
bb806a6e
GB
39 )\r
40{\r
c411b485
MK
41 UINTN SigListSize;\r
42 EFI_SIGNATURE_LIST *TmpSigList;\r
43 EFI_SIGNATURE_DATA *SigData;\r
bb806a6e
GB
44\r
45 //\r
46 // Allocate data for Signature Database\r
47 //\r
48 SigListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Size;\r
c411b485 49 TmpSigList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (SigListSize);\r
bb806a6e
GB
50 if (TmpSigList == NULL) {\r
51 return EFI_OUT_OF_RESOURCES;\r
52 }\r
53\r
54 //\r
55 // Only gEfiCertX509Guid type is supported\r
56 //\r
c411b485
MK
57 TmpSigList->SignatureListSize = (UINT32)SigListSize;\r
58 TmpSigList->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + Size);\r
bb806a6e
GB
59 TmpSigList->SignatureHeaderSize = 0;\r
60 CopyGuid (&TmpSigList->SignatureType, &gEfiCertX509Guid);\r
61\r
62 //\r
63 // Copy key data\r
64 //\r
c411b485 65 SigData = (EFI_SIGNATURE_DATA *)(TmpSigList + 1);\r
bb806a6e
GB
66 CopyGuid (&SigData->SignatureOwner, &gEfiGlobalVariableGuid);\r
67 CopyMem (&SigData->SignatureData[0], Data, Size);\r
68\r
69 *SigList = TmpSigList;\r
70\r
71 return EFI_SUCCESS;\r
72}\r
73\r
74/** Adds new signature list to signature database.\r
75\r
76 @param[in] SigLists A pointer to signature database.\r
77 @param[in] SigListAppend A signature list to be added.\r
78 @param[out] *SigListOut Created signature database.\r
79 @param[in, out] SigListsSize A size of created signature database.\r
80\r
81 @retval EFI_SUCCESS Signature List was added successfully.\r
82 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
83**/\r
84STATIC\r
85EFI_STATUS\r
86ConcatenateSigList (\r
c411b485
MK
87 IN EFI_SIGNATURE_LIST *SigLists,\r
88 IN EFI_SIGNATURE_LIST *SigListAppend,\r
89 OUT EFI_SIGNATURE_LIST **SigListOut,\r
90 IN OUT UINTN *SigListsSize\r
91 )\r
bb806a6e 92{\r
c411b485
MK
93 EFI_SIGNATURE_LIST *TmpSigList;\r
94 UINT8 *Offset;\r
95 UINTN NewSigListsSize;\r
bb806a6e
GB
96\r
97 NewSigListsSize = *SigListsSize + SigListAppend->SignatureListSize;\r
98\r
c411b485 99 TmpSigList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (NewSigListsSize);\r
bb806a6e
GB
100 if (TmpSigList == NULL) {\r
101 return EFI_OUT_OF_RESOURCES;\r
102 }\r
103\r
104 CopyMem (TmpSigList, SigLists, *SigListsSize);\r
105\r
c411b485 106 Offset = (UINT8 *)TmpSigList;\r
bb806a6e
GB
107 Offset += *SigListsSize;\r
108 CopyMem ((VOID *)Offset, SigListAppend, SigListAppend->SignatureListSize);\r
109\r
110 *SigListsSize = NewSigListsSize;\r
c411b485 111 *SigListOut = TmpSigList;\r
bb806a6e
GB
112 return EFI_SUCCESS;\r
113}\r
114\r
115/**\r
116 Create a EFI Signature List with data fetched from section specified as a argument.\r
117 Found keys are verified using RsaGetPublicKeyFromX509().\r
118\r
119 @param[in] KeyFileGuid A pointer to to the FFS filename GUID\r
120 @param[out] SigListsSize A pointer to size of signature list\r
121 @param[out] SigListOut a pointer to a callee-allocated buffer with signature lists\r
122\r
123 @retval EFI_SUCCESS Create time based payload successfully.\r
124 @retval EFI_NOT_FOUND Section with key has not been found.\r
125 @retval EFI_INVALID_PARAMETER Embedded key has a wrong format.\r
126 @retval Others Unexpected error happens.\r
127\r
128**/\r
129EFI_STATUS\r
130SecureBootFetchData (\r
c411b485
MK
131 IN EFI_GUID *KeyFileGuid,\r
132 OUT UINTN *SigListsSize,\r
133 OUT EFI_SIGNATURE_LIST **SigListOut\r
134 )\r
bb806a6e 135{\r
c411b485
MK
136 EFI_SIGNATURE_LIST *EfiSig;\r
137 EFI_SIGNATURE_LIST *TmpEfiSig;\r
138 EFI_SIGNATURE_LIST *TmpEfiSig2;\r
139 EFI_STATUS Status;\r
140 VOID *Buffer;\r
141 VOID *RsaPubKey;\r
bb806a6e
GB
142 UINTN Size;\r
143 UINTN KeyIndex;\r
144\r
c411b485
MK
145 KeyIndex = 0;\r
146 EfiSig = NULL;\r
bb806a6e
GB
147 *SigListsSize = 0;\r
148 while (1) {\r
149 Status = GetSectionFromAnyFv (\r
150 KeyFileGuid,\r
151 EFI_SECTION_RAW,\r
152 KeyIndex,\r
153 &Buffer,\r
154 &Size\r
155 );\r
156\r
157 if (Status == EFI_SUCCESS) {\r
158 RsaPubKey = NULL;\r
159 if (RsaGetPublicKeyFromX509 (Buffer, Size, &RsaPubKey) == FALSE) {\r
160 DEBUG ((DEBUG_ERROR, "%a: Invalid key format: %d\n", __FUNCTION__, KeyIndex));\r
161 if (EfiSig != NULL) {\r
c411b485 162 FreePool (EfiSig);\r
bb806a6e 163 }\r
c411b485
MK
164\r
165 FreePool (Buffer);\r
bb806a6e
GB
166 return EFI_INVALID_PARAMETER;\r
167 }\r
168\r
169 Status = CreateSigList (Buffer, Size, &TmpEfiSig);\r
170\r
171 //\r
172 // Concatenate lists if more than one section found\r
173 //\r
174 if (KeyIndex == 0) {\r
c411b485 175 EfiSig = TmpEfiSig;\r
bb806a6e
GB
176 *SigListsSize = TmpEfiSig->SignatureListSize;\r
177 } else {\r
178 ConcatenateSigList (EfiSig, TmpEfiSig, &TmpEfiSig2, SigListsSize);\r
179 FreePool (EfiSig);\r
180 FreePool (TmpEfiSig);\r
181 EfiSig = TmpEfiSig2;\r
182 }\r
183\r
184 KeyIndex++;\r
185 FreePool (Buffer);\r
c411b485
MK
186 }\r
187\r
188 if (Status == EFI_NOT_FOUND) {\r
bb806a6e
GB
189 break;\r
190 }\r
c411b485 191 }\r
bb806a6e
GB
192\r
193 if (KeyIndex == 0) {\r
194 return EFI_NOT_FOUND;\r
195 }\r
196\r
197 *SigListOut = EfiSig;\r
198\r
199 return EFI_SUCCESS;\r
200}\r
201\r
202/**\r
203 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2\r
204 descriptor with the input data. NO authentication is required in this function.\r
205\r
206 @param[in, out] DataSize On input, the size of Data buffer in bytes.\r
207 On output, the size of data returned in Data\r
208 buffer in bytes.\r
209 @param[in, out] Data On input, Pointer to data buffer to be wrapped or\r
210 pointer to NULL to wrap an empty payload.\r
211 On output, Pointer to the new payload date buffer allocated from pool,\r
212 it's caller's responsibility to free the memory when finish using it.\r
213\r
214 @retval EFI_SUCCESS Create time based payload successfully.\r
215 @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.\r
216 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
217 @retval Others Unexpected error happens.\r
218\r
219**/\r
220EFI_STATUS\r
221CreateTimeBasedPayload (\r
c411b485
MK
222 IN OUT UINTN *DataSize,\r
223 IN OUT UINT8 **Data\r
bb806a6e
GB
224 )\r
225{\r
c411b485
MK
226 EFI_STATUS Status;\r
227 UINT8 *NewData;\r
228 UINT8 *Payload;\r
229 UINTN PayloadSize;\r
230 EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;\r
231 UINTN DescriptorSize;\r
232 EFI_TIME Time;\r
233\r
234 if ((Data == NULL) || (DataSize == NULL)) {\r
bb806a6e
GB
235 return EFI_INVALID_PARAMETER;\r
236 }\r
237\r
238 //\r
239 // In Setup mode or Custom mode, the variable does not need to be signed but the\r
240 // parameters to the SetVariable() call still need to be prepared as authenticated\r
241 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate\r
242 // data in it.\r
243 //\r
244 Payload = *Data;\r
245 PayloadSize = *DataSize;\r
246\r
c411b485
MK
247 DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
248 NewData = (UINT8 *)AllocateZeroPool (DescriptorSize + PayloadSize);\r
bb806a6e
GB
249 if (NewData == NULL) {\r
250 return EFI_OUT_OF_RESOURCES;\r
251 }\r
252\r
253 if ((Payload != NULL) && (PayloadSize != 0)) {\r
254 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
255 }\r
256\r
c411b485 257 DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *)(NewData);\r
bb806a6e
GB
258\r
259 ZeroMem (&Time, sizeof (EFI_TIME));\r
260 Status = gRT->GetTime (&Time, NULL);\r
261 if (EFI_ERROR (Status)) {\r
c411b485 262 FreePool (NewData);\r
bb806a6e
GB
263 return Status;\r
264 }\r
c411b485 265\r
bb806a6e
GB
266 Time.Pad1 = 0;\r
267 Time.Nanosecond = 0;\r
268 Time.TimeZone = 0;\r
269 Time.Daylight = 0;\r
270 Time.Pad2 = 0;\r
271 CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\r
272\r
273 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
274 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;\r
275 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
276 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);\r
277\r
278 if (Payload != NULL) {\r
c411b485 279 FreePool (Payload);\r
bb806a6e
GB
280 }\r
281\r
282 *DataSize = DescriptorSize + PayloadSize;\r
283 *Data = NewData;\r
284 return EFI_SUCCESS;\r
285}\r
286\r
287/**\r
288 Internal helper function to delete a Variable given its name and GUID, NO authentication\r
289 required.\r
290\r
291 @param[in] VariableName Name of the Variable.\r
292 @param[in] VendorGuid GUID of the Variable.\r
293\r
294 @retval EFI_SUCCESS Variable deleted successfully.\r
295 @retval Others The driver failed to start the device.\r
296\r
297**/\r
298EFI_STATUS\r
299DeleteVariable (\r
c411b485
MK
300 IN CHAR16 *VariableName,\r
301 IN EFI_GUID *VendorGuid\r
bb806a6e
GB
302 )\r
303{\r
c411b485
MK
304 EFI_STATUS Status;\r
305 VOID *Variable;\r
306 UINT8 *Data;\r
307 UINTN DataSize;\r
308 UINT32 Attr;\r
bb806a6e
GB
309\r
310 GetVariable2 (VariableName, VendorGuid, &Variable, NULL);\r
311 if (Variable == NULL) {\r
312 return EFI_SUCCESS;\r
313 }\r
c411b485 314\r
bb806a6e
GB
315 FreePool (Variable);\r
316\r
317 Data = NULL;\r
318 DataSize = 0;\r
319 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
320 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
321\r
322 Status = CreateTimeBasedPayload (&DataSize, &Data);\r
323 if (EFI_ERROR (Status)) {\r
324 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));\r
325 return Status;\r
326 }\r
327\r
328 Status = gRT->SetVariable (\r
329 VariableName,\r
330 VendorGuid,\r
331 Attr,\r
332 DataSize,\r
333 Data\r
334 );\r
335 if (Data != NULL) {\r
336 FreePool (Data);\r
337 }\r
c411b485 338\r
bb806a6e
GB
339 return Status;\r
340}\r
341\r
342/**\r
343\r
344 Set the platform secure boot mode into "Custom" or "Standard" mode.\r
345\r
346 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or\r
347 CUSTOM_SECURE_BOOT_MODE.\r
348\r
349 @return EFI_SUCCESS The platform has switched to the special mode successfully.\r
350 @return other Fail to operate the secure boot mode.\r
351\r
352**/\r
353EFI_STATUS\r
354SetSecureBootMode (\r
355 IN UINT8 SecureBootMode\r
356 )\r
357{\r
358 return gRT->SetVariable (\r
359 EFI_CUSTOM_MODE_NAME,\r
360 &gEfiCustomModeEnableGuid,\r
361 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
362 sizeof (UINT8),\r
363 &SecureBootMode\r
364 );\r
365}\r
366\r
367/**\r
368 Fetches the value of SetupMode variable.\r
369\r
370 @param[out] SetupMode Pointer to UINT8 for SetupMode output\r
371\r
372 @retval other Retval from GetVariable.\r
373**/\r
374EFI_STATUS\r
375EFIAPI\r
376GetSetupMode (\r
c411b485
MK
377 OUT UINT8 *SetupMode\r
378 )\r
bb806a6e 379{\r
c411b485
MK
380 UINTN Size;\r
381 EFI_STATUS Status;\r
bb806a6e 382\r
c411b485 383 Size = sizeof (*SetupMode);\r
bb806a6e
GB
384 Status = gRT->GetVariable (\r
385 EFI_SETUP_MODE_NAME,\r
386 &gEfiGlobalVariableGuid,\r
387 NULL,\r
388 &Size,\r
389 SetupMode\r
390 );\r
391 if (EFI_ERROR (Status)) {\r
392 return Status;\r
393 }\r
394\r
395 return EFI_SUCCESS;\r
396}\r
397\r
398/**\r
399 Clears the content of the 'db' variable.\r
400\r
401 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails\r
402 while VendorGuid is NULL.\r
403 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()\r
404**/\r
405EFI_STATUS\r
406EFIAPI\r
407DeleteDb (\r
408 VOID\r
c411b485 409 )\r
bb806a6e 410{\r
c411b485 411 EFI_STATUS Status;\r
bb806a6e
GB
412\r
413 Status = DeleteVariable (\r
414 EFI_IMAGE_SECURITY_DATABASE,\r
415 &gEfiImageSecurityDatabaseGuid\r
416 );\r
417\r
418 return Status;\r
419}\r
420\r
421/**\r
422 Clears the content of the 'dbx' variable.\r
423\r
424 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails\r
425 while VendorGuid is NULL.\r
426 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()\r
427**/\r
428EFI_STATUS\r
429EFIAPI\r
430DeleteDbx (\r
431 VOID\r
c411b485 432 )\r
bb806a6e 433{\r
c411b485 434 EFI_STATUS Status;\r
bb806a6e
GB
435\r
436 Status = DeleteVariable (\r
437 EFI_IMAGE_SECURITY_DATABASE1,\r
438 &gEfiImageSecurityDatabaseGuid\r
439 );\r
440\r
441 return Status;\r
442}\r
443\r
444/**\r
445 Clears the content of the 'dbt' variable.\r
446\r
447 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails\r
448 while VendorGuid is NULL.\r
449 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()\r
450**/\r
451EFI_STATUS\r
452EFIAPI\r
453DeleteDbt (\r
454 VOID\r
c411b485 455 )\r
bb806a6e 456{\r
c411b485 457 EFI_STATUS Status;\r
bb806a6e
GB
458\r
459 Status = DeleteVariable (\r
460 EFI_IMAGE_SECURITY_DATABASE2,\r
461 &gEfiImageSecurityDatabaseGuid\r
462 );\r
463\r
464 return Status;\r
465}\r
466\r
467/**\r
468 Clears the content of the 'KEK' variable.\r
469\r
470 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails\r
471 while VendorGuid is NULL.\r
472 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()\r
473**/\r
474EFI_STATUS\r
475EFIAPI\r
476DeleteKEK (\r
477 VOID\r
c411b485 478 )\r
bb806a6e 479{\r
c411b485 480 EFI_STATUS Status;\r
bb806a6e
GB
481\r
482 Status = DeleteVariable (\r
483 EFI_KEY_EXCHANGE_KEY_NAME,\r
484 &gEfiGlobalVariableGuid\r
485 );\r
486\r
487 return Status;\r
488}\r
489\r
490/**\r
491 Remove the PK variable.\r
492\r
493 @retval EFI_SUCCESS Delete PK successfully.\r
494 @retval Others Could not allow to delete PK.\r
495\r
496**/\r
497EFI_STATUS\r
498EFIAPI\r
499DeletePlatformKey (\r
500 VOID\r
c411b485 501 )\r
bb806a6e 502{\r
c411b485 503 EFI_STATUS Status;\r
bb806a6e 504\r
c411b485 505 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
bb806a6e
GB
506 if (EFI_ERROR (Status)) {\r
507 return Status;\r
508 }\r
509\r
510 Status = DeleteVariable (\r
511 EFI_PLATFORM_KEY_NAME,\r
512 &gEfiGlobalVariableGuid\r
513 );\r
514 return Status;\r
515}\r