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