]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigImpl.c
1 /** @file
2 HII Config Access protocol implementation of SecureBoot configuration module.
3
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "SecureBootConfigImpl.h"
11 #include <UefiSecureBoot.h>
12 #include <Protocol/HiiPopup.h>
13 #include <Protocol/RealTimeClock.h>
14 #include <Library/BaseCryptLib.h>
15 #include <Library/SecureBootVariableLib.h>
16 #include <Library/SecureBootVariableProvisionLib.h>
17
18 CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";
19
20 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = {
21 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,
22 {
23 SecureBootExtractConfig,
24 SecureBootRouteConfig,
25 SecureBootCallback
26 }
27 };
28
29 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = {
30 {
31 {
32 HARDWARE_DEVICE_PATH,
33 HW_VENDOR_DP,
34 {
35 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
36 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
37 }
38 },
39 SECUREBOOT_CONFIG_FORM_SET_GUID
40 },
41 {
42 END_DEVICE_PATH_TYPE,
43 END_ENTIRE_DEVICE_PATH_SUBTYPE,
44 {
45 (UINT8)(END_DEVICE_PATH_LENGTH),
46 (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
47 }
48 }
49 };
50
51 BOOLEAN mIsEnterSecureBootForm = FALSE;
52
53 //
54 // OID ASN.1 Value for Hash Algorithms
55 //
56 UINT8 mHashOidValue[] = {
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
63 };
64
65 HASH_TABLE mHash[] = {
66 { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },
67 { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
68 { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
69 { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final }
70 };
71
72 //
73 // Variable Definitions
74 //
75 UINT32 mPeCoffHeaderOffset = 0;
76 WIN_CERTIFICATE *mCertificate = NULL;
77 IMAGE_TYPE mImageType;
78 UINT8 *mImageBase = NULL;
79 UINTN mImageSize = 0;
80 UINT8 mImageDigest[MAX_DIGEST_SIZE];
81 UINTN mImageDigestSize;
82 EFI_GUID mCertType;
83 EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL;
84 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
85
86 //
87 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
88 //
89 CHAR16 *mDerEncodedSuffix[] = {
90 L".cer",
91 L".der",
92 L".crt",
93 NULL
94 };
95 CHAR16 *mSupportX509Suffix = L"*.cer/der/crt";
96
97 //
98 // Prompt strings during certificate enrollment.
99 //
100 CHAR16 *mX509EnrollPromptTitle[] = {
101 L"",
102 L"ERROR: Unsupported file type!",
103 L"ERROR: Unsupported certificate!",
104 NULL
105 };
106 CHAR16 *mX509EnrollPromptString[] = {
107 L"",
108 L"Only DER encoded certificate file (*.cer/der/crt) is supported.",
109 L"Public key length should be equal to or greater than 2048 bits.",
110 NULL
111 };
112
113 SECUREBOOT_CONFIG_PRIVATE_DATA *gSecureBootPrivateData = NULL;
114
115 /**
116 This code cleans up enrolled file by closing file & free related resources attached to
117 enrolled file.
118
119 @param[in] FileContext FileContext cached in SecureBootConfig driver
120
121 **/
122 VOID
123 CloseEnrolledFile (
124 IN SECUREBOOT_FILE_CONTEXT *FileContext
125 )
126 {
127 if (FileContext->FHandle != NULL) {
128 CloseFile (FileContext->FHandle);
129 FileContext->FHandle = NULL;
130 }
131
132 if (FileContext->FileName != NULL) {
133 FreePool (FileContext->FileName);
134 FileContext->FileName = NULL;
135 }
136
137 FileContext->FileType = UNKNOWN_FILE_TYPE;
138 }
139
140 /**
141 Helper function to populate an EFI_TIME instance.
142
143 @param[in] Time FileContext cached in SecureBootConfig driver
144
145 **/
146 STATIC
147 EFI_STATUS
148 GetCurrentTime (
149 IN EFI_TIME *Time
150 )
151 {
152 EFI_STATUS Status;
153 VOID *TestPointer;
154
155 if (Time == NULL) {
156 return EFI_INVALID_PARAMETER;
157 }
158
159 Status = gBS->LocateProtocol (&gEfiRealTimeClockArchProtocolGuid, NULL, &TestPointer);
160 if (EFI_ERROR (Status)) {
161 return Status;
162 }
163
164 ZeroMem (Time, sizeof (EFI_TIME));
165 Status = gRT->GetTime (Time, NULL);
166 if (EFI_ERROR (Status)) {
167 DEBUG ((
168 DEBUG_ERROR,
169 "%a(), GetTime() failed, status = '%r'\n",
170 __FUNCTION__,
171 Status
172 ));
173 return Status;
174 }
175
176 Time->Pad1 = 0;
177 Time->Nanosecond = 0;
178 Time->TimeZone = 0;
179 Time->Daylight = 0;
180 Time->Pad2 = 0;
181
182 return EFI_SUCCESS;
183 }
184
185 /**
186 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
187
188 @param[in] FileSuffix The suffix of the input certificate file
189
190 @retval TRUE It's a DER-encoded certificate.
191 @retval FALSE It's NOT a DER-encoded certificate.
192
193 **/
194 BOOLEAN
195 IsDerEncodeCertificate (
196 IN CONST CHAR16 *FileSuffix
197 )
198 {
199 UINTN Index;
200
201 for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {
202 if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {
203 return TRUE;
204 }
205 }
206
207 return FALSE;
208 }
209
210 /**
211 This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
212 The function reads file content but won't open/close given FileHandle.
213
214 @param[in] FileHandle The FileHandle to be checked
215
216 @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
217 @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
218
219 **/
220 BOOLEAN
221 IsAuthentication2Format (
222 IN EFI_FILE_HANDLE FileHandle
223 )
224 {
225 EFI_STATUS Status;
226 EFI_VARIABLE_AUTHENTICATION_2 *Auth2;
227 BOOLEAN IsAuth2Format;
228
229 IsAuth2Format = FALSE;
230
231 //
232 // Read the whole file content
233 //
234 Status = ReadFileContent (
235 FileHandle,
236 (VOID **)&mImageBase,
237 &mImageSize,
238 0
239 );
240 if (EFI_ERROR (Status)) {
241 goto ON_EXIT;
242 }
243
244 Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)mImageBase;
245 if (Auth2->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
246 goto ON_EXIT;
247 }
248
249 if (CompareGuid (&gEfiCertPkcs7Guid, &Auth2->AuthInfo.CertType)) {
250 IsAuth2Format = TRUE;
251 }
252
253 ON_EXIT:
254 //
255 // Do not close File. simply check file content
256 //
257 if (mImageBase != NULL) {
258 FreePool (mImageBase);
259 mImageBase = NULL;
260 }
261
262 return IsAuth2Format;
263 }
264
265 /**
266 Set Secure Boot option into variable space.
267
268 @param[in] VarValue The option of Secure Boot.
269
270 @retval EFI_SUCCESS The operation is finished successfully.
271 @retval Others Other errors as indicated.
272
273 **/
274 EFI_STATUS
275 SaveSecureBootVariable (
276 IN UINT8 VarValue
277 )
278 {
279 EFI_STATUS Status;
280
281 Status = gRT->SetVariable (
282 EFI_SECURE_BOOT_ENABLE_NAME,
283 &gEfiSecureBootEnableDisableGuid,
284 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
285 sizeof (UINT8),
286 &VarValue
287 );
288 return Status;
289 }
290
291 /**
292 This code checks if the encode type and key strength of X.509
293 certificate is qualified.
294
295 @param[in] X509FileContext FileContext of X.509 certificate storing
296 file.
297 @param[out] Error Error type checked in the certificate.
298
299 @return EFI_SUCCESS The certificate checked successfully.
300 @return EFI_INVALID_PARAMETER The parameter is invalid.
301 @return EFI_OUT_OF_RESOURCES Memory allocation failed.
302
303 **/
304 EFI_STATUS
305 CheckX509Certificate (
306 IN SECUREBOOT_FILE_CONTEXT *X509FileContext,
307 OUT ENROLL_KEY_ERROR *Error
308 )
309 {
310 EFI_STATUS Status;
311 UINT16 *FilePostFix;
312 UINTN NameLength;
313 UINT8 *X509Data;
314 UINTN X509DataSize;
315 void *X509PubKey;
316 UINTN PubKeyModSize;
317
318 if (X509FileContext->FileName == NULL) {
319 *Error = Unsupported_Type;
320 return EFI_INVALID_PARAMETER;
321 }
322
323 X509Data = NULL;
324 X509DataSize = 0;
325 X509PubKey = NULL;
326 PubKeyModSize = 0;
327
328 //
329 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
330 //
331 NameLength = StrLen (X509FileContext->FileName);
332 if (NameLength <= 4) {
333 DEBUG ((DEBUG_ERROR, "Wrong X509 NameLength\n"));
334 *Error = Unsupported_Type;
335 return EFI_INVALID_PARAMETER;
336 }
337
338 FilePostFix = X509FileContext->FileName + NameLength - 4;
339 if (!IsDerEncodeCertificate (FilePostFix)) {
340 DEBUG ((DEBUG_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix));
341 *Error = Unsupported_Type;
342 return EFI_INVALID_PARAMETER;
343 }
344
345 DEBUG ((DEBUG_INFO, "FileName= %s\n", X509FileContext->FileName));
346 DEBUG ((DEBUG_INFO, "FilePostFix = %s\n", FilePostFix));
347
348 //
349 // Read the certificate file content
350 //
351 Status = ReadFileContent (X509FileContext->FHandle, (VOID **)&X509Data, &X509DataSize, 0);
352 if (EFI_ERROR (Status)) {
353 DEBUG ((DEBUG_ERROR, "Error occured while reading the file.\n"));
354 goto ON_EXIT;
355 }
356
357 //
358 // Parse the public key context.
359 //
360 if (RsaGetPublicKeyFromX509 (X509Data, X509DataSize, &X509PubKey) == FALSE) {
361 DEBUG ((DEBUG_ERROR, "Error occured while parsing the pubkey from certificate.\n"));
362 Status = EFI_INVALID_PARAMETER;
363 *Error = Unsupported_Type;
364 goto ON_EXIT;
365 }
366
367 //
368 // Parse Module size of public key using interface provided by CryptoPkg, which is
369 // actually the size of public key.
370 //
371 if (X509PubKey != NULL) {
372 RsaGetKey (X509PubKey, RsaKeyN, NULL, &PubKeyModSize);
373 if (PubKeyModSize < CER_PUBKEY_MIN_SIZE) {
374 DEBUG ((DEBUG_ERROR, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
375 Status = EFI_INVALID_PARAMETER;
376 *Error = Unqualified_Key;
377 }
378
379 RsaFree (X509PubKey);
380 }
381
382 ON_EXIT:
383 if (X509Data != NULL) {
384 FreePool (X509Data);
385 }
386
387 return Status;
388 }
389
390 /**
391 Generate the PK signature list from the X509 Certificate storing file (.cer)
392
393 @param[in] X509File FileHandle of X509 Certificate storing file.
394 @param[out] PkCert Point to the data buffer to store the signature list.
395
396 @return EFI_UNSUPPORTED Unsupported Key Length.
397 @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
398
399 **/
400 EFI_STATUS
401 CreatePkX509SignatureList (
402 IN EFI_FILE_HANDLE X509File,
403 OUT EFI_SIGNATURE_LIST **PkCert
404 )
405 {
406 EFI_STATUS Status;
407 UINT8 *X509Data;
408 UINTN X509DataSize;
409 EFI_SIGNATURE_DATA *PkCertData;
410
411 X509Data = NULL;
412 PkCertData = NULL;
413 X509DataSize = 0;
414
415 Status = ReadFileContent (X509File, (VOID **)&X509Data, &X509DataSize, 0);
416 if (EFI_ERROR (Status)) {
417 goto ON_EXIT;
418 }
419
420 ASSERT (X509Data != NULL);
421
422 //
423 // Allocate space for PK certificate list and initialize it.
424 // Create PK database entry with SignatureHeaderSize equals 0.
425 //
426 *PkCert = (EFI_SIGNATURE_LIST *)AllocateZeroPool (
427 sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1
428 + X509DataSize
429 );
430 if (*PkCert == NULL) {
431 Status = EFI_OUT_OF_RESOURCES;
432 goto ON_EXIT;
433 }
434
435 (*PkCert)->SignatureListSize = (UINT32)(sizeof (EFI_SIGNATURE_LIST)
436 + sizeof (EFI_SIGNATURE_DATA) - 1
437 + X509DataSize);
438 (*PkCert)->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize);
439 (*PkCert)->SignatureHeaderSize = 0;
440 CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);
441 PkCertData = (EFI_SIGNATURE_DATA *)((UINTN)(*PkCert)
442 + sizeof (EFI_SIGNATURE_LIST)
443 + (*PkCert)->SignatureHeaderSize);
444 CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);
445 //
446 // Fill the PK database with PKpub data from X509 certificate file.
447 //
448 CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);
449
450 ON_EXIT:
451
452 if (X509Data != NULL) {
453 FreePool (X509Data);
454 }
455
456 if (EFI_ERROR (Status) && (*PkCert != NULL)) {
457 FreePool (*PkCert);
458 *PkCert = NULL;
459 }
460
461 return Status;
462 }
463
464 /**
465 Enroll new PK into the System without original PK's authentication.
466
467 The SignatureOwner GUID will be the same with PK's vendorguid.
468
469 @param[in] PrivateData The module's private data.
470
471 @retval EFI_SUCCESS New PK enrolled successfully.
472 @retval EFI_INVALID_PARAMETER The parameter is invalid.
473 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
474
475 **/
476 EFI_STATUS
477 EnrollPlatformKey (
478 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
479 )
480 {
481 EFI_STATUS Status;
482 UINT32 Attr;
483 UINTN DataSize;
484 EFI_SIGNATURE_LIST *PkCert;
485 EFI_TIME Time;
486
487 PkCert = NULL;
488
489 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
490 if (EFI_ERROR (Status)) {
491 return Status;
492 }
493
494 //
495 // Prase the selected PK file and generate PK certificate list.
496 //
497 Status = CreatePkX509SignatureList (
498 Private->FileContext->FHandle,
499 &PkCert
500 );
501 if (EFI_ERROR (Status)) {
502 goto ON_EXIT;
503 }
504
505 ASSERT (PkCert != NULL);
506
507 //
508 // Set Platform Key variable.
509 //
510 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
511 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
512 DataSize = PkCert->SignatureListSize;
513 Status = GetCurrentTime (&Time);
514 if (EFI_ERROR (Status)) {
515 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
516 goto ON_EXIT;
517 }
518
519 Status = CreateTimeBasedPayload (&DataSize, (UINT8 **)&PkCert, &Time);
520 if (EFI_ERROR (Status)) {
521 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
522 goto ON_EXIT;
523 }
524
525 Status = gRT->SetVariable (
526 EFI_PLATFORM_KEY_NAME,
527 &gEfiGlobalVariableGuid,
528 Attr,
529 DataSize,
530 PkCert
531 );
532 if (EFI_ERROR (Status)) {
533 if (Status == EFI_OUT_OF_RESOURCES) {
534 DEBUG ((DEBUG_ERROR, "Enroll PK failed with out of resource.\n"));
535 }
536
537 goto ON_EXIT;
538 }
539
540 ON_EXIT:
541
542 if (PkCert != NULL) {
543 FreePool (PkCert);
544 }
545
546 CloseEnrolledFile (Private->FileContext);
547
548 return Status;
549 }
550
551 /**
552 Enroll a new KEK item from public key storing file (*.pbk).
553
554 @param[in] PrivateData The module's private data.
555
556 @retval EFI_SUCCESS New KEK enrolled successfully.
557 @retval EFI_INVALID_PARAMETER The parameter is invalid.
558 @retval EFI_UNSUPPORTED Unsupported command.
559 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
560
561 **/
562 EFI_STATUS
563 EnrollRsa2048ToKek (
564 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
565 )
566 {
567 EFI_STATUS Status;
568 UINT32 Attr;
569 UINTN DataSize;
570 EFI_SIGNATURE_LIST *KekSigList;
571 UINTN KeyBlobSize;
572 UINT8 *KeyBlob;
573 CPL_KEY_INFO *KeyInfo;
574 EFI_SIGNATURE_DATA *KEKSigData;
575 UINTN KekSigListSize;
576 UINT8 *KeyBuffer;
577 UINTN KeyLenInBytes;
578 EFI_TIME Time;
579
580 Attr = 0;
581 DataSize = 0;
582 KeyBuffer = NULL;
583 KeyBlobSize = 0;
584 KeyBlob = NULL;
585 KeyInfo = NULL;
586 KEKSigData = NULL;
587 KekSigList = NULL;
588 KekSigListSize = 0;
589
590 //
591 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
592 // First, We have to parse out public key data from the pbk key file.
593 //
594 Status = ReadFileContent (
595 Private->FileContext->FHandle,
596 (VOID **)&KeyBlob,
597 &KeyBlobSize,
598 0
599 );
600 if (EFI_ERROR (Status)) {
601 goto ON_EXIT;
602 }
603
604 ASSERT (KeyBlob != NULL);
605 KeyInfo = (CPL_KEY_INFO *)KeyBlob;
606 if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {
607 DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));
608 Status = EFI_UNSUPPORTED;
609 goto ON_EXIT;
610 }
611
612 //
613 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
614 //
615 KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;
616 KeyBuffer = AllocateZeroPool (KeyLenInBytes);
617 if (KeyBuffer == NULL) {
618 Status = EFI_OUT_OF_RESOURCES;
619 goto ON_EXIT;
620 }
621
622 Int2OctStr (
623 (UINTN *)(KeyBlob + sizeof (CPL_KEY_INFO)),
624 KeyLenInBytes / sizeof (UINTN),
625 KeyBuffer,
626 KeyLenInBytes
627 );
628 CopyMem (KeyBlob + sizeof (CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);
629
630 //
631 // Form an new EFI_SIGNATURE_LIST.
632 //
633 KekSigListSize = sizeof (EFI_SIGNATURE_LIST)
634 + sizeof (EFI_SIGNATURE_DATA) - 1
635 + WIN_CERT_UEFI_RSA2048_SIZE;
636
637 KekSigList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (KekSigListSize);
638 if (KekSigList == NULL) {
639 Status = EFI_OUT_OF_RESOURCES;
640 goto ON_EXIT;
641 }
642
643 KekSigList->SignatureListSize = sizeof (EFI_SIGNATURE_LIST)
644 + sizeof (EFI_SIGNATURE_DATA) - 1
645 + WIN_CERT_UEFI_RSA2048_SIZE;
646 KekSigList->SignatureHeaderSize = 0;
647 KekSigList->SignatureSize = sizeof (EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;
648 CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);
649
650 KEKSigData = (EFI_SIGNATURE_DATA *)((UINT8 *)KekSigList + sizeof (EFI_SIGNATURE_LIST));
651 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
652 CopyMem (
653 KEKSigData->SignatureData,
654 KeyBlob + sizeof (CPL_KEY_INFO),
655 WIN_CERT_UEFI_RSA2048_SIZE
656 );
657
658 //
659 // Check if KEK entry has been already existed.
660 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
661 // new KEK to original variable.
662 //
663 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
664 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
665 Status = GetCurrentTime (&Time);
666 if (EFI_ERROR (Status)) {
667 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
668 goto ON_EXIT;
669 }
670
671 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8 **)&KekSigList, &Time);
672 if (EFI_ERROR (Status)) {
673 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
674 goto ON_EXIT;
675 }
676
677 Status = gRT->GetVariable (
678 EFI_KEY_EXCHANGE_KEY_NAME,
679 &gEfiGlobalVariableGuid,
680 NULL,
681 &DataSize,
682 NULL
683 );
684 if (Status == EFI_BUFFER_TOO_SMALL) {
685 Attr |= EFI_VARIABLE_APPEND_WRITE;
686 } else if (Status != EFI_NOT_FOUND) {
687 goto ON_EXIT;
688 }
689
690 //
691 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
692 //
693 Status = gRT->SetVariable (
694 EFI_KEY_EXCHANGE_KEY_NAME,
695 &gEfiGlobalVariableGuid,
696 Attr,
697 KekSigListSize,
698 KekSigList
699 );
700 if (EFI_ERROR (Status)) {
701 goto ON_EXIT;
702 }
703
704 ON_EXIT:
705
706 CloseEnrolledFile (Private->FileContext);
707
708 if (Private->SignatureGUID != NULL) {
709 FreePool (Private->SignatureGUID);
710 Private->SignatureGUID = NULL;
711 }
712
713 if (KeyBlob != NULL) {
714 FreePool (KeyBlob);
715 }
716
717 if (KeyBuffer != NULL) {
718 FreePool (KeyBuffer);
719 }
720
721 if (KekSigList != NULL) {
722 FreePool (KekSigList);
723 }
724
725 return Status;
726 }
727
728 /**
729 Enroll a new KEK item from X509 certificate file.
730
731 @param[in] PrivateData The module's private data.
732
733 @retval EFI_SUCCESS New X509 is enrolled successfully.
734 @retval EFI_INVALID_PARAMETER The parameter is invalid.
735 @retval EFI_UNSUPPORTED Unsupported command.
736 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
737
738 **/
739 EFI_STATUS
740 EnrollX509ToKek (
741 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
742 )
743 {
744 EFI_STATUS Status;
745 UINTN X509DataSize;
746 VOID *X509Data;
747 EFI_SIGNATURE_DATA *KEKSigData;
748 EFI_SIGNATURE_LIST *KekSigList;
749 UINTN DataSize;
750 UINTN KekSigListSize;
751 UINT32 Attr;
752 EFI_TIME Time;
753
754 X509Data = NULL;
755 X509DataSize = 0;
756 KekSigList = NULL;
757 KekSigListSize = 0;
758 DataSize = 0;
759 KEKSigData = NULL;
760
761 Status = ReadFileContent (
762 Private->FileContext->FHandle,
763 &X509Data,
764 &X509DataSize,
765 0
766 );
767 if (EFI_ERROR (Status)) {
768 goto ON_EXIT;
769 }
770
771 ASSERT (X509Data != NULL);
772
773 KekSigListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize;
774 KekSigList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (KekSigListSize);
775 if (KekSigList == NULL) {
776 Status = EFI_OUT_OF_RESOURCES;
777 goto ON_EXIT;
778 }
779
780 //
781 // Fill Certificate Database parameters.
782 //
783 KekSigList->SignatureListSize = (UINT32)KekSigListSize;
784 KekSigList->SignatureHeaderSize = 0;
785 KekSigList->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize);
786 CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);
787
788 KEKSigData = (EFI_SIGNATURE_DATA *)((UINT8 *)KekSigList + sizeof (EFI_SIGNATURE_LIST));
789 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
790 CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);
791
792 //
793 // Check if KEK been already existed.
794 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
795 // new kek to original variable
796 //
797 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
798 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
799 Status = GetCurrentTime (&Time);
800 if (EFI_ERROR (Status)) {
801 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
802 goto ON_EXIT;
803 }
804
805 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8 **)&KekSigList, &Time);
806 if (EFI_ERROR (Status)) {
807 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
808 goto ON_EXIT;
809 }
810
811 Status = gRT->GetVariable (
812 EFI_KEY_EXCHANGE_KEY_NAME,
813 &gEfiGlobalVariableGuid,
814 NULL,
815 &DataSize,
816 NULL
817 );
818 if (Status == EFI_BUFFER_TOO_SMALL) {
819 Attr |= EFI_VARIABLE_APPEND_WRITE;
820 } else if (Status != EFI_NOT_FOUND) {
821 goto ON_EXIT;
822 }
823
824 Status = gRT->SetVariable (
825 EFI_KEY_EXCHANGE_KEY_NAME,
826 &gEfiGlobalVariableGuid,
827 Attr,
828 KekSigListSize,
829 KekSigList
830 );
831 if (EFI_ERROR (Status)) {
832 goto ON_EXIT;
833 }
834
835 ON_EXIT:
836
837 CloseEnrolledFile (Private->FileContext);
838
839 if (Private->SignatureGUID != NULL) {
840 FreePool (Private->SignatureGUID);
841 Private->SignatureGUID = NULL;
842 }
843
844 if (KekSigList != NULL) {
845 FreePool (KekSigList);
846 }
847
848 return Status;
849 }
850
851 /**
852 Enroll new KEK into the System without PK's authentication.
853 The SignatureOwner GUID will be Private->SignatureGUID.
854
855 @param[in] PrivateData The module's private data.
856
857 @retval EFI_SUCCESS New KEK enrolled successful.
858 @retval EFI_INVALID_PARAMETER The parameter is invalid.
859 @retval others Fail to enroll KEK data.
860
861 **/
862 EFI_STATUS
863 EnrollKeyExchangeKey (
864 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
865 )
866 {
867 UINT16 *FilePostFix;
868 EFI_STATUS Status;
869 UINTN NameLength;
870
871 if ((Private->FileContext->FHandle == NULL) || (Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {
872 return EFI_INVALID_PARAMETER;
873 }
874
875 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
876 if (EFI_ERROR (Status)) {
877 return Status;
878 }
879
880 //
881 // Parse the file's postfix. Supports DER-encoded X509 certificate,
882 // and .pbk as RSA public key file.
883 //
884 NameLength = StrLen (Private->FileContext->FileName);
885 if (NameLength <= 4) {
886 return EFI_INVALID_PARAMETER;
887 }
888
889 FilePostFix = Private->FileContext->FileName + NameLength - 4;
890 if (IsDerEncodeCertificate (FilePostFix)) {
891 return EnrollX509ToKek (Private);
892 } else if (CompareMem (FilePostFix, L".pbk", 4) == 0) {
893 return EnrollRsa2048ToKek (Private);
894 } else {
895 //
896 // File type is wrong, simply close it
897 //
898 CloseEnrolledFile (Private->FileContext);
899
900 return EFI_INVALID_PARAMETER;
901 }
902 }
903
904 /**
905 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
906 KEK's authentication.
907
908 @param[in] PrivateData The module's private data.
909 @param[in] VariableName Variable name of signature database, must be
910 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
911
912 @retval EFI_SUCCESS New X509 is enrolled successfully.
913 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
914
915 **/
916 EFI_STATUS
917 EnrollX509toSigDB (
918 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
919 IN CHAR16 *VariableName
920 )
921 {
922 EFI_STATUS Status;
923 UINTN X509DataSize;
924 VOID *X509Data;
925 EFI_SIGNATURE_LIST *SigDBCert;
926 EFI_SIGNATURE_DATA *SigDBCertData;
927 VOID *Data;
928 UINTN DataSize;
929 UINTN SigDBSize;
930 UINT32 Attr;
931 EFI_TIME Time;
932
933 X509DataSize = 0;
934 SigDBSize = 0;
935 DataSize = 0;
936 X509Data = NULL;
937 SigDBCert = NULL;
938 SigDBCertData = NULL;
939 Data = NULL;
940
941 Status = ReadFileContent (
942 Private->FileContext->FHandle,
943 &X509Data,
944 &X509DataSize,
945 0
946 );
947 if (EFI_ERROR (Status)) {
948 goto ON_EXIT;
949 }
950
951 ASSERT (X509Data != NULL);
952
953 SigDBSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize;
954
955 Data = AllocateZeroPool (SigDBSize);
956 if (Data == NULL) {
957 Status = EFI_OUT_OF_RESOURCES;
958 goto ON_EXIT;
959 }
960
961 //
962 // Fill Certificate Database parameters.
963 //
964 SigDBCert = (EFI_SIGNATURE_LIST *)Data;
965 SigDBCert->SignatureListSize = (UINT32)SigDBSize;
966 SigDBCert->SignatureHeaderSize = 0;
967 SigDBCert->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize);
968 CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);
969
970 SigDBCertData = (EFI_SIGNATURE_DATA *)((UINT8 *)SigDBCert + sizeof (EFI_SIGNATURE_LIST));
971 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
972 CopyMem ((UINT8 *)(SigDBCertData->SignatureData), X509Data, X509DataSize);
973
974 //
975 // Check if signature database entry has been already existed.
976 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
977 // new signature data to original variable
978 //
979 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
980 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
981 Status = GetCurrentTime (&Time);
982 if (EFI_ERROR (Status)) {
983 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
984 goto ON_EXIT;
985 }
986
987 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8 **)&Data, &Time);
988 if (EFI_ERROR (Status)) {
989 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
990 goto ON_EXIT;
991 }
992
993 Status = gRT->GetVariable (
994 VariableName,
995 &gEfiImageSecurityDatabaseGuid,
996 NULL,
997 &DataSize,
998 NULL
999 );
1000 if (Status == EFI_BUFFER_TOO_SMALL) {
1001 Attr |= EFI_VARIABLE_APPEND_WRITE;
1002 } else if (Status != EFI_NOT_FOUND) {
1003 goto ON_EXIT;
1004 }
1005
1006 Status = gRT->SetVariable (
1007 VariableName,
1008 &gEfiImageSecurityDatabaseGuid,
1009 Attr,
1010 SigDBSize,
1011 Data
1012 );
1013 if (EFI_ERROR (Status)) {
1014 goto ON_EXIT;
1015 }
1016
1017 ON_EXIT:
1018
1019 CloseEnrolledFile (Private->FileContext);
1020
1021 if (Private->SignatureGUID != NULL) {
1022 FreePool (Private->SignatureGUID);
1023 Private->SignatureGUID = NULL;
1024 }
1025
1026 if (Data != NULL) {
1027 FreePool (Data);
1028 }
1029
1030 if (X509Data != NULL) {
1031 FreePool (X509Data);
1032 }
1033
1034 return Status;
1035 }
1036
1037 /**
1038 Check whether signature is in specified database.
1039
1040 @param[in] VariableName Name of database variable that is searched in.
1041 @param[in] Signature Pointer to signature that is searched for.
1042 @param[in] SignatureSize Size of Signature.
1043
1044 @return TRUE Found the signature in the variable database.
1045 @return FALSE Not found the signature in the variable database.
1046
1047 **/
1048 BOOLEAN
1049 IsSignatureFoundInDatabase (
1050 IN CHAR16 *VariableName,
1051 IN UINT8 *Signature,
1052 IN UINTN SignatureSize
1053 )
1054 {
1055 EFI_STATUS Status;
1056 EFI_SIGNATURE_LIST *CertList;
1057 EFI_SIGNATURE_DATA *Cert;
1058 UINTN DataSize;
1059 UINT8 *Data;
1060 UINTN Index;
1061 UINTN CertCount;
1062 BOOLEAN IsFound;
1063
1064 //
1065 // Read signature database variable.
1066 //
1067 IsFound = FALSE;
1068 Data = NULL;
1069 DataSize = 0;
1070 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1071 if (Status != EFI_BUFFER_TOO_SMALL) {
1072 return FALSE;
1073 }
1074
1075 Data = (UINT8 *)AllocateZeroPool (DataSize);
1076 if (Data == NULL) {
1077 return FALSE;
1078 }
1079
1080 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
1081 if (EFI_ERROR (Status)) {
1082 goto Done;
1083 }
1084
1085 //
1086 // Enumerate all signature data in SigDB to check if signature exists for executable.
1087 //
1088 CertList = (EFI_SIGNATURE_LIST *)Data;
1089 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
1090 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1091 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1092 if ((CertList->SignatureSize == sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid))) {
1093 for (Index = 0; Index < CertCount; Index++) {
1094 if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
1095 //
1096 // Find the signature in database.
1097 //
1098 IsFound = TRUE;
1099 break;
1100 }
1101
1102 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);
1103 }
1104
1105 if (IsFound) {
1106 break;
1107 }
1108 }
1109
1110 DataSize -= CertList->SignatureListSize;
1111 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
1112 }
1113
1114 Done:
1115 if (Data != NULL) {
1116 FreePool (Data);
1117 }
1118
1119 return IsFound;
1120 }
1121
1122 /**
1123 Calculate the hash of a certificate data with the specified hash algorithm.
1124
1125 @param[in] CertData The certificate data to be hashed.
1126 @param[in] CertSize The certificate size in bytes.
1127 @param[in] HashAlg The specified hash algorithm.
1128 @param[out] CertHash The output digest of the certificate
1129
1130 @retval TRUE Successfully got the hash of the CertData.
1131 @retval FALSE Failed to get the hash of CertData.
1132
1133 **/
1134 BOOLEAN
1135 CalculateCertHash (
1136 IN UINT8 *CertData,
1137 IN UINTN CertSize,
1138 IN UINT32 HashAlg,
1139 OUT UINT8 *CertHash
1140 )
1141 {
1142 BOOLEAN Status;
1143 VOID *HashCtx;
1144 UINTN CtxSize;
1145 UINT8 *TBSCert;
1146 UINTN TBSCertSize;
1147
1148 HashCtx = NULL;
1149 Status = FALSE;
1150
1151 if (HashAlg >= HASHALG_MAX) {
1152 return FALSE;
1153 }
1154
1155 //
1156 // Retrieve the TBSCertificate for Hash Calculation.
1157 //
1158 if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {
1159 return FALSE;
1160 }
1161
1162 //
1163 // 1. Initialize context of hash.
1164 //
1165 CtxSize = mHash[HashAlg].GetContextSize ();
1166 HashCtx = AllocatePool (CtxSize);
1167 ASSERT (HashCtx != NULL);
1168
1169 //
1170 // 2. Initialize a hash context.
1171 //
1172 Status = mHash[HashAlg].HashInit (HashCtx);
1173 if (!Status) {
1174 goto Done;
1175 }
1176
1177 //
1178 // 3. Calculate the hash.
1179 //
1180 Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);
1181 if (!Status) {
1182 goto Done;
1183 }
1184
1185 //
1186 // 4. Get the hash result.
1187 //
1188 ZeroMem (CertHash, mHash[HashAlg].DigestLength);
1189 Status = mHash[HashAlg].HashFinal (HashCtx, CertHash);
1190
1191 Done:
1192 if (HashCtx != NULL) {
1193 FreePool (HashCtx);
1194 }
1195
1196 return Status;
1197 }
1198
1199 /**
1200 Check whether the hash of an X.509 certificate is in forbidden database (DBX).
1201
1202 @param[in] Certificate Pointer to X.509 Certificate that is searched for.
1203 @param[in] CertSize Size of X.509 Certificate.
1204
1205 @return TRUE Found the certificate hash in the forbidden database.
1206 @return FALSE Certificate hash is Not found in the forbidden database.
1207
1208 **/
1209 BOOLEAN
1210 IsCertHashFoundInDbx (
1211 IN UINT8 *Certificate,
1212 IN UINTN CertSize
1213 )
1214 {
1215 BOOLEAN IsFound;
1216 EFI_STATUS Status;
1217 EFI_SIGNATURE_LIST *DbxList;
1218 EFI_SIGNATURE_DATA *CertHash;
1219 UINTN CertHashCount;
1220 UINTN Index;
1221 UINT32 HashAlg;
1222 UINT8 CertDigest[MAX_DIGEST_SIZE];
1223 UINT8 *DbxCertHash;
1224 UINTN SiglistHeaderSize;
1225 UINT8 *Data;
1226 UINTN DataSize;
1227
1228 IsFound = FALSE;
1229 HashAlg = HASHALG_MAX;
1230 Data = NULL;
1231
1232 //
1233 // Read signature database variable.
1234 //
1235 DataSize = 0;
1236 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1237 if (Status != EFI_BUFFER_TOO_SMALL) {
1238 return FALSE;
1239 }
1240
1241 Data = (UINT8 *)AllocateZeroPool (DataSize);
1242 if (Data == NULL) {
1243 return FALSE;
1244 }
1245
1246 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
1247 if (EFI_ERROR (Status)) {
1248 goto Done;
1249 }
1250
1251 //
1252 // Check whether the certificate hash exists in the forbidden database.
1253 //
1254 DbxList = (EFI_SIGNATURE_LIST *)Data;
1255 while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {
1256 //
1257 // Determine Hash Algorithm of Certificate in the forbidden database.
1258 //
1259 if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
1260 HashAlg = HASHALG_SHA256;
1261 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
1262 HashAlg = HASHALG_SHA384;
1263 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
1264 HashAlg = HASHALG_SHA512;
1265 } else {
1266 DataSize -= DbxList->SignatureListSize;
1267 DbxList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxList + DbxList->SignatureListSize);
1268 continue;
1269 }
1270
1271 //
1272 // Calculate the hash value of current db certificate for comparision.
1273 //
1274 if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {
1275 goto Done;
1276 }
1277
1278 SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
1279 CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)DbxList + SiglistHeaderSize);
1280 CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
1281 for (Index = 0; Index < CertHashCount; Index++) {
1282 //
1283 // Iterate each Signature Data Node within this CertList for verify.
1284 //
1285 DbxCertHash = CertHash->SignatureData;
1286 if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
1287 //
1288 // Hash of Certificate is found in forbidden database.
1289 //
1290 IsFound = TRUE;
1291 goto Done;
1292 }
1293
1294 CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)CertHash + DbxList->SignatureSize);
1295 }
1296
1297 DataSize -= DbxList->SignatureListSize;
1298 DbxList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxList + DbxList->SignatureListSize);
1299 }
1300
1301 Done:
1302 if (Data != NULL) {
1303 FreePool (Data);
1304 }
1305
1306 return IsFound;
1307 }
1308
1309 /**
1310 Check whether the signature list exists in given variable data.
1311
1312 It searches the signature list for the certificate hash by CertType.
1313 If the signature list is found, get the offset of Database for the
1314 next hash of a certificate.
1315
1316 @param[in] Database Variable data to save signature list.
1317 @param[in] DatabaseSize Variable size.
1318 @param[in] SignatureType The type of the signature.
1319 @param[out] Offset The offset to save a new hash of certificate.
1320
1321 @return TRUE The signature list is found in the forbidden database.
1322 @return FALSE The signature list is not found in the forbidden database.
1323 **/
1324 BOOLEAN
1325 GetSignaturelistOffset (
1326 IN EFI_SIGNATURE_LIST *Database,
1327 IN UINTN DatabaseSize,
1328 IN EFI_GUID *SignatureType,
1329 OUT UINTN *Offset
1330 )
1331 {
1332 EFI_SIGNATURE_LIST *SigList;
1333 UINTN SiglistSize;
1334
1335 if ((Database == NULL) || (DatabaseSize == 0)) {
1336 *Offset = 0;
1337 return FALSE;
1338 }
1339
1340 SigList = Database;
1341 SiglistSize = DatabaseSize;
1342 while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {
1343 if (CompareGuid (&SigList->SignatureType, SignatureType)) {
1344 *Offset = DatabaseSize - SiglistSize;
1345 return TRUE;
1346 }
1347
1348 SiglistSize -= SigList->SignatureListSize;
1349 SigList = (EFI_SIGNATURE_LIST *)((UINT8 *)SigList + SigList->SignatureListSize);
1350 }
1351
1352 *Offset = 0;
1353 return FALSE;
1354 }
1355
1356 /**
1357 Enroll a new X509 certificate hash into Signature Database (dbx) without
1358 KEK's authentication.
1359
1360 @param[in] PrivateData The module's private data.
1361 @param[in] HashAlg The hash algorithm to enroll the certificate.
1362 @param[in] RevocationDate The revocation date of the certificate.
1363 @param[in] RevocationTime The revocation time of the certificate.
1364 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
1365
1366 @retval EFI_SUCCESS New X509 is enrolled successfully.
1367 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1368 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1369
1370 **/
1371 EFI_STATUS
1372 EnrollX509HashtoSigDB (
1373 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
1374 IN UINT32 HashAlg,
1375 IN EFI_HII_DATE *RevocationDate,
1376 IN EFI_HII_TIME *RevocationTime,
1377 IN BOOLEAN AlwaysRevocation
1378 )
1379 {
1380 EFI_STATUS Status;
1381 UINTN X509DataSize;
1382 VOID *X509Data;
1383 EFI_SIGNATURE_LIST *SignatureList;
1384 UINTN SignatureListSize;
1385 UINT8 *Data;
1386 UINT8 *NewData;
1387 UINTN DataSize;
1388 UINTN DbSize;
1389 UINT32 Attr;
1390 EFI_SIGNATURE_DATA *SignatureData;
1391 UINTN SignatureSize;
1392 EFI_GUID SignatureType;
1393 UINTN Offset;
1394 UINT8 CertHash[MAX_DIGEST_SIZE];
1395 UINT16 *FilePostFix;
1396 UINTN NameLength;
1397 EFI_TIME *Time;
1398 EFI_TIME NewTime;
1399
1400 X509DataSize = 0;
1401 DbSize = 0;
1402 X509Data = NULL;
1403 SignatureData = NULL;
1404 SignatureList = NULL;
1405 Data = NULL;
1406 NewData = NULL;
1407
1408 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
1409 return EFI_INVALID_PARAMETER;
1410 }
1411
1412 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
1413 if (EFI_ERROR (Status)) {
1414 return Status;
1415 }
1416
1417 //
1418 // Parse the file's postfix.
1419 //
1420 NameLength = StrLen (Private->FileContext->FileName);
1421 if (NameLength <= 4) {
1422 return EFI_INVALID_PARAMETER;
1423 }
1424
1425 FilePostFix = Private->FileContext->FileName + NameLength - 4;
1426 if (!IsDerEncodeCertificate (FilePostFix)) {
1427 //
1428 // Only supports DER-encoded X509 certificate.
1429 //
1430 return EFI_INVALID_PARAMETER;
1431 }
1432
1433 //
1434 // Get the certificate from file and calculate its hash.
1435 //
1436 Status = ReadFileContent (
1437 Private->FileContext->FHandle,
1438 &X509Data,
1439 &X509DataSize,
1440 0
1441 );
1442 if (EFI_ERROR (Status)) {
1443 goto ON_EXIT;
1444 }
1445
1446 ASSERT (X509Data != NULL);
1447
1448 if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {
1449 goto ON_EXIT;
1450 }
1451
1452 //
1453 // Get the variable for enrollment.
1454 //
1455 DataSize = 0;
1456 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1457 if (Status == EFI_BUFFER_TOO_SMALL) {
1458 Data = (UINT8 *)AllocateZeroPool (DataSize);
1459 if (Data == NULL) {
1460 return EFI_OUT_OF_RESOURCES;
1461 }
1462
1463 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
1464 if (EFI_ERROR (Status)) {
1465 goto ON_EXIT;
1466 }
1467 }
1468
1469 //
1470 // Allocate memory for Signature and fill the Signature
1471 //
1472 SignatureSize = sizeof (EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;
1473 SignatureData = (EFI_SIGNATURE_DATA *)AllocateZeroPool (SignatureSize);
1474 if (SignatureData == NULL) {
1475 return EFI_OUT_OF_RESOURCES;
1476 }
1477
1478 CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);
1479 CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);
1480
1481 //
1482 // Fill the time.
1483 //
1484 if (!AlwaysRevocation) {
1485 Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);
1486 Time->Year = RevocationDate->Year;
1487 Time->Month = RevocationDate->Month;
1488 Time->Day = RevocationDate->Day;
1489 Time->Hour = RevocationTime->Hour;
1490 Time->Minute = RevocationTime->Minute;
1491 Time->Second = RevocationTime->Second;
1492 }
1493
1494 //
1495 // Determine the GUID for certificate hash.
1496 //
1497 switch (HashAlg) {
1498 case HASHALG_SHA256:
1499 SignatureType = gEfiCertX509Sha256Guid;
1500 break;
1501 case HASHALG_SHA384:
1502 SignatureType = gEfiCertX509Sha384Guid;
1503 break;
1504 case HASHALG_SHA512:
1505 SignatureType = gEfiCertX509Sha512Guid;
1506 break;
1507 default:
1508 return FALSE;
1509 }
1510
1511 //
1512 // Add signature into the new variable data buffer
1513 //
1514 if (GetSignaturelistOffset ((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {
1515 //
1516 // Add the signature to the found signaturelist.
1517 //
1518 DbSize = DataSize + SignatureSize;
1519 NewData = AllocateZeroPool (DbSize);
1520 if (NewData == NULL) {
1521 Status = EFI_OUT_OF_RESOURCES;
1522 goto ON_EXIT;
1523 }
1524
1525 SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset);
1526 SignatureListSize = (UINTN)ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);
1527 CopyMem (NewData, Data, Offset + SignatureListSize);
1528
1529 SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);
1530 WriteUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));
1531
1532 Offset += SignatureListSize;
1533 CopyMem (NewData + Offset, SignatureData, SignatureSize);
1534 CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);
1535
1536 FreePool (Data);
1537 Data = NewData;
1538 DataSize = DbSize;
1539 } else {
1540 //
1541 // Create a new signaturelist, and add the signature into the signaturelist.
1542 //
1543 DbSize = DataSize + sizeof (EFI_SIGNATURE_LIST) + SignatureSize;
1544 NewData = AllocateZeroPool (DbSize);
1545 if (NewData == NULL) {
1546 Status = EFI_OUT_OF_RESOURCES;
1547 goto ON_EXIT;
1548 }
1549
1550 //
1551 // Fill Certificate Database parameters.
1552 //
1553 SignatureList = (EFI_SIGNATURE_LIST *)(NewData + DataSize);
1554 SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + SignatureSize;
1555 WriteUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize, (UINT32)SignatureListSize);
1556 WriteUnaligned32 ((UINT32 *)&SignatureList->SignatureSize, (UINT32)SignatureSize);
1557 CopyGuid (&SignatureList->SignatureType, &SignatureType);
1558 CopyMem ((UINT8 *)SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);
1559 if ((DataSize != 0) && (Data != NULL)) {
1560 CopyMem (NewData, Data, DataSize);
1561 FreePool (Data);
1562 }
1563
1564 Data = NewData;
1565 DataSize = DbSize;
1566 }
1567
1568 Status = GetCurrentTime (&NewTime);
1569 if (EFI_ERROR (Status)) {
1570 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
1571 goto ON_EXIT;
1572 }
1573
1574 Status = CreateTimeBasedPayload (&DataSize, (UINT8 **)&Data, &NewTime);
1575 if (EFI_ERROR (Status)) {
1576 goto ON_EXIT;
1577 }
1578
1579 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
1580 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1581 Status = gRT->SetVariable (
1582 EFI_IMAGE_SECURITY_DATABASE1,
1583 &gEfiImageSecurityDatabaseGuid,
1584 Attr,
1585 DataSize,
1586 Data
1587 );
1588 if (EFI_ERROR (Status)) {
1589 goto ON_EXIT;
1590 }
1591
1592 ON_EXIT:
1593
1594 CloseEnrolledFile (Private->FileContext);
1595
1596 if (Private->SignatureGUID != NULL) {
1597 FreePool (Private->SignatureGUID);
1598 Private->SignatureGUID = NULL;
1599 }
1600
1601 if (Data != NULL) {
1602 FreePool (Data);
1603 }
1604
1605 if (SignatureData != NULL) {
1606 FreePool (SignatureData);
1607 }
1608
1609 if (X509Data != NULL) {
1610 FreePool (X509Data);
1611 }
1612
1613 return Status;
1614 }
1615
1616 /**
1617 Check whether a certificate from a file exists in dbx.
1618
1619 @param[in] PrivateData The module's private data.
1620 @param[in] VariableName Variable name of signature database, must be
1621 EFI_IMAGE_SECURITY_DATABASE1.
1622
1623 @retval TRUE The X509 certificate is found in dbx successfully.
1624 @retval FALSE The X509 certificate is not found in dbx.
1625 **/
1626 BOOLEAN
1627 IsX509CertInDbx (
1628 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
1629 IN CHAR16 *VariableName
1630 )
1631 {
1632 EFI_STATUS Status;
1633 UINTN X509DataSize;
1634 VOID *X509Data;
1635 BOOLEAN IsFound;
1636
1637 //
1638 // Read the certificate from file
1639 //
1640 X509DataSize = 0;
1641 X509Data = NULL;
1642 Status = ReadFileContent (
1643 Private->FileContext->FHandle,
1644 &X509Data,
1645 &X509DataSize,
1646 0
1647 );
1648 if (EFI_ERROR (Status)) {
1649 return FALSE;
1650 }
1651
1652 //
1653 // Check the raw certificate.
1654 //
1655 IsFound = FALSE;
1656 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {
1657 IsFound = TRUE;
1658 goto ON_EXIT;
1659 }
1660
1661 //
1662 // Check the hash of certificate.
1663 //
1664 if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {
1665 IsFound = TRUE;
1666 goto ON_EXIT;
1667 }
1668
1669 ON_EXIT:
1670 if (X509Data != NULL) {
1671 FreePool (X509Data);
1672 }
1673
1674 return IsFound;
1675 }
1676
1677 /**
1678 Reads contents of a PE/COFF image in memory buffer.
1679
1680 Caution: This function may receive untrusted input.
1681 PE/COFF image is external input, so this function will make sure the PE/COFF image content
1682 read is within the image buffer.
1683
1684 @param FileHandle Pointer to the file handle to read the PE/COFF image.
1685 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1686 @param ReadSize On input, the size in bytes of the requested read operation.
1687 On output, the number of bytes actually read.
1688 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1689
1690 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
1691 **/
1692 EFI_STATUS
1693 EFIAPI
1694 SecureBootConfigImageRead (
1695 IN VOID *FileHandle,
1696 IN UINTN FileOffset,
1697 IN OUT UINTN *ReadSize,
1698 OUT VOID *Buffer
1699 )
1700 {
1701 UINTN EndPosition;
1702
1703 if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
1704 return EFI_INVALID_PARAMETER;
1705 }
1706
1707 if (MAX_ADDRESS - FileOffset < *ReadSize) {
1708 return EFI_INVALID_PARAMETER;
1709 }
1710
1711 EndPosition = FileOffset + *ReadSize;
1712 if (EndPosition > mImageSize) {
1713 *ReadSize = (UINT32)(mImageSize - FileOffset);
1714 }
1715
1716 if (FileOffset >= mImageSize) {
1717 *ReadSize = 0;
1718 }
1719
1720 CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
1721
1722 return EFI_SUCCESS;
1723 }
1724
1725 /**
1726 Load PE/COFF image information into internal buffer and check its validity.
1727
1728 @retval EFI_SUCCESS Successful
1729 @retval EFI_UNSUPPORTED Invalid PE/COFF file
1730 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
1731
1732 **/
1733 EFI_STATUS
1734 LoadPeImage (
1735 VOID
1736 )
1737 {
1738 EFI_IMAGE_DOS_HEADER *DosHdr;
1739 EFI_IMAGE_NT_HEADERS32 *NtHeader32;
1740 EFI_IMAGE_NT_HEADERS64 *NtHeader64;
1741 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1742 EFI_STATUS Status;
1743
1744 NtHeader32 = NULL;
1745 NtHeader64 = NULL;
1746
1747 ZeroMem (&ImageContext, sizeof (ImageContext));
1748 ImageContext.Handle = (VOID *)mImageBase;
1749 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecureBootConfigImageRead;
1750
1751 //
1752 // Get information about the image being loaded
1753 //
1754 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1755 if (EFI_ERROR (Status)) {
1756 //
1757 // The information can't be got from the invalid PeImage
1758 //
1759 DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n"));
1760 return Status;
1761 }
1762
1763 //
1764 // Read the Dos header
1765 //
1766 DosHdr = (EFI_IMAGE_DOS_HEADER *)(mImageBase);
1767 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1768 //
1769 // DOS image header is present,
1770 // So read the PE header after the DOS image header
1771 //
1772 mPeCoffHeaderOffset = DosHdr->e_lfanew;
1773 } else {
1774 mPeCoffHeaderOffset = 0;
1775 }
1776
1777 //
1778 // Read PE header and check the signature validity and machine compatibility
1779 //
1780 NtHeader32 = (EFI_IMAGE_NT_HEADERS32 *)(mImageBase + mPeCoffHeaderOffset);
1781 if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1782 return EFI_UNSUPPORTED;
1783 }
1784
1785 mNtHeader.Pe32 = NtHeader32;
1786
1787 //
1788 // Check the architecture field of PE header and get the Certificate Data Directory data
1789 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1790 //
1791 if ( (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)
1792 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)
1793 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED))
1794 {
1795 //
1796 // 32-bits Architecture
1797 //
1798 mImageType = ImageType_IA32;
1799 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY *)&(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
1800 } else if ( (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)
1801 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)
1802 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64))
1803 {
1804 //
1805 // 64-bits Architecture
1806 //
1807 mImageType = ImageType_X64;
1808 NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *)(mImageBase + mPeCoffHeaderOffset);
1809 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY *)&(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
1810 } else {
1811 return EFI_UNSUPPORTED;
1812 }
1813
1814 return EFI_SUCCESS;
1815 }
1816
1817 /**
1818 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1819 PE/COFF Specification 8.0 Appendix A
1820
1821 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
1822 the function LoadPeImage ().
1823
1824 @param[in] HashAlg Hash algorithm type.
1825
1826 @retval TRUE Successfully hash image.
1827 @retval FALSE Fail in hash image.
1828
1829 **/
1830 BOOLEAN
1831 HashPeImage (
1832 IN UINT32 HashAlg
1833 )
1834 {
1835 BOOLEAN Status;
1836 EFI_IMAGE_SECTION_HEADER *Section;
1837 VOID *HashCtx;
1838 UINTN CtxSize;
1839 UINT8 *HashBase;
1840 UINTN HashSize;
1841 UINTN SumOfBytesHashed;
1842 EFI_IMAGE_SECTION_HEADER *SectionHeader;
1843 UINTN Index;
1844 UINTN Pos;
1845
1846 HashCtx = NULL;
1847 SectionHeader = NULL;
1848 Status = FALSE;
1849
1850 if (HashAlg != HASHALG_SHA256) {
1851 return FALSE;
1852 }
1853
1854 //
1855 // Initialize context of hash.
1856 //
1857 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
1858
1859 mImageDigestSize = SHA256_DIGEST_SIZE;
1860 mCertType = gEfiCertSha256Guid;
1861
1862 CtxSize = mHash[HashAlg].GetContextSize ();
1863
1864 HashCtx = AllocatePool (CtxSize);
1865 ASSERT (HashCtx != NULL);
1866
1867 // 1. Load the image header into memory.
1868
1869 // 2. Initialize a SHA hash context.
1870 Status = mHash[HashAlg].HashInit (HashCtx);
1871 if (!Status) {
1872 goto Done;
1873 }
1874
1875 //
1876 // Measuring PE/COFF Image Header;
1877 // But CheckSum field and SECURITY data directory (certificate) are excluded
1878 //
1879
1880 //
1881 // 3. Calculate the distance from the base of the image header to the image checksum address.
1882 // 4. Hash the image header from its base to beginning of the image checksum.
1883 //
1884 HashBase = mImageBase;
1885 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1886 //
1887 // Use PE32 offset.
1888 //
1889 HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
1890 } else {
1891 //
1892 // Use PE32+ offset.
1893 //
1894 HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
1895 }
1896
1897 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
1898 if (!Status) {
1899 goto Done;
1900 }
1901
1902 //
1903 // 5. Skip over the image checksum (it occupies a single ULONG).
1904 // 6. Get the address of the beginning of the Cert Directory.
1905 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1906 //
1907 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1908 //
1909 // Use PE32 offset.
1910 //
1911 HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
1912 HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
1913 } else {
1914 //
1915 // Use PE32+ offset.
1916 //
1917 HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
1918 HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
1919 }
1920
1921 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
1922 if (!Status) {
1923 goto Done;
1924 }
1925
1926 //
1927 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1928 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1929 //
1930 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1931 //
1932 // Use PE32 offset
1933 //
1934 HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
1935 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN)(&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN)mImageBase);
1936 } else {
1937 //
1938 // Use PE32+ offset.
1939 //
1940 HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
1941 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN)mImageBase);
1942 }
1943
1944 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
1945 if (!Status) {
1946 goto Done;
1947 }
1948
1949 //
1950 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1951 //
1952 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1953 //
1954 // Use PE32 offset.
1955 //
1956 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
1957 } else {
1958 //
1959 // Use PE32+ offset
1960 //
1961 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
1962 }
1963
1964 //
1965 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1966 // structures in the image. The 'NumberOfSections' field of the image
1967 // header indicates how big the table should be. Do not include any
1968 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1969 //
1970 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
1971 ASSERT (SectionHeader != NULL);
1972 //
1973 // 12. Using the 'PointerToRawData' in the referenced section headers as
1974 // a key, arrange the elements in the table in ascending order. In other
1975 // words, sort the section headers according to the disk-file offset of
1976 // the section.
1977 //
1978 Section = (EFI_IMAGE_SECTION_HEADER *)(
1979 mImageBase +
1980 mPeCoffHeaderOffset +
1981 sizeof (UINT32) +
1982 sizeof (EFI_IMAGE_FILE_HEADER) +
1983 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
1984 );
1985 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
1986 Pos = Index;
1987 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
1988 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
1989 Pos--;
1990 }
1991
1992 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
1993 Section += 1;
1994 }
1995
1996 //
1997 // 13. Walk through the sorted table, bring the corresponding section
1998 // into memory, and hash the entire section (using the 'SizeOfRawData'
1999 // field in the section header to determine the amount of data to hash).
2000 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2001 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
2002 //
2003 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
2004 Section = &SectionHeader[Index];
2005 if (Section->SizeOfRawData == 0) {
2006 continue;
2007 }
2008
2009 HashBase = mImageBase + Section->PointerToRawData;
2010 HashSize = (UINTN)Section->SizeOfRawData;
2011
2012 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
2013 if (!Status) {
2014 goto Done;
2015 }
2016
2017 SumOfBytesHashed += HashSize;
2018 }
2019
2020 //
2021 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
2022 // data in the file that needs to be added to the hash. This data begins
2023 // at file offset SUM_OF_BYTES_HASHED and its length is:
2024 // FileSize - (CertDirectory->Size)
2025 //
2026 if (mImageSize > SumOfBytesHashed) {
2027 HashBase = mImageBase + SumOfBytesHashed;
2028 if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2029 //
2030 // Use PE32 offset.
2031 //
2032 HashSize = (UINTN)(
2033 mImageSize -
2034 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
2035 SumOfBytesHashed);
2036 } else {
2037 //
2038 // Use PE32+ offset.
2039 //
2040 HashSize = (UINTN)(
2041 mImageSize -
2042 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
2043 SumOfBytesHashed);
2044 }
2045
2046 Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
2047 if (!Status) {
2048 goto Done;
2049 }
2050 }
2051
2052 Status = mHash[HashAlg].HashFinal (HashCtx, mImageDigest);
2053
2054 Done:
2055 if (HashCtx != NULL) {
2056 FreePool (HashCtx);
2057 }
2058
2059 if (SectionHeader != NULL) {
2060 FreePool (SectionHeader);
2061 }
2062
2063 return Status;
2064 }
2065
2066 /**
2067 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
2068 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
2069 8.0 Appendix A
2070
2071 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
2072 @retval EFI_SUCCESS Hash successfully.
2073
2074 **/
2075 EFI_STATUS
2076 HashPeImageByType (
2077 VOID
2078 )
2079 {
2080 UINT8 Index;
2081 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
2082
2083 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *)(mImageBase + mSecDataDir->Offset);
2084
2085 for (Index = 0; Index < HASHALG_MAX; Index++) {
2086 //
2087 // Check the Hash algorithm in PE/COFF Authenticode.
2088 // According to PKCS#7 Definition:
2089 // SignedData ::= SEQUENCE {
2090 // version Version,
2091 // digestAlgorithms DigestAlgorithmIdentifiers,
2092 // contentInfo ContentInfo,
2093 // .... }
2094 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
2095 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
2096 // Fixed offset (+32) is calculated based on two bytes of length encoding.
2097 //
2098 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
2099 //
2100 // Only support two bytes of Long Form of Length Encoding.
2101 //
2102 continue;
2103 }
2104
2105 //
2106 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
2107 break;
2108 }
2109 }
2110
2111 if (Index == HASHALG_MAX) {
2112 return EFI_UNSUPPORTED;
2113 }
2114
2115 //
2116 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
2117 //
2118 if (!HashPeImage (Index)) {
2119 return EFI_UNSUPPORTED;
2120 }
2121
2122 return EFI_SUCCESS;
2123 }
2124
2125 /**
2126 Enroll a new signature of executable into Signature Database.
2127
2128 @param[in] PrivateData The module's private data.
2129 @param[in] VariableName Variable name of signature database, must be
2130 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2131 or EFI_IMAGE_SECURITY_DATABASE2.
2132
2133 @retval EFI_SUCCESS New signature is enrolled successfully.
2134 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2135 @retval EFI_UNSUPPORTED Unsupported command.
2136 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2137
2138 **/
2139 EFI_STATUS
2140 EnrollAuthentication2Descriptor (
2141 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
2142 IN CHAR16 *VariableName
2143 )
2144 {
2145 EFI_STATUS Status;
2146 VOID *Data;
2147 UINTN DataSize;
2148 UINT32 Attr;
2149
2150 Data = NULL;
2151
2152 //
2153 // DBT only support DER-X509 Cert Enrollment
2154 //
2155 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {
2156 return EFI_UNSUPPORTED;
2157 }
2158
2159 //
2160 // Read the whole file content
2161 //
2162 Status = ReadFileContent (
2163 Private->FileContext->FHandle,
2164 (VOID **)&mImageBase,
2165 &mImageSize,
2166 0
2167 );
2168 if (EFI_ERROR (Status)) {
2169 goto ON_EXIT;
2170 }
2171
2172 ASSERT (mImageBase != NULL);
2173
2174 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
2175 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
2176
2177 //
2178 // Check if SigDB variable has been already existed.
2179 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2180 // new signature data to original variable
2181 //
2182 DataSize = 0;
2183 Status = gRT->GetVariable (
2184 VariableName,
2185 &gEfiImageSecurityDatabaseGuid,
2186 NULL,
2187 &DataSize,
2188 NULL
2189 );
2190 if (Status == EFI_BUFFER_TOO_SMALL) {
2191 Attr |= EFI_VARIABLE_APPEND_WRITE;
2192 } else if (Status != EFI_NOT_FOUND) {
2193 goto ON_EXIT;
2194 }
2195
2196 //
2197 // Directly set AUTHENTICATION_2 data to SetVariable
2198 //
2199 Status = gRT->SetVariable (
2200 VariableName,
2201 &gEfiImageSecurityDatabaseGuid,
2202 Attr,
2203 mImageSize,
2204 mImageBase
2205 );
2206
2207 DEBUG ((DEBUG_INFO, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName, Status));
2208
2209 ON_EXIT:
2210
2211 CloseEnrolledFile (Private->FileContext);
2212
2213 if (Data != NULL) {
2214 FreePool (Data);
2215 }
2216
2217 if (mImageBase != NULL) {
2218 FreePool (mImageBase);
2219 mImageBase = NULL;
2220 }
2221
2222 return Status;
2223 }
2224
2225 /**
2226 Enroll a new signature of executable into Signature Database.
2227
2228 @param[in] PrivateData The module's private data.
2229 @param[in] VariableName Variable name of signature database, must be
2230 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
2231 or EFI_IMAGE_SECURITY_DATABASE2.
2232
2233 @retval EFI_SUCCESS New signature is enrolled successfully.
2234 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2235 @retval EFI_UNSUPPORTED Unsupported command.
2236 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2237
2238 **/
2239 EFI_STATUS
2240 EnrollImageSignatureToSigDB (
2241 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
2242 IN CHAR16 *VariableName
2243 )
2244 {
2245 EFI_STATUS Status;
2246 EFI_SIGNATURE_LIST *SigDBCert;
2247 EFI_SIGNATURE_DATA *SigDBCertData;
2248 VOID *Data;
2249 UINTN DataSize;
2250 UINTN SigDBSize;
2251 UINT32 Attr;
2252 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;
2253 EFI_TIME Time;
2254
2255 Data = NULL;
2256 GuidCertData = NULL;
2257
2258 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {
2259 return EFI_UNSUPPORTED;
2260 }
2261
2262 //
2263 // Form the SigDB certificate list.
2264 // Format the data item into EFI_SIGNATURE_LIST type.
2265 //
2266 // We need to parse signature data of executable from specified signed executable file.
2267 // In current implementation, we simply trust the pass-in signed executable file.
2268 // In reality, it's OS's responsibility to verify the signed executable file.
2269 //
2270
2271 //
2272 // Read the whole file content
2273 //
2274 Status = ReadFileContent (
2275 Private->FileContext->FHandle,
2276 (VOID **)&mImageBase,
2277 &mImageSize,
2278 0
2279 );
2280 if (EFI_ERROR (Status)) {
2281 goto ON_EXIT;
2282 }
2283
2284 ASSERT (mImageBase != NULL);
2285
2286 Status = LoadPeImage ();
2287 if (EFI_ERROR (Status)) {
2288 goto ON_EXIT;
2289 }
2290
2291 if (mSecDataDir->SizeOfCert == 0) {
2292 if (!HashPeImage (HASHALG_SHA256)) {
2293 Status = EFI_SECURITY_VIOLATION;
2294 goto ON_EXIT;
2295 }
2296 } else {
2297 //
2298 // Read the certificate data
2299 //
2300 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);
2301
2302 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
2303 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID *)mCertificate;
2304 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof (EFI_GUID)) != 0) {
2305 Status = EFI_ABORTED;
2306 goto ON_EXIT;
2307 }
2308
2309 if (!HashPeImage (HASHALG_SHA256)) {
2310 Status = EFI_ABORTED;
2311 goto ON_EXIT;
2312 }
2313 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
2314 Status = HashPeImageByType ();
2315 if (EFI_ERROR (Status)) {
2316 goto ON_EXIT;
2317 }
2318 } else {
2319 Status = EFI_ABORTED;
2320 goto ON_EXIT;
2321 }
2322 }
2323
2324 //
2325 // Create a new SigDB entry.
2326 //
2327 SigDBSize = sizeof (EFI_SIGNATURE_LIST)
2328 + sizeof (EFI_SIGNATURE_DATA) - 1
2329 + (UINT32)mImageDigestSize;
2330
2331 Data = (UINT8 *)AllocateZeroPool (SigDBSize);
2332 if (Data == NULL) {
2333 Status = EFI_OUT_OF_RESOURCES;
2334 goto ON_EXIT;
2335 }
2336
2337 //
2338 // Adjust the Certificate Database parameters.
2339 //
2340 SigDBCert = (EFI_SIGNATURE_LIST *)Data;
2341 SigDBCert->SignatureListSize = (UINT32)SigDBSize;
2342 SigDBCert->SignatureHeaderSize = 0;
2343 SigDBCert->SignatureSize = sizeof (EFI_SIGNATURE_DATA) - 1 + (UINT32)mImageDigestSize;
2344 CopyGuid (&SigDBCert->SignatureType, &mCertType);
2345
2346 SigDBCertData = (EFI_SIGNATURE_DATA *)((UINT8 *)SigDBCert + sizeof (EFI_SIGNATURE_LIST));
2347 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
2348 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);
2349
2350 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
2351 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
2352 Status = GetCurrentTime (&Time);
2353 if (EFI_ERROR (Status)) {
2354 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
2355 goto ON_EXIT;
2356 }
2357
2358 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8 **)&Data, &Time);
2359 if (EFI_ERROR (Status)) {
2360 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
2361 goto ON_EXIT;
2362 }
2363
2364 //
2365 // Check if SigDB variable has been already existed.
2366 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
2367 // new signature data to original variable
2368 //
2369 DataSize = 0;
2370 Status = gRT->GetVariable (
2371 VariableName,
2372 &gEfiImageSecurityDatabaseGuid,
2373 NULL,
2374 &DataSize,
2375 NULL
2376 );
2377 if (Status == EFI_BUFFER_TOO_SMALL) {
2378 Attr |= EFI_VARIABLE_APPEND_WRITE;
2379 } else if (Status != EFI_NOT_FOUND) {
2380 goto ON_EXIT;
2381 }
2382
2383 //
2384 // Enroll the variable.
2385 //
2386 Status = gRT->SetVariable (
2387 VariableName,
2388 &gEfiImageSecurityDatabaseGuid,
2389 Attr,
2390 SigDBSize,
2391 Data
2392 );
2393 if (EFI_ERROR (Status)) {
2394 goto ON_EXIT;
2395 }
2396
2397 ON_EXIT:
2398
2399 CloseEnrolledFile (Private->FileContext);
2400
2401 if (Private->SignatureGUID != NULL) {
2402 FreePool (Private->SignatureGUID);
2403 Private->SignatureGUID = NULL;
2404 }
2405
2406 if (Data != NULL) {
2407 FreePool (Data);
2408 }
2409
2410 if (mImageBase != NULL) {
2411 FreePool (mImageBase);
2412 mImageBase = NULL;
2413 }
2414
2415 return Status;
2416 }
2417
2418 /**
2419 Enroll signature into DB/DBX/DBT without KEK's authentication.
2420 The SignatureOwner GUID will be Private->SignatureGUID.
2421
2422 @param[in] PrivateData The module's private data.
2423 @param[in] VariableName Variable name of signature database, must be
2424 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
2425
2426 @retval EFI_SUCCESS New signature enrolled successfully.
2427 @retval EFI_INVALID_PARAMETER The parameter is invalid.
2428 @retval others Fail to enroll signature data.
2429
2430 **/
2431 EFI_STATUS
2432 EnrollSignatureDatabase (
2433 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
2434 IN CHAR16 *VariableName
2435 )
2436 {
2437 UINT16 *FilePostFix;
2438 EFI_STATUS Status;
2439 UINTN NameLength;
2440
2441 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
2442 return EFI_INVALID_PARAMETER;
2443 }
2444
2445 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
2446 if (EFI_ERROR (Status)) {
2447 return Status;
2448 }
2449
2450 //
2451 // Parse the file's postfix.
2452 //
2453 NameLength = StrLen (Private->FileContext->FileName);
2454 if (NameLength <= 4) {
2455 return EFI_INVALID_PARAMETER;
2456 }
2457
2458 FilePostFix = Private->FileContext->FileName + NameLength - 4;
2459 if (IsDerEncodeCertificate (FilePostFix)) {
2460 //
2461 // Supports DER-encoded X509 certificate.
2462 //
2463 return EnrollX509toSigDB (Private, VariableName);
2464 } else if (IsAuthentication2Format (Private->FileContext->FHandle)) {
2465 return EnrollAuthentication2Descriptor (Private, VariableName);
2466 } else {
2467 return EnrollImageSignatureToSigDB (Private, VariableName);
2468 }
2469 }
2470
2471 /**
2472 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
2473 by GUID in the page for user to select and delete as needed.
2474
2475 @param[in] PrivateData Module's private data.
2476 @param[in] VariableName The variable name of the vendor's signature database.
2477 @param[in] VendorGuid A unique identifier for the vendor.
2478 @param[in] LabelNumber Label number to insert opcodes.
2479 @param[in] FormId Form ID of current page.
2480 @param[in] QuestionIdBase Base question id of the signature list.
2481
2482 @retval EFI_SUCCESS Success to update the signature list page
2483 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
2484
2485 **/
2486 EFI_STATUS
2487 UpdateDeletePage (
2488 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
2489 IN CHAR16 *VariableName,
2490 IN EFI_GUID *VendorGuid,
2491 IN UINT16 LabelNumber,
2492 IN EFI_FORM_ID FormId,
2493 IN EFI_QUESTION_ID QuestionIdBase
2494 )
2495 {
2496 EFI_STATUS Status;
2497 UINT32 Index;
2498 UINTN CertCount;
2499 UINTN GuidIndex;
2500 VOID *StartOpCodeHandle;
2501 VOID *EndOpCodeHandle;
2502 EFI_IFR_GUID_LABEL *StartLabel;
2503 EFI_IFR_GUID_LABEL *EndLabel;
2504 UINTN DataSize;
2505 UINT8 *Data;
2506 EFI_SIGNATURE_LIST *CertList;
2507 EFI_SIGNATURE_DATA *Cert;
2508 UINT32 ItemDataSize;
2509 CHAR16 *GuidStr;
2510 EFI_STRING_ID GuidID;
2511 EFI_STRING_ID Help;
2512
2513 Data = NULL;
2514 CertList = NULL;
2515 Cert = NULL;
2516 GuidStr = NULL;
2517 StartOpCodeHandle = NULL;
2518 EndOpCodeHandle = NULL;
2519
2520 //
2521 // Initialize the container for dynamic opcodes.
2522 //
2523 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2524 if (StartOpCodeHandle == NULL) {
2525 Status = EFI_OUT_OF_RESOURCES;
2526 goto ON_EXIT;
2527 }
2528
2529 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2530 if (EndOpCodeHandle == NULL) {
2531 Status = EFI_OUT_OF_RESOURCES;
2532 goto ON_EXIT;
2533 }
2534
2535 //
2536 // Create Hii Extend Label OpCode.
2537 //
2538 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
2539 StartOpCodeHandle,
2540 &gEfiIfrTianoGuid,
2541 NULL,
2542 sizeof (EFI_IFR_GUID_LABEL)
2543 );
2544 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2545 StartLabel->Number = LabelNumber;
2546
2547 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
2548 EndOpCodeHandle,
2549 &gEfiIfrTianoGuid,
2550 NULL,
2551 sizeof (EFI_IFR_GUID_LABEL)
2552 );
2553 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2554 EndLabel->Number = LABEL_END;
2555
2556 //
2557 // Read Variable.
2558 //
2559 DataSize = 0;
2560 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
2561 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
2562 goto ON_EXIT;
2563 }
2564
2565 Data = (UINT8 *)AllocateZeroPool (DataSize);
2566 if (Data == NULL) {
2567 Status = EFI_OUT_OF_RESOURCES;
2568 goto ON_EXIT;
2569 }
2570
2571 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
2572 if (EFI_ERROR (Status)) {
2573 goto ON_EXIT;
2574 }
2575
2576 GuidStr = AllocateZeroPool (100);
2577 if (GuidStr == NULL) {
2578 Status = EFI_OUT_OF_RESOURCES;
2579 goto ON_EXIT;
2580 }
2581
2582 //
2583 // Enumerate all KEK pub data.
2584 //
2585 ItemDataSize = (UINT32)DataSize;
2586 CertList = (EFI_SIGNATURE_LIST *)Data;
2587 GuidIndex = 0;
2588
2589 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
2590 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {
2591 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);
2592 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
2593 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);
2594 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {
2595 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);
2596 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {
2597 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);
2598 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {
2599 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);
2600 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {
2601 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);
2602 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {
2603 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);
2604 } else {
2605 //
2606 // The signature type is not supported in current implementation.
2607 //
2608 ItemDataSize -= CertList->SignatureListSize;
2609 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
2610 continue;
2611 }
2612
2613 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2614 for (Index = 0; Index < CertCount; Index++) {
2615 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList
2616 + sizeof (EFI_SIGNATURE_LIST)
2617 + CertList->SignatureHeaderSize
2618 + Index * CertList->SignatureSize);
2619 //
2620 // Display GUID and help
2621 //
2622 GuidToString (&Cert->SignatureOwner, GuidStr, 100);
2623 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);
2624 HiiCreateCheckBoxOpCode (
2625 StartOpCodeHandle,
2626 (EFI_QUESTION_ID)(QuestionIdBase + GuidIndex++),
2627 0,
2628 0,
2629 GuidID,
2630 Help,
2631 EFI_IFR_FLAG_CALLBACK,
2632 0,
2633 NULL
2634 );
2635 }
2636
2637 ItemDataSize -= CertList->SignatureListSize;
2638 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
2639 }
2640
2641 ON_EXIT:
2642 HiiUpdateForm (
2643 PrivateData->HiiHandle,
2644 &gSecureBootConfigFormSetGuid,
2645 FormId,
2646 StartOpCodeHandle,
2647 EndOpCodeHandle
2648 );
2649
2650 if (StartOpCodeHandle != NULL) {
2651 HiiFreeOpCodeHandle (StartOpCodeHandle);
2652 }
2653
2654 if (EndOpCodeHandle != NULL) {
2655 HiiFreeOpCodeHandle (EndOpCodeHandle);
2656 }
2657
2658 if (Data != NULL) {
2659 FreePool (Data);
2660 }
2661
2662 if (GuidStr != NULL) {
2663 FreePool (GuidStr);
2664 }
2665
2666 return EFI_SUCCESS;
2667 }
2668
2669 /**
2670 Delete a KEK entry from KEK database.
2671
2672 @param[in] PrivateData Module's private data.
2673 @param[in] QuestionId Question id of the KEK item to delete.
2674
2675 @retval EFI_SUCCESS Delete kek item successfully.
2676 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2677
2678 **/
2679 EFI_STATUS
2680 DeleteKeyExchangeKey (
2681 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
2682 IN EFI_QUESTION_ID QuestionId
2683 )
2684 {
2685 EFI_STATUS Status;
2686 UINTN DataSize;
2687 UINT8 *Data;
2688 UINT8 *OldData;
2689 UINT32 Attr;
2690 UINT32 Index;
2691 EFI_SIGNATURE_LIST *CertList;
2692 EFI_SIGNATURE_LIST *NewCertList;
2693 EFI_SIGNATURE_DATA *Cert;
2694 UINTN CertCount;
2695 UINT32 Offset;
2696 BOOLEAN IsKEKItemFound;
2697 UINT32 KekDataSize;
2698 UINTN DeleteKekIndex;
2699 UINTN GuidIndex;
2700 EFI_TIME Time;
2701
2702 Data = NULL;
2703 OldData = NULL;
2704 CertList = NULL;
2705 Cert = NULL;
2706 Attr = 0;
2707 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;
2708
2709 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
2710 if (EFI_ERROR (Status)) {
2711 return Status;
2712 }
2713
2714 //
2715 // Get original KEK variable.
2716 //
2717 DataSize = 0;
2718 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);
2719 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
2720 goto ON_EXIT;
2721 }
2722
2723 OldData = (UINT8 *)AllocateZeroPool (DataSize);
2724 if (OldData == NULL) {
2725 Status = EFI_OUT_OF_RESOURCES;
2726 goto ON_EXIT;
2727 }
2728
2729 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);
2730 if (EFI_ERROR (Status)) {
2731 goto ON_EXIT;
2732 }
2733
2734 //
2735 // Allocate space for new variable.
2736 //
2737 Data = (UINT8 *)AllocateZeroPool (DataSize);
2738 if (Data == NULL) {
2739 Status = EFI_OUT_OF_RESOURCES;
2740 goto ON_EXIT;
2741 }
2742
2743 //
2744 // Enumerate all KEK pub data and erasing the target item.
2745 //
2746 IsKEKItemFound = FALSE;
2747 KekDataSize = (UINT32)DataSize;
2748 CertList = (EFI_SIGNATURE_LIST *)OldData;
2749 Offset = 0;
2750 GuidIndex = 0;
2751 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
2752 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
2753 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid))
2754 {
2755 CopyMem (Data + Offset, CertList, (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
2756 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);
2757 Offset += (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2758 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2759 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2760 for (Index = 0; Index < CertCount; Index++) {
2761 if (GuidIndex == DeleteKekIndex ) {
2762 //
2763 // Find it! Skip it!
2764 //
2765 NewCertList->SignatureListSize -= CertList->SignatureSize;
2766 IsKEKItemFound = TRUE;
2767 } else {
2768 //
2769 // This item doesn't match. Copy it to the Data buffer.
2770 //
2771 CopyMem (Data + Offset, Cert, CertList->SignatureSize);
2772 Offset += CertList->SignatureSize;
2773 }
2774
2775 GuidIndex++;
2776 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);
2777 }
2778 } else {
2779 //
2780 // This List doesn't match. Copy it to the Data buffer.
2781 //
2782 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);
2783 Offset += CertList->SignatureListSize;
2784 }
2785
2786 KekDataSize -= CertList->SignatureListSize;
2787 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
2788 }
2789
2790 if (!IsKEKItemFound) {
2791 //
2792 // Doesn't find the Kek Item!
2793 //
2794 Status = EFI_NOT_FOUND;
2795 goto ON_EXIT;
2796 }
2797
2798 //
2799 // Delete the Signature header if there is no signature in the list.
2800 //
2801 KekDataSize = Offset;
2802 CertList = (EFI_SIGNATURE_LIST *)Data;
2803 Offset = 0;
2804 ZeroMem (OldData, KekDataSize);
2805 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
2806 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2807 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));
2808 if (CertCount != 0) {
2809 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);
2810 Offset += CertList->SignatureListSize;
2811 }
2812
2813 KekDataSize -= CertList->SignatureListSize;
2814 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
2815 }
2816
2817 DataSize = Offset;
2818 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
2819 Status = GetCurrentTime (&Time);
2820 if (EFI_ERROR (Status)) {
2821 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
2822 goto ON_EXIT;
2823 }
2824
2825 Status = CreateTimeBasedPayload (&DataSize, &OldData, &Time);
2826 if (EFI_ERROR (Status)) {
2827 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
2828 goto ON_EXIT;
2829 }
2830 }
2831
2832 Status = gRT->SetVariable (
2833 EFI_KEY_EXCHANGE_KEY_NAME,
2834 &gEfiGlobalVariableGuid,
2835 Attr,
2836 DataSize,
2837 OldData
2838 );
2839 if (EFI_ERROR (Status)) {
2840 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
2841 goto ON_EXIT;
2842 }
2843
2844 ON_EXIT:
2845 if (Data != NULL) {
2846 FreePool (Data);
2847 }
2848
2849 if (OldData != NULL) {
2850 FreePool (OldData);
2851 }
2852
2853 return UpdateDeletePage (
2854 PrivateData,
2855 EFI_KEY_EXCHANGE_KEY_NAME,
2856 &gEfiGlobalVariableGuid,
2857 LABEL_KEK_DELETE,
2858 FORMID_DELETE_KEK_FORM,
2859 OPTION_DEL_KEK_QUESTION_ID
2860 );
2861 }
2862
2863 /**
2864 Delete a signature entry from signature database.
2865
2866 @param[in] PrivateData Module's private data.
2867 @param[in] VariableName The variable name of the vendor's signature database.
2868 @param[in] VendorGuid A unique identifier for the vendor.
2869 @param[in] LabelNumber Label number to insert opcodes.
2870 @param[in] FormId Form ID of current page.
2871 @param[in] QuestionIdBase Base question id of the signature list.
2872 @param[in] DeleteIndex Signature index to delete.
2873
2874 @retval EFI_SUCCESS Delete signature successfully.
2875 @retval EFI_NOT_FOUND Can't find the signature item,
2876 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
2877 **/
2878 EFI_STATUS
2879 DeleteSignature (
2880 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
2881 IN CHAR16 *VariableName,
2882 IN EFI_GUID *VendorGuid,
2883 IN UINT16 LabelNumber,
2884 IN EFI_FORM_ID FormId,
2885 IN EFI_QUESTION_ID QuestionIdBase,
2886 IN UINTN DeleteIndex
2887 )
2888 {
2889 EFI_STATUS Status;
2890 UINTN DataSize;
2891 UINT8 *Data;
2892 UINT8 *OldData;
2893 UINT32 Attr;
2894 UINT32 Index;
2895 EFI_SIGNATURE_LIST *CertList;
2896 EFI_SIGNATURE_LIST *NewCertList;
2897 EFI_SIGNATURE_DATA *Cert;
2898 UINTN CertCount;
2899 UINT32 Offset;
2900 BOOLEAN IsItemFound;
2901 UINT32 ItemDataSize;
2902 UINTN GuidIndex;
2903 EFI_TIME Time;
2904
2905 Data = NULL;
2906 OldData = NULL;
2907 CertList = NULL;
2908 Cert = NULL;
2909 Attr = 0;
2910
2911 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
2912 if (EFI_ERROR (Status)) {
2913 return Status;
2914 }
2915
2916 //
2917 // Get original signature list data.
2918 //
2919 DataSize = 0;
2920 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
2921 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
2922 goto ON_EXIT;
2923 }
2924
2925 OldData = (UINT8 *)AllocateZeroPool (DataSize);
2926 if (OldData == NULL) {
2927 Status = EFI_OUT_OF_RESOURCES;
2928 goto ON_EXIT;
2929 }
2930
2931 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
2932 if (EFI_ERROR (Status)) {
2933 goto ON_EXIT;
2934 }
2935
2936 //
2937 // Allocate space for new variable.
2938 //
2939 Data = (UINT8 *)AllocateZeroPool (DataSize);
2940 if (Data == NULL) {
2941 Status = EFI_OUT_OF_RESOURCES;
2942 goto ON_EXIT;
2943 }
2944
2945 //
2946 // Enumerate all signature data and erasing the target item.
2947 //
2948 IsItemFound = FALSE;
2949 ItemDataSize = (UINT32)DataSize;
2950 CertList = (EFI_SIGNATURE_LIST *)OldData;
2951 Offset = 0;
2952 GuidIndex = 0;
2953 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
2954 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
2955 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||
2956 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||
2957 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||
2958 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||
2959 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||
2960 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)
2961 )
2962 {
2963 //
2964 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2965 //
2966 CopyMem (Data + Offset, CertList, (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
2967 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);
2968 Offset += (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2969 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2970 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2971 for (Index = 0; Index < CertCount; Index++) {
2972 if (GuidIndex == DeleteIndex) {
2973 //
2974 // Find it! Skip it!
2975 //
2976 NewCertList->SignatureListSize -= CertList->SignatureSize;
2977 IsItemFound = TRUE;
2978 } else {
2979 //
2980 // This item doesn't match. Copy it to the Data buffer.
2981 //
2982 CopyMem (Data + Offset, (UINT8 *)(Cert), CertList->SignatureSize);
2983 Offset += CertList->SignatureSize;
2984 }
2985
2986 GuidIndex++;
2987 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);
2988 }
2989 } else {
2990 //
2991 // This List doesn't match. Just copy it to the Data buffer.
2992 //
2993 CopyMem (Data + Offset, (UINT8 *)(CertList), CertList->SignatureListSize);
2994 Offset += CertList->SignatureListSize;
2995 }
2996
2997 ItemDataSize -= CertList->SignatureListSize;
2998 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
2999 }
3000
3001 if (!IsItemFound) {
3002 //
3003 // Doesn't find the signature Item!
3004 //
3005 Status = EFI_NOT_FOUND;
3006 goto ON_EXIT;
3007 }
3008
3009 //
3010 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
3011 //
3012 ItemDataSize = Offset;
3013 CertList = (EFI_SIGNATURE_LIST *)Data;
3014 Offset = 0;
3015 ZeroMem (OldData, ItemDataSize);
3016 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
3017 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
3018 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));
3019 if (CertCount != 0) {
3020 CopyMem (OldData + Offset, (UINT8 *)(CertList), CertList->SignatureListSize);
3021 Offset += CertList->SignatureListSize;
3022 }
3023
3024 ItemDataSize -= CertList->SignatureListSize;
3025 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
3026 }
3027
3028 DataSize = Offset;
3029 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
3030 Status = GetCurrentTime (&Time);
3031 if (EFI_ERROR (Status)) {
3032 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
3033 goto ON_EXIT;
3034 }
3035
3036 Status = CreateTimeBasedPayload (&DataSize, &OldData, &Time);
3037 if (EFI_ERROR (Status)) {
3038 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
3039 goto ON_EXIT;
3040 }
3041 }
3042
3043 Status = gRT->SetVariable (
3044 VariableName,
3045 VendorGuid,
3046 Attr,
3047 DataSize,
3048 OldData
3049 );
3050 if (EFI_ERROR (Status)) {
3051 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
3052 goto ON_EXIT;
3053 }
3054
3055 ON_EXIT:
3056 if (Data != NULL) {
3057 FreePool (Data);
3058 }
3059
3060 if (OldData != NULL) {
3061 FreePool (OldData);
3062 }
3063
3064 return UpdateDeletePage (
3065 PrivateData,
3066 VariableName,
3067 VendorGuid,
3068 LabelNumber,
3069 FormId,
3070 QuestionIdBase
3071 );
3072 }
3073
3074 /**
3075 This function to delete signature list or data, according by DelType.
3076
3077 @param[in] PrivateData Module's private data.
3078 @param[in] DelType Indicate delete signature list or data.
3079 @param[in] CheckedCount Indicate how many signature data have
3080 been checked in current signature list.
3081
3082 @retval EFI_SUCCESS Success to update the signature list page
3083 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3084 **/
3085 EFI_STATUS
3086 DeleteSignatureEx (
3087 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
3088 IN SIGNATURE_DELETE_TYPE DelType,
3089 IN UINT32 CheckedCount
3090 )
3091 {
3092 EFI_STATUS Status;
3093 EFI_SIGNATURE_LIST *ListWalker;
3094 EFI_SIGNATURE_LIST *NewCertList;
3095 EFI_SIGNATURE_DATA *DataWalker;
3096 CHAR16 VariableName[BUFFER_MAX_SIZE];
3097 UINT32 VariableAttr;
3098 UINTN VariableDataSize;
3099 UINTN RemainingSize;
3100 UINTN ListIndex;
3101 UINTN Index;
3102 UINTN Offset;
3103 UINT8 *VariableData;
3104 UINT8 *NewVariableData;
3105 EFI_TIME Time;
3106
3107 Status = EFI_SUCCESS;
3108 VariableAttr = 0;
3109 VariableDataSize = 0;
3110 ListIndex = 0;
3111 Offset = 0;
3112 VariableData = NULL;
3113 NewVariableData = NULL;
3114
3115 if (PrivateData->VariableName == Variable_DB) {
3116 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);
3117 } else if (PrivateData->VariableName == Variable_DBX) {
3118 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);
3119 } else if (PrivateData->VariableName == Variable_DBT) {
3120 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);
3121 } else {
3122 goto ON_EXIT;
3123 }
3124
3125 Status = gRT->GetVariable (
3126 VariableName,
3127 &gEfiImageSecurityDatabaseGuid,
3128 &VariableAttr,
3129 &VariableDataSize,
3130 VariableData
3131 );
3132 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
3133 goto ON_EXIT;
3134 }
3135
3136 VariableData = AllocateZeroPool (VariableDataSize);
3137 if (VariableData == NULL) {
3138 Status = EFI_OUT_OF_RESOURCES;
3139 goto ON_EXIT;
3140 }
3141
3142 Status = gRT->GetVariable (
3143 VariableName,
3144 &gEfiImageSecurityDatabaseGuid,
3145 &VariableAttr,
3146 &VariableDataSize,
3147 VariableData
3148 );
3149 if (EFI_ERROR (Status)) {
3150 goto ON_EXIT;
3151 }
3152
3153 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
3154 if (EFI_ERROR (Status)) {
3155 goto ON_EXIT;
3156 }
3157
3158 NewVariableData = AllocateZeroPool (VariableDataSize);
3159 if (NewVariableData == NULL) {
3160 Status = EFI_OUT_OF_RESOURCES;
3161 goto ON_EXIT;
3162 }
3163
3164 RemainingSize = VariableDataSize;
3165 ListWalker = (EFI_SIGNATURE_LIST *)(VariableData);
3166 if (DelType == Delete_Signature_List_All) {
3167 VariableDataSize = 0;
3168 } else {
3169 //
3170 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
3171 //
3172 while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex < PrivateData->ListIndex) {
3173 CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, ListWalker->SignatureListSize);
3174 Offset += ListWalker->SignatureListSize;
3175
3176 RemainingSize -= ListWalker->SignatureListSize;
3177 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
3178 ListIndex++;
3179 }
3180
3181 //
3182 // Handle the target EFI_SIGNATURE_LIST.
3183 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
3184 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
3185 //
3186 if ((CheckedCount < SIGNATURE_DATA_COUNTS (ListWalker)) && (DelType == Delete_Signature_Data)) {
3187 NewCertList = (EFI_SIGNATURE_LIST *)(NewVariableData + Offset);
3188 //
3189 // Copy header.
3190 //
3191 CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);
3192 Offset += sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize;
3193
3194 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);
3195 for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) {
3196 if (PrivateData->CheckArray[Index]) {
3197 //
3198 // Delete checked signature data, and update the size of whole signature list.
3199 //
3200 NewCertList->SignatureListSize -= NewCertList->SignatureSize;
3201 } else {
3202 //
3203 // Remain the unchecked signature data.
3204 //
3205 CopyMem ((UINT8 *)NewVariableData + Offset, DataWalker, ListWalker->SignatureSize);
3206 Offset += ListWalker->SignatureSize;
3207 }
3208
3209 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);
3210 }
3211 }
3212
3213 RemainingSize -= ListWalker->SignatureListSize;
3214 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
3215
3216 //
3217 // Copy remaining data, maybe 0.
3218 //
3219 CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, RemainingSize);
3220 Offset += RemainingSize;
3221
3222 VariableDataSize = Offset;
3223 }
3224
3225 if ((VariableAttr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
3226 Status = GetCurrentTime (&Time);
3227 if (EFI_ERROR (Status)) {
3228 DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status));
3229 goto ON_EXIT;
3230 }
3231
3232 Status = CreateTimeBasedPayload (&VariableDataSize, &NewVariableData, &Time);
3233 if (EFI_ERROR (Status)) {
3234 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
3235 goto ON_EXIT;
3236 }
3237 }
3238
3239 Status = gRT->SetVariable (
3240 VariableName,
3241 &gEfiImageSecurityDatabaseGuid,
3242 VariableAttr,
3243 VariableDataSize,
3244 NewVariableData
3245 );
3246 if (EFI_ERROR (Status)) {
3247 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r", Status));
3248 goto ON_EXIT;
3249 }
3250
3251 ON_EXIT:
3252 SECUREBOOT_FREE_NON_NULL (VariableData);
3253 SECUREBOOT_FREE_NON_NULL (NewVariableData);
3254
3255 return Status;
3256 }
3257
3258 /**
3259
3260 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
3261 and STR_CUR_SECURE_BOOT_MODE_CONTENT.
3262
3263 @param[in] PrivateData Module's private data.
3264
3265 @return EFI_SUCCESS Update secure boot strings successfully.
3266 @return other Fail to update secure boot strings.
3267
3268 **/
3269 EFI_STATUS
3270 UpdateSecureBootString (
3271 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
3272 )
3273 {
3274 UINT8 *SecureBoot;
3275
3276 SecureBoot = NULL;
3277
3278 //
3279 // Get current secure boot state.
3280 //
3281 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID **)&SecureBoot, NULL);
3282 if (SecureBoot == NULL) {
3283 return EFI_NOT_FOUND;
3284 }
3285
3286 if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {
3287 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);
3288 } else {
3289 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);
3290 }
3291
3292 FreePool (SecureBoot);
3293
3294 return EFI_SUCCESS;
3295 }
3296
3297 /**
3298 This function extracts configuration from variable.
3299
3300 @param[in] Private Point to SecureBoot configuration driver private data.
3301 @param[in, out] ConfigData Point to SecureBoot configuration private data.
3302
3303 **/
3304 VOID
3305 SecureBootExtractConfigFromVariable (
3306 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
3307 IN OUT SECUREBOOT_CONFIGURATION *ConfigData
3308 )
3309 {
3310 UINT8 *SecureBootEnable;
3311 UINT8 *SetupMode;
3312 UINT8 *SecureBootMode;
3313 EFI_TIME CurrTime;
3314
3315 SecureBootEnable = NULL;
3316 SetupMode = NULL;
3317 SecureBootMode = NULL;
3318
3319 //
3320 // Initialize the Date and Time using system time.
3321 //
3322 ConfigData->CertificateFormat = HASHALG_RAW;
3323 ConfigData->AlwaysRevocation = TRUE;
3324 gRT->GetTime (&CurrTime, NULL);
3325 ConfigData->RevocationDate.Year = CurrTime.Year;
3326 ConfigData->RevocationDate.Month = CurrTime.Month;
3327 ConfigData->RevocationDate.Day = CurrTime.Day;
3328 ConfigData->RevocationTime.Hour = CurrTime.Hour;
3329 ConfigData->RevocationTime.Minute = CurrTime.Minute;
3330 ConfigData->RevocationTime.Second = 0;
3331 if (Private->FileContext->FHandle != NULL) {
3332 ConfigData->FileEnrollType = Private->FileContext->FileType;
3333 } else {
3334 ConfigData->FileEnrollType = UNKNOWN_FILE_TYPE;
3335 }
3336
3337 //
3338 // If it is Physical Presence User, set the PhysicalPresent to true.
3339 //
3340 if (UserPhysicalPresent ()) {
3341 ConfigData->PhysicalPresent = TRUE;
3342 } else {
3343 ConfigData->PhysicalPresent = FALSE;
3344 }
3345
3346 //
3347 // If there is no PK then the Delete Pk button will be gray.
3348 //
3349 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID **)&SetupMode, NULL);
3350 if ((SetupMode == NULL) || ((*SetupMode) == SETUP_MODE)) {
3351 ConfigData->HasPk = FALSE;
3352 } else {
3353 ConfigData->HasPk = TRUE;
3354 }
3355
3356 //
3357 // Check SecureBootEnable & Pk status, fix the inconsistency.
3358 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
3359 // Checkbox.
3360 //
3361 ConfigData->AttemptSecureBoot = FALSE;
3362 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **)&SecureBootEnable, NULL);
3363
3364 //
3365 // Fix Pk and SecureBootEnable inconsistency
3366 //
3367 if ((SetupMode != NULL) && ((*SetupMode) == USER_MODE)) {
3368 ConfigData->HideSecureBoot = FALSE;
3369 if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) {
3370 ConfigData->AttemptSecureBoot = TRUE;
3371 }
3372 } else {
3373 ConfigData->HideSecureBoot = TRUE;
3374 }
3375
3376 //
3377 // Get the SecureBootMode from CustomMode variable.
3378 //
3379 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID **)&SecureBootMode, NULL);
3380 if (SecureBootMode == NULL) {
3381 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
3382 } else {
3383 ConfigData->SecureBootMode = *(SecureBootMode);
3384 }
3385
3386 if (SecureBootEnable != NULL) {
3387 FreePool (SecureBootEnable);
3388 }
3389
3390 if (SetupMode != NULL) {
3391 FreePool (SetupMode);
3392 }
3393
3394 if (SecureBootMode != NULL) {
3395 FreePool (SecureBootMode);
3396 }
3397 }
3398
3399 /**
3400 This function allows a caller to extract the current configuration for one
3401 or more named elements from the target driver.
3402
3403 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3404 @param[in] Request A null-terminated Unicode string in
3405 <ConfigRequest> format.
3406 @param[out] Progress On return, points to a character in the Request
3407 string. Points to the string's null terminator if
3408 request was successful. Points to the most recent
3409 '&' before the first failing name/value pair (or
3410 the beginning of the string if the failure is in
3411 the first name/value pair) if the request was not
3412 successful.
3413 @param[out] Results A null-terminated Unicode string in
3414 <ConfigAltResp> format which has all values filled
3415 in for the names in the Request string. String to
3416 be allocated by the called function.
3417
3418 @retval EFI_SUCCESS The Results is filled with the requested values.
3419 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3420 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3421 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3422 driver.
3423
3424 **/
3425 EFI_STATUS
3426 EFIAPI
3427 SecureBootExtractConfig (
3428 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3429 IN CONST EFI_STRING Request,
3430 OUT EFI_STRING *Progress,
3431 OUT EFI_STRING *Results
3432 )
3433 {
3434 EFI_STATUS Status;
3435 UINTN BufferSize;
3436 UINTN Size;
3437 SECUREBOOT_CONFIGURATION Configuration;
3438 EFI_STRING ConfigRequest;
3439 EFI_STRING ConfigRequestHdr;
3440 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
3441 BOOLEAN AllocatedRequest;
3442
3443 if ((Progress == NULL) || (Results == NULL)) {
3444 return EFI_INVALID_PARAMETER;
3445 }
3446
3447 AllocatedRequest = FALSE;
3448 ConfigRequestHdr = NULL;
3449 ConfigRequest = NULL;
3450 Size = 0;
3451
3452 ZeroMem (&Configuration, sizeof (Configuration));
3453 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
3454 *Progress = Request;
3455
3456 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
3457 return EFI_NOT_FOUND;
3458 }
3459
3460 ZeroMem (&Configuration, sizeof (SECUREBOOT_CONFIGURATION));
3461
3462 //
3463 // Get Configuration from Variable.
3464 //
3465 SecureBootExtractConfigFromVariable (PrivateData, &Configuration);
3466
3467 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
3468 ConfigRequest = Request;
3469 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
3470 //
3471 // Request is set to NULL or OFFSET is NULL, construct full request string.
3472 //
3473 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3474 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3475 //
3476 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);
3477 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
3478 ConfigRequest = AllocateZeroPool (Size);
3479 ASSERT (ConfigRequest != NULL);
3480 AllocatedRequest = TRUE;
3481 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
3482 FreePool (ConfigRequestHdr);
3483 ConfigRequestHdr = NULL;
3484 }
3485
3486 Status = gHiiConfigRouting->BlockToConfig (
3487 gHiiConfigRouting,
3488 ConfigRequest,
3489 (UINT8 *)&Configuration,
3490 BufferSize,
3491 Results,
3492 Progress
3493 );
3494
3495 //
3496 // Free the allocated config request string.
3497 //
3498 if (AllocatedRequest) {
3499 FreePool (ConfigRequest);
3500 }
3501
3502 //
3503 // Set Progress string to the original request string.
3504 //
3505 if (Request == NULL) {
3506 *Progress = NULL;
3507 } else if (StrStr (Request, L"OFFSET") == NULL) {
3508 *Progress = Request + StrLen (Request);
3509 }
3510
3511 return Status;
3512 }
3513
3514 /**
3515 This function processes the results of changes in configuration.
3516
3517 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3518 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
3519 format.
3520 @param[out] Progress A pointer to a string filled in with the offset of
3521 the most recent '&' before the first failing
3522 name/value pair (or the beginning of the string if
3523 the failure is in the first name/value pair) or
3524 the terminating NULL if all was successful.
3525
3526 @retval EFI_SUCCESS The Results is processed successfully.
3527 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3528 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
3529 driver.
3530
3531 **/
3532 EFI_STATUS
3533 EFIAPI
3534 SecureBootRouteConfig (
3535 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3536 IN CONST EFI_STRING Configuration,
3537 OUT EFI_STRING *Progress
3538 )
3539 {
3540 SECUREBOOT_CONFIGURATION IfrNvData;
3541 UINTN BufferSize;
3542 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
3543 EFI_STATUS Status;
3544
3545 if ((Configuration == NULL) || (Progress == NULL)) {
3546 return EFI_INVALID_PARAMETER;
3547 }
3548
3549 *Progress = Configuration;
3550 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
3551 return EFI_NOT_FOUND;
3552 }
3553
3554 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
3555
3556 //
3557 // Get Configuration from Variable.
3558 //
3559 SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData);
3560
3561 //
3562 // Map the Configuration to the configuration block.
3563 //
3564 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
3565 Status = gHiiConfigRouting->ConfigToBlock (
3566 gHiiConfigRouting,
3567 Configuration,
3568 (UINT8 *)&IfrNvData,
3569 &BufferSize,
3570 Progress
3571 );
3572 if (EFI_ERROR (Status)) {
3573 return Status;
3574 }
3575
3576 //
3577 // Store Buffer Storage back to EFI variable if needed
3578 //
3579 if (!IfrNvData.HideSecureBoot) {
3580 Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);
3581 if (EFI_ERROR (Status)) {
3582 return Status;
3583 }
3584 }
3585
3586 *Progress = Configuration + StrLen (Configuration);
3587 return EFI_SUCCESS;
3588 }
3589
3590 /**
3591 This function to load signature list, the update the menu page.
3592
3593 @param[in] PrivateData Module's private data.
3594 @param[in] LabelId Label number to insert opcodes.
3595 @param[in] FormId Form ID of current page.
3596 @param[in] QuestionIdBase Base question id of the signature list.
3597
3598 @retval EFI_SUCCESS Success to update the signature list page
3599 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3600 **/
3601 EFI_STATUS
3602 LoadSignatureList (
3603 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
3604 IN UINT16 LabelId,
3605 IN EFI_FORM_ID FormId,
3606 IN EFI_QUESTION_ID QuestionIdBase
3607 )
3608 {
3609 EFI_STATUS Status;
3610 EFI_STRING_ID ListType;
3611 EFI_STRING FormatNameString;
3612 EFI_STRING FormatHelpString;
3613 EFI_STRING FormatTypeString;
3614 EFI_SIGNATURE_LIST *ListWalker;
3615 EFI_IFR_GUID_LABEL *StartLabel;
3616 EFI_IFR_GUID_LABEL *EndLabel;
3617 EFI_IFR_GUID_LABEL *StartGoto;
3618 EFI_IFR_GUID_LABEL *EndGoto;
3619 EFI_FORM_ID DstFormId;
3620 VOID *StartOpCodeHandle;
3621 VOID *EndOpCodeHandle;
3622 VOID *StartGotoHandle;
3623 VOID *EndGotoHandle;
3624 UINTN DataSize;
3625 UINTN RemainingSize;
3626 UINT16 Index;
3627 UINT8 *VariableData;
3628 CHAR16 VariableName[BUFFER_MAX_SIZE];
3629 CHAR16 NameBuffer[BUFFER_MAX_SIZE];
3630 CHAR16 HelpBuffer[BUFFER_MAX_SIZE];
3631
3632 Status = EFI_SUCCESS;
3633 FormatNameString = NULL;
3634 FormatHelpString = NULL;
3635 StartOpCodeHandle = NULL;
3636 EndOpCodeHandle = NULL;
3637 StartGotoHandle = NULL;
3638 EndGotoHandle = NULL;
3639 Index = 0;
3640 VariableData = NULL;
3641
3642 //
3643 // Initialize the container for dynamic opcodes.
3644 //
3645 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
3646 if (StartOpCodeHandle == NULL) {
3647 Status = EFI_OUT_OF_RESOURCES;
3648 goto ON_EXIT;
3649 }
3650
3651 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
3652 if (EndOpCodeHandle == NULL) {
3653 Status = EFI_OUT_OF_RESOURCES;
3654 goto ON_EXIT;
3655 }
3656
3657 StartGotoHandle = HiiAllocateOpCodeHandle ();
3658 if (StartGotoHandle == NULL) {
3659 Status = EFI_OUT_OF_RESOURCES;
3660 goto ON_EXIT;
3661 }
3662
3663 EndGotoHandle = HiiAllocateOpCodeHandle ();
3664 if (EndGotoHandle == NULL) {
3665 Status = EFI_OUT_OF_RESOURCES;
3666 goto ON_EXIT;
3667 }
3668
3669 //
3670 // Create Hii Extend Label OpCode.
3671 //
3672 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
3673 StartOpCodeHandle,
3674 &gEfiIfrTianoGuid,
3675 NULL,
3676 sizeof (EFI_IFR_GUID_LABEL)
3677 );
3678 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
3679 StartLabel->Number = LabelId;
3680
3681 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
3682 EndOpCodeHandle,
3683 &gEfiIfrTianoGuid,
3684 NULL,
3685 sizeof (EFI_IFR_GUID_LABEL)
3686 );
3687 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
3688 EndLabel->Number = LABEL_END;
3689
3690 StartGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
3691 StartGotoHandle,
3692 &gEfiIfrTianoGuid,
3693 NULL,
3694 sizeof (EFI_IFR_GUID_LABEL)
3695 );
3696 StartGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
3697 StartGoto->Number = LABEL_DELETE_ALL_LIST_BUTTON;
3698
3699 EndGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
3700 EndGotoHandle,
3701 &gEfiIfrTianoGuid,
3702 NULL,
3703 sizeof (EFI_IFR_GUID_LABEL)
3704 );
3705 EndGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
3706 EndGoto->Number = LABEL_END;
3707
3708 if (PrivateData->VariableName == Variable_DB) {
3709 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);
3710 DstFormId = FORMID_SECURE_BOOT_DB_OPTION_FORM;
3711 } else if (PrivateData->VariableName == Variable_DBX) {
3712 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);
3713 DstFormId = FORMID_SECURE_BOOT_DBX_OPTION_FORM;
3714 } else if (PrivateData->VariableName == Variable_DBT) {
3715 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);
3716 DstFormId = FORMID_SECURE_BOOT_DBT_OPTION_FORM;
3717 } else {
3718 goto ON_EXIT;
3719 }
3720
3721 HiiCreateGotoOpCode (
3722 StartGotoHandle,
3723 DstFormId,
3724 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),
3725 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),
3726 EFI_IFR_FLAG_CALLBACK,
3727 KEY_SECURE_BOOT_DELETE_ALL_LIST
3728 );
3729
3730 //
3731 // Read Variable, the variable name save in the PrivateData->VariableName.
3732 //
3733 DataSize = 0;
3734 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
3735 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
3736 goto ON_EXIT;
3737 }
3738
3739 VariableData = AllocateZeroPool (DataSize);
3740 if (VariableData == NULL) {
3741 Status = EFI_OUT_OF_RESOURCES;
3742 goto ON_EXIT;
3743 }
3744
3745 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
3746 if (EFI_ERROR (Status)) {
3747 goto ON_EXIT;
3748 }
3749
3750 FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT), NULL);
3751 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT), NULL);
3752 if ((FormatNameString == NULL) || (FormatHelpString == NULL)) {
3753 goto ON_EXIT;
3754 }
3755
3756 RemainingSize = DataSize;
3757 ListWalker = (EFI_SIGNATURE_LIST *)VariableData;
3758 while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) {
3759 if (CompareGuid (&ListWalker->SignatureType, &gEfiCertRsa2048Guid)) {
3760 ListType = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256);
3761 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) {
3762 ListType = STRING_TOKEN (STR_LIST_TYPE_X509);
3763 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha1Guid)) {
3764 ListType = STRING_TOKEN (STR_LIST_TYPE_SHA1);
3765 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) {
3766 ListType = STRING_TOKEN (STR_LIST_TYPE_SHA256);
3767 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) {
3768 ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);
3769 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) {
3770 ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384);
3771 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha512Guid)) {
3772 ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512);
3773 } else {
3774 ListType = STRING_TOKEN (STR_LIST_TYPE_UNKNOWN);
3775 }
3776
3777 FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListType, NULL);
3778 if (FormatTypeString == NULL) {
3779 goto ON_EXIT;
3780 }
3781
3782 ZeroMem (NameBuffer, sizeof (NameBuffer));
3783 UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);
3784
3785 ZeroMem (HelpBuffer, sizeof (HelpBuffer));
3786 UnicodeSPrint (
3787 HelpBuffer,
3788 sizeof (HelpBuffer),
3789 FormatHelpString,
3790 FormatTypeString,
3791 SIGNATURE_DATA_COUNTS (ListWalker)
3792 );
3793 SECUREBOOT_FREE_NON_NULL (FormatTypeString);
3794 FormatTypeString = NULL;
3795
3796 HiiCreateGotoOpCode (
3797 StartOpCodeHandle,
3798 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,
3799 HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),
3800 HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL),
3801 EFI_IFR_FLAG_CALLBACK,
3802 QuestionIdBase + Index++
3803 );
3804
3805 RemainingSize -= ListWalker->SignatureListSize;
3806 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
3807 }
3808
3809 ON_EXIT:
3810 HiiUpdateForm (
3811 PrivateData->HiiHandle,
3812 &gSecureBootConfigFormSetGuid,
3813 FormId,
3814 StartOpCodeHandle,
3815 EndOpCodeHandle
3816 );
3817
3818 HiiUpdateForm (
3819 PrivateData->HiiHandle,
3820 &gSecureBootConfigFormSetGuid,
3821 FormId,
3822 StartGotoHandle,
3823 EndGotoHandle
3824 );
3825
3826 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);
3827 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);
3828 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle);
3829 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle);
3830
3831 SECUREBOOT_FREE_NON_NULL (VariableData);
3832 SECUREBOOT_FREE_NON_NULL (FormatNameString);
3833 SECUREBOOT_FREE_NON_NULL (FormatHelpString);
3834
3835 PrivateData->ListCount = Index;
3836
3837 return Status;
3838 }
3839
3840 /**
3841 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
3842 The buffer is callee allocated and should be freed by the caller.
3843
3844 @param[in] ListEntry The pointer point to the signature list.
3845 @param[in] DataEntry The signature data we are processing.
3846 @param[out] BufferToReturn Buffer to save the hash value.
3847
3848 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3849 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3850 @retval EFI_SUCCESS Operation success.
3851 **/
3852 EFI_STATUS
3853 ParseHashValue (
3854 IN EFI_SIGNATURE_LIST *ListEntry,
3855 IN EFI_SIGNATURE_DATA *DataEntry,
3856 OUT CHAR16 **BufferToReturn
3857 )
3858 {
3859 UINTN Index;
3860 UINTN BufferIndex;
3861 UINTN TotalSize;
3862 UINTN DataSize;
3863 UINTN Line;
3864 UINTN OneLineBytes;
3865
3866 //
3867 // Assume that, display 8 bytes in one line.
3868 //
3869 OneLineBytes = 8;
3870
3871 if ((ListEntry == NULL) || (DataEntry == NULL) || (BufferToReturn == NULL)) {
3872 return EFI_INVALID_PARAMETER;
3873 }
3874
3875 DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID);
3876 Line = (DataSize + OneLineBytes - 1) / OneLineBytes;
3877
3878 //
3879 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
3880 //
3881 TotalSize = ((DataSize + Line) * 2 * sizeof (CHAR16));
3882
3883 *BufferToReturn = AllocateZeroPool (TotalSize);
3884 if (*BufferToReturn == NULL) {
3885 return EFI_OUT_OF_RESOURCES;
3886 }
3887
3888 for (Index = 0, BufferIndex = 0; Index < DataSize; Index = Index + 1) {
3889 if ((Index > 0) && (Index % OneLineBytes == 0)) {
3890 BufferIndex += UnicodeSPrint (&(*BufferToReturn)[BufferIndex], TotalSize - sizeof (CHAR16) * BufferIndex, L"\n");
3891 }
3892
3893 BufferIndex += UnicodeSPrint (&(*BufferToReturn)[BufferIndex], TotalSize - sizeof (CHAR16) * BufferIndex, L"%02x", DataEntry->SignatureData[Index]);
3894 }
3895
3896 BufferIndex += UnicodeSPrint (&(*BufferToReturn)[BufferIndex], TotalSize - sizeof (CHAR16) * BufferIndex, L"\n");
3897
3898 return EFI_SUCCESS;
3899 }
3900
3901 /**
3902 Function to get the common name from the X509 format certificate.
3903 The buffer is callee allocated and should be freed by the caller.
3904
3905 @param[in] ListEntry The pointer point to the signature list.
3906 @param[in] DataEntry The signature data we are processing.
3907 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
3908
3909 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
3910 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3911 @retval EFI_SUCCESS Operation success.
3912 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
3913 **/
3914 EFI_STATUS
3915 GetCommonNameFromX509 (
3916 IN EFI_SIGNATURE_LIST *ListEntry,
3917 IN EFI_SIGNATURE_DATA *DataEntry,
3918 OUT CHAR16 **BufferToReturn
3919 )
3920 {
3921 EFI_STATUS Status;
3922 CHAR8 *CNBuffer;
3923 UINTN CNBufferSize;
3924
3925 Status = EFI_SUCCESS;
3926 CNBuffer = NULL;
3927
3928 CNBuffer = AllocateZeroPool (256);
3929 if (CNBuffer == NULL) {
3930 Status = EFI_OUT_OF_RESOURCES;
3931 goto ON_EXIT;
3932 }
3933
3934 CNBufferSize = 256;
3935 X509GetCommonName (
3936 (UINT8 *)DataEntry + sizeof (EFI_GUID),
3937 ListEntry->SignatureSize - sizeof (EFI_GUID),
3938 CNBuffer,
3939 &CNBufferSize
3940 );
3941
3942 *BufferToReturn = AllocateZeroPool (256 * sizeof (CHAR16));
3943 if (*BufferToReturn == NULL) {
3944 Status = EFI_OUT_OF_RESOURCES;
3945 goto ON_EXIT;
3946 }
3947
3948 AsciiStrToUnicodeStrS (CNBuffer, *BufferToReturn, 256);
3949
3950 ON_EXIT:
3951 SECUREBOOT_FREE_NON_NULL (CNBuffer);
3952
3953 return Status;
3954 }
3955
3956 /**
3957 Format the help info for the signature data, each help info contain 3 parts.
3958 1. Onwer Guid.
3959 2. Content, depends on the type of the signature list.
3960 3. Revocation time.
3961
3962 @param[in] PrivateData Module's private data.
3963 @param[in] ListEntry Point to the signature list.
3964 @param[in] DataEntry Point to the signature data we are processing.
3965 @param[out] StringId Save the string id of help info.
3966
3967 @retval EFI_SUCCESS Operation success.
3968 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
3969 **/
3970 EFI_STATUS
3971 FormatHelpInfo (
3972 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
3973 IN EFI_SIGNATURE_LIST *ListEntry,
3974 IN EFI_SIGNATURE_DATA *DataEntry,
3975 OUT EFI_STRING_ID *StringId
3976 )
3977 {
3978 EFI_STATUS Status;
3979 EFI_TIME *Time;
3980 EFI_STRING_ID ListTypeId;
3981 EFI_STRING FormatHelpString;
3982 EFI_STRING FormatTypeString;
3983 UINTN DataSize;
3984 UINTN HelpInfoIndex;
3985 UINTN TotalSize;
3986 CHAR16 GuidString[BUFFER_MAX_SIZE];
3987 CHAR16 TimeString[BUFFER_MAX_SIZE];
3988 CHAR16 *DataString;
3989 CHAR16 *HelpInfoString;
3990 BOOLEAN IsCert;
3991
3992 Status = EFI_SUCCESS;
3993 Time = NULL;
3994 FormatTypeString = NULL;
3995 HelpInfoIndex = 0;
3996 DataString = NULL;
3997 HelpInfoString = NULL;
3998 IsCert = FALSE;
3999
4000 if (CompareGuid (&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) {
4001 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256);
4002 DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID);
4003 IsCert = TRUE;
4004 } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Guid)) {
4005 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509);
4006 DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID);
4007 IsCert = TRUE;
4008 } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha1Guid)) {
4009 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA1);
4010 DataSize = 20;
4011 } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha256Guid)) {
4012 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA256);
4013 DataSize = 32;
4014 } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) {
4015 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);
4016 DataSize = 32;
4017 Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);
4018 } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha384Guid)) {
4019 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384);
4020 DataSize = 48;
4021 Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);
4022 } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha512Guid)) {
4023 ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512);
4024 DataSize = 64;
4025 Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);
4026 } else {
4027 Status = EFI_UNSUPPORTED;
4028 goto ON_EXIT;
4029 }
4030
4031 FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListTypeId, NULL);
4032 if (FormatTypeString == NULL) {
4033 goto ON_EXIT;
4034 }
4035
4036 TotalSize = 1024;
4037 HelpInfoString = AllocateZeroPool (TotalSize);
4038 if (HelpInfoString == NULL) {
4039 Status = EFI_OUT_OF_RESOURCES;
4040 goto ON_EXIT;
4041 }
4042
4043 //
4044 // Format GUID part.
4045 //
4046 ZeroMem (GuidString, sizeof (GuidString));
4047 GuidToString (&DataEntry->SignatureOwner, GuidString, BUFFER_MAX_SIZE);
4048 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID), NULL);
4049 if (FormatHelpString == NULL) {
4050 goto ON_EXIT;
4051 }
4052
4053 HelpInfoIndex += UnicodeSPrint (
4054 &HelpInfoString[HelpInfoIndex],
4055 TotalSize - sizeof (CHAR16) * HelpInfoIndex,
4056 FormatHelpString,
4057 GuidString
4058 );
4059 SECUREBOOT_FREE_NON_NULL (FormatHelpString);
4060 FormatHelpString = NULL;
4061
4062 //
4063 // Format content part, it depends on the type of signature list, hash value or CN.
4064 //
4065 if (IsCert) {
4066 GetCommonNameFromX509 (ListEntry, DataEntry, &DataString);
4067 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN), NULL);
4068 } else {
4069 //
4070 // Format hash value for each signature data entry.
4071 //
4072 ParseHashValue (ListEntry, DataEntry, &DataString);
4073 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH), NULL);
4074 }
4075
4076 if (FormatHelpString == NULL) {
4077 goto ON_EXIT;
4078 }
4079
4080 HelpInfoIndex += UnicodeSPrint (
4081 &HelpInfoString[HelpInfoIndex],
4082 TotalSize - sizeof (CHAR16) * HelpInfoIndex,
4083 FormatHelpString,
4084 FormatTypeString,
4085 DataSize,
4086 DataString
4087 );
4088 SECUREBOOT_FREE_NON_NULL (FormatHelpString);
4089 FormatHelpString = NULL;
4090
4091 //
4092 // Format revocation time part.
4093 //
4094 if (Time != NULL) {
4095 ZeroMem (TimeString, sizeof (TimeString));
4096 UnicodeSPrint (
4097 TimeString,
4098 sizeof (TimeString),
4099 L"%d-%d-%d %d:%d:%d",
4100 Time->Year,
4101 Time->Month,
4102 Time->Day,
4103 Time->Hour,
4104 Time->Minute,
4105 Time->Second
4106 );
4107 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME), NULL);
4108 if (FormatHelpString == NULL) {
4109 goto ON_EXIT;
4110 }
4111
4112 UnicodeSPrint (
4113 &HelpInfoString[HelpInfoIndex],
4114 TotalSize - sizeof (CHAR16) * HelpInfoIndex,
4115 FormatHelpString,
4116 TimeString
4117 );
4118 SECUREBOOT_FREE_NON_NULL (FormatHelpString);
4119 FormatHelpString = NULL;
4120 }
4121
4122 *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL);
4123 ON_EXIT:
4124 SECUREBOOT_FREE_NON_NULL (DataString);
4125 SECUREBOOT_FREE_NON_NULL (HelpInfoString);
4126
4127 SECUREBOOT_FREE_NON_NULL (FormatTypeString);
4128
4129 return Status;
4130 }
4131
4132 /**
4133 This function to load signature data under the signature list.
4134
4135 @param[in] PrivateData Module's private data.
4136 @param[in] LabelId Label number to insert opcodes.
4137 @param[in] FormId Form ID of current page.
4138 @param[in] QuestionIdBase Base question id of the signature list.
4139 @param[in] ListIndex Indicate to load which signature list.
4140
4141 @retval EFI_SUCCESS Success to update the signature list page
4142 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
4143 **/
4144 EFI_STATUS
4145 LoadSignatureData (
4146 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
4147 IN UINT16 LabelId,
4148 IN EFI_FORM_ID FormId,
4149 IN EFI_QUESTION_ID QuestionIdBase,
4150 IN UINT16 ListIndex
4151 )
4152 {
4153 EFI_STATUS Status;
4154 EFI_SIGNATURE_LIST *ListWalker;
4155 EFI_SIGNATURE_DATA *DataWalker;
4156 EFI_IFR_GUID_LABEL *StartLabel;
4157 EFI_IFR_GUID_LABEL *EndLabel;
4158 EFI_STRING_ID HelpStringId;
4159 EFI_STRING FormatNameString;
4160 VOID *StartOpCodeHandle;
4161 VOID *EndOpCodeHandle;
4162 UINTN DataSize;
4163 UINTN RemainingSize;
4164 UINT16 Index;
4165 UINT8 *VariableData;
4166 CHAR16 VariableName[BUFFER_MAX_SIZE];
4167 CHAR16 NameBuffer[BUFFER_MAX_SIZE];
4168
4169 Status = EFI_SUCCESS;
4170 FormatNameString = NULL;
4171 StartOpCodeHandle = NULL;
4172 EndOpCodeHandle = NULL;
4173 Index = 0;
4174 VariableData = NULL;
4175
4176 //
4177 // Initialize the container for dynamic opcodes.
4178 //
4179 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
4180 if (StartOpCodeHandle == NULL) {
4181 Status = EFI_OUT_OF_RESOURCES;
4182 goto ON_EXIT;
4183 }
4184
4185 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
4186 if (EndOpCodeHandle == NULL) {
4187 Status = EFI_OUT_OF_RESOURCES;
4188 goto ON_EXIT;
4189 }
4190
4191 //
4192 // Create Hii Extend Label OpCode.
4193 //
4194 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
4195 StartOpCodeHandle,
4196 &gEfiIfrTianoGuid,
4197 NULL,
4198 sizeof (EFI_IFR_GUID_LABEL)
4199 );
4200 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
4201 StartLabel->Number = LabelId;
4202
4203 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
4204 EndOpCodeHandle,
4205 &gEfiIfrTianoGuid,
4206 NULL,
4207 sizeof (EFI_IFR_GUID_LABEL)
4208 );
4209 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
4210 EndLabel->Number = LABEL_END;
4211
4212 if (PrivateData->VariableName == Variable_DB) {
4213 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);
4214 } else if (PrivateData->VariableName == Variable_DBX) {
4215 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);
4216 } else if (PrivateData->VariableName == Variable_DBT) {
4217 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);
4218 } else {
4219 goto ON_EXIT;
4220 }
4221
4222 //
4223 // Read Variable, the variable name save in the PrivateData->VariableName.
4224 //
4225 DataSize = 0;
4226 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
4227 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
4228 goto ON_EXIT;
4229 }
4230
4231 VariableData = AllocateZeroPool (DataSize);
4232 if (VariableData == NULL) {
4233 Status = EFI_OUT_OF_RESOURCES;
4234 goto ON_EXIT;
4235 }
4236
4237 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
4238 if (EFI_ERROR (Status)) {
4239 goto ON_EXIT;
4240 }
4241
4242 RemainingSize = DataSize;
4243 ListWalker = (EFI_SIGNATURE_LIST *)VariableData;
4244
4245 //
4246 // Skip signature list.
4247 //
4248 while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex-- > 0) {
4249 RemainingSize -= ListWalker->SignatureListSize;
4250 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
4251 }
4252
4253 FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT), NULL);
4254 if (FormatNameString == NULL) {
4255 goto ON_EXIT;
4256 }
4257
4258 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);
4259 for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) {
4260 //
4261 // Format name buffer.
4262 //
4263 ZeroMem (NameBuffer, sizeof (NameBuffer));
4264 UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);
4265
4266 //
4267 // Format help info buffer.
4268 //
4269 Status = FormatHelpInfo (PrivateData, ListWalker, DataWalker, &HelpStringId);
4270 if (EFI_ERROR (Status)) {
4271 goto ON_EXIT;
4272 }
4273
4274 HiiCreateCheckBoxOpCode (
4275 StartOpCodeHandle,
4276 (EFI_QUESTION_ID)(QuestionIdBase + Index),
4277 0,
4278 0,
4279 HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),
4280 HelpStringId,
4281 EFI_IFR_FLAG_CALLBACK,
4282 0,
4283 NULL
4284 );
4285
4286 ZeroMem (NameBuffer, 100);
4287 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);
4288 }
4289
4290 //
4291 // Allocate a buffer to record which signature data will be checked.
4292 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
4293 //
4294 PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker) * sizeof (BOOLEAN));
4295 ON_EXIT:
4296 HiiUpdateForm (
4297 PrivateData->HiiHandle,
4298 &gSecureBootConfigFormSetGuid,
4299 FormId,
4300 StartOpCodeHandle,
4301 EndOpCodeHandle
4302 );
4303
4304 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);
4305 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);
4306
4307 SECUREBOOT_FREE_NON_NULL (VariableData);
4308 SECUREBOOT_FREE_NON_NULL (FormatNameString);
4309
4310 return Status;
4311 }
4312
4313 /**
4314 This function reinitializes Secure Boot variables with default values.
4315
4316 @retval EFI_SUCCESS Success to update the signature list page
4317 @retval others Fail to delete or enroll signature data.
4318 **/
4319 STATIC EFI_STATUS
4320 EFIAPI
4321 KeyEnrollReset (
4322 VOID
4323 )
4324 {
4325 EFI_STATUS Status;
4326 UINT8 SetupMode;
4327
4328 Status = EFI_SUCCESS;
4329
4330 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
4331 if (EFI_ERROR (Status)) {
4332 return Status;
4333 }
4334
4335 // Clear all the keys and databases
4336 Status = DeleteDb ();
4337 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
4338 DEBUG ((DEBUG_ERROR, "Fail to clear DB: %r\n", Status));
4339 return Status;
4340 }
4341
4342 Status = DeleteDbx ();
4343 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
4344 DEBUG ((DEBUG_ERROR, "Fail to clear DBX: %r\n", Status));
4345 return Status;
4346 }
4347
4348 Status = DeleteDbt ();
4349 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
4350 DEBUG ((DEBUG_ERROR, "Fail to clear DBT: %r\n", Status));
4351 return Status;
4352 }
4353
4354 Status = DeleteKEK ();
4355 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
4356 DEBUG ((DEBUG_ERROR, "Fail to clear KEK: %r\n", Status));
4357 return Status;
4358 }
4359
4360 Status = DeletePlatformKey ();
4361 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
4362 DEBUG ((DEBUG_ERROR, "Fail to clear PK: %r\n", Status));
4363 return Status;
4364 }
4365
4366 // After PK clear, Setup Mode shall be enabled
4367 Status = GetSetupMode (&SetupMode);
4368 if (EFI_ERROR (Status)) {
4369 DEBUG ((
4370 DEBUG_ERROR,
4371 "Cannot get SetupMode variable: %r\n",
4372 Status
4373 ));
4374 return Status;
4375 }
4376
4377 if (SetupMode == USER_MODE) {
4378 DEBUG ((DEBUG_INFO, "Skipped - USER_MODE\n"));
4379 return EFI_SUCCESS;
4380 }
4381
4382 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
4383 if (EFI_ERROR (Status)) {
4384 DEBUG ((
4385 DEBUG_ERROR,
4386 "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n",
4387 Status
4388 ));
4389 return EFI_SUCCESS;
4390 }
4391
4392 // Enroll all the keys from default variables
4393 Status = EnrollDbFromDefault ();
4394 if (EFI_ERROR (Status)) {
4395 DEBUG ((DEBUG_ERROR, "Cannot enroll db: %r\n", Status));
4396 goto error;
4397 }
4398
4399 Status = EnrollDbxFromDefault ();
4400 if (EFI_ERROR (Status)) {
4401 DEBUG ((DEBUG_ERROR, "Cannot enroll dbx: %r\n", Status));
4402 }
4403
4404 Status = EnrollDbtFromDefault ();
4405 if (EFI_ERROR (Status)) {
4406 DEBUG ((DEBUG_ERROR, "Cannot enroll dbt: %r\n", Status));
4407 }
4408
4409 Status = EnrollKEKFromDefault ();
4410 if (EFI_ERROR (Status)) {
4411 DEBUG ((DEBUG_ERROR, "Cannot enroll KEK: %r\n", Status));
4412 goto cleardbs;
4413 }
4414
4415 Status = EnrollPKFromDefault ();
4416 if (EFI_ERROR (Status)) {
4417 DEBUG ((DEBUG_ERROR, "Cannot enroll PK: %r\n", Status));
4418 goto clearKEK;
4419 }
4420
4421 Status = SetSecureBootMode (STANDARD_SECURE_BOOT_MODE);
4422 if (EFI_ERROR (Status)) {
4423 DEBUG ((
4424 DEBUG_ERROR,
4425 "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
4426 "Please do it manually, otherwise system can be easily compromised\n"
4427 ));
4428 }
4429
4430 return Status;
4431
4432 clearKEK:
4433 DeleteKEK ();
4434
4435 cleardbs:
4436 DeleteDbt ();
4437 DeleteDbx ();
4438 DeleteDb ();
4439
4440 error:
4441 if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE) != EFI_SUCCESS) {
4442 DEBUG ((DEBUG_ERROR, "Cannot set mode to Secure: %r\n", Status));
4443 }
4444
4445 return Status;
4446 }
4447
4448 /**
4449 This function is called to provide results data to the driver.
4450
4451 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
4452 @param[in] Action Specifies the type of action taken by the browser.
4453 @param[in] QuestionId A unique value which is sent to the original
4454 exporting driver so that it can identify the type
4455 of data to expect.
4456 @param[in] Type The type of value for the question.
4457 @param[in] Value A pointer to the data being sent to the original
4458 exporting driver.
4459 @param[out] ActionRequest On return, points to the action requested by the
4460 callback function.
4461
4462 @retval EFI_SUCCESS The callback successfully handled the action.
4463 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
4464 variable and its data.
4465 @retval EFI_DEVICE_ERROR The variable could not be saved.
4466 @retval EFI_UNSUPPORTED The specified Action is not supported by the
4467 callback.
4468
4469 **/
4470 EFI_STATUS
4471 EFIAPI
4472 SecureBootCallback (
4473 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
4474 IN EFI_BROWSER_ACTION Action,
4475 IN EFI_QUESTION_ID QuestionId,
4476 IN UINT8 Type,
4477 IN EFI_IFR_TYPE_VALUE *Value,
4478 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
4479 )
4480 {
4481 EFI_INPUT_KEY Key;
4482 EFI_STATUS Status;
4483 RETURN_STATUS RStatus;
4484 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;
4485 UINTN BufferSize;
4486 SECUREBOOT_CONFIGURATION *IfrNvData;
4487 UINT16 LabelId;
4488 UINT8 *SecureBootEnable;
4489 UINT8 *Pk;
4490 UINT8 *SecureBootMode;
4491 UINT8 *SetupMode;
4492 CHAR16 PromptString[100];
4493 EFI_DEVICE_PATH_PROTOCOL *File;
4494 UINTN NameLength;
4495 UINT16 *FilePostFix;
4496 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
4497 BOOLEAN GetBrowserDataResult;
4498 ENROLL_KEY_ERROR EnrollKeyErrorCode;
4499 EFI_HII_POPUP_PROTOCOL *HiiPopup;
4500 EFI_HII_POPUP_SELECTION UserSelection;
4501
4502 Status = EFI_SUCCESS;
4503 SecureBootEnable = NULL;
4504 SecureBootMode = NULL;
4505 SetupMode = NULL;
4506 File = NULL;
4507 EnrollKeyErrorCode = None_Error;
4508
4509 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
4510 return EFI_INVALID_PARAMETER;
4511 }
4512
4513 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
4514
4515 gSecureBootPrivateData = Private;
4516
4517 //
4518 // Retrieve uncommitted data from Browser
4519 //
4520 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
4521 IfrNvData = AllocateZeroPool (BufferSize);
4522 if (IfrNvData == NULL) {
4523 return EFI_OUT_OF_RESOURCES;
4524 }
4525
4526 GetBrowserDataResult = HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *)IfrNvData);
4527
4528 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
4529 if (QuestionId == KEY_SECURE_BOOT_MODE) {
4530 //
4531 // Update secure boot strings when opening this form
4532 //
4533 Status = UpdateSecureBootString (Private);
4534 SecureBootExtractConfigFromVariable (Private, IfrNvData);
4535 mIsEnterSecureBootForm = TRUE;
4536 } else {
4537 //
4538 // When entering SecureBoot OPTION Form
4539 // always close opened file & free resource
4540 //
4541 if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) ||
4542 (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) ||
4543 (QuestionId == KEY_SECURE_BOOT_DB_OPTION) ||
4544 (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) ||
4545 (QuestionId == KEY_SECURE_BOOT_DBT_OPTION))
4546 {
4547 CloseEnrolledFile (Private->FileContext);
4548 } else if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_LIST) {
4549 //
4550 // Update ListCount field in varstore
4551 // Button "Delete All Signature List" is
4552 // enable when ListCount is greater than 0.
4553 //
4554 IfrNvData->ListCount = Private->ListCount;
4555 }
4556 }
4557
4558 goto EXIT;
4559 }
4560
4561 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
4562 Status = EFI_UNSUPPORTED;
4563 if (QuestionId == KEY_SECURE_BOOT_MODE) {
4564 if (mIsEnterSecureBootForm) {
4565 Value->u8 = SECURE_BOOT_MODE_STANDARD;
4566 Status = EFI_SUCCESS;
4567 }
4568 }
4569
4570 goto EXIT;
4571 }
4572
4573 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
4574 (Action != EFI_BROWSER_ACTION_CHANGING) &&
4575 (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&
4576 (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD))
4577 {
4578 Status = EFI_UNSUPPORTED;
4579 goto EXIT;
4580 }
4581
4582 if (Action == EFI_BROWSER_ACTION_CHANGING) {
4583 switch (QuestionId) {
4584 case KEY_SECURE_BOOT_ENABLE:
4585 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **)&SecureBootEnable, NULL);
4586 if (NULL != SecureBootEnable) {
4587 FreePool (SecureBootEnable);
4588 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {
4589 CreatePopUp (
4590 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4591 &Key,
4592 L"Only Physical Presence User could disable secure boot!",
4593 NULL
4594 );
4595 Status = EFI_UNSUPPORTED;
4596 } else {
4597 CreatePopUp (
4598 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4599 &Key,
4600 L"Configuration changed, please reset the platform to take effect!",
4601 NULL
4602 );
4603 }
4604 }
4605
4606 break;
4607
4608 case KEY_SECURE_BOOT_KEK_OPTION:
4609 case KEY_SECURE_BOOT_DB_OPTION:
4610 case KEY_SECURE_BOOT_DBX_OPTION:
4611 case KEY_SECURE_BOOT_DBT_OPTION:
4612 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
4613 //
4614 // Clear Signature GUID.
4615 //
4616 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));
4617 if (Private->SignatureGUID == NULL) {
4618 Private->SignatureGUID = (EFI_GUID *)AllocateZeroPool (sizeof (EFI_GUID));
4619 if (Private->SignatureGUID == NULL) {
4620 return EFI_OUT_OF_RESOURCES;
4621 }
4622 }
4623
4624 //
4625 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
4626 //
4627 SecureBootExtractConfigFromVariable (PrivateData, IfrNvData);
4628
4629 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {
4630 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
4631 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {
4632 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
4633 } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {
4634 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
4635 } else {
4636 LabelId = FORMID_ENROLL_KEK_FORM;
4637 }
4638
4639 //
4640 // Refresh selected file.
4641 //
4642 CleanUpPage (LabelId, Private);
4643 break;
4644 case KEY_SECURE_BOOT_PK_OPTION:
4645 LabelId = FORMID_ENROLL_PK_FORM;
4646 //
4647 // Refresh selected file.
4648 //
4649 CleanUpPage (LabelId, Private);
4650 break;
4651
4652 case FORMID_ENROLL_PK_FORM:
4653 ChooseFile (NULL, NULL, UpdatePKFromFile, &File);
4654 break;
4655
4656 case FORMID_ENROLL_KEK_FORM:
4657 ChooseFile (NULL, NULL, UpdateKEKFromFile, &File);
4658 break;
4659
4660 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:
4661 ChooseFile (NULL, NULL, UpdateDBFromFile, &File);
4662 break;
4663
4664 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:
4665 ChooseFile (NULL, NULL, UpdateDBXFromFile, &File);
4666
4667 if (Private->FileContext->FHandle != NULL) {
4668 //
4669 // Parse the file's postfix.
4670 //
4671 NameLength = StrLen (Private->FileContext->FileName);
4672 if (NameLength <= 4) {
4673 return FALSE;
4674 }
4675
4676 FilePostFix = Private->FileContext->FileName + NameLength - 4;
4677
4678 if (IsDerEncodeCertificate (FilePostFix)) {
4679 //
4680 // Supports DER-encoded X509 certificate.
4681 //
4682 IfrNvData->FileEnrollType = X509_CERT_FILE_TYPE;
4683 } else if (IsAuthentication2Format (Private->FileContext->FHandle)) {
4684 IfrNvData->FileEnrollType = AUTHENTICATION_2_FILE_TYPE;
4685 } else {
4686 IfrNvData->FileEnrollType = PE_IMAGE_FILE_TYPE;
4687 }
4688
4689 Private->FileContext->FileType = IfrNvData->FileEnrollType;
4690
4691 //
4692 // Clean up Certificate Format if File type is not X509 DER
4693 //
4694 if (IfrNvData->FileEnrollType != X509_CERT_FILE_TYPE) {
4695 IfrNvData->CertificateFormat = HASHALG_RAW;
4696 }
4697
4698 DEBUG ((DEBUG_ERROR, "IfrNvData->FileEnrollType %d\n", Private->FileContext->FileType));
4699 }
4700
4701 break;
4702
4703 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:
4704 ChooseFile (NULL, NULL, UpdateDBTFromFile, &File);
4705 break;
4706
4707 case KEY_SECURE_BOOT_DELETE_PK:
4708 if (Value->u8) {
4709 CreatePopUp (
4710 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4711 &Key,
4712 L"Are you sure you want to delete PK? Secure boot will be disabled!",
4713 L"Press 'Y' to delete PK and exit, 'N' to discard change and return",
4714 NULL
4715 );
4716 if ((Key.UnicodeChar == 'y') || (Key.UnicodeChar == 'Y')) {
4717 Status = DeletePlatformKey ();
4718 if (EFI_ERROR (Status)) {
4719 CreatePopUp (
4720 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4721 &Key,
4722 L"Only Physical Presence User could delete PK in custom mode!",
4723 NULL
4724 );
4725 }
4726 }
4727 }
4728
4729 break;
4730
4731 case KEY_DELETE_KEK:
4732 UpdateDeletePage (
4733 Private,
4734 EFI_KEY_EXCHANGE_KEY_NAME,
4735 &gEfiGlobalVariableGuid,
4736 LABEL_KEK_DELETE,
4737 FORMID_DELETE_KEK_FORM,
4738 OPTION_DEL_KEK_QUESTION_ID
4739 );
4740 break;
4741
4742 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:
4743 UpdateDeletePage (
4744 Private,
4745 EFI_IMAGE_SECURITY_DATABASE,
4746 &gEfiImageSecurityDatabaseGuid,
4747 LABEL_DB_DELETE,
4748 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
4749 OPTION_DEL_DB_QUESTION_ID
4750 );
4751 break;
4752
4753 //
4754 // From DBX option to the level-1 form, display signature list.
4755 //
4756 case KEY_VALUE_FROM_DBX_TO_LIST_FORM:
4757 Private->VariableName = Variable_DBX;
4758 LoadSignatureList (
4759 Private,
4760 LABEL_SIGNATURE_LIST_START,
4761 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
4762 OPTION_SIGNATURE_LIST_QUESTION_ID
4763 );
4764 break;
4765
4766 //
4767 // Delete all signature list and reload.
4768 //
4769 case KEY_SECURE_BOOT_DELETE_ALL_LIST:
4770 CreatePopUp (
4771 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4772 &Key,
4773 L"Press 'Y' to delete signature list.",
4774 L"Press other key to cancel and exit.",
4775 NULL
4776 );
4777
4778 if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) {
4779 DeleteSignatureEx (Private, Delete_Signature_List_All, IfrNvData->CheckedDataCount);
4780 }
4781
4782 LoadSignatureList (
4783 Private,
4784 LABEL_SIGNATURE_LIST_START,
4785 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
4786 OPTION_SIGNATURE_LIST_QUESTION_ID
4787 );
4788 break;
4789
4790 //
4791 // Delete one signature list and reload.
4792 //
4793 case KEY_SECURE_BOOT_DELETE_ALL_DATA:
4794 CreatePopUp (
4795 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4796 &Key,
4797 L"Press 'Y' to delete signature data.",
4798 L"Press other key to cancel and exit.",
4799 NULL
4800 );
4801
4802 if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) {
4803 DeleteSignatureEx (Private, Delete_Signature_List_One, IfrNvData->CheckedDataCount);
4804 }
4805
4806 LoadSignatureList (
4807 Private,
4808 LABEL_SIGNATURE_LIST_START,
4809 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
4810 OPTION_SIGNATURE_LIST_QUESTION_ID
4811 );
4812 break;
4813
4814 //
4815 // Delete checked signature data and reload.
4816 //
4817 case KEY_SECURE_BOOT_DELETE_CHECK_DATA:
4818 CreatePopUp (
4819 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4820 &Key,
4821 L"Press 'Y' to delete signature data.",
4822 L"Press other key to cancel and exit.",
4823 NULL
4824 );
4825
4826 if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) {
4827 DeleteSignatureEx (Private, Delete_Signature_Data, IfrNvData->CheckedDataCount);
4828 }
4829
4830 LoadSignatureList (
4831 Private,
4832 LABEL_SIGNATURE_LIST_START,
4833 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
4834 OPTION_SIGNATURE_LIST_QUESTION_ID
4835 );
4836 break;
4837
4838 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:
4839 UpdateDeletePage (
4840 Private,
4841 EFI_IMAGE_SECURITY_DATABASE2,
4842 &gEfiImageSecurityDatabaseGuid,
4843 LABEL_DBT_DELETE,
4844 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
4845 OPTION_DEL_DBT_QUESTION_ID
4846 );
4847
4848 break;
4849
4850 case KEY_VALUE_SAVE_AND_EXIT_KEK:
4851 Status = EnrollKeyExchangeKey (Private);
4852 if (EFI_ERROR (Status)) {
4853 CreatePopUp (
4854 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4855 &Key,
4856 L"ERROR: Unsupported file type!",
4857 L"Only supports DER-encoded X509 certificate",
4858 NULL
4859 );
4860 }
4861
4862 break;
4863
4864 case KEY_VALUE_SAVE_AND_EXIT_DB:
4865 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);
4866 if (EFI_ERROR (Status)) {
4867 CreatePopUp (
4868 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4869 &Key,
4870 L"ERROR: Unsupported file type!",
4871 L"Only supports DER-encoded X509 certificate and executable EFI image",
4872 NULL
4873 );
4874 }
4875
4876 break;
4877
4878 case KEY_VALUE_SAVE_AND_EXIT_DBX:
4879 if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {
4880 CreatePopUp (
4881 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4882 &Key,
4883 L"Enrollment failed! Same certificate had already been in the dbx!",
4884 NULL
4885 );
4886
4887 //
4888 // Cert already exists in DBX. Close opened file before exit.
4889 //
4890 CloseEnrolledFile (Private->FileContext);
4891 break;
4892 }
4893
4894 if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {
4895 Status = EnrollX509HashtoSigDB (
4896 Private,
4897 IfrNvData->CertificateFormat,
4898 &IfrNvData->RevocationDate,
4899 &IfrNvData->RevocationTime,
4900 IfrNvData->AlwaysRevocation
4901 );
4902 IfrNvData->CertificateFormat = HASHALG_RAW;
4903 } else {
4904 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);
4905 }
4906
4907 if (EFI_ERROR (Status)) {
4908 CreatePopUp (
4909 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4910 &Key,
4911 L"ERROR: Unsupported file type!",
4912 L"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
4913 NULL
4914 );
4915 }
4916
4917 break;
4918
4919 case KEY_VALUE_SAVE_AND_EXIT_DBT:
4920 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);
4921 if (EFI_ERROR (Status)) {
4922 CreatePopUp (
4923 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4924 &Key,
4925 L"ERROR: Unsupported file type!",
4926 L"Only supports DER-encoded X509 certificate.",
4927 NULL
4928 );
4929 }
4930
4931 break;
4932 case KEY_VALUE_SAVE_AND_EXIT_PK:
4933 //
4934 // Check the suffix, encode type and the key strength of PK certificate.
4935 //
4936 Status = CheckX509Certificate (Private->FileContext, &EnrollKeyErrorCode);
4937 if (EFI_ERROR (Status)) {
4938 if ((EnrollKeyErrorCode != None_Error) && (EnrollKeyErrorCode < Enroll_Error_Max)) {
4939 CreatePopUp (
4940 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4941 &Key,
4942 mX509EnrollPromptTitle[EnrollKeyErrorCode],
4943 mX509EnrollPromptString[EnrollKeyErrorCode],
4944 NULL
4945 );
4946 break;
4947 }
4948 } else {
4949 Status = EnrollPlatformKey (Private);
4950 }
4951
4952 if (EFI_ERROR (Status)) {
4953 UnicodeSPrint (
4954 PromptString,
4955 sizeof (PromptString),
4956 L"Error status: %x.",
4957 Status
4958 );
4959 CreatePopUp (
4960 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
4961 &Key,
4962 L"ERROR: Enrollment failed!",
4963 PromptString,
4964 NULL
4965 );
4966 }
4967
4968 break;
4969 default:
4970 if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&
4971 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE)))
4972 {
4973 DeleteKeyExchangeKey (Private, QuestionId);
4974 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&
4975 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE)))
4976 {
4977 DeleteSignature (
4978 Private,
4979 EFI_IMAGE_SECURITY_DATABASE,
4980 &gEfiImageSecurityDatabaseGuid,
4981 LABEL_DB_DELETE,
4982 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
4983 OPTION_DEL_DB_QUESTION_ID,
4984 QuestionId - OPTION_DEL_DB_QUESTION_ID
4985 );
4986 } else if ((QuestionId >= OPTION_SIGNATURE_LIST_QUESTION_ID) &&
4987 (QuestionId < (OPTION_SIGNATURE_LIST_QUESTION_ID + OPTION_CONFIG_RANGE)))
4988 {
4989 LoadSignatureData (
4990 Private,
4991 LABEL_SIGNATURE_DATA_START,
4992 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,
4993 OPTION_SIGNATURE_DATA_QUESTION_ID,
4994 QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID
4995 );
4996 Private->ListIndex = QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID;
4997 } else if ((QuestionId >= OPTION_SIGNATURE_DATA_QUESTION_ID) &&
4998 (QuestionId < (OPTION_SIGNATURE_DATA_QUESTION_ID + OPTION_CONFIG_RANGE)))
4999 {
5000 if (Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID]) {
5001 IfrNvData->CheckedDataCount--;
5002 Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = FALSE;
5003 } else {
5004 IfrNvData->CheckedDataCount++;
5005 Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = TRUE;
5006 }
5007 } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&
5008 (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE)))
5009 {
5010 DeleteSignature (
5011 Private,
5012 EFI_IMAGE_SECURITY_DATABASE2,
5013 &gEfiImageSecurityDatabaseGuid,
5014 LABEL_DBT_DELETE,
5015 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
5016 OPTION_DEL_DBT_QUESTION_ID,
5017 QuestionId - OPTION_DEL_DBT_QUESTION_ID
5018 );
5019 }
5020
5021 break;
5022
5023 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:
5024 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:
5025 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:
5026 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:
5027 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:
5028 CloseEnrolledFile (Private->FileContext);
5029
5030 if (Private->SignatureGUID != NULL) {
5031 FreePool (Private->SignatureGUID);
5032 Private->SignatureGUID = NULL;
5033 }
5034
5035 break;
5036 }
5037 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
5038 switch (QuestionId) {
5039 case KEY_SECURE_BOOT_ENABLE:
5040 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
5041 break;
5042 case KEY_SECURE_BOOT_MODE:
5043 mIsEnterSecureBootForm = FALSE;
5044 break;
5045 case KEY_SECURE_BOOT_KEK_GUID:
5046 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:
5047 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:
5048 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:
5049 ASSERT (Private->SignatureGUID != NULL);
5050 RStatus = StrToGuid (IfrNvData->SignatureGuid, Private->SignatureGUID);
5051 if (RETURN_ERROR (RStatus) || (IfrNvData->SignatureGuid[GUID_STRING_LENGTH] != L'\0')) {
5052 Status = EFI_INVALID_PARAMETER;
5053 break;
5054 }
5055
5056 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
5057 break;
5058 case KEY_SECURE_BOOT_DELETE_PK:
5059 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID **)&SetupMode, NULL);
5060 if ((SetupMode == NULL) || ((*SetupMode) == SETUP_MODE)) {
5061 IfrNvData->DeletePk = TRUE;
5062 IfrNvData->HasPk = FALSE;
5063 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
5064 } else {
5065 IfrNvData->DeletePk = FALSE;
5066 IfrNvData->HasPk = TRUE;
5067 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
5068 }
5069
5070 if (SetupMode != NULL) {
5071 FreePool (SetupMode);
5072 }
5073
5074 break;
5075 case KEY_SECURE_BOOT_RESET_TO_DEFAULT:
5076 {
5077 Status = gBS->LocateProtocol (&gEfiHiiPopupProtocolGuid, NULL, (VOID **)&HiiPopup);
5078 if (EFI_ERROR (Status)) {
5079 return Status;
5080 }
5081
5082 Status = HiiPopup->CreatePopup (
5083 HiiPopup,
5084 EfiHiiPopupStyleInfo,
5085 EfiHiiPopupTypeYesNo,
5086 Private->HiiHandle,
5087 STRING_TOKEN (STR_RESET_TO_DEFAULTS_POPUP),
5088 &UserSelection
5089 );
5090 if (UserSelection == EfiHiiPopupSelectionYes) {
5091 Status = KeyEnrollReset ();
5092 }
5093
5094 //
5095 // Update secure boot strings after key reset
5096 //
5097 if (Status == EFI_SUCCESS) {
5098 Status = UpdateSecureBootString (Private);
5099 SecureBootExtractConfigFromVariable (Private, IfrNvData);
5100 }
5101 }
5102 default:
5103 break;
5104 }
5105 } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {
5106 if (QuestionId == KEY_HIDE_SECURE_BOOT) {
5107 GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **)&Pk, NULL);
5108 if (Pk == NULL) {
5109 IfrNvData->HideSecureBoot = TRUE;
5110 } else {
5111 FreePool (Pk);
5112 IfrNvData->HideSecureBoot = FALSE;
5113 }
5114
5115 Value->b = IfrNvData->HideSecureBoot;
5116 }
5117 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
5118 //
5119 // Force the platform back to Standard Mode once user leave the setup screen.
5120 //
5121 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID **)&SecureBootMode, NULL);
5122 if ((NULL != SecureBootMode) && (*SecureBootMode == CUSTOM_SECURE_BOOT_MODE)) {
5123 IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
5124 SetSecureBootMode (STANDARD_SECURE_BOOT_MODE);
5125 }
5126
5127 if (SecureBootMode != NULL) {
5128 FreePool (SecureBootMode);
5129 }
5130
5131 if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_DATA) {
5132 //
5133 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
5134 //
5135 SECUREBOOT_FREE_NON_NULL (Private->CheckArray);
5136 IfrNvData->CheckedDataCount = 0;
5137 }
5138 }
5139
5140 EXIT:
5141
5142 if (!EFI_ERROR (Status) && GetBrowserDataResult) {
5143 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
5144 HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *)IfrNvData, NULL);
5145 }
5146
5147 FreePool (IfrNvData);
5148
5149 if (File != NULL) {
5150 FreePool (File);
5151 File = NULL;
5152 }
5153
5154 return EFI_SUCCESS;
5155 }
5156
5157 /**
5158 This function publish the SecureBoot configuration Form.
5159
5160 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5161
5162 @retval EFI_SUCCESS HII Form is installed successfully.
5163 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
5164 @retval Others Other errors as indicated.
5165
5166 **/
5167 EFI_STATUS
5168 InstallSecureBootConfigForm (
5169 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
5170 )
5171 {
5172 EFI_STATUS Status;
5173 EFI_HII_HANDLE HiiHandle;
5174 EFI_HANDLE DriverHandle;
5175 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
5176
5177 DriverHandle = NULL;
5178 ConfigAccess = &PrivateData->ConfigAccess;
5179 Status = gBS->InstallMultipleProtocolInterfaces (
5180 &DriverHandle,
5181 &gEfiDevicePathProtocolGuid,
5182 &mSecureBootHiiVendorDevicePath,
5183 &gEfiHiiConfigAccessProtocolGuid,
5184 ConfigAccess,
5185 NULL
5186 );
5187 if (EFI_ERROR (Status)) {
5188 return Status;
5189 }
5190
5191 PrivateData->DriverHandle = DriverHandle;
5192
5193 //
5194 // Publish the HII package list
5195 //
5196 HiiHandle = HiiAddPackages (
5197 &gSecureBootConfigFormSetGuid,
5198 DriverHandle,
5199 SecureBootConfigDxeStrings,
5200 SecureBootConfigBin,
5201 NULL
5202 );
5203 if (HiiHandle == NULL) {
5204 gBS->UninstallMultipleProtocolInterfaces (
5205 DriverHandle,
5206 &gEfiDevicePathProtocolGuid,
5207 &mSecureBootHiiVendorDevicePath,
5208 &gEfiHiiConfigAccessProtocolGuid,
5209 ConfigAccess,
5210 NULL
5211 );
5212 return EFI_OUT_OF_RESOURCES;
5213 }
5214
5215 PrivateData->HiiHandle = HiiHandle;
5216
5217 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));
5218
5219 if (PrivateData->FileContext == NULL) {
5220 UninstallSecureBootConfigForm (PrivateData);
5221 return EFI_OUT_OF_RESOURCES;
5222 }
5223
5224 //
5225 // Init OpCode Handle and Allocate space for creation of Buffer
5226 //
5227 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
5228 if (mStartOpCodeHandle == NULL) {
5229 UninstallSecureBootConfigForm (PrivateData);
5230 return EFI_OUT_OF_RESOURCES;
5231 }
5232
5233 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
5234 if (mEndOpCodeHandle == NULL) {
5235 UninstallSecureBootConfigForm (PrivateData);
5236 return EFI_OUT_OF_RESOURCES;
5237 }
5238
5239 //
5240 // Create Hii Extend Label OpCode as the start opcode
5241 //
5242 mStartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
5243 mStartOpCodeHandle,
5244 &gEfiIfrTianoGuid,
5245 NULL,
5246 sizeof (EFI_IFR_GUID_LABEL)
5247 );
5248 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
5249
5250 //
5251 // Create Hii Extend Label OpCode as the end opcode
5252 //
5253 mEndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
5254 mEndOpCodeHandle,
5255 &gEfiIfrTianoGuid,
5256 NULL,
5257 sizeof (EFI_IFR_GUID_LABEL)
5258 );
5259 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
5260 mEndLabel->Number = LABEL_END;
5261
5262 return EFI_SUCCESS;
5263 }
5264
5265 /**
5266 This function removes SecureBoot configuration Form.
5267
5268 @param[in, out] PrivateData Points to SecureBoot configuration private data.
5269
5270 **/
5271 VOID
5272 UninstallSecureBootConfigForm (
5273 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
5274 )
5275 {
5276 //
5277 // Uninstall HII package list
5278 //
5279 if (PrivateData->HiiHandle != NULL) {
5280 HiiRemovePackages (PrivateData->HiiHandle);
5281 PrivateData->HiiHandle = NULL;
5282 }
5283
5284 //
5285 // Uninstall HII Config Access Protocol
5286 //
5287 if (PrivateData->DriverHandle != NULL) {
5288 gBS->UninstallMultipleProtocolInterfaces (
5289 PrivateData->DriverHandle,
5290 &gEfiDevicePathProtocolGuid,
5291 &mSecureBootHiiVendorDevicePath,
5292 &gEfiHiiConfigAccessProtocolGuid,
5293 &PrivateData->ConfigAccess,
5294 NULL
5295 );
5296 PrivateData->DriverHandle = NULL;
5297 }
5298
5299 if (PrivateData->SignatureGUID != NULL) {
5300 FreePool (PrivateData->SignatureGUID);
5301 }
5302
5303 if (PrivateData->FileContext != NULL) {
5304 FreePool (PrivateData->FileContext);
5305 }
5306
5307 FreePool (PrivateData);
5308
5309 if (mStartOpCodeHandle != NULL) {
5310 HiiFreeOpCodeHandle (mStartOpCodeHandle);
5311 }
5312
5313 if (mEndOpCodeHandle != NULL) {
5314 HiiFreeOpCodeHandle (mEndOpCodeHandle);
5315 }
5316 }