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