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