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