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