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