]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
OvmfPkg/QemuFlashFvbServices: factor out SetPcdFlashNvStorageBaseAddresses
[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 /**
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 **/
54 STATIC
55 EFI_STATUS
56 GetPkKek1 (
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 ASSERT (DecodedCertSize > 0);
158 break;
159 case EFI_SUCCESS:
160 AsciiPrint ("error: empty certificate after app prefix %g\n",
161 &gOvmfPkKek1AppPrefixGuid);
162 return EFI_PROTOCOL_ERROR;
163 default:
164 AsciiPrint ("error: invalid base64 string after app prefix %g\n",
165 &gOvmfPkKek1AppPrefixGuid);
166 return EFI_PROTOCOL_ERROR;
167 }
168
169 //
170 // Allocate the output buffer.
171 //
172 DecodedCert = AllocatePool (DecodedCertSize);
173 if (DecodedCert == NULL) {
174 AsciiPrint ("error: failed to allocate memory\n");
175 return EFI_OUT_OF_RESOURCES;
176 }
177
178 //
179 // Decoding will succeed at this point.
180 //
181 Status = Base64Decode (Base64Cert, Base64CertLen, DecodedCert,
182 &DecodedCertSize);
183 ASSERT_EFI_ERROR (Status);
184
185 *PkKek1 = DecodedCert;
186 *SizeOfPkKek1 = DecodedCertSize;
187 return EFI_SUCCESS;
188 }
189
190
191 /**
192 Enroll a set of certificates in a global variable, overwriting it.
193
194 The variable will be rewritten with NV+BS+RT+AT attributes.
195
196 @param[in] VariableName The name of the variable to overwrite.
197
198 @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to
199 overwrite.
200
201 @param[in] CertType The GUID determining the type of all the
202 certificates in the set that is passed in. For
203 example, gEfiCertX509Guid stands for DER-encoded
204 X.509 certificates, while gEfiCertSha256Guid stands
205 for SHA256 image hashes.
206
207 @param[in] ... A list of
208
209 IN CONST UINT8 *Cert,
210 IN UINTN CertSize,
211 IN CONST EFI_GUID *OwnerGuid
212
213 triplets. If the first component of a triplet is
214 NULL, then the other two components are not
215 accessed, and processing is terminated. The list of
216 certificates is enrolled in the variable specified,
217 overwriting it. The OwnerGuid component identifies
218 the agent installing the certificate.
219
220 @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert
221 value is NULL), or one of the CertSize values
222 is 0, or one of the CertSize values would
223 overflow the accumulated UINT32 data size.
224
225 @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable
226 payload.
227
228 @retval EFI_SUCCESS Enrollment successful; the variable has been
229 overwritten (or created).
230
231 @return Error codes from gRT->GetTime() and
232 gRT->SetVariable().
233 **/
234 STATIC
235 EFI_STATUS
236 EFIAPI
237 EnrollListOfCerts (
238 IN CHAR16 *VariableName,
239 IN EFI_GUID *VendorGuid,
240 IN EFI_GUID *CertType,
241 ...
242 )
243 {
244 UINTN DataSize;
245 SINGLE_HEADER *SingleHeader;
246 REPEATING_HEADER *RepeatingHeader;
247 VA_LIST Marker;
248 CONST UINT8 *Cert;
249 EFI_STATUS Status;
250 UINT8 *Data;
251 UINT8 *Position;
252
253 Status = EFI_SUCCESS;
254
255 //
256 // compute total size first, for UINT32 range check, and allocation
257 //
258 DataSize = sizeof *SingleHeader;
259 VA_START (Marker, CertType);
260 for (Cert = VA_ARG (Marker, CONST UINT8 *);
261 Cert != NULL;
262 Cert = VA_ARG (Marker, CONST UINT8 *)) {
263 UINTN CertSize;
264
265 CertSize = VA_ARG (Marker, UINTN);
266 (VOID)VA_ARG (Marker, CONST EFI_GUID *);
267
268 if (CertSize == 0 ||
269 CertSize > MAX_UINT32 - sizeof *RepeatingHeader ||
270 DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) {
271 Status = EFI_INVALID_PARAMETER;
272 break;
273 }
274 DataSize += sizeof *RepeatingHeader + CertSize;
275 }
276 VA_END (Marker);
277
278 if (DataSize == sizeof *SingleHeader) {
279 Status = EFI_INVALID_PARAMETER;
280 }
281 if (EFI_ERROR (Status)) {
282 goto Out;
283 }
284
285 Data = AllocatePool (DataSize);
286 if (Data == NULL) {
287 Status = EFI_OUT_OF_RESOURCES;
288 goto Out;
289 }
290
291 Position = Data;
292
293 SingleHeader = (SINGLE_HEADER *)Position;
294 Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL);
295 if (EFI_ERROR (Status)) {
296 goto FreeData;
297 }
298 SingleHeader->TimeStamp.Pad1 = 0;
299 SingleHeader->TimeStamp.Nanosecond = 0;
300 SingleHeader->TimeStamp.TimeZone = 0;
301 SingleHeader->TimeStamp.Daylight = 0;
302 SingleHeader->TimeStamp.Pad2 = 0;
303 #if 0
304 SingleHeader->dwLength = DataSize - sizeof SingleHeader->TimeStamp;
305 #else
306 //
307 // This looks like a bug in edk2. According to the UEFI specification,
308 // dwLength is "The length of the entire certificate, including the length of
309 // the header, in bytes". That shouldn't stop right after CertType -- it
310 // should include everything below it.
311 //
312 SingleHeader->dwLength = sizeof *SingleHeader
313 - sizeof SingleHeader->TimeStamp;
314 #endif
315 SingleHeader->wRevision = 0x0200;
316 SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID;
317 CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid);
318 Position += sizeof *SingleHeader;
319
320 VA_START (Marker, CertType);
321 for (Cert = VA_ARG (Marker, CONST UINT8 *);
322 Cert != NULL;
323 Cert = VA_ARG (Marker, CONST UINT8 *)) {
324 UINTN CertSize;
325 CONST EFI_GUID *OwnerGuid;
326
327 CertSize = VA_ARG (Marker, UINTN);
328 OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *);
329
330 RepeatingHeader = (REPEATING_HEADER *)Position;
331 CopyGuid (&RepeatingHeader->SignatureType, CertType);
332 RepeatingHeader->SignatureListSize =
333 (UINT32)(sizeof *RepeatingHeader + CertSize);
334 RepeatingHeader->SignatureHeaderSize = 0;
335 RepeatingHeader->SignatureSize =
336 (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize);
337 CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid);
338 Position += sizeof *RepeatingHeader;
339
340 CopyMem (Position, Cert, CertSize);
341 Position += CertSize;
342 }
343 VA_END (Marker);
344
345 ASSERT (Data + DataSize == Position);
346
347 Status = gRT->SetVariable (VariableName, VendorGuid,
348 (EFI_VARIABLE_NON_VOLATILE |
349 EFI_VARIABLE_BOOTSERVICE_ACCESS |
350 EFI_VARIABLE_RUNTIME_ACCESS |
351 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),
352 DataSize, Data);
353
354 FreeData:
355 FreePool (Data);
356
357 Out:
358 if (EFI_ERROR (Status)) {
359 AsciiPrint ("error: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName,
360 VendorGuid, Status);
361 }
362 return Status;
363 }
364
365
366 /**
367 Read a UEFI variable into a caller-allocated buffer, enforcing an exact size.
368
369 @param[in] VariableName The name of the variable to read; passed to
370 gRT->GetVariable().
371
372 @param[in] VendorGuid The vendor (namespace) GUID of the variable to read;
373 passed to gRT->GetVariable().
374
375 @param[out] Data The caller-allocated buffer that is supposed to
376 receive the variable's contents. On error, the
377 contents of Data are indeterminate.
378
379 @param[in] DataSize The size in bytes that the caller requires the UEFI
380 variable to have. The caller is responsible for
381 providing room for DataSize bytes in Data.
382
383 @param[in] AllowMissing If FALSE, the variable is required to exist. If
384 TRUE, the variable is permitted to be missing.
385
386 @retval EFI_SUCCESS The UEFI variable exists, has the required size
387 (DataSize), and has been read into Data.
388
389 @retval EFI_SUCCESS The UEFI variable doesn't exist, and
390 AllowMissing is TRUE. DataSize bytes in Data
391 have been zeroed out.
392
393 @retval EFI_NOT_FOUND The UEFI variable doesn't exist, and
394 AllowMissing is FALSE.
395
396 @retval EFI_BUFFER_TOO_SMALL The UEFI variable exists, but its size is
397 greater than DataSize.
398
399 @retval EFI_PROTOCOL_ERROR The UEFI variable exists, but its size is
400 smaller than DataSize.
401
402 @return Error codes propagated from gRT->GetVariable().
403 **/
404 STATIC
405 EFI_STATUS
406 GetExact (
407 IN CHAR16 *VariableName,
408 IN EFI_GUID *VendorGuid,
409 OUT VOID *Data,
410 IN UINTN DataSize,
411 IN BOOLEAN AllowMissing
412 )
413 {
414 UINTN Size;
415 EFI_STATUS Status;
416
417 Size = DataSize;
418 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data);
419 if (EFI_ERROR (Status)) {
420 if (Status == EFI_NOT_FOUND && AllowMissing) {
421 ZeroMem (Data, DataSize);
422 return EFI_SUCCESS;
423 }
424
425 AsciiPrint ("error: GetVariable(\"%s\", %g): %r\n", VariableName,
426 VendorGuid, Status);
427 return Status;
428 }
429
430 if (Size != DataSize) {
431 AsciiPrint ("error: GetVariable(\"%s\", %g): expected size 0x%Lx, "
432 "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size);
433 return EFI_PROTOCOL_ERROR;
434 }
435
436 return EFI_SUCCESS;
437 }
438
439
440 /**
441 Populate a SETTINGS structure from the underlying UEFI variables.
442
443 The following UEFI variables are standard variables:
444 - L"SetupMode" (EFI_SETUP_MODE_NAME)
445 - L"SecureBoot" (EFI_SECURE_BOOT_MODE_NAME)
446 - L"VendorKeys" (EFI_VENDOR_KEYS_VARIABLE_NAME)
447
448 The following UEFI variables are edk2 extensions:
449 - L"SecureBootEnable" (EFI_SECURE_BOOT_ENABLE_NAME)
450 - L"CustomMode" (EFI_CUSTOM_MODE_NAME)
451
452 The L"SecureBootEnable" UEFI variable is permitted to be missing, in which
453 case the corresponding field in the SETTINGS object will be zeroed out. The
454 rest of the covered UEFI variables are required to exist; otherwise, the
455 function will fail.
456
457 @param[out] Settings The SETTINGS object to fill.
458
459 @retval EFI_SUCCESS Settings has been populated.
460
461 @return Error codes propagated from the GetExact() function. The
462 contents of Settings are indeterminate.
463 **/
464 STATIC
465 EFI_STATUS
466 GetSettings (
467 OUT SETTINGS *Settings
468 )
469 {
470 EFI_STATUS Status;
471
472 Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid,
473 &Settings->SetupMode, sizeof Settings->SetupMode, FALSE);
474 if (EFI_ERROR (Status)) {
475 return Status;
476 }
477
478 Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid,
479 &Settings->SecureBoot, sizeof Settings->SecureBoot, FALSE);
480 if (EFI_ERROR (Status)) {
481 return Status;
482 }
483
484 Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME,
485 &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable,
486 sizeof Settings->SecureBootEnable, TRUE);
487 if (EFI_ERROR (Status)) {
488 return Status;
489 }
490
491 Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
492 &Settings->CustomMode, sizeof Settings->CustomMode, FALSE);
493 if (EFI_ERROR (Status)) {
494 return Status;
495 }
496
497 Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid,
498 &Settings->VendorKeys, sizeof Settings->VendorKeys, FALSE);
499 return Status;
500 }
501
502
503 /**
504 Print the contents of a SETTINGS structure to the UEFI console.
505
506 @param[in] Settings The SETTINGS object to print the contents of.
507 **/
508 STATIC
509 VOID
510 PrintSettings (
511 IN CONST SETTINGS *Settings
512 )
513 {
514 AsciiPrint ("info: SetupMode=%d SecureBoot=%d SecureBootEnable=%d "
515 "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot,
516 Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys);
517 }
518
519
520 /**
521 Entry point function of this shell application.
522 **/
523 INTN
524 EFIAPI
525 ShellAppMain (
526 IN UINTN Argc,
527 IN CHAR16 **Argv
528 )
529 {
530 INTN RetVal;
531 EFI_STATUS Status;
532 SETTINGS Settings;
533 UINT8 *PkKek1;
534 UINTN SizeOfPkKek1;
535 BOOLEAN NoDefault;
536
537 if (Argc == 2 && StrCmp (Argv[1], L"--no-default") == 0) {
538 NoDefault = TRUE;
539 } else {
540 NoDefault = FALSE;
541 }
542
543 //
544 // Prepare for failure.
545 //
546 RetVal = 1;
547
548 //
549 // If we're not in Setup Mode, we can't do anything.
550 //
551 Status = GetSettings (&Settings);
552 if (EFI_ERROR (Status)) {
553 return RetVal;
554 }
555 PrintSettings (&Settings);
556
557 if (Settings.SetupMode != 1) {
558 AsciiPrint ("error: already in User Mode\n");
559 return RetVal;
560 }
561
562 //
563 // Set PkKek1 and SizeOfPkKek1 to suppress incorrect compiler/analyzer
564 // warnings.
565 //
566 PkKek1 = NULL;
567 SizeOfPkKek1 = 0;
568
569 //
570 // Fetch the X509 certificate (to be used as Platform Key and first Key
571 // Exchange Key) from SMBIOS.
572 //
573 Status = GetPkKek1 (&PkKek1, &SizeOfPkKek1);
574 if (EFI_ERROR (Status)) {
575 return RetVal;
576 }
577
578 //
579 // Enter Custom Mode so we can enroll PK, KEK, db, and dbx without signature
580 // checks on those variable writes.
581 //
582 if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) {
583 Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE;
584 Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
585 (EFI_VARIABLE_NON_VOLATILE |
586 EFI_VARIABLE_BOOTSERVICE_ACCESS),
587 sizeof Settings.CustomMode, &Settings.CustomMode);
588 if (EFI_ERROR (Status)) {
589 AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
590 &gEfiCustomModeEnableGuid, Status);
591 goto FreePkKek1;
592 }
593 }
594
595 //
596 // Enroll db.
597 //
598 if (NoDefault) {
599 Status = EnrollListOfCerts (
600 EFI_IMAGE_SECURITY_DATABASE,
601 &gEfiImageSecurityDatabaseGuid,
602 &gEfiCertX509Guid,
603 PkKek1, SizeOfPkKek1, &gEfiCallerIdGuid,
604 NULL);
605 } else {
606 Status = EnrollListOfCerts (
607 EFI_IMAGE_SECURITY_DATABASE,
608 &gEfiImageSecurityDatabaseGuid,
609 &gEfiCertX509Guid,
610 mMicrosoftPca, mSizeOfMicrosoftPca, &gMicrosoftVendorGuid,
611 mMicrosoftUefiCa, mSizeOfMicrosoftUefiCa, &gMicrosoftVendorGuid,
612 NULL);
613 }
614 if (EFI_ERROR (Status)) {
615 goto FreePkKek1;
616 }
617
618 //
619 // Enroll dbx.
620 //
621 Status = EnrollListOfCerts (
622 EFI_IMAGE_SECURITY_DATABASE1,
623 &gEfiImageSecurityDatabaseGuid,
624 &gEfiCertSha256Guid,
625 mSha256OfDevNull, mSizeOfSha256OfDevNull, &gEfiCallerIdGuid,
626 NULL);
627 if (EFI_ERROR (Status)) {
628 goto FreePkKek1;
629 }
630
631 //
632 // Enroll KEK.
633 //
634 if (NoDefault) {
635 Status = EnrollListOfCerts (
636 EFI_KEY_EXCHANGE_KEY_NAME,
637 &gEfiGlobalVariableGuid,
638 &gEfiCertX509Guid,
639 PkKek1, SizeOfPkKek1, &gEfiCallerIdGuid,
640 NULL);
641 } else {
642 Status = EnrollListOfCerts (
643 EFI_KEY_EXCHANGE_KEY_NAME,
644 &gEfiGlobalVariableGuid,
645 &gEfiCertX509Guid,
646 PkKek1, SizeOfPkKek1, &gEfiCallerIdGuid,
647 mMicrosoftKek, mSizeOfMicrosoftKek, &gMicrosoftVendorGuid,
648 NULL);
649 }
650 if (EFI_ERROR (Status)) {
651 goto FreePkKek1;
652 }
653
654 //
655 // Enroll PK, leaving Setup Mode (entering User Mode) at once.
656 //
657 Status = EnrollListOfCerts (
658 EFI_PLATFORM_KEY_NAME,
659 &gEfiGlobalVariableGuid,
660 &gEfiCertX509Guid,
661 PkKek1, SizeOfPkKek1, &gEfiGlobalVariableGuid,
662 NULL);
663 if (EFI_ERROR (Status)) {
664 goto FreePkKek1;
665 }
666
667 //
668 // Leave Custom Mode, so that updates to PK, KEK, db, and dbx require valid
669 // signatures.
670 //
671 Settings.CustomMode = STANDARD_SECURE_BOOT_MODE;
672 Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
673 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
674 sizeof Settings.CustomMode, &Settings.CustomMode);
675 if (EFI_ERROR (Status)) {
676 AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
677 &gEfiCustomModeEnableGuid, Status);
678 goto FreePkKek1;
679 }
680
681 //
682 // Final sanity check:
683 //
684 // [SetupMode]
685 // (read-only, standardized by UEFI)
686 // / \_
687 // 0 1, default
688 // / \_
689 // PK enrolled no PK enrolled yet,
690 // (this is called "User Mode") PK enrollment possible
691 // |
692 // |
693 // [SecureBootEnable]
694 // (read-write, edk2-specific, boot service only)
695 // / \_
696 // 0 1, default
697 // / \_
698 // [SecureBoot]=0 [SecureBoot]=1
699 // (read-only, standardized by UEFI) (read-only, standardized by UEFI)
700 // images are not verified images are verified, platform is
701 // operating in Secure Boot mode
702 // |
703 // |
704 // [CustomMode]
705 // (read-write, edk2-specific, boot service only)
706 // / \_
707 // 0, default 1
708 // / \_
709 // PK, KEK, db, dbx PK, KEK, db, dbx
710 // updates are verified updates are not verified
711 //
712 Status = GetSettings (&Settings);
713 if (EFI_ERROR (Status)) {
714 goto FreePkKek1;
715 }
716 PrintSettings (&Settings);
717
718 if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 ||
719 Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 ||
720 Settings.VendorKeys != 0) {
721 AsciiPrint ("error: unexpected\n");
722 goto FreePkKek1;
723 }
724
725 AsciiPrint ("info: success\n");
726 RetVal = 0;
727
728 FreePkKek1:
729 FreePool (PkKek1);
730
731 return RetVal;
732 }