]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c
SecurityPkg: SecureBootVariableProvisionLib: Updated implementation
[mirror_edk2.git] / SecurityPkg / Library / SecureBootVariableProvisionLib / SecureBootVariableProvisionLib.c
1 /** @file
2 This library provides functions to set/clear Secure Boot
3 keys and databases.
4
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
10 **/
11 #include <Uefi.h>
12 #include <UefiSecureBoot.h>
13 #include <Guid/GlobalVariable.h>
14 #include <Guid/AuthenticatedVariableFormat.h>
15 #include <Guid/ImageAuthentication.h>
16 #include <Library/BaseLib.h>
17 #include <Library/BaseCryptLib.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/SecureBootVariableProvisionLib.h>
25 #include <Library/DxeServicesLib.h>
26
27 /**
28 Create a EFI Signature List with data fetched from section specified as a argument.
29 Found keys are verified using RsaGetPublicKeyFromX509().
30
31 @param[in] KeyFileGuid A pointer to to the FFS filename GUID
32 @param[out] SigListsSize A pointer to size of signature list
33 @param[out] SigListOut a pointer to a callee-allocated buffer with signature lists
34
35 @retval EFI_SUCCESS Create time based payload successfully.
36 @retval EFI_NOT_FOUND Section with key has not been found.
37 @retval EFI_INVALID_PARAMETER Embedded key has a wrong format.
38 @retval Others Unexpected error happens.
39
40 **/
41 STATIC
42 EFI_STATUS
43 SecureBootFetchData (
44 IN EFI_GUID *KeyFileGuid,
45 OUT UINTN *SigListsSize,
46 OUT EFI_SIGNATURE_LIST **SigListOut
47 )
48 {
49 EFI_SIGNATURE_LIST *EfiSig;
50 EFI_STATUS Status;
51 VOID *Buffer;
52 VOID *RsaPubKey;
53 UINTN Size;
54 UINTN KeyIndex;
55 UINTN Index;
56 SECURE_BOOT_CERTIFICATE_INFO *CertInfo;
57 SECURE_BOOT_CERTIFICATE_INFO *NewCertInfo;
58
59 KeyIndex = 0;
60 EfiSig = NULL;
61 *SigListOut = NULL;
62 *SigListsSize = 0;
63 CertInfo = AllocatePool (sizeof (SECURE_BOOT_CERTIFICATE_INFO));
64 NewCertInfo = CertInfo;
65 while (1) {
66 if (NewCertInfo == NULL) {
67 Status = EFI_OUT_OF_RESOURCES;
68 break;
69 } else {
70 CertInfo = NewCertInfo;
71 }
72
73 Status = GetSectionFromAnyFv (
74 KeyFileGuid,
75 EFI_SECTION_RAW,
76 KeyIndex,
77 &Buffer,
78 &Size
79 );
80
81 if (Status == EFI_SUCCESS) {
82 RsaPubKey = NULL;
83 if (RsaGetPublicKeyFromX509 (Buffer, Size, &RsaPubKey) == FALSE) {
84 DEBUG ((DEBUG_ERROR, "%a: Invalid key format: %d\n", __FUNCTION__, KeyIndex));
85 if (EfiSig != NULL) {
86 FreePool (EfiSig);
87 }
88
89 FreePool (Buffer);
90 Status = EFI_INVALID_PARAMETER;
91 break;
92 }
93
94 CertInfo[KeyIndex].Data = Buffer;
95 CertInfo[KeyIndex].DataSize = Size;
96 KeyIndex++;
97 NewCertInfo = ReallocatePool (
98 sizeof (SECURE_BOOT_CERTIFICATE_INFO) * KeyIndex,
99 sizeof (SECURE_BOOT_CERTIFICATE_INFO) * (KeyIndex + 1),
100 CertInfo
101 );
102 }
103
104 if (Status == EFI_NOT_FOUND) {
105 Status = EFI_SUCCESS;
106 break;
107 }
108 }
109
110 if (EFI_ERROR (Status)) {
111 goto Cleanup;
112 }
113
114 if (KeyIndex == 0) {
115 Status = EFI_NOT_FOUND;
116 goto Cleanup;
117 }
118
119 // Now that we collected all certs from FV, convert it into sig list
120 Status = SecureBootCreateDataFromInput (SigListsSize, SigListOut, KeyIndex, CertInfo);
121 if (EFI_ERROR (Status)) {
122 goto Cleanup;
123 }
124
125 Cleanup:
126 if (CertInfo) {
127 for (Index = 0; Index < KeyIndex; Index++) {
128 FreePool ((VOID *)CertInfo[Index].Data);
129 }
130
131 FreePool (CertInfo);
132 }
133
134 return Status;
135 }
136
137 /**
138 Enroll a key/certificate based on a default variable.
139
140 @param[in] VariableName The name of the key/database.
141 @param[in] DefaultName The name of the default variable.
142 @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable
143
144 @retval EFI_OUT_OF_RESOURCES Out of memory while allocating AuthHeader.
145 @retval EFI_SUCCESS Successful enrollment.
146 @return Error codes from GetTime () and SetVariable ().
147 **/
148 STATIC
149 EFI_STATUS
150 EnrollFromDefault (
151 IN CHAR16 *VariableName,
152 IN CHAR16 *DefaultName,
153 IN EFI_GUID *VendorGuid
154 )
155 {
156 VOID *Data;
157 UINTN DataSize;
158 EFI_STATUS Status;
159
160 Status = EFI_SUCCESS;
161
162 DataSize = 0;
163 Status = GetVariable2 (DefaultName, &gEfiGlobalVariableGuid, &Data, &DataSize);
164 if (EFI_ERROR (Status)) {
165 DEBUG ((DEBUG_ERROR, "error: GetVariable (\"%s): %r\n", DefaultName, Status));
166 return Status;
167 }
168
169 Status = EnrollFromInput (VariableName, VendorGuid, DataSize, Data);
170
171 if (Data != NULL) {
172 FreePool (Data);
173 }
174
175 return Status;
176 }
177
178 /** Initializes PKDefault variable with data from FFS section.
179
180 @retval EFI_SUCCESS Variable was initialized successfully.
181 @retval EFI_UNSUPPORTED Variable already exists.
182 **/
183 EFI_STATUS
184 SecureBootInitPKDefault (
185 IN VOID
186 )
187 {
188 EFI_SIGNATURE_LIST *EfiSig;
189 UINTN SigListsSize;
190 EFI_STATUS Status;
191 UINT8 *Data;
192 UINTN DataSize;
193
194 //
195 // Check if variable exists, if so do not change it
196 //
197 Status = GetVariable2 (EFI_PK_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **)&Data, &DataSize);
198 if (Status == EFI_SUCCESS) {
199 DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_PK_DEFAULT_VARIABLE_NAME));
200 FreePool (Data);
201 return EFI_UNSUPPORTED;
202 }
203
204 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
205 return Status;
206 }
207
208 //
209 // Variable does not exist, can be initialized
210 //
211 DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_PK_DEFAULT_VARIABLE_NAME));
212
213 Status = SecureBootFetchData (&gDefaultPKFileGuid, &SigListsSize, &EfiSig);
214 if (EFI_ERROR (Status)) {
215 DEBUG ((DEBUG_INFO, "Content for %s not found\n", EFI_PK_DEFAULT_VARIABLE_NAME));
216 return Status;
217 }
218
219 Status = gRT->SetVariable (
220 EFI_PK_DEFAULT_VARIABLE_NAME,
221 &gEfiGlobalVariableGuid,
222 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
223 SigListsSize,
224 (VOID *)EfiSig
225 );
226 if (EFI_ERROR (Status)) {
227 DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_PK_DEFAULT_VARIABLE_NAME));
228 }
229
230 FreePool (EfiSig);
231
232 return Status;
233 }
234
235 /** Initializes KEKDefault variable with data from FFS section.
236
237 @retval EFI_SUCCESS Variable was initialized successfully.
238 @retval EFI_UNSUPPORTED Variable already exists.
239 **/
240 EFI_STATUS
241 SecureBootInitKEKDefault (
242 IN VOID
243 )
244 {
245 EFI_SIGNATURE_LIST *EfiSig;
246 UINTN SigListsSize;
247 EFI_STATUS Status;
248 UINT8 *Data;
249 UINTN DataSize;
250
251 //
252 // Check if variable exists, if so do not change it
253 //
254 Status = GetVariable2 (EFI_KEK_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **)&Data, &DataSize);
255 if (Status == EFI_SUCCESS) {
256 DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
257 FreePool (Data);
258 return EFI_UNSUPPORTED;
259 }
260
261 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
262 return Status;
263 }
264
265 //
266 // Variable does not exist, can be initialized
267 //
268 DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
269
270 Status = SecureBootFetchData (&gDefaultKEKFileGuid, &SigListsSize, &EfiSig);
271 if (EFI_ERROR (Status)) {
272 DEBUG ((DEBUG_INFO, "Content for %s not found\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
273 return Status;
274 }
275
276 Status = gRT->SetVariable (
277 EFI_KEK_DEFAULT_VARIABLE_NAME,
278 &gEfiGlobalVariableGuid,
279 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
280 SigListsSize,
281 (VOID *)EfiSig
282 );
283 if (EFI_ERROR (Status)) {
284 DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
285 }
286
287 FreePool (EfiSig);
288
289 return Status;
290 }
291
292 /** Initializes dbDefault variable with data from FFS section.
293
294 @retval EFI_SUCCESS Variable was initialized successfully.
295 @retval EFI_UNSUPPORTED Variable already exists.
296 **/
297 EFI_STATUS
298 SecureBootInitDbDefault (
299 IN VOID
300 )
301 {
302 EFI_SIGNATURE_LIST *EfiSig;
303 UINTN SigListsSize;
304 EFI_STATUS Status;
305 UINT8 *Data;
306 UINTN DataSize;
307
308 Status = GetVariable2 (EFI_DB_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **)&Data, &DataSize);
309 if (Status == EFI_SUCCESS) {
310 DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_DB_DEFAULT_VARIABLE_NAME));
311 FreePool (Data);
312 return EFI_UNSUPPORTED;
313 }
314
315 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
316 return Status;
317 }
318
319 DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_DB_DEFAULT_VARIABLE_NAME));
320
321 Status = SecureBootFetchData (&gDefaultdbFileGuid, &SigListsSize, &EfiSig);
322 if (EFI_ERROR (Status)) {
323 return Status;
324 }
325
326 Status = gRT->SetVariable (
327 EFI_DB_DEFAULT_VARIABLE_NAME,
328 &gEfiGlobalVariableGuid,
329 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
330 SigListsSize,
331 (VOID *)EfiSig
332 );
333 if (EFI_ERROR (Status)) {
334 DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_DB_DEFAULT_VARIABLE_NAME));
335 }
336
337 FreePool (EfiSig);
338
339 return Status;
340 }
341
342 /** Initializes dbxDefault variable with data from FFS section.
343
344 @retval EFI_SUCCESS Variable was initialized successfully.
345 @retval EFI_UNSUPPORTED Variable already exists.
346 **/
347 EFI_STATUS
348 SecureBootInitDbxDefault (
349 IN VOID
350 )
351 {
352 EFI_SIGNATURE_LIST *EfiSig;
353 UINTN SigListsSize;
354 EFI_STATUS Status;
355 UINT8 *Data;
356 UINTN DataSize;
357
358 //
359 // Check if variable exists, if so do not change it
360 //
361 Status = GetVariable2 (EFI_DBX_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **)&Data, &DataSize);
362 if (Status == EFI_SUCCESS) {
363 DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
364 FreePool (Data);
365 return EFI_UNSUPPORTED;
366 }
367
368 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
369 return Status;
370 }
371
372 //
373 // Variable does not exist, can be initialized
374 //
375 DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
376
377 Status = SecureBootFetchData (&gDefaultdbxFileGuid, &SigListsSize, &EfiSig);
378 if (EFI_ERROR (Status)) {
379 DEBUG ((DEBUG_INFO, "Content for %s not found\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
380 return Status;
381 }
382
383 Status = gRT->SetVariable (
384 EFI_DBX_DEFAULT_VARIABLE_NAME,
385 &gEfiGlobalVariableGuid,
386 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
387 SigListsSize,
388 (VOID *)EfiSig
389 );
390 if (EFI_ERROR (Status)) {
391 DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
392 }
393
394 FreePool (EfiSig);
395
396 return Status;
397 }
398
399 /** Initializes dbtDefault variable with data from FFS section.
400
401 @retval EFI_SUCCESS Variable was initialized successfully.
402 @retval EFI_UNSUPPORTED Variable already exists.
403 **/
404 EFI_STATUS
405 SecureBootInitDbtDefault (
406 IN VOID
407 )
408 {
409 EFI_SIGNATURE_LIST *EfiSig;
410 UINTN SigListsSize;
411 EFI_STATUS Status;
412 UINT8 *Data;
413 UINTN DataSize;
414
415 //
416 // Check if variable exists, if so do not change it
417 //
418 Status = GetVariable2 (EFI_DBT_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **)&Data, &DataSize);
419 if (Status == EFI_SUCCESS) {
420 DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_DBT_DEFAULT_VARIABLE_NAME));
421 FreePool (Data);
422 return EFI_UNSUPPORTED;
423 }
424
425 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
426 return Status;
427 }
428
429 //
430 // Variable does not exist, can be initialized
431 //
432 DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_DBT_DEFAULT_VARIABLE_NAME));
433
434 Status = SecureBootFetchData (&gDefaultdbtFileGuid, &SigListsSize, &EfiSig);
435 if (EFI_ERROR (Status)) {
436 return Status;
437 }
438
439 Status = gRT->SetVariable (
440 EFI_DBT_DEFAULT_VARIABLE_NAME,
441 &gEfiGlobalVariableGuid,
442 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
443 SigListsSize,
444 (VOID *)EfiSig
445 );
446 if (EFI_ERROR (Status)) {
447 DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_DBT_DEFAULT_VARIABLE_NAME));
448 }
449
450 FreePool (EfiSig);
451
452 return EFI_SUCCESS;
453 }
454
455 /**
456 Sets the content of the 'db' variable based on 'dbDefault' variable content.
457
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 ()
461 **/
462 EFI_STATUS
463 EFIAPI
464 EnrollDbFromDefault (
465 VOID
466 )
467 {
468 EFI_STATUS Status;
469
470 Status = EnrollFromDefault (
471 EFI_IMAGE_SECURITY_DATABASE,
472 EFI_DB_DEFAULT_VARIABLE_NAME,
473 &gEfiImageSecurityDatabaseGuid
474 );
475
476 return Status;
477 }
478
479 /**
480 Sets the content of the 'dbx' variable based on 'dbxDefault' variable content.
481
482 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
483 while VendorGuid is NULL.
484 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
485 **/
486 EFI_STATUS
487 EFIAPI
488 EnrollDbxFromDefault (
489 VOID
490 )
491 {
492 EFI_STATUS Status;
493
494 Status = EnrollFromDefault (
495 EFI_IMAGE_SECURITY_DATABASE1,
496 EFI_DBX_DEFAULT_VARIABLE_NAME,
497 &gEfiImageSecurityDatabaseGuid
498 );
499
500 return Status;
501 }
502
503 /**
504 Sets the content of the 'dbt' variable based on 'dbtDefault' variable content.
505
506 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
507 while VendorGuid is NULL.
508 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
509 **/
510 EFI_STATUS
511 EFIAPI
512 EnrollDbtFromDefault (
513 VOID
514 )
515 {
516 EFI_STATUS Status;
517
518 Status = EnrollFromDefault (
519 EFI_IMAGE_SECURITY_DATABASE2,
520 EFI_DBT_DEFAULT_VARIABLE_NAME,
521 &gEfiImageSecurityDatabaseGuid
522 );
523
524 return Status;
525 }
526
527 /**
528 Sets the content of the 'KEK' variable based on 'KEKDefault' variable content.
529
530 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
531 while VendorGuid is NULL.
532 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
533 **/
534 EFI_STATUS
535 EFIAPI
536 EnrollKEKFromDefault (
537 VOID
538 )
539 {
540 EFI_STATUS Status;
541
542 Status = EnrollFromDefault (
543 EFI_KEY_EXCHANGE_KEY_NAME,
544 EFI_KEK_DEFAULT_VARIABLE_NAME,
545 &gEfiGlobalVariableGuid
546 );
547
548 return Status;
549 }
550
551 /**
552 Sets the content of the 'KEK' variable based on 'KEKDefault' variable content.
553
554 @retval EFI_OUT_OF_RESOURCES If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
555 while VendorGuid is NULL.
556 @retval other Errors from GetVariable2 (), GetTime () and SetVariable ()
557 **/
558 EFI_STATUS
559 EFIAPI
560 EnrollPKFromDefault (
561 VOID
562 )
563 {
564 EFI_STATUS Status;
565
566 Status = EnrollFromDefault (
567 EFI_PLATFORM_KEY_NAME,
568 EFI_PK_DEFAULT_VARIABLE_NAME,
569 &gEfiGlobalVariableGuid
570 );
571
572 return Status;
573 }