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