VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c@ 85716

Last change on this file since 85716 was 80721, checked in by vboxsync, 5 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

  • Property svn:eol-style set to native
File size: 23.0 KB
Line 
1/** @file
2 Enroll default PK, KEK, db, dbx.
3
4 Copyright (C) 2014-2019, Red Hat, Inc.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7**/
8#include <Guid/AuthenticatedVariableFormat.h> // gEfiCustomModeEnableGuid
9#include <Guid/GlobalVariable.h> // EFI_SETUP_MODE_NAME
10#include <Guid/ImageAuthentication.h> // EFI_IMAGE_SECURITY_DATABASE
11#include <Guid/MicrosoftVendor.h> // gMicrosoftVendorGuid
12#include <Guid/OvmfPkKek1AppPrefix.h> // gOvmfPkKek1AppPrefixGuid
13#include <IndustryStandard/SmBios.h> // SMBIOS_HANDLE_PI_RESERVED
14#include <Library/BaseLib.h> // GUID_STRING_LENGTH
15#include <Library/BaseMemoryLib.h> // CopyGuid()
16#include <Library/DebugLib.h> // ASSERT()
17#include <Library/MemoryAllocationLib.h> // FreePool()
18#include <Library/PrintLib.h> // AsciiSPrint()
19#include <Library/ShellCEntryLib.h> // ShellAppMain()
20#include <Library/UefiBootServicesTableLib.h> // gBS
21#include <Library/UefiLib.h> // AsciiPrint()
22#include <Library/UefiRuntimeServicesTableLib.h> // gRT
23#include <Protocol/Smbios.h> // EFI_SMBIOS_PROTOCOL
24
25#include "EnrollDefaultKeys.h"
26
27
28/**
29 Fetch the X509 certificate (to be used as Platform Key and first Key Exchange
30 Key) from SMBIOS.
31
32 @param[out] PkKek1 The X509 certificate in DER encoding from the
33 hypervisor, to be enrolled as PK and first KEK
34 entry. On success, the caller is responsible for
35 releasing PkKek1 with FreePool().
36
37 @param[out] SizeOfPkKek1 The size of PkKek1 in bytes.
38
39 @retval EFI_SUCCESS PkKek1 and SizeOfPkKek1 have been set
40 successfully.
41
42 @retval EFI_NOT_FOUND An OEM String matching
43 OVMF_PK_KEK1_APP_PREFIX_GUID has not been
44 found.
45
46 @retval EFI_PROTOCOL_ERROR In the OEM String matching
47 OVMF_PK_KEK1_APP_PREFIX_GUID, the certificate
48 is empty, or it has invalid base64 encoding.
49
50 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
51
52 @return Error codes from gBS->LocateProtocol().
53**/
54STATIC
55EFI_STATUS
56GetPkKek1 (
57 OUT UINT8 **PkKek1,
58 OUT UINTN *SizeOfPkKek1
59 )
60{
61 CONST CHAR8 *Base64Cert;
62 CHAR8 OvmfPkKek1AppPrefix[GUID_STRING_LENGTH + 1 + 1];
63 EFI_STATUS Status;
64 EFI_SMBIOS_PROTOCOL *Smbios;
65 EFI_SMBIOS_HANDLE Handle;
66 EFI_SMBIOS_TYPE Type;
67 EFI_SMBIOS_TABLE_HEADER *Header;
68 SMBIOS_TABLE_TYPE11 *OemStringsTable;
69 UINTN Base64CertLen;
70 UINTN DecodedCertSize;
71 UINT8 *DecodedCert;
72
73 Base64Cert = NULL;
74
75 //
76 // Format the application prefix, for OEM String matching.
77 //
78 AsciiSPrint (OvmfPkKek1AppPrefix, sizeof OvmfPkKek1AppPrefix, "%g:",
79 &gOvmfPkKek1AppPrefixGuid);
80
81 //
82 // Scan all "OEM Strings" tables.
83 //
84 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL,
85 (VOID **)&Smbios);
86 if (EFI_ERROR (Status)) {
87 AsciiPrint ("error: failed to locate EFI_SMBIOS_PROTOCOL: %r\n", Status);
88 return Status;
89 }
90
91 Handle = SMBIOS_HANDLE_PI_RESERVED;
92 Type = SMBIOS_TYPE_OEM_STRINGS;
93 for (Status = Smbios->GetNext (Smbios, &Handle, &Type, &Header, NULL);
94 !EFI_ERROR (Status);
95 Status = Smbios->GetNext (Smbios, &Handle, &Type, &Header, NULL)) {
96 CONST CHAR8 *OemString;
97 UINTN Idx;
98
99 if (Header->Length < sizeof *OemStringsTable) {
100 //
101 // Malformed table header, skip to next.
102 //
103 continue;
104 }
105 OemStringsTable = (SMBIOS_TABLE_TYPE11 *)Header;
106
107 //
108 // Scan all strings in the unformatted area of the current "OEM Strings"
109 // table.
110 //
111 OemString = (CONST CHAR8 *)(OemStringsTable + 1);
112 for (Idx = 0; Idx < OemStringsTable->StringCount; ++Idx) {
113 CHAR8 CandidatePrefix[sizeof OvmfPkKek1AppPrefix];
114
115 //
116 // NUL-terminate the candidate prefix for case-insensitive comparison.
117 //
118 AsciiStrnCpyS (CandidatePrefix, sizeof CandidatePrefix, OemString,
119 GUID_STRING_LENGTH + 1);
120 if (AsciiStriCmp (OvmfPkKek1AppPrefix, CandidatePrefix) == 0) {
121 //
122 // The current string matches the prefix.
123 //
124 Base64Cert = OemString + GUID_STRING_LENGTH + 1;
125 break;
126 }
127 OemString += AsciiStrSize (OemString);
128 }
129
130 if (Idx < OemStringsTable->StringCount) {
131 //
132 // The current table has a matching string.
133 //
134 break;
135 }
136 }
137
138 if (EFI_ERROR (Status)) {
139 //
140 // No table with a matching string has been found.
141 //
142 AsciiPrint ("error: OEM String with app prefix %g not found: %r\n",
143 &gOvmfPkKek1AppPrefixGuid, Status);
144 return EFI_NOT_FOUND;
145 }
146
147 ASSERT (Base64Cert != NULL);
148 Base64CertLen = AsciiStrLen (Base64Cert);
149
150 //
151 // Verify the base64 encoding, and determine the decoded size.
152 //
153 DecodedCertSize = 0;
154 Status = Base64Decode (Base64Cert, Base64CertLen, NULL, &DecodedCertSize);
155 switch (Status) {
156 case EFI_BUFFER_TOO_SMALL:
157 if (DecodedCertSize > 0) {
158 break;
159 }
160 //
161 // Fall through: the above Base64Decode() call is ill-specified in BaseLib
162 // if Source decodes to zero bytes (for example if it consists of ignored
163 // whitespace only).
164 //
165 case EFI_SUCCESS:
166 AsciiPrint ("error: empty certificate after app prefix %g\n",
167 &gOvmfPkKek1AppPrefixGuid);
168 return EFI_PROTOCOL_ERROR;
169 default:
170 AsciiPrint ("error: invalid base64 string after app prefix %g\n",
171 &gOvmfPkKek1AppPrefixGuid);
172 return EFI_PROTOCOL_ERROR;
173 }
174
175 //
176 // Allocate the output buffer.
177 //
178 DecodedCert = AllocatePool (DecodedCertSize);
179 if (DecodedCert == NULL) {
180 AsciiPrint ("error: failed to allocate memory\n");
181 return EFI_OUT_OF_RESOURCES;
182 }
183
184 //
185 // Decoding will succeed at this point.
186 //
187 Status = Base64Decode (Base64Cert, Base64CertLen, DecodedCert,
188 &DecodedCertSize);
189 ASSERT_EFI_ERROR (Status);
190
191 *PkKek1 = DecodedCert;
192 *SizeOfPkKek1 = DecodedCertSize;
193 return EFI_SUCCESS;
194}
195
196
197/**
198 Enroll a set of certificates in a global variable, overwriting it.
199
200 The variable will be rewritten with NV+BS+RT+AT attributes.
201
202 @param[in] VariableName The name of the variable to overwrite.
203
204 @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to
205 overwrite.
206
207 @param[in] CertType The GUID determining the type of all the
208 certificates in the set that is passed in. For
209 example, gEfiCertX509Guid stands for DER-encoded
210 X.509 certificates, while gEfiCertSha256Guid stands
211 for SHA256 image hashes.
212
213 @param[in] ... A list of
214
215 IN CONST UINT8 *Cert,
216 IN UINTN CertSize,
217 IN CONST EFI_GUID *OwnerGuid
218
219 triplets. If the first component of a triplet is
220 NULL, then the other two components are not
221 accessed, and processing is terminated. The list of
222 certificates is enrolled in the variable specified,
223 overwriting it. The OwnerGuid component identifies
224 the agent installing the certificate.
225
226 @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert
227 value is NULL), or one of the CertSize values
228 is 0, or one of the CertSize values would
229 overflow the accumulated UINT32 data size.
230
231 @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable
232 payload.
233
234 @retval EFI_SUCCESS Enrollment successful; the variable has been
235 overwritten (or created).
236
237 @return Error codes from gRT->GetTime() and
238 gRT->SetVariable().
239**/
240STATIC
241EFI_STATUS
242EFIAPI
243EnrollListOfCerts (
244 IN CHAR16 *VariableName,
245 IN EFI_GUID *VendorGuid,
246 IN EFI_GUID *CertType,
247 ...
248 )
249{
250 UINTN DataSize;
251 SINGLE_HEADER *SingleHeader;
252 REPEATING_HEADER *RepeatingHeader;
253 VA_LIST Marker;
254 CONST UINT8 *Cert;
255 EFI_STATUS Status;
256 UINT8 *Data;
257 UINT8 *Position;
258
259 Status = EFI_SUCCESS;
260
261 //
262 // compute total size first, for UINT32 range check, and allocation
263 //
264 DataSize = sizeof *SingleHeader;
265 VA_START (Marker, CertType);
266 for (Cert = VA_ARG (Marker, CONST UINT8 *);
267 Cert != NULL;
268 Cert = VA_ARG (Marker, CONST UINT8 *)) {
269 UINTN CertSize;
270
271 CertSize = VA_ARG (Marker, UINTN);
272 (VOID)VA_ARG (Marker, CONST EFI_GUID *);
273
274 if (CertSize == 0 ||
275 CertSize > MAX_UINT32 - sizeof *RepeatingHeader ||
276 DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) {
277 Status = EFI_INVALID_PARAMETER;
278 break;
279 }
280 DataSize += sizeof *RepeatingHeader + CertSize;
281 }
282 VA_END (Marker);
283
284 if (DataSize == sizeof *SingleHeader) {
285 Status = EFI_INVALID_PARAMETER;
286 }
287 if (EFI_ERROR (Status)) {
288 goto Out;
289 }
290
291 Data = AllocatePool (DataSize);
292 if (Data == NULL) {
293 Status = EFI_OUT_OF_RESOURCES;
294 goto Out;
295 }
296
297 Position = Data;
298
299 SingleHeader = (SINGLE_HEADER *)Position;
300 Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL);
301 if (EFI_ERROR (Status)) {
302 goto FreeData;
303 }
304 SingleHeader->TimeStamp.Pad1 = 0;
305 SingleHeader->TimeStamp.Nanosecond = 0;
306 SingleHeader->TimeStamp.TimeZone = 0;
307 SingleHeader->TimeStamp.Daylight = 0;
308 SingleHeader->TimeStamp.Pad2 = 0;
309#if 0
310 SingleHeader->dwLength = DataSize - sizeof SingleHeader->TimeStamp;
311#else
312 //
313 // This looks like a bug in edk2. According to the UEFI specification,
314 // dwLength is "The length of the entire certificate, including the length of
315 // the header, in bytes". That shouldn't stop right after CertType -- it
316 // should include everything below it.
317 //
318 SingleHeader->dwLength = sizeof *SingleHeader
319 - sizeof SingleHeader->TimeStamp;
320#endif
321 SingleHeader->wRevision = 0x0200;
322 SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID;
323 CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid);
324 Position += sizeof *SingleHeader;
325
326 VA_START (Marker, CertType);
327 for (Cert = VA_ARG (Marker, CONST UINT8 *);
328 Cert != NULL;
329 Cert = VA_ARG (Marker, CONST UINT8 *)) {
330 UINTN CertSize;
331 CONST EFI_GUID *OwnerGuid;
332
333 CertSize = VA_ARG (Marker, UINTN);
334 OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *);
335
336 RepeatingHeader = (REPEATING_HEADER *)Position;
337 CopyGuid (&RepeatingHeader->SignatureType, CertType);
338 RepeatingHeader->SignatureListSize =
339 (UINT32)(sizeof *RepeatingHeader + CertSize);
340 RepeatingHeader->SignatureHeaderSize = 0;
341 RepeatingHeader->SignatureSize =
342 (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize);
343 CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid);
344 Position += sizeof *RepeatingHeader;
345
346 CopyMem (Position, Cert, CertSize);
347 Position += CertSize;
348 }
349 VA_END (Marker);
350
351 ASSERT (Data + DataSize == Position);
352
353 Status = gRT->SetVariable (VariableName, VendorGuid,
354 (EFI_VARIABLE_NON_VOLATILE |
355 EFI_VARIABLE_BOOTSERVICE_ACCESS |
356 EFI_VARIABLE_RUNTIME_ACCESS |
357 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),
358 DataSize, Data);
359
360FreeData:
361 FreePool (Data);
362
363Out:
364 if (EFI_ERROR (Status)) {
365 AsciiPrint ("error: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName,
366 VendorGuid, Status);
367 }
368 return Status;
369}
370
371
372/**
373 Read a UEFI variable into a caller-allocated buffer, enforcing an exact size.
374
375 @param[in] VariableName The name of the variable to read; passed to
376 gRT->GetVariable().
377
378 @param[in] VendorGuid The vendor (namespace) GUID of the variable to read;
379 passed to gRT->GetVariable().
380
381 @param[out] Data The caller-allocated buffer that is supposed to
382 receive the variable's contents. On error, the
383 contents of Data are indeterminate.
384
385 @param[in] DataSize The size in bytes that the caller requires the UEFI
386 variable to have. The caller is responsible for
387 providing room for DataSize bytes in Data.
388
389 @param[in] AllowMissing If FALSE, the variable is required to exist. If
390 TRUE, the variable is permitted to be missing.
391
392 @retval EFI_SUCCESS The UEFI variable exists, has the required size
393 (DataSize), and has been read into Data.
394
395 @retval EFI_SUCCESS The UEFI variable doesn't exist, and
396 AllowMissing is TRUE. DataSize bytes in Data
397 have been zeroed out.
398
399 @retval EFI_NOT_FOUND The UEFI variable doesn't exist, and
400 AllowMissing is FALSE.
401
402 @retval EFI_BUFFER_TOO_SMALL The UEFI variable exists, but its size is
403 greater than DataSize.
404
405 @retval EFI_PROTOCOL_ERROR The UEFI variable exists, but its size is
406 smaller than DataSize.
407
408 @return Error codes propagated from gRT->GetVariable().
409**/
410STATIC
411EFI_STATUS
412GetExact (
413 IN CHAR16 *VariableName,
414 IN EFI_GUID *VendorGuid,
415 OUT VOID *Data,
416 IN UINTN DataSize,
417 IN BOOLEAN AllowMissing
418 )
419{
420 UINTN Size;
421 EFI_STATUS Status;
422
423 Size = DataSize;
424 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data);
425 if (EFI_ERROR (Status)) {
426 if (Status == EFI_NOT_FOUND && AllowMissing) {
427 ZeroMem (Data, DataSize);
428 return EFI_SUCCESS;
429 }
430
431 AsciiPrint ("error: GetVariable(\"%s\", %g): %r\n", VariableName,
432 VendorGuid, Status);
433 return Status;
434 }
435
436 if (Size != DataSize) {
437 AsciiPrint ("error: GetVariable(\"%s\", %g): expected size 0x%Lx, "
438 "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size);
439 return EFI_PROTOCOL_ERROR;
440 }
441
442 return EFI_SUCCESS;
443}
444
445
446/**
447 Populate a SETTINGS structure from the underlying UEFI variables.
448
449 The following UEFI variables are standard variables:
450 - L"SetupMode" (EFI_SETUP_MODE_NAME)
451 - L"SecureBoot" (EFI_SECURE_BOOT_MODE_NAME)
452 - L"VendorKeys" (EFI_VENDOR_KEYS_VARIABLE_NAME)
453
454 The following UEFI variables are edk2 extensions:
455 - L"SecureBootEnable" (EFI_SECURE_BOOT_ENABLE_NAME)
456 - L"CustomMode" (EFI_CUSTOM_MODE_NAME)
457
458 The L"SecureBootEnable" UEFI variable is permitted to be missing, in which
459 case the corresponding field in the SETTINGS object will be zeroed out. The
460 rest of the covered UEFI variables are required to exist; otherwise, the
461 function will fail.
462
463 @param[out] Settings The SETTINGS object to fill.
464
465 @retval EFI_SUCCESS Settings has been populated.
466
467 @return Error codes propagated from the GetExact() function. The
468 contents of Settings are indeterminate.
469**/
470STATIC
471EFI_STATUS
472GetSettings (
473 OUT SETTINGS *Settings
474 )
475{
476 EFI_STATUS Status;
477
478 Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid,
479 &Settings->SetupMode, sizeof Settings->SetupMode, FALSE);
480 if (EFI_ERROR (Status)) {
481 return Status;
482 }
483
484 Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid,
485 &Settings->SecureBoot, sizeof Settings->SecureBoot, FALSE);
486 if (EFI_ERROR (Status)) {
487 return Status;
488 }
489
490 Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME,
491 &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable,
492 sizeof Settings->SecureBootEnable, TRUE);
493 if (EFI_ERROR (Status)) {
494 return Status;
495 }
496
497 Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
498 &Settings->CustomMode, sizeof Settings->CustomMode, FALSE);
499 if (EFI_ERROR (Status)) {
500 return Status;
501 }
502
503 Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid,
504 &Settings->VendorKeys, sizeof Settings->VendorKeys, FALSE);
505 return Status;
506}
507
508
509/**
510 Print the contents of a SETTINGS structure to the UEFI console.
511
512 @param[in] Settings The SETTINGS object to print the contents of.
513**/
514STATIC
515VOID
516PrintSettings (
517 IN CONST SETTINGS *Settings
518 )
519{
520 AsciiPrint ("info: SetupMode=%d SecureBoot=%d SecureBootEnable=%d "
521 "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot,
522 Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys);
523}
524
525
526/**
527 Entry point function of this shell application.
528**/
529INTN
530EFIAPI
531ShellAppMain (
532 IN UINTN Argc,
533 IN CHAR16 **Argv
534 )
535{
536 INTN RetVal;
537 EFI_STATUS Status;
538 SETTINGS Settings;
539 UINT8 *PkKek1;
540 UINTN SizeOfPkKek1;
541 BOOLEAN NoDefault;
542
543 if (Argc == 2 && StrCmp (Argv[1], L"--no-default") == 0) {
544 NoDefault = TRUE;
545 } else {
546 NoDefault = FALSE;
547 }
548
549 //
550 // Prepare for failure.
551 //
552 RetVal = 1;
553
554 //
555 // If we're not in Setup Mode, we can't do anything.
556 //
557 Status = GetSettings (&Settings);
558 if (EFI_ERROR (Status)) {
559 return RetVal;
560 }
561 PrintSettings (&Settings);
562
563 if (Settings.SetupMode != 1) {
564 AsciiPrint ("error: already in User Mode\n");
565 return RetVal;
566 }
567
568 //
569 // Set PkKek1 and SizeOfPkKek1 to suppress incorrect compiler/analyzer
570 // warnings.
571 //
572 PkKek1 = NULL;
573 SizeOfPkKek1 = 0;
574
575 //
576 // Fetch the X509 certificate (to be used as Platform Key and first Key
577 // Exchange Key) from SMBIOS.
578 //
579 Status = GetPkKek1 (&PkKek1, &SizeOfPkKek1);
580 if (EFI_ERROR (Status)) {
581 return RetVal;
582 }
583
584 //
585 // Enter Custom Mode so we can enroll PK, KEK, db, and dbx without signature
586 // checks on those variable writes.
587 //
588 if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) {
589 Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE;
590 Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
591 (EFI_VARIABLE_NON_VOLATILE |
592 EFI_VARIABLE_BOOTSERVICE_ACCESS),
593 sizeof Settings.CustomMode, &Settings.CustomMode);
594 if (EFI_ERROR (Status)) {
595 AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
596 &gEfiCustomModeEnableGuid, Status);
597 goto FreePkKek1;
598 }
599 }
600
601 //
602 // Enroll db.
603 //
604 if (NoDefault) {
605 Status = EnrollListOfCerts (
606 EFI_IMAGE_SECURITY_DATABASE,
607 &gEfiImageSecurityDatabaseGuid,
608 &gEfiCertX509Guid,
609 PkKek1, SizeOfPkKek1, &gEfiCallerIdGuid,
610 NULL);
611 } else {
612 Status = EnrollListOfCerts (
613 EFI_IMAGE_SECURITY_DATABASE,
614 &gEfiImageSecurityDatabaseGuid,
615 &gEfiCertX509Guid,
616 mMicrosoftPca, mSizeOfMicrosoftPca, &gMicrosoftVendorGuid,
617 mMicrosoftUefiCa, mSizeOfMicrosoftUefiCa, &gMicrosoftVendorGuid,
618 NULL);
619 }
620 if (EFI_ERROR (Status)) {
621 goto FreePkKek1;
622 }
623
624 //
625 // Enroll dbx.
626 //
627 Status = EnrollListOfCerts (
628 EFI_IMAGE_SECURITY_DATABASE1,
629 &gEfiImageSecurityDatabaseGuid,
630 &gEfiCertSha256Guid,
631 mSha256OfDevNull, mSizeOfSha256OfDevNull, &gEfiCallerIdGuid,
632 NULL);
633 if (EFI_ERROR (Status)) {
634 goto FreePkKek1;
635 }
636
637 //
638 // Enroll KEK.
639 //
640 if (NoDefault) {
641 Status = EnrollListOfCerts (
642 EFI_KEY_EXCHANGE_KEY_NAME,
643 &gEfiGlobalVariableGuid,
644 &gEfiCertX509Guid,
645 PkKek1, SizeOfPkKek1, &gEfiCallerIdGuid,
646 NULL);
647 } else {
648 Status = EnrollListOfCerts (
649 EFI_KEY_EXCHANGE_KEY_NAME,
650 &gEfiGlobalVariableGuid,
651 &gEfiCertX509Guid,
652 PkKek1, SizeOfPkKek1, &gEfiCallerIdGuid,
653 mMicrosoftKek, mSizeOfMicrosoftKek, &gMicrosoftVendorGuid,
654 NULL);
655 }
656 if (EFI_ERROR (Status)) {
657 goto FreePkKek1;
658 }
659
660 //
661 // Enroll PK, leaving Setup Mode (entering User Mode) at once.
662 //
663 Status = EnrollListOfCerts (
664 EFI_PLATFORM_KEY_NAME,
665 &gEfiGlobalVariableGuid,
666 &gEfiCertX509Guid,
667 PkKek1, SizeOfPkKek1, &gEfiGlobalVariableGuid,
668 NULL);
669 if (EFI_ERROR (Status)) {
670 goto FreePkKek1;
671 }
672
673 //
674 // Leave Custom Mode, so that updates to PK, KEK, db, and dbx require valid
675 // signatures.
676 //
677 Settings.CustomMode = STANDARD_SECURE_BOOT_MODE;
678 Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
679 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
680 sizeof Settings.CustomMode, &Settings.CustomMode);
681 if (EFI_ERROR (Status)) {
682 AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
683 &gEfiCustomModeEnableGuid, Status);
684 goto FreePkKek1;
685 }
686
687 //
688 // Final sanity check:
689 //
690 // [SetupMode]
691 // (read-only, standardized by UEFI)
692 // / \_
693 // 0 1, default
694 // / \_
695 // PK enrolled no PK enrolled yet,
696 // (this is called "User Mode") PK enrollment possible
697 // |
698 // |
699 // [SecureBootEnable]
700 // (read-write, edk2-specific, boot service only)
701 // / \_
702 // 0 1, default
703 // / \_
704 // [SecureBoot]=0 [SecureBoot]=1
705 // (read-only, standardized by UEFI) (read-only, standardized by UEFI)
706 // images are not verified images are verified, platform is
707 // operating in Secure Boot mode
708 // |
709 // |
710 // [CustomMode]
711 // (read-write, edk2-specific, boot service only)
712 // / \_
713 // 0, default 1
714 // / \_
715 // PK, KEK, db, dbx PK, KEK, db, dbx
716 // updates are verified updates are not verified
717 //
718 Status = GetSettings (&Settings);
719 if (EFI_ERROR (Status)) {
720 goto FreePkKek1;
721 }
722 PrintSettings (&Settings);
723
724 if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 ||
725 Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 ||
726 Settings.VendorKeys != 0) {
727 AsciiPrint ("error: unexpected\n");
728 goto FreePkKek1;
729 }
730
731 AsciiPrint ("info: success\n");
732 RetVal = 0;
733
734FreePkKek1:
735 FreePool (PkKek1);
736
737 return RetVal;
738}
Note: See TracBrowser for help on using the repository browser.

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