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