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