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