]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
659952a63a05c7738d5e8235a0237a39deeec207
[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 - 2013, 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
17 CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";
18
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,
21 {
22 SecureBootExtractConfig,
23 SecureBootRouteConfig,
24 SecureBootCallback
25 }
26 };
27
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = {
29 {
30 {
31 HARDWARE_DEVICE_PATH,
32 HW_VENDOR_DP,
33 {
34 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
35 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
36 }
37 },
38 SECUREBOOT_CONFIG_FORM_SET_GUID
39 },
40 {
41 END_DEVICE_PATH_TYPE,
42 END_ENTIRE_DEVICE_PATH_SUBTYPE,
43 {
44 (UINT8) (END_DEVICE_PATH_LENGTH),
45 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
46 }
47 }
48 };
49
50
51 //
52 // OID ASN.1 Value for Hash Algorithms
53 //
54 UINT8 mHashOidValue[] = {
55 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
56 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
57 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
58 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
61 };
62
63 HASH_TABLE mHash[] = {
64 { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
65 { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },
66 { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},
67 { L"SHA384", 48, &mHashOidValue[31], 9, NULL, NULL, NULL, NULL },
68 { L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL }
69 };
70
71 //
72 // Variable Definitions
73 //
74 UINT32 mPeCoffHeaderOffset = 0;
75 WIN_CERTIFICATE *mCertificate = NULL;
76 IMAGE_TYPE mImageType;
77 UINT8 *mImageBase = NULL;
78 UINTN mImageSize = 0;
79 UINT8 mImageDigest[MAX_DIGEST_SIZE];
80 UINTN mImageDigestSize;
81 EFI_GUID mCertType;
82 EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL;
83 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
84
85 //
86 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
87 //
88 CHAR16* mDerEncodedSuffix[] = {
89 L".cer",
90 L".der",
91 L".crt",
92 NULL
93 };
94 CHAR16* mSupportX509Suffix = L"*.cer/der/crt";
95
96 /**
97 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
98
99 @param[in] FileSuffix The suffix of the input certificate file
100
101 @retval TRUE It's a DER-encoded certificate.
102 @retval FALSE It's NOT a DER-encoded certificate.
103
104 **/
105 BOOLEAN
106 IsDerEncodeCertificate (
107 IN CONST CHAR16 *FileSuffix
108 )
109 {
110 UINTN Index;
111 for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {
112 if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {
113 return TRUE;
114 }
115 }
116 return FALSE;
117 }
118
119 /**
120 Set Secure Boot option into variable space.
121
122 @param[in] VarValue The option of Secure Boot.
123
124 @retval EFI_SUCCESS The operation is finished successfully.
125 @retval Others Other errors as indicated.
126
127 **/
128 EFI_STATUS
129 SaveSecureBootVariable (
130 IN UINT8 VarValue
131 )
132 {
133 EFI_STATUS Status;
134
135 Status = gRT->SetVariable (
136 EFI_SECURE_BOOT_ENABLE_NAME,
137 &gEfiSecureBootEnableDisableGuid,
138 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
139 sizeof (UINT8),
140 &VarValue
141 );
142 return Status;
143 }
144
145 /**
146 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
147 descriptor with the input data. NO authentication is required in this function.
148
149 @param[in, out] DataSize On input, the size of Data buffer in bytes.
150 On output, the size of data returned in Data
151 buffer in bytes.
152 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
153 pointer to NULL to wrap an empty payload.
154 On output, Pointer to the new payload date buffer allocated from pool,
155 it's caller's responsibility to free the memory when finish using it.
156
157 @retval EFI_SUCCESS Create time based payload successfully.
158 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
159 @retval EFI_INVALID_PARAMETER The parameter is invalid.
160 @retval Others Unexpected error happens.
161
162 **/
163 EFI_STATUS
164 CreateTimeBasedPayload (
165 IN OUT UINTN *DataSize,
166 IN OUT UINT8 **Data
167 )
168 {
169 EFI_STATUS Status;
170 UINT8 *NewData;
171 UINT8 *Payload;
172 UINTN PayloadSize;
173 EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
174 UINTN DescriptorSize;
175 EFI_TIME Time;
176
177 if (Data == NULL || DataSize == NULL) {
178 return EFI_INVALID_PARAMETER;
179 }
180
181 //
182 // In Setup mode or Custom mode, the variable does not need to be signed but the
183 // parameters to the SetVariable() call still need to be prepared as authenticated
184 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
185 // data in it.
186 //
187 Payload = *Data;
188 PayloadSize = *DataSize;
189
190 DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
191 NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
192 if (NewData == NULL) {
193 return EFI_OUT_OF_RESOURCES;
194 }
195
196 if ((Payload != NULL) && (PayloadSize != 0)) {
197 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
198 }
199
200 DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
201
202 ZeroMem (&Time, sizeof (EFI_TIME));
203 Status = gRT->GetTime (&Time, NULL);
204 if (EFI_ERROR (Status)) {
205 FreePool(NewData);
206 return Status;
207 }
208 Time.Pad1 = 0;
209 Time.Nanosecond = 0;
210 Time.TimeZone = 0;
211 Time.Daylight = 0;
212 Time.Pad2 = 0;
213 CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
214
215 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
216 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
217 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
218 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
219
220 if (Payload != NULL) {
221 FreePool(Payload);
222 }
223
224 *DataSize = DescriptorSize + PayloadSize;
225 *Data = NewData;
226 return EFI_SUCCESS;
227 }
228
229 /**
230 Internal helper function to delete a Variable given its name and GUID, NO authentication
231 required.
232
233 @param[in] VariableName Name of the Variable.
234 @param[in] VendorGuid GUID of the Variable.
235
236 @retval EFI_SUCCESS Variable deleted successfully.
237 @retval Others The driver failed to start the device.
238
239 **/
240 EFI_STATUS
241 DeleteVariable (
242 IN CHAR16 *VariableName,
243 IN EFI_GUID *VendorGuid
244 )
245 {
246 EFI_STATUS Status;
247 VOID* Variable;
248 UINT8 *Data;
249 UINTN DataSize;
250 UINT32 Attr;
251
252 GetVariable2 (VariableName, VendorGuid, &Variable, NULL);
253 if (Variable == NULL) {
254 return EFI_SUCCESS;
255 }
256 FreePool (Variable);
257
258 Data = NULL;
259 DataSize = 0;
260 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
261 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
262
263 Status = CreateTimeBasedPayload (&DataSize, &Data);
264 if (EFI_ERROR (Status)) {
265 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
266 return Status;
267 }
268
269 Status = gRT->SetVariable (
270 VariableName,
271 VendorGuid,
272 Attr,
273 DataSize,
274 Data
275 );
276 if (Data != NULL) {
277 FreePool (Data);
278 }
279 return Status;
280 }
281
282 /**
283
284 Set the platform secure boot mode into "Custom" or "Standard" mode.
285
286 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
287 CUSTOM_SECURE_BOOT_MODE.
288
289 @return EFI_SUCCESS The platform has switched to the special mode successfully.
290 @return other Fail to operate the secure boot mode.
291
292 **/
293 EFI_STATUS
294 SetSecureBootMode (
295 IN UINT8 SecureBootMode
296 )
297 {
298 return gRT->SetVariable (
299 EFI_CUSTOM_MODE_NAME,
300 &gEfiCustomModeEnableGuid,
301 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
302 sizeof (UINT8),
303 &SecureBootMode
304 );
305 }
306
307 /**
308 Generate the PK signature list from the X509 Certificate storing file (.cer)
309
310 @param[in] X509File FileHandle of X509 Certificate storing file.
311 @param[out] PkCert Point to the data buffer to store the signature list.
312
313 @return EFI_UNSUPPORTED Unsupported Key Length.
314 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
315
316 **/
317 EFI_STATUS
318 CreatePkX509SignatureList (
319 IN EFI_FILE_HANDLE X509File,
320 OUT EFI_SIGNATURE_LIST **PkCert
321 )
322 {
323 EFI_STATUS Status;
324 UINT8 *X509Data;
325 UINTN X509DataSize;
326 EFI_SIGNATURE_DATA *PkCertData;
327
328 X509Data = NULL;
329 PkCertData = NULL;
330 X509DataSize = 0;
331
332 Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);
333 if (EFI_ERROR (Status)) {
334 goto ON_EXIT;
335 }
336 ASSERT (X509Data != NULL);
337
338 //
339 // Allocate space for PK certificate list and initialize it.
340 // Create PK database entry with SignatureHeaderSize equals 0.
341 //
342 *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (
343 sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1
344 + X509DataSize
345 );
346 if (*PkCert == NULL) {
347 Status = EFI_OUT_OF_RESOURCES;
348 goto ON_EXIT;
349 }
350
351 (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST)
352 + sizeof(EFI_SIGNATURE_DATA) - 1
353 + X509DataSize);
354 (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
355 (*PkCert)->SignatureHeaderSize = 0;
356 CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);
357 PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert)
358 + sizeof(EFI_SIGNATURE_LIST)
359 + (*PkCert)->SignatureHeaderSize);
360 CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);
361 //
362 // Fill the PK database with PKpub data from X509 certificate file.
363 //
364 CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);
365
366 ON_EXIT:
367
368 if (X509Data != NULL) {
369 FreePool (X509Data);
370 }
371
372 if (EFI_ERROR(Status) && *PkCert != NULL) {
373 FreePool (*PkCert);
374 *PkCert = NULL;
375 }
376
377 return Status;
378 }
379
380 /**
381 Enroll new PK into the System without original PK's authentication.
382
383 The SignatureOwner GUID will be the same with PK's vendorguid.
384
385 @param[in] PrivateData The module's private data.
386
387 @retval EFI_SUCCESS New PK enrolled successfully.
388 @retval EFI_INVALID_PARAMETER The parameter is invalid.
389 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
390
391 **/
392 EFI_STATUS
393 EnrollPlatformKey (
394 IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private
395 )
396 {
397 EFI_STATUS Status;
398 UINT32 Attr;
399 UINTN DataSize;
400 EFI_SIGNATURE_LIST *PkCert;
401 UINT16* FilePostFix;
402 UINTN NameLength;
403
404 if (Private->FileContext->FileName == NULL) {
405 return EFI_INVALID_PARAMETER;
406 }
407
408 PkCert = NULL;
409
410 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
411 if (EFI_ERROR (Status)) {
412 return Status;
413 }
414
415 //
416 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
417 //
418 NameLength = StrLen (Private->FileContext->FileName);
419 if (NameLength <= 4) {
420 return EFI_INVALID_PARAMETER;
421 }
422 FilePostFix = Private->FileContext->FileName + NameLength - 4;
423 if (!IsDerEncodeCertificate(FilePostFix)) {
424 DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));
425 return EFI_INVALID_PARAMETER;
426 }
427 DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));
428 DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));
429
430 //
431 // Prase the selected PK file and generature PK certificate list.
432 //
433 Status = CreatePkX509SignatureList (
434 Private->FileContext->FHandle,
435 &PkCert
436 );
437 if (EFI_ERROR (Status)) {
438 goto ON_EXIT;
439 }
440 ASSERT (PkCert != NULL);
441
442 //
443 // Set Platform Key variable.
444 //
445 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
446 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
447 DataSize = PkCert->SignatureListSize;
448 Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);
449 if (EFI_ERROR (Status)) {
450 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
451 goto ON_EXIT;
452 }
453
454 Status = gRT->SetVariable(
455 EFI_PLATFORM_KEY_NAME,
456 &gEfiGlobalVariableGuid,
457 Attr,
458 DataSize,
459 PkCert
460 );
461 if (EFI_ERROR (Status)) {
462 if (Status == EFI_OUT_OF_RESOURCES) {
463 DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));
464 }
465 goto ON_EXIT;
466 }
467
468 ON_EXIT:
469
470 if (PkCert != NULL) {
471 FreePool(PkCert);
472 }
473
474 if (Private->FileContext->FHandle != NULL) {
475 CloseFile (Private->FileContext->FHandle);
476 Private->FileContext->FHandle = NULL;
477 }
478
479 return Status;
480 }
481
482 /**
483 Remove the PK variable.
484
485 @retval EFI_SUCCESS Delete PK successfully.
486 @retval Others Could not allow to delete PK.
487
488 **/
489 EFI_STATUS
490 DeletePlatformKey (
491 VOID
492 )
493 {
494 EFI_STATUS Status;
495
496 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
497 if (EFI_ERROR (Status)) {
498 return Status;
499 }
500
501 Status = DeleteVariable (
502 EFI_PLATFORM_KEY_NAME,
503 &gEfiGlobalVariableGuid
504 );
505 return Status;
506 }
507
508 /**
509 Enroll a new KEK item from public key storing file (*.pbk).
510
511 @param[in] PrivateData The module's private data.
512
513 @retval EFI_SUCCESS New KEK enrolled successfully.
514 @retval EFI_INVALID_PARAMETER The parameter is invalid.
515 @retval EFI_UNSUPPORTED Unsupported command.
516 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
517
518 **/
519 EFI_STATUS
520 EnrollRsa2048ToKek (
521 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
522 )
523 {
524 EFI_STATUS Status;
525 UINT32 Attr;
526 UINTN DataSize;
527 EFI_SIGNATURE_LIST *KekSigList;
528 UINTN KeyBlobSize;
529 UINT8 *KeyBlob;
530 CPL_KEY_INFO *KeyInfo;
531 EFI_SIGNATURE_DATA *KEKSigData;
532 UINTN KekSigListSize;
533 UINT8 *KeyBuffer;
534 UINTN KeyLenInBytes;
535
536 Attr = 0;
537 DataSize = 0;
538 KeyBuffer = NULL;
539 KeyBlobSize = 0;
540 KeyBlob = NULL;
541 KeyInfo = NULL;
542 KEKSigData = NULL;
543 KekSigList = NULL;
544 KekSigListSize = 0;
545
546 //
547 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
548 // First, We have to parse out public key data from the pbk key file.
549 //
550 Status = ReadFileContent (
551 Private->FileContext->FHandle,
552 (VOID**) &KeyBlob,
553 &KeyBlobSize,
554 0
555 );
556 if (EFI_ERROR (Status)) {
557 goto ON_EXIT;
558 }
559 ASSERT (KeyBlob != NULL);
560 KeyInfo = (CPL_KEY_INFO *) KeyBlob;
561 if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {
562 DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));
563 Status = EFI_UNSUPPORTED;
564 goto ON_EXIT;
565 }
566
567 //
568 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
569 //
570 KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;
571 KeyBuffer = AllocateZeroPool (KeyLenInBytes);
572 if (KeyBuffer == NULL) {
573 Status = EFI_OUT_OF_RESOURCES;
574 goto ON_EXIT;
575 }
576 Int2OctStr (
577 (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),
578 KeyLenInBytes / sizeof (UINTN),
579 KeyBuffer,
580 KeyLenInBytes
581 );
582 CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);
583
584 //
585 // Form an new EFI_SIGNATURE_LIST.
586 //
587 KekSigListSize = sizeof(EFI_SIGNATURE_LIST)
588 + sizeof(EFI_SIGNATURE_DATA) - 1
589 + WIN_CERT_UEFI_RSA2048_SIZE;
590
591 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);
592 if (KekSigList == NULL) {
593 Status = EFI_OUT_OF_RESOURCES;
594 goto ON_EXIT;
595 }
596
597 KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST)
598 + sizeof(EFI_SIGNATURE_DATA) - 1
599 + WIN_CERT_UEFI_RSA2048_SIZE;
600 KekSigList->SignatureHeaderSize = 0;
601 KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;
602 CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);
603
604 KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));
605 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
606 CopyMem (
607 KEKSigData->SignatureData,
608 KeyBlob + sizeof(CPL_KEY_INFO),
609 WIN_CERT_UEFI_RSA2048_SIZE
610 );
611
612 //
613 // Check if KEK entry has been already existed.
614 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
615 // new KEK to original variable.
616 //
617 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
618 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
619 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
620 if (EFI_ERROR (Status)) {
621 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
622 goto ON_EXIT;
623 }
624
625 Status = gRT->GetVariable(
626 EFI_KEY_EXCHANGE_KEY_NAME,
627 &gEfiGlobalVariableGuid,
628 NULL,
629 &DataSize,
630 NULL
631 );
632 if (Status == EFI_BUFFER_TOO_SMALL) {
633 Attr |= EFI_VARIABLE_APPEND_WRITE;
634 } else if (Status != EFI_NOT_FOUND) {
635 goto ON_EXIT;
636 }
637
638 //
639 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
640 //
641 Status = gRT->SetVariable(
642 EFI_KEY_EXCHANGE_KEY_NAME,
643 &gEfiGlobalVariableGuid,
644 Attr,
645 KekSigListSize,
646 KekSigList
647 );
648 if (EFI_ERROR (Status)) {
649 goto ON_EXIT;
650 }
651
652 ON_EXIT:
653
654 CloseFile (Private->FileContext->FHandle);
655 Private->FileContext->FHandle = NULL;
656 Private->FileContext->FileName = NULL;
657
658 if (Private->SignatureGUID != NULL) {
659 FreePool (Private->SignatureGUID);
660 Private->SignatureGUID = NULL;
661 }
662
663 if (KeyBlob != NULL) {
664 FreePool (KeyBlob);
665 }
666 if (KeyBuffer != NULL) {
667 FreePool (KeyBuffer);
668 }
669 if (KekSigList != NULL) {
670 FreePool (KekSigList);
671 }
672
673 return Status;
674 }
675
676 /**
677 Enroll a new KEK item from X509 certificate file.
678
679 @param[in] PrivateData The module's private data.
680
681 @retval EFI_SUCCESS New X509 is enrolled successfully.
682 @retval EFI_INVALID_PARAMETER The parameter is invalid.
683 @retval EFI_UNSUPPORTED Unsupported command.
684 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
685
686 **/
687 EFI_STATUS
688 EnrollX509ToKek (
689 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
690 )
691 {
692 EFI_STATUS Status;
693 UINTN X509DataSize;
694 VOID *X509Data;
695 EFI_SIGNATURE_DATA *KEKSigData;
696 EFI_SIGNATURE_LIST *KekSigList;
697 UINTN DataSize;
698 UINTN KekSigListSize;
699 UINT32 Attr;
700
701 X509Data = NULL;
702 X509DataSize = 0;
703 KekSigList = NULL;
704 KekSigListSize = 0;
705 DataSize = 0;
706 KEKSigData = NULL;
707
708 Status = ReadFileContent (
709 Private->FileContext->FHandle,
710 &X509Data,
711 &X509DataSize,
712 0
713 );
714 if (EFI_ERROR (Status)) {
715 goto ON_EXIT;
716 }
717 ASSERT (X509Data != NULL);
718
719 KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
720 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);
721 if (KekSigList == NULL) {
722 Status = EFI_OUT_OF_RESOURCES;
723 goto ON_EXIT;
724 }
725
726 //
727 // Fill Certificate Database parameters.
728 //
729 KekSigList->SignatureListSize = (UINT32) KekSigListSize;
730 KekSigList->SignatureHeaderSize = 0;
731 KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
732 CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);
733
734 KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));
735 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
736 CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);
737
738 //
739 // Check if KEK been already existed.
740 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
741 // new kek to original variable
742 //
743 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
744 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
745 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
746 if (EFI_ERROR (Status)) {
747 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
748 goto ON_EXIT;
749 }
750
751 Status = gRT->GetVariable(
752 EFI_KEY_EXCHANGE_KEY_NAME,
753 &gEfiGlobalVariableGuid,
754 NULL,
755 &DataSize,
756 NULL
757 );
758 if (Status == EFI_BUFFER_TOO_SMALL) {
759 Attr |= EFI_VARIABLE_APPEND_WRITE;
760 } else if (Status != EFI_NOT_FOUND) {
761 goto ON_EXIT;
762 }
763
764 Status = gRT->SetVariable(
765 EFI_KEY_EXCHANGE_KEY_NAME,
766 &gEfiGlobalVariableGuid,
767 Attr,
768 KekSigListSize,
769 KekSigList
770 );
771 if (EFI_ERROR (Status)) {
772 goto ON_EXIT;
773 }
774
775 ON_EXIT:
776
777 CloseFile (Private->FileContext->FHandle);
778 Private->FileContext->FileName = NULL;
779 Private->FileContext->FHandle = NULL;
780
781 if (Private->SignatureGUID != NULL) {
782 FreePool (Private->SignatureGUID);
783 Private->SignatureGUID = NULL;
784 }
785
786 if (KekSigList != NULL) {
787 FreePool (KekSigList);
788 }
789
790 return Status;
791 }
792
793 /**
794 Enroll new KEK into the System without PK's authentication.
795 The SignatureOwner GUID will be Private->SignatureGUID.
796
797 @param[in] PrivateData The module's private data.
798
799 @retval EFI_SUCCESS New KEK enrolled successful.
800 @retval EFI_INVALID_PARAMETER The parameter is invalid.
801 @retval others Fail to enroll KEK data.
802
803 **/
804 EFI_STATUS
805 EnrollKeyExchangeKey (
806 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
807 )
808 {
809 UINT16* FilePostFix;
810 EFI_STATUS Status;
811 UINTN NameLength;
812
813 if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {
814 return EFI_INVALID_PARAMETER;
815 }
816
817 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
818 if (EFI_ERROR (Status)) {
819 return Status;
820 }
821
822 //
823 // Parse the file's postfix. Supports DER-encoded X509 certificate,
824 // and .pbk as RSA public key file.
825 //
826 NameLength = StrLen (Private->FileContext->FileName);
827 if (NameLength <= 4) {
828 return EFI_INVALID_PARAMETER;
829 }
830 FilePostFix = Private->FileContext->FileName + NameLength - 4;
831 if (IsDerEncodeCertificate(FilePostFix)) {
832 return EnrollX509ToKek (Private);
833 } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {
834 return EnrollRsa2048ToKek (Private);
835 } else {
836 return EFI_INVALID_PARAMETER;
837 }
838 }
839
840 /**
841 Enroll a new X509 certificate into Signature Database (DB or DBX) without
842 KEK's authentication.
843
844 @param[in] PrivateData The module's private data.
845 @param[in] VariableName Variable name of signature database, must be
846 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
847
848 @retval EFI_SUCCESS New X509 is enrolled successfully.
849 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
850
851 **/
852 EFI_STATUS
853 EnrollX509toSigDB (
854 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
855 IN CHAR16 *VariableName
856 )
857 {
858 EFI_STATUS Status;
859 UINTN X509DataSize;
860 VOID *X509Data;
861 EFI_SIGNATURE_LIST *SigDBCert;
862 EFI_SIGNATURE_DATA *SigDBCertData;
863 VOID *Data;
864 UINTN DataSize;
865 UINTN SigDBSize;
866 UINT32 Attr;
867
868 X509DataSize = 0;
869 SigDBSize = 0;
870 DataSize = 0;
871 X509Data = NULL;
872 SigDBCert = NULL;
873 SigDBCertData = NULL;
874 Data = NULL;
875
876 Status = ReadFileContent (
877 Private->FileContext->FHandle,
878 &X509Data,
879 &X509DataSize,
880 0
881 );
882 if (EFI_ERROR (Status)) {
883 goto ON_EXIT;
884 }
885 ASSERT (X509Data != NULL);
886
887 SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
888
889 Data = AllocateZeroPool (SigDBSize);
890 if (Data == NULL) {
891 Status = EFI_OUT_OF_RESOURCES;
892 goto ON_EXIT;
893 }
894
895 //
896 // Fill Certificate Database parameters.
897 //
898 SigDBCert = (EFI_SIGNATURE_LIST*) Data;
899 SigDBCert->SignatureListSize = (UINT32) SigDBSize;
900 SigDBCert->SignatureHeaderSize = 0;
901 SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
902 CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);
903
904 SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));
905 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
906 CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);
907
908 //
909 // Check if signature database entry has been already existed.
910 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
911 // new signature data to original variable
912 //
913 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
914 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
915 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
916 if (EFI_ERROR (Status)) {
917 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
918 goto ON_EXIT;
919 }
920
921 Status = gRT->GetVariable(
922 VariableName,
923 &gEfiImageSecurityDatabaseGuid,
924 NULL,
925 &DataSize,
926 NULL
927 );
928 if (Status == EFI_BUFFER_TOO_SMALL) {
929 Attr |= EFI_VARIABLE_APPEND_WRITE;
930 } else if (Status != EFI_NOT_FOUND) {
931 goto ON_EXIT;
932 }
933
934 Status = gRT->SetVariable(
935 VariableName,
936 &gEfiImageSecurityDatabaseGuid,
937 Attr,
938 SigDBSize,
939 Data
940 );
941 if (EFI_ERROR (Status)) {
942 goto ON_EXIT;
943 }
944
945 ON_EXIT:
946
947 CloseFile (Private->FileContext->FHandle);
948 Private->FileContext->FileName = NULL;
949 Private->FileContext->FHandle = NULL;
950
951 if (Private->SignatureGUID != NULL) {
952 FreePool (Private->SignatureGUID);
953 Private->SignatureGUID = NULL;
954 }
955
956 if (Data != NULL) {
957 FreePool (Data);
958 }
959
960 if (X509Data != NULL) {
961 FreePool (X509Data);
962 }
963
964 return Status;
965 }
966
967 /**
968 Load PE/COFF image information into internal buffer and check its validity.
969
970 @retval EFI_SUCCESS Successful
971 @retval EFI_UNSUPPORTED Invalid PE/COFF file
972 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
973
974 **/
975 EFI_STATUS
976 LoadPeImage (
977 VOID
978 )
979 {
980 EFI_IMAGE_DOS_HEADER *DosHdr;
981 EFI_IMAGE_NT_HEADERS32 *NtHeader32;
982 EFI_IMAGE_NT_HEADERS64 *NtHeader64;
983
984 NtHeader32 = NULL;
985 NtHeader64 = NULL;
986 //
987 // Read the Dos header
988 //
989 DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);
990 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
991 {
992 //
993 // DOS image header is present,
994 // So read the PE header after the DOS image header
995 //
996 mPeCoffHeaderOffset = DosHdr->e_lfanew;
997 }
998 else
999 {
1000 mPeCoffHeaderOffset = 0;
1001 }
1002
1003 //
1004 // Read PE header and check the signature validity and machine compatibility
1005 //
1006 NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);
1007 if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)
1008 {
1009 return EFI_UNSUPPORTED;
1010 }
1011
1012 mNtHeader.Pe32 = NtHeader32;
1013
1014 //
1015 // Check the architecture field of PE header and get the Certificate Data Directory data
1016 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1017 //
1018 if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)
1019 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) {
1020 //
1021 // IA-32 Architecture
1022 //
1023 mImageType = ImageType_IA32;
1024 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
1025 }
1026 else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)
1027 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) {
1028 //
1029 // 64-bits Architecture
1030 //
1031 mImageType = ImageType_X64;
1032 NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);
1033 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
1034 } else {
1035 return EFI_UNSUPPORTED;
1036 }
1037
1038 return EFI_SUCCESS;
1039 }
1040
1041 /**
1042 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1043 PE/COFF Specification 8.0 Appendix A
1044
1045 @param[in] HashAlg Hash algorithm type.
1046
1047 @retval TRUE Successfully hash image.
1048 @retval FALSE Fail in hash image.
1049
1050 **/
1051 BOOLEAN
1052 HashPeImage (
1053 IN UINT32 HashAlg
1054 )
1055 {
1056 BOOLEAN Status;
1057 UINT16 Magic;
1058 EFI_IMAGE_SECTION_HEADER *Section;
1059 VOID *HashCtx;
1060 UINTN CtxSize;
1061 UINT8 *HashBase;
1062 UINTN HashSize;
1063 UINTN SumOfBytesHashed;
1064 EFI_IMAGE_SECTION_HEADER *SectionHeader;
1065 UINTN Index;
1066 UINTN Pos;
1067
1068 HashCtx = NULL;
1069 SectionHeader = NULL;
1070 Status = FALSE;
1071
1072 if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
1073 return FALSE;
1074 }
1075
1076 //
1077 // Initialize context of hash.
1078 //
1079 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
1080
1081 if (HashAlg == HASHALG_SHA1) {
1082 mImageDigestSize = SHA1_DIGEST_SIZE;
1083 mCertType = gEfiCertSha1Guid;
1084 } else if (HashAlg == HASHALG_SHA256) {
1085 mImageDigestSize = SHA256_DIGEST_SIZE;
1086 mCertType = gEfiCertSha256Guid;
1087 }
1088
1089 CtxSize = mHash[HashAlg].GetContextSize();
1090
1091 HashCtx = AllocatePool (CtxSize);
1092 ASSERT (HashCtx != NULL);
1093
1094 // 1. Load the image header into memory.
1095
1096 // 2. Initialize a SHA hash context.
1097 Status = mHash[HashAlg].HashInit(HashCtx);
1098 if (!Status) {
1099 goto Done;
1100 }
1101 //
1102 // Measuring PE/COFF Image Header;
1103 // But CheckSum field and SECURITY data directory (certificate) are excluded
1104 //
1105 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1106 //
1107 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1108 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1109 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1110 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1111 //
1112 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1113 } else {
1114 //
1115 // Get the magic value from the PE/COFF Optional Header
1116 //
1117 Magic = mNtHeader.Pe32->OptionalHeader.Magic;
1118 }
1119
1120 //
1121 // 3. Calculate the distance from the base of the image header to the image checksum address.
1122 // 4. Hash the image header from its base to beginning of the image checksum.
1123 //
1124 HashBase = mImageBase;
1125 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1126 //
1127 // Use PE32 offset.
1128 //
1129 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
1130 } else {
1131 //
1132 // Use PE32+ offset.
1133 //
1134 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
1135 }
1136
1137 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
1138 if (!Status) {
1139 goto Done;
1140 }
1141 //
1142 // 5. Skip over the image checksum (it occupies a single ULONG).
1143 // 6. Get the address of the beginning of the Cert Directory.
1144 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1145 //
1146 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1147 //
1148 // Use PE32 offset.
1149 //
1150 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
1151 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
1152 } else {
1153 //
1154 // Use PE32+ offset.
1155 //
1156 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
1157 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
1158 }
1159
1160 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
1161 if (!Status) {
1162 goto Done;
1163 }
1164 //
1165 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1166 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1167 //
1168 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1169 //
1170 // Use PE32 offset
1171 //
1172 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
1173 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);
1174 } else {
1175 //
1176 // Use PE32+ offset.
1177 //
1178 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
1179 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);
1180 }
1181
1182 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
1183 if (!Status) {
1184 goto Done;
1185 }
1186 //
1187 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1188 //
1189 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1190 //
1191 // Use PE32 offset.
1192 //
1193 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
1194 } else {
1195 //
1196 // Use PE32+ offset
1197 //
1198 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
1199 }
1200
1201 //
1202 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1203 // structures in the image. The 'NumberOfSections' field of the image
1204 // header indicates how big the table should be. Do not include any
1205 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1206 //
1207 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
1208 ASSERT (SectionHeader != NULL);
1209 //
1210 // 12. Using the 'PointerToRawData' in the referenced section headers as
1211 // a key, arrange the elements in the table in ascending order. In other
1212 // words, sort the section headers according to the disk-file offset of
1213 // the section.
1214 //
1215 Section = (EFI_IMAGE_SECTION_HEADER *) (
1216 mImageBase +
1217 mPeCoffHeaderOffset +
1218 sizeof (UINT32) +
1219 sizeof (EFI_IMAGE_FILE_HEADER) +
1220 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
1221 );
1222 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
1223 Pos = Index;
1224 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
1225 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
1226 Pos--;
1227 }
1228 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
1229 Section += 1;
1230 }
1231
1232 //
1233 // 13. Walk through the sorted table, bring the corresponding section
1234 // into memory, and hash the entire section (using the 'SizeOfRawData'
1235 // field in the section header to determine the amount of data to hash).
1236 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1237 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1238 //
1239 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
1240 Section = &SectionHeader[Index];
1241 if (Section->SizeOfRawData == 0) {
1242 continue;
1243 }
1244 HashBase = mImageBase + Section->PointerToRawData;
1245 HashSize = (UINTN) Section->SizeOfRawData;
1246
1247 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
1248 if (!Status) {
1249 goto Done;
1250 }
1251
1252 SumOfBytesHashed += HashSize;
1253 }
1254
1255 //
1256 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1257 // data in the file that needs to be added to the hash. This data begins
1258 // at file offset SUM_OF_BYTES_HASHED and its length is:
1259 // FileSize - (CertDirectory->Size)
1260 //
1261 if (mImageSize > SumOfBytesHashed) {
1262 HashBase = mImageBase + SumOfBytesHashed;
1263 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1264 //
1265 // Use PE32 offset.
1266 //
1267 HashSize = (UINTN)(
1268 mImageSize -
1269 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
1270 SumOfBytesHashed);
1271 } else {
1272 //
1273 // Use PE32+ offset.
1274 //
1275 HashSize = (UINTN)(
1276 mImageSize -
1277 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
1278 SumOfBytesHashed);
1279 }
1280
1281 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
1282 if (!Status) {
1283 goto Done;
1284 }
1285 }
1286
1287 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);
1288
1289 Done:
1290 if (HashCtx != NULL) {
1291 FreePool (HashCtx);
1292 }
1293 if (SectionHeader != NULL) {
1294 FreePool (SectionHeader);
1295 }
1296 return Status;
1297 }
1298
1299 /**
1300 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1301 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1302 8.0 Appendix A
1303
1304 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1305 @retval EFI_SUCCESS Hash successfully.
1306
1307 **/
1308 EFI_STATUS
1309 HashPeImageByType (
1310 VOID
1311 )
1312 {
1313 UINT8 Index;
1314 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
1315
1316 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);
1317
1318 for (Index = 0; Index < HASHALG_MAX; Index++) {
1319 //
1320 // Check the Hash algorithm in PE/COFF Authenticode.
1321 // According to PKCS#7 Definition:
1322 // SignedData ::= SEQUENCE {
1323 // version Version,
1324 // digestAlgorithms DigestAlgorithmIdentifiers,
1325 // contentInfo ContentInfo,
1326 // .... }
1327 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1328 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1329 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1330 //
1331 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
1332 //
1333 // Only support two bytes of Long Form of Length Encoding.
1334 //
1335 continue;
1336 }
1337
1338 //
1339 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
1340 break;
1341 }
1342 }
1343
1344 if (Index == HASHALG_MAX) {
1345 return EFI_UNSUPPORTED;
1346 }
1347
1348 //
1349 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1350 //
1351 if (!HashPeImage(Index)) {
1352 return EFI_UNSUPPORTED;
1353 }
1354
1355 return EFI_SUCCESS;
1356 }
1357
1358 /**
1359 Enroll a new executable's signature into Signature Database.
1360
1361 @param[in] PrivateData The module's private data.
1362 @param[in] VariableName Variable name of signature database, must be
1363 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1364
1365 @retval EFI_SUCCESS New signature is enrolled successfully.
1366 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1367 @retval EFI_UNSUPPORTED Unsupported command.
1368 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1369
1370 **/
1371 EFI_STATUS
1372 EnrollImageSignatureToSigDB (
1373 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
1374 IN CHAR16 *VariableName
1375 )
1376 {
1377 EFI_STATUS Status;
1378 EFI_SIGNATURE_LIST *SigDBCert;
1379 EFI_SIGNATURE_DATA *SigDBCertData;
1380 VOID *Data;
1381 UINTN DataSize;
1382 UINTN SigDBSize;
1383 UINT32 Attr;
1384 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;
1385
1386 Data = NULL;
1387 GuidCertData = NULL;
1388
1389 //
1390 // Form the SigDB certificate list.
1391 // Format the data item into EFI_SIGNATURE_LIST type.
1392 //
1393 // We need to parse executable's signature data from specified signed executable file.
1394 // In current implementation, we simply trust the pass-in signed executable file.
1395 // In reality, it's OS's responsibility to verify the signed executable file.
1396 //
1397
1398 //
1399 // Read the whole file content
1400 //
1401 Status = ReadFileContent(
1402 Private->FileContext->FHandle,
1403 (VOID **) &mImageBase,
1404 &mImageSize,
1405 0
1406 );
1407 if (EFI_ERROR (Status)) {
1408 goto ON_EXIT;
1409 }
1410 ASSERT (mImageBase != NULL);
1411
1412 Status = LoadPeImage ();
1413 if (EFI_ERROR (Status)) {
1414 goto ON_EXIT;
1415 }
1416
1417 if (mSecDataDir->SizeOfCert == 0) {
1418 if (!HashPeImage (HASHALG_SHA256)) {
1419 Status = EFI_SECURITY_VIOLATION;
1420 goto ON_EXIT;
1421 }
1422 } else {
1423
1424 //
1425 // Read the certificate data
1426 //
1427 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);
1428
1429 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
1430 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;
1431 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {
1432 Status = EFI_ABORTED;
1433 goto ON_EXIT;
1434 }
1435
1436 if (!HashPeImage (HASHALG_SHA256)) {
1437 Status = EFI_ABORTED;
1438 goto ON_EXIT;;
1439 }
1440
1441 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
1442
1443 Status = HashPeImageByType ();
1444 if (EFI_ERROR (Status)) {
1445 goto ON_EXIT;;
1446 }
1447 } else {
1448 Status = EFI_ABORTED;
1449 goto ON_EXIT;
1450 }
1451 }
1452
1453 //
1454 // Create a new SigDB entry.
1455 //
1456 SigDBSize = sizeof(EFI_SIGNATURE_LIST)
1457 + sizeof(EFI_SIGNATURE_DATA) - 1
1458 + (UINT32) mImageDigestSize;
1459
1460 Data = (UINT8*) AllocateZeroPool (SigDBSize);
1461 if (Data == NULL) {
1462 Status = EFI_OUT_OF_RESOURCES;
1463 goto ON_EXIT;
1464 }
1465
1466 //
1467 // Adjust the Certificate Database parameters.
1468 //
1469 SigDBCert = (EFI_SIGNATURE_LIST*) Data;
1470 SigDBCert->SignatureListSize = (UINT32) SigDBSize;
1471 SigDBCert->SignatureHeaderSize = 0;
1472 SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;
1473 CopyGuid (&SigDBCert->SignatureType, &mCertType);
1474
1475 SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));
1476 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
1477 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);
1478
1479 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
1480 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1481 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
1482 if (EFI_ERROR (Status)) {
1483 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
1484 goto ON_EXIT;
1485 }
1486
1487 //
1488 // Check if SigDB variable has been already existed.
1489 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1490 // new signature data to original variable
1491 //
1492 DataSize = 0;
1493 Status = gRT->GetVariable(
1494 VariableName,
1495 &gEfiImageSecurityDatabaseGuid,
1496 NULL,
1497 &DataSize,
1498 NULL
1499 );
1500 if (Status == EFI_BUFFER_TOO_SMALL) {
1501 Attr |= EFI_VARIABLE_APPEND_WRITE;
1502 } else if (Status != EFI_NOT_FOUND) {
1503 goto ON_EXIT;
1504 }
1505
1506 //
1507 // Enroll the variable.
1508 //
1509 Status = gRT->SetVariable(
1510 VariableName,
1511 &gEfiImageSecurityDatabaseGuid,
1512 Attr,
1513 SigDBSize,
1514 Data
1515 );
1516 if (EFI_ERROR (Status)) {
1517 goto ON_EXIT;
1518 }
1519
1520 ON_EXIT:
1521
1522 CloseFile (Private->FileContext->FHandle);
1523 Private->FileContext->FHandle = NULL;
1524 Private->FileContext->FileName = NULL;
1525
1526 if (Private->SignatureGUID != NULL) {
1527 FreePool (Private->SignatureGUID);
1528 Private->SignatureGUID = NULL;
1529 }
1530
1531 if (Data != NULL) {
1532 FreePool (Data);
1533 }
1534
1535 if (mImageBase != NULL) {
1536 FreePool (mImageBase);
1537 mImageBase = NULL;
1538 }
1539
1540 return Status;
1541 }
1542
1543 /**
1544 Enroll signature into DB/DBX without KEK's authentication.
1545 The SignatureOwner GUID will be Private->SignatureGUID.
1546
1547 @param[in] PrivateData The module's private data.
1548 @param[in] VariableName Variable name of signature database, must be
1549 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1550
1551 @retval EFI_SUCCESS New signature enrolled successfully.
1552 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1553 @retval others Fail to enroll signature data.
1554
1555 **/
1556 EFI_STATUS
1557 EnrollSignatureDatabase (
1558 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
1559 IN CHAR16 *VariableName
1560 )
1561 {
1562 UINT16* FilePostFix;
1563 EFI_STATUS Status;
1564 UINTN NameLength;
1565
1566 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
1567 return EFI_INVALID_PARAMETER;
1568 }
1569
1570 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
1571 if (EFI_ERROR (Status)) {
1572 return Status;
1573 }
1574
1575 //
1576 // Parse the file's postfix.
1577 //
1578 NameLength = StrLen (Private->FileContext->FileName);
1579 if (NameLength <= 4) {
1580 return EFI_INVALID_PARAMETER;
1581 }
1582 FilePostFix = Private->FileContext->FileName + NameLength - 4;
1583 if (IsDerEncodeCertificate(FilePostFix)) {
1584 //
1585 // Supports DER-encoded X509 certificate.
1586 //
1587 return EnrollX509toSigDB (Private, VariableName);
1588 }
1589
1590 return EnrollImageSignatureToSigDB (Private, VariableName);
1591 }
1592
1593 /**
1594 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1595 by GUID in the page for user to select and delete as needed.
1596
1597 @param[in] PrivateData Module's private data.
1598 @param[in] VariableName The variable name of the vendor's signature database.
1599 @param[in] VendorGuid A unique identifier for the vendor.
1600 @param[in] LabelNumber Label number to insert opcodes.
1601 @param[in] FormId Form ID of current page.
1602 @param[in] QuestionIdBase Base question id of the signature list.
1603
1604 @retval EFI_SUCCESS Success to update the signature list page
1605 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1606
1607 **/
1608 EFI_STATUS
1609 UpdateDeletePage (
1610 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
1611 IN CHAR16 *VariableName,
1612 IN EFI_GUID *VendorGuid,
1613 IN UINT16 LabelNumber,
1614 IN EFI_FORM_ID FormId,
1615 IN EFI_QUESTION_ID QuestionIdBase
1616 )
1617 {
1618 EFI_STATUS Status;
1619 UINT32 Index;
1620 UINTN CertCount;
1621 UINTN GuidIndex;
1622 VOID *StartOpCodeHandle;
1623 VOID *EndOpCodeHandle;
1624 EFI_IFR_GUID_LABEL *StartLabel;
1625 EFI_IFR_GUID_LABEL *EndLabel;
1626 UINTN DataSize;
1627 UINT8 *Data;
1628 EFI_SIGNATURE_LIST *CertList;
1629 EFI_SIGNATURE_DATA *Cert;
1630 UINT32 ItemDataSize;
1631 CHAR16 *GuidStr;
1632 EFI_STRING_ID GuidID;
1633 EFI_STRING_ID Help;
1634
1635 Data = NULL;
1636 CertList = NULL;
1637 Cert = NULL;
1638 GuidStr = NULL;
1639 StartOpCodeHandle = NULL;
1640 EndOpCodeHandle = NULL;
1641
1642 //
1643 // Initialize the container for dynamic opcodes.
1644 //
1645 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1646 if (StartOpCodeHandle == NULL) {
1647 Status = EFI_OUT_OF_RESOURCES;
1648 goto ON_EXIT;
1649 }
1650
1651 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
1652 if (EndOpCodeHandle == NULL) {
1653 Status = EFI_OUT_OF_RESOURCES;
1654 goto ON_EXIT;
1655 }
1656
1657 //
1658 // Create Hii Extend Label OpCode.
1659 //
1660 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1661 StartOpCodeHandle,
1662 &gEfiIfrTianoGuid,
1663 NULL,
1664 sizeof (EFI_IFR_GUID_LABEL)
1665 );
1666 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1667 StartLabel->Number = LabelNumber;
1668
1669 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1670 EndOpCodeHandle,
1671 &gEfiIfrTianoGuid,
1672 NULL,
1673 sizeof (EFI_IFR_GUID_LABEL)
1674 );
1675 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1676 EndLabel->Number = LABEL_END;
1677
1678 //
1679 // Read Variable.
1680 //
1681 DataSize = 0;
1682 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
1683 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
1684 goto ON_EXIT;
1685 }
1686
1687 Data = (UINT8 *) AllocateZeroPool (DataSize);
1688 if (Data == NULL) {
1689 Status = EFI_OUT_OF_RESOURCES;
1690 goto ON_EXIT;
1691 }
1692
1693 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
1694 if (EFI_ERROR (Status)) {
1695 goto ON_EXIT;
1696 }
1697
1698 GuidStr = AllocateZeroPool (100);
1699 if (GuidStr == NULL) {
1700 Status = EFI_OUT_OF_RESOURCES;
1701 goto ON_EXIT;
1702 }
1703
1704 //
1705 // Enumerate all KEK pub data.
1706 //
1707 ItemDataSize = (UINT32) DataSize;
1708 CertList = (EFI_SIGNATURE_LIST *) Data;
1709 GuidIndex = 0;
1710
1711 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
1712
1713 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {
1714 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);
1715 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1716 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);
1717 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {
1718 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);
1719 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {
1720 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);
1721 } else {
1722 //
1723 // The signature type is not supported in current implementation.
1724 //
1725 ItemDataSize -= CertList->SignatureListSize;
1726 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1727 continue;
1728 }
1729
1730 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1731 for (Index = 0; Index < CertCount; Index++) {
1732 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
1733 + sizeof (EFI_SIGNATURE_LIST)
1734 + CertList->SignatureHeaderSize
1735 + Index * CertList->SignatureSize);
1736 //
1737 // Display GUID and help
1738 //
1739 GuidToString (&Cert->SignatureOwner, GuidStr, 100);
1740 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);
1741 HiiCreateCheckBoxOpCode (
1742 StartOpCodeHandle,
1743 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
1744 0,
1745 0,
1746 GuidID,
1747 Help,
1748 EFI_IFR_FLAG_CALLBACK,
1749 0,
1750 NULL
1751 );
1752 }
1753
1754 ItemDataSize -= CertList->SignatureListSize;
1755 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1756 }
1757
1758 ON_EXIT:
1759 HiiUpdateForm (
1760 PrivateData->HiiHandle,
1761 &gSecureBootConfigFormSetGuid,
1762 FormId,
1763 StartOpCodeHandle,
1764 EndOpCodeHandle
1765 );
1766
1767 if (StartOpCodeHandle != NULL) {
1768 HiiFreeOpCodeHandle (StartOpCodeHandle);
1769 }
1770
1771 if (EndOpCodeHandle != NULL) {
1772 HiiFreeOpCodeHandle (EndOpCodeHandle);
1773 }
1774
1775 if (Data != NULL) {
1776 FreePool (Data);
1777 }
1778
1779 if (GuidStr != NULL) {
1780 FreePool (GuidStr);
1781 }
1782
1783 return EFI_SUCCESS;
1784 }
1785
1786 /**
1787 Delete a KEK entry from KEK database.
1788
1789 @param[in] PrivateData Module's private data.
1790 @param[in] QuestionId Question id of the KEK item to delete.
1791
1792 @retval EFI_SUCCESS Delete kek item successfully.
1793 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1794
1795 **/
1796 EFI_STATUS
1797 DeleteKeyExchangeKey (
1798 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
1799 IN EFI_QUESTION_ID QuestionId
1800 )
1801 {
1802 EFI_STATUS Status;
1803 UINTN DataSize;
1804 UINT8 *Data;
1805 UINT8 *OldData;
1806 UINT32 Attr;
1807 UINT32 Index;
1808 EFI_SIGNATURE_LIST *CertList;
1809 EFI_SIGNATURE_LIST *NewCertList;
1810 EFI_SIGNATURE_DATA *Cert;
1811 UINTN CertCount;
1812 UINT32 Offset;
1813 BOOLEAN IsKEKItemFound;
1814 UINT32 KekDataSize;
1815 UINTN DeleteKekIndex;
1816 UINTN GuidIndex;
1817
1818 Data = NULL;
1819 OldData = NULL;
1820 CertList = NULL;
1821 Cert = NULL;
1822 Attr = 0;
1823 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;
1824
1825 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
1826 if (EFI_ERROR (Status)) {
1827 return Status;
1828 }
1829
1830 //
1831 // Get original KEK variable.
1832 //
1833 DataSize = 0;
1834 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);
1835 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
1836 goto ON_EXIT;
1837 }
1838
1839 OldData = (UINT8*)AllocateZeroPool(DataSize);
1840 if (OldData == NULL) {
1841 Status = EFI_OUT_OF_RESOURCES;
1842 goto ON_EXIT;
1843 }
1844
1845 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);
1846 if (EFI_ERROR(Status)) {
1847 goto ON_EXIT;
1848 }
1849
1850 //
1851 // Allocate space for new variable.
1852 //
1853 Data = (UINT8*) AllocateZeroPool (DataSize);
1854 if (Data == NULL) {
1855 Status = EFI_OUT_OF_RESOURCES;
1856 goto ON_EXIT;
1857 }
1858
1859 //
1860 // Enumerate all KEK pub data and erasing the target item.
1861 //
1862 IsKEKItemFound = FALSE;
1863 KekDataSize = (UINT32) DataSize;
1864 CertList = (EFI_SIGNATURE_LIST *) OldData;
1865 Offset = 0;
1866 GuidIndex = 0;
1867 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
1868 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
1869 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1870 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
1871 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);
1872 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1873 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1874 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1875 for (Index = 0; Index < CertCount; Index++) {
1876 if (GuidIndex == DeleteKekIndex ) {
1877 //
1878 // Find it! Skip it!
1879 //
1880 NewCertList->SignatureListSize -= CertList->SignatureSize;
1881 IsKEKItemFound = TRUE;
1882 } else {
1883 //
1884 // This item doesn't match. Copy it to the Data buffer.
1885 //
1886 CopyMem (Data + Offset, Cert, CertList->SignatureSize);
1887 Offset += CertList->SignatureSize;
1888 }
1889 GuidIndex++;
1890 Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);
1891 }
1892 } else {
1893 //
1894 // This List doesn't match. Copy it to the Data buffer.
1895 //
1896 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);
1897 Offset += CertList->SignatureListSize;
1898 }
1899
1900 KekDataSize -= CertList->SignatureListSize;
1901 CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);
1902 }
1903
1904 if (!IsKEKItemFound) {
1905 //
1906 // Doesn't find the Kek Item!
1907 //
1908 Status = EFI_NOT_FOUND;
1909 goto ON_EXIT;
1910 }
1911
1912 //
1913 // Delete the Signature header if there is no signature in the list.
1914 //
1915 KekDataSize = Offset;
1916 CertList = (EFI_SIGNATURE_LIST*) Data;
1917 Offset = 0;
1918 ZeroMem (OldData, KekDataSize);
1919 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
1920 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1921 DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount));
1922 if (CertCount != 0) {
1923 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);
1924 Offset += CertList->SignatureListSize;
1925 }
1926 KekDataSize -= CertList->SignatureListSize;
1927 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1928 }
1929
1930 DataSize = Offset;
1931 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
1932 Status = CreateTimeBasedPayload (&DataSize, &OldData);
1933 if (EFI_ERROR (Status)) {
1934 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
1935 goto ON_EXIT;
1936 }
1937 }
1938
1939 Status = gRT->SetVariable(
1940 EFI_KEY_EXCHANGE_KEY_NAME,
1941 &gEfiGlobalVariableGuid,
1942 Attr,
1943 DataSize,
1944 OldData
1945 );
1946 if (EFI_ERROR (Status)) {
1947 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
1948 goto ON_EXIT;
1949 }
1950
1951 ON_EXIT:
1952 if (Data != NULL) {
1953 FreePool(Data);
1954 }
1955
1956 if (OldData != NULL) {
1957 FreePool(OldData);
1958 }
1959
1960 return UpdateDeletePage (
1961 PrivateData,
1962 EFI_KEY_EXCHANGE_KEY_NAME,
1963 &gEfiGlobalVariableGuid,
1964 LABEL_KEK_DELETE,
1965 FORMID_DELETE_KEK_FORM,
1966 OPTION_DEL_KEK_QUESTION_ID
1967 );
1968 }
1969
1970 /**
1971 Delete a signature entry from siganture database.
1972
1973 @param[in] PrivateData Module's private data.
1974 @param[in] VariableName The variable name of the vendor's signature database.
1975 @param[in] VendorGuid A unique identifier for the vendor.
1976 @param[in] LabelNumber Label number to insert opcodes.
1977 @param[in] FormId Form ID of current page.
1978 @param[in] QuestionIdBase Base question id of the signature list.
1979 @param[in] DeleteIndex Signature index to delete.
1980
1981 @retval EFI_SUCCESS Delete siganture successfully.
1982 @retval EFI_NOT_FOUND Can't find the signature item,
1983 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1984 **/
1985 EFI_STATUS
1986 DeleteSignature (
1987 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
1988 IN CHAR16 *VariableName,
1989 IN EFI_GUID *VendorGuid,
1990 IN UINT16 LabelNumber,
1991 IN EFI_FORM_ID FormId,
1992 IN EFI_QUESTION_ID QuestionIdBase,
1993 IN UINTN DeleteIndex
1994 )
1995 {
1996 EFI_STATUS Status;
1997 UINTN DataSize;
1998 UINT8 *Data;
1999 UINT8 *OldData;
2000 UINT32 Attr;
2001 UINT32 Index;
2002 EFI_SIGNATURE_LIST *CertList;
2003 EFI_SIGNATURE_LIST *NewCertList;
2004 EFI_SIGNATURE_DATA *Cert;
2005 UINTN CertCount;
2006 UINT32 Offset;
2007 BOOLEAN IsItemFound;
2008 UINT32 ItemDataSize;
2009 UINTN GuidIndex;
2010
2011 Data = NULL;
2012 OldData = NULL;
2013 CertList = NULL;
2014 Cert = NULL;
2015 Attr = 0;
2016
2017 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
2018 if (EFI_ERROR (Status)) {
2019 return Status;
2020 }
2021
2022 //
2023 // Get original signature list data.
2024 //
2025 DataSize = 0;
2026 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
2027 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
2028 goto ON_EXIT;
2029 }
2030
2031 OldData = (UINT8 *) AllocateZeroPool (DataSize);
2032 if (OldData == NULL) {
2033 Status = EFI_OUT_OF_RESOURCES;
2034 goto ON_EXIT;
2035 }
2036
2037 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
2038 if (EFI_ERROR(Status)) {
2039 goto ON_EXIT;
2040 }
2041
2042 //
2043 // Allocate space for new variable.
2044 //
2045 Data = (UINT8*) AllocateZeroPool (DataSize);
2046 if (Data == NULL) {
2047 Status = EFI_OUT_OF_RESOURCES;
2048 goto ON_EXIT;
2049 }
2050
2051 //
2052 // Enumerate all signature data and erasing the target item.
2053 //
2054 IsItemFound = FALSE;
2055 ItemDataSize = (UINT32) DataSize;
2056 CertList = (EFI_SIGNATURE_LIST *) OldData;
2057 Offset = 0;
2058 GuidIndex = 0;
2059 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
2060 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
2061 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||
2062 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||
2063 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)
2064 ) {
2065 //
2066 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2067 //
2068 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
2069 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
2070 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2071 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2072 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2073 for (Index = 0; Index < CertCount; Index++) {
2074 if (GuidIndex == DeleteIndex) {
2075 //
2076 // Find it! Skip it!
2077 //
2078 NewCertList->SignatureListSize -= CertList->SignatureSize;
2079 IsItemFound = TRUE;
2080 } else {
2081 //
2082 // This item doesn't match. Copy it to the Data buffer.
2083 //
2084 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
2085 Offset += CertList->SignatureSize;
2086 }
2087 GuidIndex++;
2088 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
2089 }
2090 } else {
2091 //
2092 // This List doesn't match. Just copy it to the Data buffer.
2093 //
2094 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
2095 Offset += CertList->SignatureListSize;
2096 }
2097
2098 ItemDataSize -= CertList->SignatureListSize;
2099 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
2100 }
2101
2102 if (!IsItemFound) {
2103 //
2104 // Doesn't find the signature Item!
2105 //
2106 Status = EFI_NOT_FOUND;
2107 goto ON_EXIT;
2108 }
2109
2110 //
2111 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2112 //
2113 ItemDataSize = Offset;
2114 CertList = (EFI_SIGNATURE_LIST *) Data;
2115 Offset = 0;
2116 ZeroMem (OldData, ItemDataSize);
2117 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
2118 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2119 DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount));
2120 if (CertCount != 0) {
2121 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
2122 Offset += CertList->SignatureListSize;
2123 }
2124 ItemDataSize -= CertList->SignatureListSize;
2125 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
2126 }
2127
2128 DataSize = Offset;
2129 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
2130 Status = CreateTimeBasedPayload (&DataSize, &OldData);
2131 if (EFI_ERROR (Status)) {
2132 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
2133 goto ON_EXIT;
2134 }
2135 }
2136
2137 Status = gRT->SetVariable(
2138 VariableName,
2139 VendorGuid,
2140 Attr,
2141 DataSize,
2142 OldData
2143 );
2144 if (EFI_ERROR (Status)) {
2145 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
2146 goto ON_EXIT;
2147 }
2148
2149 ON_EXIT:
2150 if (Data != NULL) {
2151 FreePool(Data);
2152 }
2153
2154 if (OldData != NULL) {
2155 FreePool(OldData);
2156 }
2157
2158 return UpdateDeletePage (
2159 PrivateData,
2160 VariableName,
2161 VendorGuid,
2162 LabelNumber,
2163 FormId,
2164 QuestionIdBase
2165 );
2166 }
2167
2168 /**
2169 This function extracts configuration from variable.
2170
2171 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2172
2173 **/
2174 VOID
2175 SecureBootExtractConfigFromVariable (
2176 IN OUT SECUREBOOT_CONFIGURATION *ConfigData
2177 )
2178 {
2179 UINT8 *SecureBootEnable;
2180 UINT8 *SetupMode;
2181 UINT8 *SecureBootMode;
2182
2183 SecureBootEnable = NULL;
2184 SetupMode = NULL;
2185 SecureBootMode = NULL;
2186
2187 //
2188 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2189 // Checkbox.
2190 //
2191 ConfigData->AttemptSecureBoot = FALSE;
2192 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
2193 if (SecureBootEnable == NULL) {
2194 ConfigData->HideSecureBoot = TRUE;
2195 } else {
2196 ConfigData->HideSecureBoot = FALSE;
2197 if ((*SecureBootEnable) == SECURE_BOOT_ENABLE) {
2198 ConfigData->AttemptSecureBoot = TRUE;
2199 }
2200 }
2201
2202 //
2203 // If it is Physical Presence User, set the PhysicalPresent to true.
2204 //
2205 if (UserPhysicalPresent()) {
2206 ConfigData->PhysicalPresent = TRUE;
2207 } else {
2208 ConfigData->PhysicalPresent = FALSE;
2209 }
2210
2211 //
2212 // If there is no PK then the Delete Pk button will be gray.
2213 //
2214 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
2215 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
2216 ConfigData->HasPk = FALSE;
2217 } else {
2218 ConfigData->HasPk = TRUE;
2219 }
2220
2221 //
2222 // Get the SecureBootMode from CustomMode variable.
2223 //
2224 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
2225 if (SecureBootMode == NULL) {
2226 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
2227 } else {
2228 ConfigData->SecureBootMode = *(SecureBootMode);
2229 }
2230
2231 if (SecureBootEnable != NULL) {
2232 FreePool (SecureBootEnable);
2233 }
2234 if (SetupMode != NULL) {
2235 FreePool (SetupMode);
2236 }
2237 if (SecureBootMode != NULL) {
2238 FreePool (SecureBootMode);
2239 }
2240 }
2241
2242 /**
2243 This function allows a caller to extract the current configuration for one
2244 or more named elements from the target driver.
2245
2246 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2247 @param[in] Request A null-terminated Unicode string in
2248 <ConfigRequest> format.
2249 @param[out] Progress On return, points to a character in the Request
2250 string. Points to the string's null terminator if
2251 request was successful. Points to the most recent
2252 '&' before the first failing name/value pair (or
2253 the beginning of the string if the failure is in
2254 the first name/value pair) if the request was not
2255 successful.
2256 @param[out] Results A null-terminated Unicode string in
2257 <ConfigAltResp> format which has all values filled
2258 in for the names in the Request string. String to
2259 be allocated by the called function.
2260
2261 @retval EFI_SUCCESS The Results is filled with the requested values.
2262 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2263 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2264 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2265 driver.
2266
2267 **/
2268 EFI_STATUS
2269 EFIAPI
2270 SecureBootExtractConfig (
2271 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2272 IN CONST EFI_STRING Request,
2273 OUT EFI_STRING *Progress,
2274 OUT EFI_STRING *Results
2275 )
2276 {
2277 EFI_STATUS Status;
2278 UINTN BufferSize;
2279 UINTN Size;
2280 SECUREBOOT_CONFIGURATION Configuration;
2281 EFI_STRING ConfigRequest;
2282 EFI_STRING ConfigRequestHdr;
2283 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
2284 BOOLEAN AllocatedRequest;
2285 UINT8 *SecureBoot;
2286
2287 if (Progress == NULL || Results == NULL) {
2288 return EFI_INVALID_PARAMETER;
2289 }
2290
2291 AllocatedRequest = FALSE;
2292 ConfigRequestHdr = NULL;
2293 ConfigRequest = NULL;
2294 Size = 0;
2295 SecureBoot = NULL;
2296
2297 ZeroMem (&Configuration, sizeof (Configuration));
2298 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
2299 *Progress = Request;
2300
2301 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
2302 return EFI_NOT_FOUND;
2303 }
2304
2305 //
2306 // Get Configuration from Variable.
2307 //
2308 SecureBootExtractConfigFromVariable (&Configuration);
2309
2310 //
2311 // Update current secure boot state.
2312 //
2313 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);
2314 if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {
2315 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);
2316 } else {
2317 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);
2318 }
2319 if (SecureBoot != NULL) {
2320 FreePool (SecureBoot);
2321 }
2322
2323 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
2324 ConfigRequest = Request;
2325 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
2326 //
2327 // Request is set to NULL or OFFSET is NULL, construct full request string.
2328 //
2329 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2330 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2331 //
2332 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);
2333 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
2334 ConfigRequest = AllocateZeroPool (Size);
2335 ASSERT (ConfigRequest != NULL);
2336 AllocatedRequest = TRUE;
2337 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
2338 FreePool (ConfigRequestHdr);
2339 ConfigRequestHdr = NULL;
2340 }
2341
2342 Status = gHiiConfigRouting->BlockToConfig (
2343 gHiiConfigRouting,
2344 ConfigRequest,
2345 (UINT8 *) &Configuration,
2346 BufferSize,
2347 Results,
2348 Progress
2349 );
2350
2351 //
2352 // Free the allocated config request string.
2353 //
2354 if (AllocatedRequest) {
2355 FreePool (ConfigRequest);
2356 }
2357
2358 //
2359 // Set Progress string to the original request string.
2360 //
2361 if (Request == NULL) {
2362 *Progress = NULL;
2363 } else if (StrStr (Request, L"OFFSET") == NULL) {
2364 *Progress = Request + StrLen (Request);
2365 }
2366
2367 return Status;
2368 }
2369
2370 /**
2371 This function processes the results of changes in configuration.
2372
2373 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2374 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2375 format.
2376 @param[out] Progress A pointer to a string filled in with the offset of
2377 the most recent '&' before the first failing
2378 name/value pair (or the beginning of the string if
2379 the failure is in the first name/value pair) or
2380 the terminating NULL if all was successful.
2381
2382 @retval EFI_SUCCESS The Results is processed successfully.
2383 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2384 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2385 driver.
2386
2387 **/
2388 EFI_STATUS
2389 EFIAPI
2390 SecureBootRouteConfig (
2391 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2392 IN CONST EFI_STRING Configuration,
2393 OUT EFI_STRING *Progress
2394 )
2395 {
2396 UINT8 *SecureBootEnable;
2397 SECUREBOOT_CONFIGURATION IfrNvData;
2398 UINTN BufferSize;
2399 EFI_STATUS Status;
2400
2401 if (Configuration == NULL || Progress == NULL) {
2402 return EFI_INVALID_PARAMETER;
2403 }
2404
2405 *Progress = Configuration;
2406 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
2407 return EFI_NOT_FOUND;
2408 }
2409
2410 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
2411 Status = gHiiConfigRouting->ConfigToBlock (
2412 gHiiConfigRouting,
2413 Configuration,
2414 (UINT8 *)&IfrNvData,
2415 &BufferSize,
2416 Progress
2417 );
2418 if (EFI_ERROR (Status)) {
2419 return Status;
2420 }
2421
2422 //
2423 // Store Buffer Storage back to EFI variable if needed
2424 //
2425 SecureBootEnable = NULL;
2426 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
2427 if (NULL != SecureBootEnable) {
2428 FreePool (SecureBootEnable);
2429 Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);
2430 if (EFI_ERROR (Status)) {
2431 return Status;
2432 }
2433 }
2434
2435 *Progress = Configuration + StrLen (Configuration);
2436 return EFI_SUCCESS;
2437 }
2438
2439 /**
2440 This function is called to provide results data to the driver.
2441
2442 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2443 @param[in] Action Specifies the type of action taken by the browser.
2444 @param[in] QuestionId A unique value which is sent to the original
2445 exporting driver so that it can identify the type
2446 of data to expect.
2447 @param[in] Type The type of value for the question.
2448 @param[in] Value A pointer to the data being sent to the original
2449 exporting driver.
2450 @param[out] ActionRequest On return, points to the action requested by the
2451 callback function.
2452
2453 @retval EFI_SUCCESS The callback successfully handled the action.
2454 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2455 variable and its data.
2456 @retval EFI_DEVICE_ERROR The variable could not be saved.
2457 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2458 callback.
2459
2460 **/
2461 EFI_STATUS
2462 EFIAPI
2463 SecureBootCallback (
2464 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2465 IN EFI_BROWSER_ACTION Action,
2466 IN EFI_QUESTION_ID QuestionId,
2467 IN UINT8 Type,
2468 IN EFI_IFR_TYPE_VALUE *Value,
2469 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
2470 )
2471 {
2472 EFI_INPUT_KEY Key;
2473 EFI_STATUS Status;
2474 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;
2475 UINTN BufferSize;
2476 SECUREBOOT_CONFIGURATION *IfrNvData;
2477 UINT16 LabelId;
2478 UINT8 *SecureBootEnable;
2479 UINT8 *SecureBootMode;
2480 UINT8 *SetupMode;
2481 CHAR16 PromptString[100];
2482
2483 SecureBootEnable = NULL;
2484 SecureBootMode = NULL;
2485 SetupMode = NULL;
2486
2487 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
2488 return EFI_INVALID_PARAMETER;
2489 }
2490
2491 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
2492 (Action != EFI_BROWSER_ACTION_CHANGING) &&
2493 (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&
2494 (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {
2495 return EFI_UNSUPPORTED;
2496 }
2497
2498 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
2499
2500 //
2501 // Retrieve uncommitted data from Browser
2502 //
2503 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
2504 IfrNvData = AllocateZeroPool (BufferSize);
2505 if (IfrNvData == NULL) {
2506 return EFI_OUT_OF_RESOURCES;
2507 }
2508
2509 Status = EFI_SUCCESS;
2510
2511 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
2512
2513 if (Action == EFI_BROWSER_ACTION_CHANGING) {
2514
2515 switch (QuestionId) {
2516 case KEY_SECURE_BOOT_ENABLE:
2517 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
2518 if (NULL != SecureBootEnable) {
2519 FreePool (SecureBootEnable);
2520 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {
2521 CreatePopUp (
2522 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2523 &Key,
2524 L"Only Physical Presence User could disable secure boot!",
2525 NULL
2526 );
2527 Status = EFI_UNSUPPORTED;
2528 } else {
2529 CreatePopUp (
2530 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2531 &Key,
2532 L"Configuration changed, please reset the platform to take effect!",
2533 NULL
2534 );
2535 }
2536 }
2537 break;
2538
2539 case KEY_SECURE_BOOT_OPTION:
2540 FreeMenu (&DirectoryMenu);
2541 FreeMenu (&FsOptionMenu);
2542 break;
2543
2544 case KEY_SECURE_BOOT_KEK_OPTION:
2545 case KEY_SECURE_BOOT_DB_OPTION:
2546 case KEY_SECURE_BOOT_DBX_OPTION:
2547 //
2548 // Clear Signature GUID.
2549 //
2550 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));
2551 if (Private->SignatureGUID == NULL) {
2552 Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
2553 if (Private->SignatureGUID == NULL) {
2554 return EFI_OUT_OF_RESOURCES;
2555 }
2556 }
2557
2558 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {
2559 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
2560 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {
2561 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
2562 } else {
2563 LabelId = FORMID_ENROLL_KEK_FORM;
2564 }
2565
2566 //
2567 // Refresh selected file.
2568 //
2569 CleanUpPage (LabelId, Private);
2570 break;
2571
2572 case SECUREBOOT_ADD_PK_FILE_FORM_ID:
2573 case FORMID_ENROLL_KEK_FORM:
2574 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:
2575 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:
2576 if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {
2577 Private->FeCurrentState = FileExplorerStateEnrollPkFile;
2578 } else if (QuestionId == FORMID_ENROLL_KEK_FORM) {
2579 Private->FeCurrentState = FileExplorerStateEnrollKekFile;
2580 } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {
2581 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;
2582 } else {
2583 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;
2584 }
2585
2586 Private->FeDisplayContext = FileExplorerDisplayUnknown;
2587 CleanUpPage (FORM_FILE_EXPLORER_ID, Private);
2588 UpdateFileExplorer (Private, 0);
2589 break;
2590
2591 case KEY_SECURE_BOOT_DELETE_PK:
2592 if (Value->u8) {
2593 CreatePopUp (
2594 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2595 &Key,
2596 L"Are you sure you want to delete PK? Secure boot will be disabled!",
2597 L"Press 'Y' to delete PK and exit, 'N' to discard change and return",
2598 NULL
2599 );
2600 if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
2601 Status = DeletePlatformKey ();
2602 if (EFI_ERROR (Status)) {
2603 CreatePopUp (
2604 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2605 &Key,
2606 L"Only Physical Presence User could delete PK in custom mode!",
2607 NULL
2608 );
2609 }
2610 }
2611 }
2612 break;
2613
2614 case KEY_DELETE_KEK:
2615 UpdateDeletePage (
2616 Private,
2617 EFI_KEY_EXCHANGE_KEY_NAME,
2618 &gEfiGlobalVariableGuid,
2619 LABEL_KEK_DELETE,
2620 FORMID_DELETE_KEK_FORM,
2621 OPTION_DEL_KEK_QUESTION_ID
2622 );
2623 break;
2624
2625 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:
2626 UpdateDeletePage (
2627 Private,
2628 EFI_IMAGE_SECURITY_DATABASE,
2629 &gEfiImageSecurityDatabaseGuid,
2630 LABEL_DB_DELETE,
2631 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
2632 OPTION_DEL_DB_QUESTION_ID
2633 );
2634 break;
2635
2636 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:
2637 UpdateDeletePage (
2638 Private,
2639 EFI_IMAGE_SECURITY_DATABASE1,
2640 &gEfiImageSecurityDatabaseGuid,
2641 LABEL_DBX_DELETE,
2642 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,
2643 OPTION_DEL_DBX_QUESTION_ID
2644 );
2645
2646 break;
2647
2648 case KEY_VALUE_SAVE_AND_EXIT_KEK:
2649 Status = EnrollKeyExchangeKey (Private);
2650 if (EFI_ERROR (Status)) {
2651 CreatePopUp (
2652 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2653 &Key,
2654 L"ERROR: Unsupported file type!",
2655 L"Only supports DER-encoded X509 certificate",
2656 NULL
2657 );
2658 }
2659 break;
2660
2661 case KEY_VALUE_SAVE_AND_EXIT_DB:
2662 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);
2663 if (EFI_ERROR (Status)) {
2664 CreatePopUp (
2665 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2666 &Key,
2667 L"ERROR: Unsupported file type!",
2668 L"Only supports DER-encoded X509 certificate and executable EFI image",
2669 NULL
2670 );
2671 }
2672 break;
2673
2674 case KEY_VALUE_SAVE_AND_EXIT_DBX:
2675 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);
2676 if (EFI_ERROR (Status)) {
2677 CreatePopUp (
2678 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2679 &Key,
2680 L"ERROR: Unsupported file type!",
2681 L"Only supports DER-encoded X509 certificate and executable EFI image",
2682 NULL
2683 );
2684 }
2685 break;
2686
2687 default:
2688 if (QuestionId >= FILE_OPTION_OFFSET) {
2689 UpdateFileExplorer (Private, QuestionId);
2690 } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&
2691 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {
2692 DeleteKeyExchangeKey (Private, QuestionId);
2693 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&
2694 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {
2695 DeleteSignature (
2696 Private,
2697 EFI_IMAGE_SECURITY_DATABASE,
2698 &gEfiImageSecurityDatabaseGuid,
2699 LABEL_DB_DELETE,
2700 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
2701 OPTION_DEL_DB_QUESTION_ID,
2702 QuestionId - OPTION_DEL_DB_QUESTION_ID
2703 );
2704 } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&
2705 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {
2706 DeleteSignature (
2707 Private,
2708 EFI_IMAGE_SECURITY_DATABASE1,
2709 &gEfiImageSecurityDatabaseGuid,
2710 LABEL_DBX_DELETE,
2711 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,
2712 OPTION_DEL_DBX_QUESTION_ID,
2713 QuestionId - OPTION_DEL_DBX_QUESTION_ID
2714 );
2715 }
2716 break;
2717 }
2718 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
2719 switch (QuestionId) {
2720 case KEY_SECURE_BOOT_ENABLE:
2721 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2722 break;
2723 case KEY_VALUE_SAVE_AND_EXIT_PK:
2724 Status = EnrollPlatformKey (Private);
2725 if (EFI_ERROR (Status)) {
2726 UnicodeSPrint (
2727 PromptString,
2728 sizeof (PromptString),
2729 L"Only DER encoded certificate file (%s) is supported.",
2730 mSupportX509Suffix
2731 );
2732 CreatePopUp (
2733 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2734 &Key,
2735 L"ERROR: Unsupported file type!",
2736 PromptString,
2737 NULL
2738 );
2739 } else {
2740 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
2741 }
2742 break;
2743
2744 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:
2745 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:
2746 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:
2747 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:
2748 if (Private->FileContext->FHandle != NULL) {
2749 CloseFile (Private->FileContext->FHandle);
2750 Private->FileContext->FHandle = NULL;
2751 Private->FileContext->FileName = NULL;
2752 }
2753
2754 if (Private->SignatureGUID != NULL) {
2755 FreePool (Private->SignatureGUID);
2756 Private->SignatureGUID = NULL;
2757 }
2758 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
2759 break;
2760
2761 case KEY_SECURE_BOOT_MODE:
2762 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
2763 if (NULL != SecureBootMode) {
2764 Status = gRT->SetVariable (
2765 EFI_CUSTOM_MODE_NAME,
2766 &gEfiCustomModeEnableGuid,
2767 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
2768 sizeof (UINT8),
2769 &Value->u8
2770 );
2771 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2772 IfrNvData->SecureBootMode = Value->u8;
2773 FreePool (SecureBootMode);
2774 }
2775 break;
2776
2777 case KEY_SECURE_BOOT_KEK_GUID:
2778 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:
2779 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:
2780 ASSERT (Private->SignatureGUID != NULL);
2781 Status = StringToGuid (
2782 IfrNvData->SignatureGuid,
2783 StrLen (IfrNvData->SignatureGuid),
2784 Private->SignatureGUID
2785 );
2786 if (EFI_ERROR (Status)) {
2787 break;
2788 }
2789
2790 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2791 break;
2792
2793 case KEY_SECURE_BOOT_DELETE_PK:
2794 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
2795 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
2796 IfrNvData->DeletePk = TRUE;
2797 IfrNvData->HasPk = FALSE;
2798 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
2799 } else {
2800 IfrNvData->DeletePk = FALSE;
2801 IfrNvData->HasPk = TRUE;
2802 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2803 }
2804 if (SetupMode != NULL) {
2805 FreePool (SetupMode);
2806 }
2807 break;
2808 }
2809 } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {
2810 if (QuestionId == KEY_HIDE_SECURE_BOOT) {
2811 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
2812 if (SecureBootEnable == NULL) {
2813 IfrNvData->HideSecureBoot = TRUE;
2814 } else {
2815 FreePool (SecureBootEnable);
2816 IfrNvData->HideSecureBoot = FALSE;
2817 }
2818 Value->b = IfrNvData->HideSecureBoot;
2819 }
2820 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
2821 //
2822 // Force the platform back to Standard Mode once user leave the setup screen.
2823 //
2824 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
2825 if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {
2826 IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
2827 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);
2828 }
2829 if (SecureBootMode != NULL) {
2830 FreePool (SecureBootMode);
2831 }
2832 }
2833
2834 if (!EFI_ERROR (Status)) {
2835 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
2836 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8*) IfrNvData, NULL);
2837 }
2838 FreePool (IfrNvData);
2839
2840 return EFI_SUCCESS;
2841 }
2842
2843 /**
2844 This function publish the SecureBoot configuration Form.
2845
2846 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2847
2848 @retval EFI_SUCCESS HII Form is installed successfully.
2849 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2850 @retval Others Other errors as indicated.
2851
2852 **/
2853 EFI_STATUS
2854 InstallSecureBootConfigForm (
2855 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
2856 )
2857 {
2858 EFI_STATUS Status;
2859 EFI_HII_HANDLE HiiHandle;
2860 EFI_HANDLE DriverHandle;
2861 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2862
2863 DriverHandle = NULL;
2864 ConfigAccess = &PrivateData->ConfigAccess;
2865 Status = gBS->InstallMultipleProtocolInterfaces (
2866 &DriverHandle,
2867 &gEfiDevicePathProtocolGuid,
2868 &mSecureBootHiiVendorDevicePath,
2869 &gEfiHiiConfigAccessProtocolGuid,
2870 ConfigAccess,
2871 NULL
2872 );
2873 if (EFI_ERROR (Status)) {
2874 return Status;
2875 }
2876
2877 PrivateData->DriverHandle = DriverHandle;
2878
2879 //
2880 // Publish the HII package list
2881 //
2882 HiiHandle = HiiAddPackages (
2883 &gSecureBootConfigFormSetGuid,
2884 DriverHandle,
2885 SecureBootConfigDxeStrings,
2886 SecureBootConfigBin,
2887 NULL
2888 );
2889 if (HiiHandle == NULL) {
2890 gBS->UninstallMultipleProtocolInterfaces (
2891 DriverHandle,
2892 &gEfiDevicePathProtocolGuid,
2893 &mSecureBootHiiVendorDevicePath,
2894 &gEfiHiiConfigAccessProtocolGuid,
2895 ConfigAccess,
2896 NULL
2897 );
2898 return EFI_OUT_OF_RESOURCES;
2899 }
2900
2901 PrivateData->HiiHandle = HiiHandle;
2902
2903 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));
2904 PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));
2905
2906 if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) {
2907 UninstallSecureBootConfigForm (PrivateData);
2908 return EFI_OUT_OF_RESOURCES;
2909 }
2910
2911 PrivateData->FeCurrentState = FileExplorerStateInActive;
2912 PrivateData->FeDisplayContext = FileExplorerDisplayUnknown;
2913
2914 InitializeListHead (&FsOptionMenu.Head);
2915 InitializeListHead (&DirectoryMenu.Head);
2916
2917 //
2918 // Init OpCode Handle and Allocate space for creation of Buffer
2919 //
2920 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
2921 if (mStartOpCodeHandle == NULL) {
2922 UninstallSecureBootConfigForm (PrivateData);
2923 return EFI_OUT_OF_RESOURCES;
2924 }
2925
2926 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
2927 if (mEndOpCodeHandle == NULL) {
2928 UninstallSecureBootConfigForm (PrivateData);
2929 return EFI_OUT_OF_RESOURCES;
2930 }
2931
2932 //
2933 // Create Hii Extend Label OpCode as the start opcode
2934 //
2935 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2936 mStartOpCodeHandle,
2937 &gEfiIfrTianoGuid,
2938 NULL,
2939 sizeof (EFI_IFR_GUID_LABEL)
2940 );
2941 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2942
2943 //
2944 // Create Hii Extend Label OpCode as the end opcode
2945 //
2946 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2947 mEndOpCodeHandle,
2948 &gEfiIfrTianoGuid,
2949 NULL,
2950 sizeof (EFI_IFR_GUID_LABEL)
2951 );
2952 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2953 mEndLabel->Number = LABEL_END;
2954
2955 return EFI_SUCCESS;
2956 }
2957
2958 /**
2959 This function removes SecureBoot configuration Form.
2960
2961 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2962
2963 **/
2964 VOID
2965 UninstallSecureBootConfigForm (
2966 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
2967 )
2968 {
2969 //
2970 // Uninstall HII package list
2971 //
2972 if (PrivateData->HiiHandle != NULL) {
2973 HiiRemovePackages (PrivateData->HiiHandle);
2974 PrivateData->HiiHandle = NULL;
2975 }
2976
2977 //
2978 // Uninstall HII Config Access Protocol
2979 //
2980 if (PrivateData->DriverHandle != NULL) {
2981 gBS->UninstallMultipleProtocolInterfaces (
2982 PrivateData->DriverHandle,
2983 &gEfiDevicePathProtocolGuid,
2984 &mSecureBootHiiVendorDevicePath,
2985 &gEfiHiiConfigAccessProtocolGuid,
2986 &PrivateData->ConfigAccess,
2987 NULL
2988 );
2989 PrivateData->DriverHandle = NULL;
2990 }
2991
2992 if (PrivateData->SignatureGUID != NULL) {
2993 FreePool (PrivateData->SignatureGUID);
2994 }
2995
2996 if (PrivateData->MenuEntry != NULL) {
2997 FreePool (PrivateData->MenuEntry);
2998 }
2999
3000 if (PrivateData->FileContext != NULL) {
3001 FreePool (PrivateData->FileContext);
3002 }
3003
3004 FreePool (PrivateData);
3005
3006 FreeMenu (&DirectoryMenu);
3007 FreeMenu (&FsOptionMenu);
3008
3009 if (mStartOpCodeHandle != NULL) {
3010 HiiFreeOpCodeHandle (mStartOpCodeHandle);
3011 }
3012
3013 if (mEndOpCodeHandle != NULL) {
3014 HiiFreeOpCodeHandle (mEndOpCodeHandle);
3015 }
3016 }