VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c

Last change on this file was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette