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