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