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