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