]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
PcAtChipsetPkg: Clean up source files
[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
c035e373 4Copyright (c) 2011 - 2017, 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
5e9dfc67
LG
1819 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in \r
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
1834 UINT16 Magic;\r
1835 EFI_IMAGE_SECTION_HEADER *Section;\r
1836 VOID *HashCtx;\r
1837 UINTN CtxSize;\r
1838 UINT8 *HashBase;\r
1839 UINTN HashSize;\r
1840 UINTN SumOfBytesHashed;\r
1841 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1842 UINTN Index;\r
1843 UINTN Pos;\r
1844\r
1845 HashCtx = NULL;\r
1846 SectionHeader = NULL;\r
1847 Status = FALSE;\r
1848\r
c035e373 1849 if (HashAlg != HASHALG_SHA256) {\r
ecc722ad 1850 return FALSE;\r
1851 }\r
20333c6d 1852\r
ecc722ad 1853 //\r
1854 // Initialize context of hash.\r
1855 //\r
1856 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
1857\r
c035e373
ZL
1858 mImageDigestSize = SHA256_DIGEST_SIZE;\r
1859 mCertType = gEfiCertSha256Guid;\r
ecc722ad 1860\r
1861 CtxSize = mHash[HashAlg].GetContextSize();\r
20333c6d 1862\r
ecc722ad 1863 HashCtx = AllocatePool (CtxSize);\r
1864 ASSERT (HashCtx != NULL);\r
1865\r
1866 // 1. Load the image header into memory.\r
1867\r
1868 // 2. Initialize a SHA hash context.\r
1869 Status = mHash[HashAlg].HashInit(HashCtx);\r
1870 if (!Status) {\r
1871 goto Done;\r
1872 }\r
1873 //\r
1874 // Measuring PE/COFF Image Header;\r
1875 // But CheckSum field and SECURITY data directory (certificate) are excluded\r
1876 //\r
de2447dd 1877 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1878 //\r
20333c6d
QL
1879 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
1880 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
de2447dd 1881 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1882 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1883 //\r
1884 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
1885 } else {\r
1886 //\r
1887 // Get the magic value from the PE/COFF Optional Header\r
1888 //\r
1889 Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
1890 }\r
20333c6d 1891\r
ecc722ad 1892 //\r
1893 // 3. Calculate the distance from the base of the image header to the image checksum address.\r
1894 // 4. Hash the image header from its base to beginning of the image checksum.\r
1895 //\r
1896 HashBase = mImageBase;\r
1897 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1898 //\r
1899 // Use PE32 offset.\r
1900 //\r
4333b99d 1901 HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
ecc722ad 1902 } else {\r
1903 //\r
1904 // Use PE32+ offset.\r
1905 //\r
4333b99d 1906 HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
ecc722ad 1907 }\r
1908\r
1909 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1910 if (!Status) {\r
1911 goto Done;\r
1912 }\r
1913 //\r
1914 // 5. Skip over the image checksum (it occupies a single ULONG).\r
1915 // 6. Get the address of the beginning of the Cert Directory.\r
1916 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
1917 //\r
1918 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1919 //\r
1920 // Use PE32 offset.\r
1921 //\r
1922 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
4333b99d 1923 HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
ecc722ad 1924 } else {\r
1925 //\r
1926 // Use PE32+ offset.\r
20333c6d 1927 //\r
ecc722ad 1928 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
4333b99d 1929 HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
ecc722ad 1930 }\r
1931\r
1932 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1933 if (!Status) {\r
1934 goto Done;\r
1935 }\r
1936 //\r
1937 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
1938 // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
1939 //\r
1940 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1941 //\r
1942 // Use PE32 offset\r
1943 //\r
1944 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
4333b99d 1945 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase);\r
ecc722ad 1946 } else {\r
1947 //\r
1948 // Use PE32+ offset.\r
1949 //\r
1950 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
4333b99d 1951 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase);\r
ecc722ad 1952 }\r
1953\r
1954 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1955 if (!Status) {\r
1956 goto Done;\r
1957 }\r
1958 //\r
1959 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
1960 //\r
1961 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1962 //\r
1963 // Use PE32 offset.\r
1964 //\r
1965 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
1966 } else {\r
1967 //\r
1968 // Use PE32+ offset\r
1969 //\r
1970 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
1971 }\r
1972\r
1973 //\r
1974 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
1975 // structures in the image. The 'NumberOfSections' field of the image\r
1976 // header indicates how big the table should be. Do not include any\r
1977 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
1978 //\r
1979 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
1980 ASSERT (SectionHeader != NULL);\r
1981 //\r
1982 // 12. Using the 'PointerToRawData' in the referenced section headers as\r
1983 // a key, arrange the elements in the table in ascending order. In other\r
1984 // words, sort the section headers according to the disk-file offset of\r
1985 // the section.\r
1986 //\r
1987 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1988 mImageBase +\r
1989 mPeCoffHeaderOffset +\r
1990 sizeof (UINT32) +\r
1991 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1992 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
1993 );\r
1994 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1995 Pos = Index;\r
1996 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
1997 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
1998 Pos--;\r
1999 }\r
2000 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
2001 Section += 1;\r
2002 }\r
2003\r
2004 //\r
2005 // 13. Walk through the sorted table, bring the corresponding section\r
2006 // into memory, and hash the entire section (using the 'SizeOfRawData'\r
2007 // field in the section header to determine the amount of data to hash).\r
2008 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
2009 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.\r
2010 //\r
2011 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
2012 Section = &SectionHeader[Index];\r
2013 if (Section->SizeOfRawData == 0) {\r
2014 continue;\r
2015 }\r
2016 HashBase = mImageBase + Section->PointerToRawData;\r
2017 HashSize = (UINTN) Section->SizeOfRawData;\r
2018\r
2019 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
2020 if (!Status) {\r
2021 goto Done;\r
2022 }\r
2023\r
2024 SumOfBytesHashed += HashSize;\r
2025 }\r
2026\r
2027 //\r
2028 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
2029 // data in the file that needs to be added to the hash. This data begins\r
2030 // at file offset SUM_OF_BYTES_HASHED and its length is:\r
2031 // FileSize - (CertDirectory->Size)\r
2032 //\r
2033 if (mImageSize > SumOfBytesHashed) {\r
2034 HashBase = mImageBase + SumOfBytesHashed;\r
2035 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
2036 //\r
2037 // Use PE32 offset.\r
2038 //\r
2039 HashSize = (UINTN)(\r
2040 mImageSize -\r
2041 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
2042 SumOfBytesHashed);\r
2043 } else {\r
2044 //\r
2045 // Use PE32+ offset.\r
2046 //\r
2047 HashSize = (UINTN)(\r
2048 mImageSize -\r
2049 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
20333c6d 2050 SumOfBytesHashed);\r
ecc722ad 2051 }\r
2052\r
2053 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
2054 if (!Status) {\r
2055 goto Done;\r
2056 }\r
2057 }\r
2058\r
2059 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
2060\r
2061Done:\r
2062 if (HashCtx != NULL) {\r
2063 FreePool (HashCtx);\r
2064 }\r
2065 if (SectionHeader != NULL) {\r
2066 FreePool (SectionHeader);\r
2067 }\r
2068 return Status;\r
2069}\r
2070\r
2071/**\r
69f8bb52 2072 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of\r
20333c6d 2073 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification\r
ecc722ad 2074 8.0 Appendix A\r
2075\r
2076 @retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
2077 @retval EFI_SUCCESS Hash successfully.\r
2078\r
2079**/\r
20333c6d 2080EFI_STATUS\r
ecc722ad 2081HashPeImageByType (\r
2082 VOID\r
2083 )\r
2084{\r
2085 UINT8 Index;\r
2086 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
2087\r
2088 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
2089\r
20333c6d 2090 for (Index = 0; Index < HASHALG_MAX; Index++) {\r
ecc722ad 2091 //\r
2092 // Check the Hash algorithm in PE/COFF Authenticode.\r
20333c6d 2093 // According to PKCS#7 Definition:\r
ecc722ad 2094 // SignedData ::= SEQUENCE {\r
2095 // version Version,\r
2096 // digestAlgorithms DigestAlgorithmIdentifiers,\r
2097 // contentInfo ContentInfo,\r
2098 // .... }\r
2099 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
2100 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
2101 // Fixed offset (+32) is calculated based on two bytes of length encoding.\r
2102 //\r
2103 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
2104 //\r
2105 // Only support two bytes of Long Form of Length Encoding.\r
2106 //\r
2107 continue;\r
2108 }\r
2109\r
20333c6d 2110 //\r
ecc722ad 2111 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
2112 break;\r
2113 }\r
2114 }\r
2115\r
2116 if (Index == HASHALG_MAX) {\r
2117 return EFI_UNSUPPORTED;\r
2118 }\r
2119\r
2120 //\r
2121 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
2122 //\r
2123 if (!HashPeImage(Index)) {\r
2124 return EFI_UNSUPPORTED;\r
2125 }\r
2126\r
2127 return EFI_SUCCESS;\r
2128}\r
2129\r
4de754e1
ZC
2130/**\r
2131 Enroll a new executable's signature into Signature Database.\r
2132\r
2133 @param[in] PrivateData The module's private data.\r
2134 @param[in] VariableName Variable name of signature database, must be\r
2135 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1\r
2136 or EFI_IMAGE_SECURITY_DATABASE2.\r
2137\r
2138 @retval EFI_SUCCESS New signature is enrolled successfully.\r
2139 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2140 @retval EFI_UNSUPPORTED Unsupported command.\r
2141 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
2142\r
2143**/\r
2144EFI_STATUS\r
2145EnrollAuthentication2Descriptor (\r
2146 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2147 IN CHAR16 *VariableName\r
2148 )\r
2149{\r
2150 EFI_STATUS Status;\r
2151 VOID *Data;\r
2152 UINTN DataSize;\r
2153 UINT32 Attr;\r
2154\r
2155 Data = NULL;\r
2156\r
2157 //\r
2158 // DBT only support DER-X509 Cert Enrollment\r
2159 //\r
2160 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {\r
2161 return EFI_UNSUPPORTED;\r
2162 }\r
2163\r
2164 //\r
2165 // Read the whole file content\r
2166 //\r
2167 Status = ReadFileContent(\r
2168 Private->FileContext->FHandle,\r
2169 (VOID **) &mImageBase,\r
2170 &mImageSize,\r
2171 0\r
2172 );\r
2173 if (EFI_ERROR (Status)) {\r
2174 goto ON_EXIT;\r
2175 }\r
2176 ASSERT (mImageBase != NULL);\r
2177\r
2178 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
2179 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
2180\r
2181 //\r
2182 // Check if SigDB variable has been already existed.\r
2183 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
2184 // new signature data to original variable\r
2185 //\r
2186 DataSize = 0;\r
2187 Status = gRT->GetVariable(\r
2188 VariableName,\r
2189 &gEfiImageSecurityDatabaseGuid,\r
2190 NULL,\r
2191 &DataSize,\r
2192 NULL\r
2193 );\r
2194 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2195 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
2196 } else if (Status != EFI_NOT_FOUND) {\r
2197 goto ON_EXIT;\r
2198 }\r
2199\r
2200 //\r
2201 // Diretly set AUTHENTICATION_2 data to SetVariable\r
2202 //\r
2203 Status = gRT->SetVariable(\r
2204 VariableName,\r
2205 &gEfiImageSecurityDatabaseGuid,\r
2206 Attr,\r
2207 mImageSize,\r
2208 mImageBase\r
2209 );\r
2210\r
2211 DEBUG((DEBUG_INFO, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName, Status));\r
2212\r
2213ON_EXIT:\r
2214\r
2215 CloseEnrolledFile(Private->FileContext);\r
2216\r
2217 if (Data != NULL) {\r
2218 FreePool (Data);\r
2219 }\r
2220\r
2221 if (mImageBase != NULL) {\r
2222 FreePool (mImageBase);\r
2223 mImageBase = NULL;\r
2224 }\r
2225\r
2226 return Status;\r
2227\r
2228}\r
2229\r
2230\r
ecc722ad 2231/**\r
20333c6d 2232 Enroll a new executable's signature into Signature Database.\r
ecc722ad 2233\r
2234 @param[in] PrivateData The module's private data.\r
20333c6d
QL
2235 @param[in] VariableName Variable name of signature database, must be\r
2236 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1\r
2237 or EFI_IMAGE_SECURITY_DATABASE2.\r
ecc722ad 2238\r
2239 @retval EFI_SUCCESS New signature is enrolled successfully.\r
2240 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2241 @retval EFI_UNSUPPORTED Unsupported command.\r
2242 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
2243\r
2244**/\r
2245EFI_STATUS\r
2246EnrollImageSignatureToSigDB (\r
2247 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2248 IN CHAR16 *VariableName\r
2249 )\r
2250{\r
2251 EFI_STATUS Status;\r
2252 EFI_SIGNATURE_LIST *SigDBCert;\r
2253 EFI_SIGNATURE_DATA *SigDBCertData;\r
2254 VOID *Data;\r
2255 UINTN DataSize;\r
2256 UINTN SigDBSize;\r
2257 UINT32 Attr;\r
2258 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;\r
2259\r
2260 Data = NULL;\r
2261 GuidCertData = NULL;\r
ecc722ad 2262\r
20333c6d
QL
2263 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {\r
2264 return EFI_UNSUPPORTED;\r
2265 }\r
2266\r
ecc722ad 2267 //\r
2268 // Form the SigDB certificate list.\r
2269 // Format the data item into EFI_SIGNATURE_LIST type.\r
2270 //\r
2271 // We need to parse executable's signature data from specified signed executable file.\r
2272 // In current implementation, we simply trust the pass-in signed executable file.\r
2273 // In reality, it's OS's responsibility to verify the signed executable file.\r
2274 //\r
2275\r
2276 //\r
2277 // Read the whole file content\r
2278 //\r
2279 Status = ReadFileContent(\r
2280 Private->FileContext->FHandle,\r
20333c6d
QL
2281 (VOID **) &mImageBase,\r
2282 &mImageSize,\r
ecc722ad 2283 0\r
2284 );\r
2285 if (EFI_ERROR (Status)) {\r
2286 goto ON_EXIT;\r
20333c6d 2287 }\r
ba57d4fd 2288 ASSERT (mImageBase != NULL);\r
ecc722ad 2289\r
2290 Status = LoadPeImage ();\r
2291 if (EFI_ERROR (Status)) {\r
2292 goto ON_EXIT;\r
2293 }\r
2294\r
2295 if (mSecDataDir->SizeOfCert == 0) {\r
2296 if (!HashPeImage (HASHALG_SHA256)) {\r
2297 Status = EFI_SECURITY_VIOLATION;\r
2298 goto ON_EXIT;\r
2299 }\r
2300 } else {\r
20333c6d 2301\r
ecc722ad 2302 //\r
2303 // Read the certificate data\r
2304 //\r
2305 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
2306\r
2307 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
2308 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
2309 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
2310 Status = EFI_ABORTED;\r
2311 goto ON_EXIT;\r
2312 }\r
2313\r
2314 if (!HashPeImage (HASHALG_SHA256)) {\r
2315 Status = EFI_ABORTED;\r
2316 goto ON_EXIT;;\r
2317 }\r
20333c6d 2318\r
ecc722ad 2319 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
2320\r
2321 Status = HashPeImageByType ();\r
2322 if (EFI_ERROR (Status)) {\r
2323 goto ON_EXIT;;\r
2324 }\r
2325 } else {\r
2326 Status = EFI_ABORTED;\r
2327 goto ON_EXIT;\r
2328 }\r
2329 }\r
2330\r
2331 //\r
2332 // Create a new SigDB entry.\r
2333 //\r
20333c6d 2334 SigDBSize = sizeof(EFI_SIGNATURE_LIST)\r
ecc722ad 2335 + sizeof(EFI_SIGNATURE_DATA) - 1\r
2336 + (UINT32) mImageDigestSize;\r
2337\r
2338 Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
2339 if (Data == NULL) {\r
2340 Status = EFI_OUT_OF_RESOURCES;\r
2341 goto ON_EXIT;\r
2342 }\r
20333c6d 2343\r
ecc722ad 2344 //\r
2345 // Adjust the Certificate Database parameters.\r
20333c6d 2346 //\r
ecc722ad 2347 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
2348 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
2349 SigDBCert->SignatureHeaderSize = 0;\r
2350 SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
2351 CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
2352\r
2353 SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
2354 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
2355 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
2356\r
20333c6d 2357 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 2358 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
2359 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
2360 if (EFI_ERROR (Status)) {\r
2361 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2362 goto ON_EXIT;\r
2363 }\r
20333c6d 2364\r
ecc722ad 2365 //\r
20333c6d
QL
2366 // Check if SigDB variable has been already existed.\r
2367 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 2368 // new signature data to original variable\r
20333c6d 2369 //\r
ecc722ad 2370 DataSize = 0;\r
2371 Status = gRT->GetVariable(\r
20333c6d
QL
2372 VariableName,\r
2373 &gEfiImageSecurityDatabaseGuid,\r
2374 NULL,\r
2375 &DataSize,\r
ecc722ad 2376 NULL\r
2377 );\r
2378 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2379 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
2380 } else if (Status != EFI_NOT_FOUND) {\r
2381 goto ON_EXIT;\r
20333c6d 2382 }\r
ecc722ad 2383\r
2384 //\r
2385 // Enroll the variable.\r
2386 //\r
2387 Status = gRT->SetVariable(\r
20333c6d
QL
2388 VariableName,\r
2389 &gEfiImageSecurityDatabaseGuid,\r
2390 Attr,\r
2391 SigDBSize,\r
ecc722ad 2392 Data\r
2393 );\r
2394 if (EFI_ERROR (Status)) {\r
2395 goto ON_EXIT;\r
2396 }\r
2397\r
2398ON_EXIT:\r
2399\r
4de754e1 2400 CloseEnrolledFile(Private->FileContext);\r
ecc722ad 2401\r
2402 if (Private->SignatureGUID != NULL) {\r
2403 FreePool (Private->SignatureGUID);\r
2404 Private->SignatureGUID = NULL;\r
2405 }\r
2406\r
2407 if (Data != NULL) {\r
2408 FreePool (Data);\r
2409 }\r
2410\r
2411 if (mImageBase != NULL) {\r
2412 FreePool (mImageBase);\r
2413 mImageBase = NULL;\r
2414 }\r
2415\r
2416 return Status;\r
2417}\r
2418\r
2419/**\r
20333c6d 2420 Enroll signature into DB/DBX/DBT without KEK's authentication.\r
ecc722ad 2421 The SignatureOwner GUID will be Private->SignatureGUID.\r
20333c6d 2422\r
ecc722ad 2423 @param[in] PrivateData The module's private data.\r
20333c6d 2424 @param[in] VariableName Variable name of signature database, must be\r
ecc722ad 2425 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
20333c6d 2426\r
ecc722ad 2427 @retval EFI_SUCCESS New signature enrolled successfully.\r
2428 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2429 @retval others Fail to enroll signature data.\r
20333c6d 2430\r
ecc722ad 2431**/\r
2432EFI_STATUS\r
2433EnrollSignatureDatabase (\r
2434 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2435 IN CHAR16 *VariableName\r
20333c6d 2436 )\r
ecc722ad 2437{\r
2438 UINT16* FilePostFix;\r
f71ed839 2439 EFI_STATUS Status;\r
fd64f84f 2440 UINTN NameLength;\r
ecc722ad 2441\r
2442 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
2443 return EFI_INVALID_PARAMETER;\r
2444 }\r
2445\r
20333c6d 2446 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
f71ed839 2447 if (EFI_ERROR (Status)) {\r
2448 return Status;\r
2449 }\r
20333c6d 2450\r
ecc722ad 2451 //\r
20333c6d 2452 // Parse the file's postfix.\r
ecc722ad 2453 //\r
fd64f84f
GCPL
2454 NameLength = StrLen (Private->FileContext->FileName);\r
2455 if (NameLength <= 4) {\r
2456 return EFI_INVALID_PARAMETER;\r
2457 }\r
2458 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
20333c6d 2459 if (IsDerEncodeCertificate (FilePostFix)) {\r
ecc722ad 2460 //\r
e4d7370d 2461 // Supports DER-encoded X509 certificate.\r
ecc722ad 2462 //\r
2463 return EnrollX509toSigDB (Private, VariableName);\r
4de754e1
ZC
2464 } else if (IsAuthentication2Format(Private->FileContext->FHandle)){\r
2465 return EnrollAuthentication2Descriptor(Private, VariableName);\r
2466 } else {\r
2467 return EnrollImageSignatureToSigDB (Private, VariableName);\r
ecc722ad 2468 }\r
ecc722ad 2469}\r
2470\r
2471/**\r
20333c6d 2472 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)\r
ecc722ad 2473 by GUID in the page for user to select and delete as needed.\r
2474\r
2475 @param[in] PrivateData Module's private data.\r
2476 @param[in] VariableName The variable name of the vendor's signature database.\r
2477 @param[in] VendorGuid A unique identifier for the vendor.\r
2478 @param[in] LabelNumber Label number to insert opcodes.\r
2479 @param[in] FormId Form ID of current page.\r
2480 @param[in] QuestionIdBase Base question id of the signature list.\r
2481\r
2482 @retval EFI_SUCCESS Success to update the signature list page\r
2483 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
20333c6d 2484\r
ecc722ad 2485**/\r
2486EFI_STATUS\r
2487UpdateDeletePage (\r
2488 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2489 IN CHAR16 *VariableName,\r
2490 IN EFI_GUID *VendorGuid,\r
2491 IN UINT16 LabelNumber,\r
2492 IN EFI_FORM_ID FormId,\r
2493 IN EFI_QUESTION_ID QuestionIdBase\r
2494 )\r
2495{\r
2496 EFI_STATUS Status;\r
2497 UINT32 Index;\r
2498 UINTN CertCount;\r
2499 UINTN GuidIndex;\r
2500 VOID *StartOpCodeHandle;\r
2501 VOID *EndOpCodeHandle;\r
2502 EFI_IFR_GUID_LABEL *StartLabel;\r
20333c6d 2503 EFI_IFR_GUID_LABEL *EndLabel;\r
ecc722ad 2504 UINTN DataSize;\r
2505 UINT8 *Data;\r
2506 EFI_SIGNATURE_LIST *CertList;\r
2507 EFI_SIGNATURE_DATA *Cert;\r
2508 UINT32 ItemDataSize;\r
2509 CHAR16 *GuidStr;\r
2510 EFI_STRING_ID GuidID;\r
2511 EFI_STRING_ID Help;\r
2512\r
2513 Data = NULL;\r
2514 CertList = NULL;\r
2515 Cert = NULL;\r
2516 GuidStr = NULL;\r
2517 StartOpCodeHandle = NULL;\r
2518 EndOpCodeHandle = NULL;\r
20333c6d 2519\r
ecc722ad 2520 //\r
2521 // Initialize the container for dynamic opcodes.\r
2522 //\r
2523 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2524 if (StartOpCodeHandle == NULL) {\r
2525 Status = EFI_OUT_OF_RESOURCES;\r
20333c6d 2526 goto ON_EXIT;\r
ecc722ad 2527 }\r
2528\r
2529 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2530 if (EndOpCodeHandle == NULL) {\r
2531 Status = EFI_OUT_OF_RESOURCES;\r
20333c6d 2532 goto ON_EXIT;\r
ecc722ad 2533 }\r
2534\r
2535 //\r
2536 // Create Hii Extend Label OpCode.\r
2537 //\r
2538 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2539 StartOpCodeHandle,\r
2540 &gEfiIfrTianoGuid,\r
2541 NULL,\r
2542 sizeof (EFI_IFR_GUID_LABEL)\r
2543 );\r
2544 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2545 StartLabel->Number = LabelNumber;\r
2546\r
2547 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2548 EndOpCodeHandle,\r
2549 &gEfiIfrTianoGuid,\r
2550 NULL,\r
2551 sizeof (EFI_IFR_GUID_LABEL)\r
2552 );\r
2553 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2554 EndLabel->Number = LABEL_END;\r
2555\r
2556 //\r
2557 // Read Variable.\r
2558 //\r
2559 DataSize = 0;\r
20333c6d 2560 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
ecc722ad 2561 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2562 goto ON_EXIT;\r
2563 }\r
2564\r
2565 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
2566 if (Data == NULL) {\r
2567 Status = EFI_OUT_OF_RESOURCES;\r
2568 goto ON_EXIT;\r
2569 }\r
2570\r
2571 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
2572 if (EFI_ERROR (Status)) {\r
2573 goto ON_EXIT;\r
2574 }\r
2575\r
2576 GuidStr = AllocateZeroPool (100);\r
2577 if (GuidStr == NULL) {\r
2578 Status = EFI_OUT_OF_RESOURCES;\r
2579 goto ON_EXIT;\r
2580 }\r
2581\r
2582 //\r
2583 // Enumerate all KEK pub data.\r
2584 //\r
2585 ItemDataSize = (UINT32) DataSize;\r
2586 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2587 GuidIndex = 0;\r
2588\r
2589 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2590\r
2591 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
2592 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
2593 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
2594 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
2595 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
2596 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
2597 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
2598 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
20333c6d
QL
2599 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
2600 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);\r
2601 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
2602 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);\r
2603 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
2604 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);\r
ecc722ad 2605 } else {\r
2606 //\r
2607 // The signature type is not supported in current implementation.\r
2608 //\r
b7d269ea 2609 ItemDataSize -= CertList->SignatureListSize;\r
2610 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
ecc722ad 2611 continue;\r
2612 }\r
2613\r
2614 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2615 for (Index = 0; Index < CertCount; Index++) {\r
20333c6d
QL
2616 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList\r
2617 + sizeof (EFI_SIGNATURE_LIST)\r
2618 + CertList->SignatureHeaderSize\r
ecc722ad 2619 + Index * CertList->SignatureSize);\r
2620 //\r
20333c6d 2621 // Display GUID and help\r
ecc722ad 2622 //\r
2623 GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
2624 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
2625 HiiCreateCheckBoxOpCode (\r
2626 StartOpCodeHandle,\r
2627 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
20333c6d
QL
2628 0,\r
2629 0,\r
2630 GuidID,\r
ecc722ad 2631 Help,\r
2632 EFI_IFR_FLAG_CALLBACK,\r
2633 0,\r
2634 NULL\r
20333c6d 2635 );\r
ecc722ad 2636 }\r
2637\r
2638 ItemDataSize -= CertList->SignatureListSize;\r
2639 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2640 }\r
2641\r
2642ON_EXIT:\r
2643 HiiUpdateForm (\r
2644 PrivateData->HiiHandle,\r
2645 &gSecureBootConfigFormSetGuid,\r
2646 FormId,\r
2647 StartOpCodeHandle,\r
2648 EndOpCodeHandle\r
2649 );\r
2650\r
2651 if (StartOpCodeHandle != NULL) {\r
2652 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2653 }\r
2654\r
2655 if (EndOpCodeHandle != NULL) {\r
2656 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2657 }\r
20333c6d 2658\r
ecc722ad 2659 if (Data != NULL) {\r
2660 FreePool (Data);\r
2661 }\r
2662\r
2663 if (GuidStr != NULL) {\r
2664 FreePool (GuidStr);\r
2665 }\r
2666\r
2667 return EFI_SUCCESS;\r
2668}\r
2669\r
beda2356 2670/**\r
20333c6d 2671 Delete a KEK entry from KEK database.\r
beda2356 2672\r
ecc722ad 2673 @param[in] PrivateData Module's private data.\r
2674 @param[in] QuestionId Question id of the KEK item to delete.\r
beda2356 2675\r
ecc722ad 2676 @retval EFI_SUCCESS Delete kek item successfully.\r
2677 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
20333c6d 2678\r
ecc722ad 2679**/\r
2680EFI_STATUS\r
2681DeleteKeyExchangeKey (\r
2682 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2683 IN EFI_QUESTION_ID QuestionId\r
2684 )\r
2685{\r
2686 EFI_STATUS Status;\r
2687 UINTN DataSize;\r
2688 UINT8 *Data;\r
2689 UINT8 *OldData;\r
2690 UINT32 Attr;\r
2691 UINT32 Index;\r
2692 EFI_SIGNATURE_LIST *CertList;\r
2693 EFI_SIGNATURE_LIST *NewCertList;\r
2694 EFI_SIGNATURE_DATA *Cert;\r
2695 UINTN CertCount;\r
2696 UINT32 Offset;\r
2697 BOOLEAN IsKEKItemFound;\r
2698 UINT32 KekDataSize;\r
2699 UINTN DeleteKekIndex;\r
2700 UINTN GuidIndex;\r
2701\r
2702 Data = NULL;\r
2703 OldData = NULL;\r
2704 CertList = NULL;\r
2705 Cert = NULL;\r
20333c6d 2706 Attr = 0;\r
ecc722ad 2707 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
f71ed839 2708\r
2709 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2710 if (EFI_ERROR (Status)) {\r
2711 return Status;\r
2712 }\r
20333c6d 2713\r
ecc722ad 2714 //\r
2715 // Get original KEK variable.\r
20333c6d
QL
2716 //\r
2717 DataSize = 0;\r
ecc722ad 2718 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
2719 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2720 goto ON_EXIT;\r
2721 }\r
2722\r
2723 OldData = (UINT8*)AllocateZeroPool(DataSize);\r
2724 if (OldData == NULL) {\r
20333c6d 2725 Status = EFI_OUT_OF_RESOURCES;\r
ecc722ad 2726 goto ON_EXIT;\r
2727 }\r
2728\r
2729 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
2730 if (EFI_ERROR(Status)) {\r
2731 goto ON_EXIT;\r
2732 }\r
2733\r
2734 //\r
20333c6d 2735 // Allocate space for new variable.\r
ecc722ad 2736 //\r
2737 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2738 if (Data == NULL) {\r
2739 Status = EFI_OUT_OF_RESOURCES;\r
2740 goto ON_EXIT;\r
2741 }\r
2742\r
2743 //\r
2744 // Enumerate all KEK pub data and erasing the target item.\r
2745 //\r
2746 IsKEKItemFound = FALSE;\r
2747 KekDataSize = (UINT32) DataSize;\r
2748 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2749 Offset = 0;\r
2750 GuidIndex = 0;\r
2751 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
2752 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2753 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
2754 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2755 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
2756 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2757 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2758 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2759 for (Index = 0; Index < CertCount; Index++) {\r
2760 if (GuidIndex == DeleteKekIndex ) {\r
2761 //\r
2762 // Find it! Skip it!\r
2763 //\r
2764 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
20333c6d 2765 IsKEKItemFound = TRUE;\r
ecc722ad 2766 } else {\r
2767 //\r
2768 // This item doesn't match. Copy it to the Data buffer.\r
2769 //\r
2770 CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
2771 Offset += CertList->SignatureSize;\r
2772 }\r
2773 GuidIndex++;\r
2774 Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
2775 }\r
2776 } else {\r
2777 //\r
2778 // This List doesn't match. Copy it to the Data buffer.\r
2779 //\r
2780 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
2781 Offset += CertList->SignatureListSize;\r
2782 }\r
20333c6d 2783\r
ecc722ad 2784 KekDataSize -= CertList->SignatureListSize;\r
2785 CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
2786 }\r
2787\r
2788 if (!IsKEKItemFound) {\r
2789 //\r
2790 // Doesn't find the Kek Item!\r
2791 //\r
2792 Status = EFI_NOT_FOUND;\r
2793 goto ON_EXIT;\r
2794 }\r
2795\r
2796 //\r
2797 // Delete the Signature header if there is no signature in the list.\r
2798 //\r
2799 KekDataSize = Offset;\r
2800 CertList = (EFI_SIGNATURE_LIST*) Data;\r
2801 Offset = 0;\r
2802 ZeroMem (OldData, KekDataSize);\r
2803 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
2804 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
33985e3b 2805 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));\r
ecc722ad 2806 if (CertCount != 0) {\r
2807 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
2808 Offset += CertList->SignatureListSize;\r
20333c6d 2809 }\r
ecc722ad 2810 KekDataSize -= CertList->SignatureListSize;\r
2811 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2812 }\r
2813\r
ecc722ad 2814 DataSize = Offset;\r
8c1babfd 2815 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2816 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2817 if (EFI_ERROR (Status)) {\r
2818 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2819 goto ON_EXIT;\r
2820 }\r
2821 }\r
ecc722ad 2822\r
2823 Status = gRT->SetVariable(\r
20333c6d
QL
2824 EFI_KEY_EXCHANGE_KEY_NAME,\r
2825 &gEfiGlobalVariableGuid,\r
2826 Attr,\r
2827 DataSize,\r
ecc722ad 2828 OldData\r
2829 );\r
2830 if (EFI_ERROR (Status)) {\r
2831 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2832 goto ON_EXIT;\r
2833 }\r
20333c6d 2834\r
ecc722ad 2835ON_EXIT:\r
2836 if (Data != NULL) {\r
2837 FreePool(Data);\r
2838 }\r
2839\r
2840 if (OldData != NULL) {\r
2841 FreePool(OldData);\r
2842 }\r
2843\r
2844 return UpdateDeletePage (\r
20333c6d 2845 PrivateData,\r
ecc722ad 2846 EFI_KEY_EXCHANGE_KEY_NAME,\r
2847 &gEfiGlobalVariableGuid,\r
2848 LABEL_KEK_DELETE,\r
2849 FORMID_DELETE_KEK_FORM,\r
2850 OPTION_DEL_KEK_QUESTION_ID\r
2851 );\r
2852}\r
2853\r
2854/**\r
85974aef 2855 Delete a signature entry from signature database.\r
beda2356 2856\r
ecc722ad 2857 @param[in] PrivateData Module's private data.\r
2858 @param[in] VariableName The variable name of the vendor's signature database.\r
2859 @param[in] VendorGuid A unique identifier for the vendor.\r
2860 @param[in] LabelNumber Label number to insert opcodes.\r
2861 @param[in] FormId Form ID of current page.\r
2862 @param[in] QuestionIdBase Base question id of the signature list.\r
2863 @param[in] DeleteIndex Signature index to delete.\r
20333c6d 2864\r
85974aef 2865 @retval EFI_SUCCESS Delete signature successfully.\r
ecc722ad 2866 @retval EFI_NOT_FOUND Can't find the signature item,\r
2867 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
beda2356 2868**/\r
2869EFI_STATUS\r
ecc722ad 2870DeleteSignature (\r
2871 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2872 IN CHAR16 *VariableName,\r
2873 IN EFI_GUID *VendorGuid,\r
2874 IN UINT16 LabelNumber,\r
2875 IN EFI_FORM_ID FormId,\r
2876 IN EFI_QUESTION_ID QuestionIdBase,\r
2877 IN UINTN DeleteIndex\r
beda2356 2878 )\r
2879{\r
ecc722ad 2880 EFI_STATUS Status;\r
2881 UINTN DataSize;\r
2882 UINT8 *Data;\r
2883 UINT8 *OldData;\r
2884 UINT32 Attr;\r
2885 UINT32 Index;\r
2886 EFI_SIGNATURE_LIST *CertList;\r
2887 EFI_SIGNATURE_LIST *NewCertList;\r
2888 EFI_SIGNATURE_DATA *Cert;\r
2889 UINTN CertCount;\r
2890 UINT32 Offset;\r
2891 BOOLEAN IsItemFound;\r
2892 UINT32 ItemDataSize;\r
2893 UINTN GuidIndex;\r
bc0c99b3 2894\r
ecc722ad 2895 Data = NULL;\r
2896 OldData = NULL;\r
2897 CertList = NULL;\r
2898 Cert = NULL;\r
20333c6d 2899 Attr = 0;\r
ecc722ad 2900\r
f71ed839 2901 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2902 if (EFI_ERROR (Status)) {\r
2903 return Status;\r
2904 }\r
2905\r
ecc722ad 2906 //\r
2907 // Get original signature list data.\r
20333c6d 2908 //\r
ecc722ad 2909 DataSize = 0;\r
2910 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
2911 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2912 goto ON_EXIT;\r
2913 }\r
2914\r
2915 OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
2916 if (OldData == NULL) {\r
20333c6d 2917 Status = EFI_OUT_OF_RESOURCES;\r
ecc722ad 2918 goto ON_EXIT;\r
2919 }\r
2920\r
2921 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
2922 if (EFI_ERROR(Status)) {\r
2923 goto ON_EXIT;\r
20333c6d 2924 }\r
ecc722ad 2925\r
2926 //\r
20333c6d 2927 // Allocate space for new variable.\r
ecc722ad 2928 //\r
2929 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2930 if (Data == NULL) {\r
2931 Status = EFI_OUT_OF_RESOURCES;\r
2932 goto ON_EXIT;\r
2933 }\r
2934\r
2935 //\r
2936 // Enumerate all signature data and erasing the target item.\r
2937 //\r
2938 IsItemFound = FALSE;\r
2939 ItemDataSize = (UINT32) DataSize;\r
2940 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2941 Offset = 0;\r
2942 GuidIndex = 0;\r
2943 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2944 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2945 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
2946 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
20333c6d
QL
2947 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||\r
2948 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||\r
2949 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||\r
2950 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)\r
ecc722ad 2951 ) {\r
2952 //\r
2953 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
2954 //\r
2955 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2956 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
2957 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2958 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2959 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2960 for (Index = 0; Index < CertCount; Index++) {\r
2961 if (GuidIndex == DeleteIndex) {\r
2962 //\r
2963 // Find it! Skip it!\r
2964 //\r
2965 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
20333c6d 2966 IsItemFound = TRUE;\r
ecc722ad 2967 } else {\r
2968 //\r
2969 // This item doesn't match. Copy it to the Data buffer.\r
2970 //\r
2971 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
2972 Offset += CertList->SignatureSize;\r
2973 }\r
2974 GuidIndex++;\r
2975 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
2976 }\r
2977 } else {\r
2978 //\r
2979 // This List doesn't match. Just copy it to the Data buffer.\r
2980 //\r
2981 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2982 Offset += CertList->SignatureListSize;\r
2983 }\r
20333c6d 2984\r
ecc722ad 2985 ItemDataSize -= CertList->SignatureListSize;\r
2986 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2987 }\r
2988\r
2989 if (!IsItemFound) {\r
2990 //\r
2991 // Doesn't find the signature Item!\r
2992 //\r
2993 Status = EFI_NOT_FOUND;\r
2994 goto ON_EXIT;\r
2995 }\r
2996\r
2997 //\r
2998 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
2999 //\r
3000 ItemDataSize = Offset;\r
3001 CertList = (EFI_SIGNATURE_LIST *) Data;\r
3002 Offset = 0;\r
3003 ZeroMem (OldData, ItemDataSize);\r
3004 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
3005 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
33985e3b 3006 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));\r
ecc722ad 3007 if (CertCount != 0) {\r
3008 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
3009 Offset += CertList->SignatureListSize;\r
20333c6d 3010 }\r
ecc722ad 3011 ItemDataSize -= CertList->SignatureListSize;\r
3012 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
3013 }\r
3014\r
ecc722ad 3015 DataSize = Offset;\r
8c1babfd 3016 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
3017 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
3018 if (EFI_ERROR (Status)) {\r
3019 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
3020 goto ON_EXIT;\r
3021 }\r
3022 }\r
ecc722ad 3023\r
3024 Status = gRT->SetVariable(\r
20333c6d
QL
3025 VariableName,\r
3026 VendorGuid,\r
3027 Attr,\r
3028 DataSize,\r
ecc722ad 3029 OldData\r
3030 );\r
beda2356 3031 if (EFI_ERROR (Status)) {\r
ecc722ad 3032 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
3033 goto ON_EXIT;\r
beda2356 3034 }\r
20333c6d 3035\r
ecc722ad 3036ON_EXIT:\r
3037 if (Data != NULL) {\r
3038 FreePool(Data);\r
3039 }\r
3040\r
3041 if (OldData != NULL) {\r
3042 FreePool(OldData);\r
3043 }\r
3044\r
3045 return UpdateDeletePage (\r
20333c6d 3046 PrivateData,\r
ecc722ad 3047 VariableName,\r
3048 VendorGuid,\r
3049 LabelNumber,\r
3050 FormId,\r
3051 QuestionIdBase\r
3052 );\r
3053}\r
3054\r
85974aef 3055/**\r
3056 This function to delete signature list or data, according by DelType.\r
3057\r
3058 @param[in] PrivateData Module's private data.\r
3059 @param[in] DelType Indicate delete signature list or data.\r
3060 @param[in] CheckedCount Indicate how many signature data have\r
3061 been checked in current signature list.\r
3062\r
3063 @retval EFI_SUCCESS Success to update the signature list page\r
3064 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
3065**/\r
3066EFI_STATUS\r
3067DeleteSignatureEx (\r
3068 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
3069 IN SIGNATURE_DELETE_TYPE DelType,\r
3070 IN UINT32 CheckedCount\r
3071 )\r
3072{\r
3073 EFI_STATUS Status;\r
3074 EFI_SIGNATURE_LIST *ListWalker;\r
3075 EFI_SIGNATURE_LIST *NewCertList;\r
3076 EFI_SIGNATURE_DATA *DataWalker;\r
65c77f02 3077 CHAR16 VariableName[BUFFER_MAX_SIZE];\r
85974aef 3078 UINT32 VariableAttr;\r
3079 UINTN VariableDataSize;\r
3080 UINTN RemainingSize;\r
3081 UINTN ListIndex;\r
3082 UINTN Index;\r
3083 UINTN Offset;\r
3084 UINT8 *VariableData;\r
3085 UINT8 *NewVariableData;\r
3086\r
3087 Status = EFI_SUCCESS;\r
85974aef 3088 VariableAttr = 0;\r
3089 VariableDataSize = 0;\r
3090 ListIndex = 0;\r
3091 Offset = 0;\r
3092 VariableData = NULL;\r
3093 NewVariableData = NULL;\r
3094\r
0085d619 3095 if (PrivateData->VariableName == Variable_DB) {\r
65c77f02 3096 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);\r
0085d619 3097 } else if (PrivateData->VariableName == Variable_DBX) {\r
65c77f02 3098 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);\r
0085d619 3099 } else if (PrivateData->VariableName == Variable_DBT) {\r
65c77f02 3100 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);\r
85974aef 3101 } else {\r
3102 goto ON_EXIT;\r
3103 }\r
3104\r
3105 Status = gRT->GetVariable (\r
3106 VariableName,\r
3107 &gEfiImageSecurityDatabaseGuid,\r
3108 &VariableAttr,\r
3109 &VariableDataSize,\r
3110 VariableData\r
3111 );\r
3112 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
3113 goto ON_EXIT;\r
3114 }\r
3115\r
3116 VariableData = AllocateZeroPool (VariableDataSize);\r
3117 if (VariableData == NULL) {\r
3118 Status = EFI_OUT_OF_RESOURCES;\r
3119 goto ON_EXIT;\r
3120 }\r
3121\r
3122 Status = gRT->GetVariable (\r
3123 VariableName,\r
3124 &gEfiImageSecurityDatabaseGuid,\r
3125 &VariableAttr,\r
3126 &VariableDataSize,\r
3127 VariableData\r
3128 );\r
3129 if (EFI_ERROR (Status)) {\r
3130 goto ON_EXIT;\r
3131 }\r
3132\r
3133 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
3134 if (EFI_ERROR (Status)) {\r
3135 goto ON_EXIT;\r
3136 }\r
3137\r
3138 NewVariableData = AllocateZeroPool (VariableDataSize);\r
3139 if (NewVariableData == NULL) {\r
3140 Status = EFI_OUT_OF_RESOURCES;\r
3141 goto ON_EXIT;\r
3142 }\r
3143\r
3144 RemainingSize = VariableDataSize;\r
3145 ListWalker = (EFI_SIGNATURE_LIST *)(VariableData);\r
0085d619 3146 if (DelType == Delete_Signature_List_All) {\r
85974aef 3147 VariableDataSize = 0;\r
3148 } else {\r
dcd70885
LG
3149 //\r
3150 // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.\r
3151 //\r
85974aef 3152 while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex < PrivateData->ListIndex) {\r
3153 CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, ListWalker->SignatureListSize);\r
3154 Offset += ListWalker->SignatureListSize;\r
3155\r
3156 RemainingSize -= ListWalker->SignatureListSize;\r
3157 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
3158 ListIndex++;\r
3159 }\r
3160\r
dcd70885
LG
3161 //\r
3162 // Handle the target EFI_SIGNATURE_LIST.\r
3163 // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One\r
3164 // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.\r
3165 //\r
3166 if (CheckedCount < SIGNATURE_DATA_COUNTS (ListWalker) && DelType == Delete_Signature_Data) {\r
85974aef 3167 NewCertList = (EFI_SIGNATURE_LIST *)(NewVariableData + Offset);\r
3168 //\r
3169 // Copy header.\r
3170 //\r
dcd70885 3171 CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);\r
85974aef 3172 Offset += sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize;\r
3173\r
3174 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof(EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);\r
3175 for (Index = 0; Index < SIGNATURE_DATA_COUNTS(ListWalker); Index = Index + 1) {\r
3176 if (PrivateData->CheckArray[Index]) {\r
3177 //\r
3178 // Delete checked signature data, and update the size of whole signature list.\r
3179 //\r
3180 NewCertList->SignatureListSize -= NewCertList->SignatureSize;\r
3181 } else {\r
3182 //\r
3183 // Remain the unchecked signature data.\r
3184 //\r
3185 CopyMem ((UINT8 *)NewVariableData + Offset, DataWalker, ListWalker->SignatureSize);\r
3186 Offset += ListWalker->SignatureSize;\r
3187 }\r
3188 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);\r
3189 }\r
85974aef 3190 }\r
3191\r
dcd70885
LG
3192 RemainingSize -= ListWalker->SignatureListSize;\r
3193 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
3194\r
85974aef 3195 //\r
3196 // Copy remaining data, maybe 0.\r
3197 //\r
3198 CopyMem((UINT8 *)NewVariableData + Offset, ListWalker, RemainingSize);\r
3199 Offset += RemainingSize;\r
3200\r
3201 VariableDataSize = Offset;\r
3202 }\r
3203\r
3204 if ((VariableAttr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
3205 Status = CreateTimeBasedPayload (&VariableDataSize, &NewVariableData);\r
3206 if (EFI_ERROR (Status)) {\r
3207 DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));\r
3208 goto ON_EXIT;\r
3209 }\r
3210 }\r
3211\r
3212 Status = gRT->SetVariable (\r
3213 VariableName,\r
3214 &gEfiImageSecurityDatabaseGuid,\r
3215 VariableAttr,\r
3216 VariableDataSize,\r
3217 NewVariableData\r
3218 );\r
3219 if (EFI_ERROR (Status)) {\r
3220 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r", Status));\r
3221 goto ON_EXIT;\r
3222 }\r
3223\r
3224ON_EXIT:\r
85974aef 3225 SECUREBOOT_FREE_NON_NULL (VariableData);\r
3226 SECUREBOOT_FREE_NON_NULL (NewVariableData);\r
3227\r
3228 return Status;\r
3229}\r
3230\r
02dd6af9
CZ
3231/**\r
3232\r
3233 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT\r
3234 and STR_CUR_SECURE_BOOT_MODE_CONTENT.\r
3235\r
3236 @param[in] PrivateData Module's private data.\r
3237\r
3238 @return EFI_SUCCESS Update secure boot strings successfully.\r
3239 @return other Fail to update secure boot strings.\r
3240\r
3241**/\r
3242EFI_STATUS\r
3243UpdateSecureBootString(\r
3244 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
abffadf0
ZC
3245 )\r
3246{\r
02dd6af9
CZ
3247 UINT8 *SecureBoot;\r
3248\r
e8cd9b80
CZ
3249 SecureBoot = NULL;\r
3250\r
02dd6af9
CZ
3251 //\r
3252 // Get current secure boot state.\r
3253 //\r
e8cd9b80
CZ
3254 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
3255 if (SecureBoot == NULL) {\r
3256 return EFI_NOT_FOUND;\r
02dd6af9
CZ
3257 }\r
3258\r
3259 if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
3260 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
3261 } else {\r
3262 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
3263 }\r
02dd6af9
CZ
3264\r
3265 FreePool(SecureBoot);\r
3266\r
3267 return EFI_SUCCESS;\r
3268}\r
3269\r
ecc722ad 3270/**\r
3271 This function extracts configuration from variable.\r
20333c6d 3272\r
4de754e1 3273 @param[in] Private Point to SecureBoot configuration driver private data.\r
ecc722ad 3274 @param[in, out] ConfigData Point to SecureBoot configuration private data.\r
3275\r
3276**/\r
3277VOID\r
3278SecureBootExtractConfigFromVariable (\r
4de754e1 3279 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
ecc722ad 3280 IN OUT SECUREBOOT_CONFIGURATION *ConfigData\r
20333c6d 3281 )\r
ecc722ad 3282{\r
20333c6d 3283 UINT8 *SecureBootEnable;\r
12087ff6 3284 UINT8 *SetupMode;\r
20333c6d
QL
3285 UINT8 *SecureBootMode;\r
3286 EFI_TIME CurrTime;\r
ecc722ad 3287\r
3288 SecureBootEnable = NULL;\r
12087ff6 3289 SetupMode = NULL;\r
ecc722ad 3290 SecureBootMode = NULL;\r
20333c6d
QL
3291\r
3292 //\r
3293 // Initilize the Date and Time using system time.\r
3294 //\r
3295 ConfigData->CertificateFormat = HASHALG_RAW;\r
3296 ConfigData->AlwaysRevocation = TRUE;\r
3297 gRT->GetTime (&CurrTime, NULL);\r
3298 ConfigData->RevocationDate.Year = CurrTime.Year;\r
3299 ConfigData->RevocationDate.Month = CurrTime.Month;\r
3300 ConfigData->RevocationDate.Day = CurrTime.Day;\r
3301 ConfigData->RevocationTime.Hour = CurrTime.Hour;\r
3302 ConfigData->RevocationTime.Minute = CurrTime.Minute;\r
3303 ConfigData->RevocationTime.Second = 0;\r
4de754e1
ZC
3304 if (Private->FileContext->FHandle != NULL) {\r
3305 ConfigData->FileEnrollType = Private->FileContext->FileType;\r
3306 } else {\r
3307 ConfigData->FileEnrollType = UNKNOWN_FILE_TYPE;\r
3308 }\r
20333c6d 3309\r
ecc722ad 3310 //\r
3311 // If it is Physical Presence User, set the PhysicalPresent to true.\r
3312 //\r
3313 if (UserPhysicalPresent()) {\r
3314 ConfigData->PhysicalPresent = TRUE;\r
3315 } else {\r
3316 ConfigData->PhysicalPresent = FALSE;\r
3317 }\r
20333c6d 3318\r
96832eef
CZ
3319 //\r
3320 // If there is no PK then the Delete Pk button will be gray.\r
3321 //\r
12087ff6
ZC
3322 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
3323 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
96832eef
CZ
3324 ConfigData->HasPk = FALSE;\r
3325 } else {\r
3326 ConfigData->HasPk = TRUE;\r
3327 }\r
3328\r
126f3b1d
ZC
3329 //\r
3330 // Check SecureBootEnable & Pk status, fix the inconsistence. \r
3331 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
3332 // Checkbox.\r
3333 //\r
3334 ConfigData->AttemptSecureBoot = FALSE;\r
3335 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); \r
3336\r
3337 //\r
3338 // Fix Pk, SecureBootEnable inconsistence\r
3339 //\r
f1005559 3340 if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) {\r
126f3b1d
ZC
3341 ConfigData->HideSecureBoot = FALSE;\r
3342 if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) {\r
3343 ConfigData->AttemptSecureBoot = TRUE;\r
3344 }\r
3345 } else {\r
3346 ConfigData->HideSecureBoot = TRUE;\r
3347 }\r
3348\r
12087ff6
ZC
3349 //\r
3350 // Get the SecureBootMode from CustomMode variable.\r
3351 //\r
3352 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
3353 if (SecureBootMode == NULL) {\r
3354 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
3355 } else {\r
3356 ConfigData->SecureBootMode = *(SecureBootMode);\r
3357 }\r
3358\r
f71ed839 3359 if (SecureBootEnable != NULL) {\r
3360 FreePool (SecureBootEnable);\r
3361 }\r
12087ff6
ZC
3362 if (SetupMode != NULL) {\r
3363 FreePool (SetupMode);\r
3364 }\r
f71ed839 3365 if (SecureBootMode != NULL) {\r
3366 FreePool (SecureBootMode);\r
3367 }\r
beda2356 3368}\r
3369\r
3370/**\r
3371 This function allows a caller to extract the current configuration for one\r
3372 or more named elements from the target driver.\r
3373\r
3374 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3375 @param[in] Request A null-terminated Unicode string in\r
3376 <ConfigRequest> format.\r
3377 @param[out] Progress On return, points to a character in the Request\r
3378 string. Points to the string's null terminator if\r
3379 request was successful. Points to the most recent\r
3380 '&' before the first failing name/value pair (or\r
3381 the beginning of the string if the failure is in\r
3382 the first name/value pair) if the request was not\r
3383 successful.\r
3384 @param[out] Results A null-terminated Unicode string in\r
3385 <ConfigAltResp> format which has all values filled\r
3386 in for the names in the Request string. String to\r
3387 be allocated by the called function.\r
3388\r
3389 @retval EFI_SUCCESS The Results is filled with the requested values.\r
3390 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
3391 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
3392 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
3393 driver.\r
3394\r
3395**/\r
3396EFI_STATUS\r
3397EFIAPI\r
3398SecureBootExtractConfig (\r
3399 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3400 IN CONST EFI_STRING Request,\r
3401 OUT EFI_STRING *Progress,\r
3402 OUT EFI_STRING *Results\r
3403 )\r
3404{\r
3405 EFI_STATUS Status;\r
3406 UINTN BufferSize;\r
bc0c99b3 3407 UINTN Size;\r
beda2356 3408 SECUREBOOT_CONFIGURATION Configuration;\r
beda2356 3409 EFI_STRING ConfigRequest;\r
bc0c99b3 3410 EFI_STRING ConfigRequestHdr;\r
bc0c99b3 3411 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
3412 BOOLEAN AllocatedRequest;\r
3413\r
beda2356 3414 if (Progress == NULL || Results == NULL) {\r
3415 return EFI_INVALID_PARAMETER;\r
3416 }\r
20333c6d 3417\r
bc0c99b3 3418 AllocatedRequest = FALSE;\r
3419 ConfigRequestHdr = NULL;\r
3420 ConfigRequest = NULL;\r
3421 Size = 0;\r
20333c6d 3422\r
ea71453f 3423 ZeroMem (&Configuration, sizeof (Configuration));\r
bc0c99b3 3424 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
3425 *Progress = Request;\r
20333c6d 3426\r
beda2356 3427 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
3428 return EFI_NOT_FOUND;\r
3429 }\r
3430\r
4de754e1
ZC
3431 ZeroMem(&Configuration, sizeof(SECUREBOOT_CONFIGURATION));\r
3432\r
beda2356 3433 //\r
ecc722ad 3434 // Get Configuration from Variable.\r
beda2356 3435 //\r
4de754e1 3436 SecureBootExtractConfigFromVariable (PrivateData, &Configuration);\r
f71ed839 3437\r
bc0c99b3 3438 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
beda2356 3439 ConfigRequest = Request;\r
bc0c99b3 3440 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
3441 //\r
3442 // Request is set to NULL or OFFSET is NULL, construct full request string.\r
bc0c99b3 3443 //\r
3444 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
3445 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
3446 //\r
3447 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
3448 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
3449 ConfigRequest = AllocateZeroPool (Size);\r
3450 ASSERT (ConfigRequest != NULL);\r
3451 AllocatedRequest = TRUE;\r
3452 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
3453 FreePool (ConfigRequestHdr);\r
3454 ConfigRequestHdr = NULL;\r
3455 }\r
beda2356 3456\r
3457 Status = gHiiConfigRouting->BlockToConfig (\r
3458 gHiiConfigRouting,\r
3459 ConfigRequest,\r
3460 (UINT8 *) &Configuration,\r
3461 BufferSize,\r
3462 Results,\r
3463 Progress\r
3464 );\r
bc0c99b3 3465\r
3466 //\r
3467 // Free the allocated config request string.\r
3468 //\r
3469 if (AllocatedRequest) {\r
3470 FreePool (ConfigRequest);\r
3471 }\r
3472\r
beda2356 3473 //\r
3474 // Set Progress string to the original request string.\r
3475 //\r
3476 if (Request == NULL) {\r
3477 *Progress = NULL;\r
3478 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
3479 *Progress = Request + StrLen (Request);\r
3480 }\r
3481\r
3482 return Status;\r
3483}\r
3484\r
3485/**\r
3486 This function processes the results of changes in configuration.\r
3487\r
3488 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3489 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>\r
3490 format.\r
3491 @param[out] Progress A pointer to a string filled in with the offset of\r
3492 the most recent '&' before the first failing\r
3493 name/value pair (or the beginning of the string if\r
3494 the failure is in the first name/value pair) or\r
3495 the terminating NULL if all was successful.\r
3496\r
3497 @retval EFI_SUCCESS The Results is processed successfully.\r
3498 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
3499 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
3500 driver.\r
3501\r
3502**/\r
3503EFI_STATUS\r
3504EFIAPI\r
3505SecureBootRouteConfig (\r
3506 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3507 IN CONST EFI_STRING Configuration,\r
3508 OUT EFI_STRING *Progress\r
3509 )\r
3510{\r
4de754e1
ZC
3511 SECUREBOOT_CONFIGURATION IfrNvData;\r
3512 UINTN BufferSize;\r
3513 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
3514 EFI_STATUS Status;\r
20333c6d 3515\r
beda2356 3516 if (Configuration == NULL || Progress == NULL) {\r
3517 return EFI_INVALID_PARAMETER;\r
3518 }\r
3519\r
3520 *Progress = Configuration;\r
3521 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
3522 return EFI_NOT_FOUND;\r
3523 }\r
3524\r
4de754e1
ZC
3525 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
3526\r
a365eed4
FS
3527 //\r
3528 // Get Configuration from Variable.\r
3529 //\r
4de754e1 3530 SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData);\r
a365eed4
FS
3531\r
3532 //\r
3533 // Map the Configuration to the configuration block.\r
3534 //\r
a2f2c258 3535 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
3536 Status = gHiiConfigRouting->ConfigToBlock (\r
3537 gHiiConfigRouting,\r
3538 Configuration,\r
3539 (UINT8 *)&IfrNvData,\r
3540 &BufferSize,\r
3541 Progress\r
3542 );\r
3543 if (EFI_ERROR (Status)) {\r
3544 return Status;\r
3545 }\r
3546\r
3547 //\r
3548 // Store Buffer Storage back to EFI variable if needed\r
3549 //\r
126f3b1d 3550 if (!IfrNvData.HideSecureBoot) {\r
a2f2c258 3551 Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);\r
3552 if (EFI_ERROR (Status)) {\r
3553 return Status;\r
3554 }\r
3555 }\r
3556\r
ecc722ad 3557 *Progress = Configuration + StrLen (Configuration);\r
beda2356 3558 return EFI_SUCCESS;\r
3559}\r
3560\r
85974aef 3561/**\r
3562 This function to load signature list, the update the menu page.\r
3563\r
3564 @param[in] PrivateData Module's private data.\r
3565 @param[in] LabelId Label number to insert opcodes.\r
3566 @param[in] FormId Form ID of current page.\r
3567 @param[in] QuestionIdBase Base question id of the signature list.\r
3568\r
3569 @retval EFI_SUCCESS Success to update the signature list page\r
3570 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
3571**/\r
3572EFI_STATUS\r
3573LoadSignatureList (\r
3574 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
3575 IN UINT16 LabelId,\r
3576 IN EFI_FORM_ID FormId,\r
3577 IN EFI_QUESTION_ID QuestionIdBase\r
3578 )\r
3579{\r
3580 EFI_STATUS Status;\r
3581 EFI_STRING_ID ListType;\r
3539e850 3582 EFI_STRING FormatNameString;\r
3583 EFI_STRING FormatHelpString;\r
3584 EFI_STRING FormatTypeString;\r
85974aef 3585 EFI_SIGNATURE_LIST *ListWalker;\r
3586 EFI_IFR_GUID_LABEL *StartLabel;\r
3587 EFI_IFR_GUID_LABEL *EndLabel;\r
3588 EFI_IFR_GUID_LABEL *StartGoto;\r
3589 EFI_IFR_GUID_LABEL *EndGoto;\r
3590 EFI_FORM_ID DstFormId;\r
3591 VOID *StartOpCodeHandle;\r
3592 VOID *EndOpCodeHandle;\r
3593 VOID *StartGotoHandle;\r
3594 VOID *EndGotoHandle;\r
3595 UINTN DataSize;\r
3596 UINTN RemainingSize;\r
3597 UINT16 Index;\r
3598 UINT8 *VariableData;\r
65c77f02 3599 CHAR16 VariableName[BUFFER_MAX_SIZE];\r
3600 CHAR16 NameBuffer[BUFFER_MAX_SIZE];\r
3601 CHAR16 HelpBuffer[BUFFER_MAX_SIZE];\r
85974aef 3602\r
3603 Status = EFI_SUCCESS;\r
3539e850 3604 FormatNameString = NULL;\r
3605 FormatHelpString = NULL;\r
85974aef 3606 StartOpCodeHandle = NULL;\r
3607 EndOpCodeHandle = NULL;\r
3608 StartGotoHandle = NULL;\r
3609 EndGotoHandle = NULL;\r
3610 Index = 0;\r
3611 VariableData = NULL;\r
85974aef 3612\r
3613 //\r
3614 // Initialize the container for dynamic opcodes.\r
3615 //\r
3616 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
3617 if (StartOpCodeHandle == NULL) {\r
3618 Status = EFI_OUT_OF_RESOURCES;\r
3619 goto ON_EXIT;\r
3620 }\r
3621\r
3622 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
3623 if (EndOpCodeHandle == NULL) {\r
3624 Status = EFI_OUT_OF_RESOURCES;\r
3625 goto ON_EXIT;\r
3626 }\r
3627\r
3628 StartGotoHandle = HiiAllocateOpCodeHandle ();\r
3629 if (StartGotoHandle == NULL) {\r
3630 Status = EFI_OUT_OF_RESOURCES;\r
3631 goto ON_EXIT;\r
3632 }\r
3633\r
3634 EndGotoHandle = HiiAllocateOpCodeHandle ();\r
3635 if (EndGotoHandle == NULL) {\r
3636 Status = EFI_OUT_OF_RESOURCES;\r
3637 goto ON_EXIT;\r
3638 }\r
3639\r
3640 //\r
3641 // Create Hii Extend Label OpCode.\r
3642 //\r
3643 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
3644 StartOpCodeHandle,\r
3645 &gEfiIfrTianoGuid,\r
3646 NULL,\r
3647 sizeof (EFI_IFR_GUID_LABEL)\r
3648 );\r
3649 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3650 StartLabel->Number = LabelId;\r
3651\r
3652 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
3653 EndOpCodeHandle,\r
3654 &gEfiIfrTianoGuid,\r
3655 NULL,\r
3656 sizeof (EFI_IFR_GUID_LABEL)\r
3657 );\r
3658 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3659 EndLabel->Number = LABEL_END;\r
3660\r
3661 StartGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode(\r
3662 StartGotoHandle,\r
3663 &gEfiIfrTianoGuid,\r
3664 NULL,\r
3665 sizeof(EFI_IFR_GUID_LABEL)\r
3666 );\r
3667 StartGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3668 StartGoto->Number = LABEL_DELETE_ALL_LIST_BUTTON;\r
3669\r
3670 EndGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode(\r
3671 EndGotoHandle,\r
3672 &gEfiIfrTianoGuid,\r
3673 NULL,\r
3674 sizeof(EFI_IFR_GUID_LABEL)\r
3675 );\r
3676 EndGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3677 EndGoto->Number = LABEL_END;\r
3678\r
0085d619 3679 if (PrivateData->VariableName == Variable_DB) {\r
65c77f02 3680 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);\r
85974aef 3681 DstFormId = FORMID_SECURE_BOOT_DB_OPTION_FORM;\r
0085d619 3682 } else if (PrivateData->VariableName == Variable_DBX) {\r
65c77f02 3683 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);\r
85974aef 3684 DstFormId = FORMID_SECURE_BOOT_DBX_OPTION_FORM;\r
0085d619 3685 } else if (PrivateData->VariableName == Variable_DBT) {\r
65c77f02 3686 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);\r
85974aef 3687 DstFormId = FORMID_SECURE_BOOT_DBT_OPTION_FORM;\r
3688 } else {\r
3689 goto ON_EXIT;\r
3690 }\r
3691\r
3692 HiiCreateGotoOpCode (\r
3693 StartGotoHandle,\r
3694 DstFormId,\r
3695 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),\r
3696 STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),\r
3697 EFI_IFR_FLAG_CALLBACK,\r
3698 KEY_SECURE_BOOT_DELETE_ALL_LIST\r
3699 );\r
3700\r
3701 //\r
3702 // Read Variable, the variable name save in the PrivateData->VariableName.\r
3703 //\r
3704 DataSize = 0;\r
3705 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
3706 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
3707 goto ON_EXIT;\r
3708 }\r
3709\r
3710 VariableData = AllocateZeroPool (DataSize);\r
3711 if (VariableData == NULL) {\r
3712 Status = EFI_OUT_OF_RESOURCES;\r
3713 goto ON_EXIT;\r
3714 }\r
3715 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
3716 if (EFI_ERROR (Status)) {\r
3717 goto ON_EXIT;\r
3718 }\r
3719\r
3539e850 3720 FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT), NULL);\r
3721 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT), NULL);\r
3722 if (FormatNameString == NULL || FormatHelpString == NULL) {\r
3723 goto ON_EXIT;\r
3724 }\r
3725\r
85974aef 3726 RemainingSize = DataSize;\r
3727 ListWalker = (EFI_SIGNATURE_LIST *)VariableData;\r
3728 while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) {\r
3729 if (CompareGuid (&ListWalker->SignatureType, &gEfiCertRsa2048Guid)) {\r
3730 ListType = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256);\r
3731 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) {\r
3732 ListType = STRING_TOKEN (STR_LIST_TYPE_X509);\r
3733 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha1Guid)) {\r
3734 ListType = STRING_TOKEN (STR_LIST_TYPE_SHA1);\r
3735 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) {\r
3736 ListType = STRING_TOKEN (STR_LIST_TYPE_SHA256);\r
3737 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) {\r
3738 ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);\r
3739 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) {\r
3740 ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384);\r
3741 } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha512Guid)) {\r
3742 ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512);\r
3743 } else {\r
3744 ListType = STRING_TOKEN (STR_LIST_TYPE_UNKNOWN);\r
3745 }\r
3539e850 3746 FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListType, NULL);\r
3747 if (FormatTypeString == NULL) {\r
3748 goto ON_EXIT;\r
3749 }\r
85974aef 3750\r
65c77f02 3751 ZeroMem (NameBuffer, sizeof (NameBuffer));\r
3539e850 3752 UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);\r
65c77f02 3753\r
3754 ZeroMem (HelpBuffer, sizeof (HelpBuffer));\r
85974aef 3755 UnicodeSPrint (HelpBuffer,\r
65c77f02 3756 sizeof (HelpBuffer),\r
3539e850 3757 FormatHelpString,\r
3758 FormatTypeString,\r
85974aef 3759 SIGNATURE_DATA_COUNTS (ListWalker)\r
3760 );\r
3539e850 3761 SECUREBOOT_FREE_NON_NULL (FormatTypeString);\r
3762 FormatTypeString = NULL;\r
85974aef 3763\r
3764 HiiCreateGotoOpCode (\r
3765 StartOpCodeHandle,\r
3766 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,\r
3767 HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),\r
3768 HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL),\r
3769 EFI_IFR_FLAG_CALLBACK,\r
3770 QuestionIdBase + Index++\r
3771 );\r
3772\r
85974aef 3773 RemainingSize -= ListWalker->SignatureListSize;\r
3774 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
3775 }\r
3776\r
3777ON_EXIT:\r
3778 HiiUpdateForm (\r
3779 PrivateData->HiiHandle,\r
3780 &gSecureBootConfigFormSetGuid,\r
3781 FormId,\r
3782 StartOpCodeHandle,\r
3783 EndOpCodeHandle\r
3784 );\r
3785\r
3786 HiiUpdateForm (\r
3787 PrivateData->HiiHandle,\r
3788 &gSecureBootConfigFormSetGuid,\r
3789 FormId,\r
3790 StartGotoHandle,\r
3791 EndGotoHandle\r
3792 );\r
3793\r
3794 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);\r
3795 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);\r
3796 SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle);\r
3797 SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle);\r
3798\r
85974aef 3799 SECUREBOOT_FREE_NON_NULL (VariableData);\r
3539e850 3800 SECUREBOOT_FREE_NON_NULL (FormatNameString);\r
3801 SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
85974aef 3802\r
3803 PrivateData->ListCount = Index;\r
3804\r
3805 return Status;\r
3806}\r
3807\r
3808/**\r
3809 Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.\r
3810 The buffer is callee allocated and should be freed by the caller.\r
3811\r
3812 @param[in] ListEntry The pointer point to the signature list.\r
3813 @param[in] DataEntry The signature data we are processing.\r
3814 @param[out] BufferToReturn Buffer to save the hash value.\r
3815\r
3816 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.\r
3817 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
3818 @retval EFI_SUCCESS Operation success.\r
3819**/\r
3820EFI_STATUS\r
3821ParseHashValue (\r
3822 IN EFI_SIGNATURE_LIST *ListEntry,\r
3823 IN EFI_SIGNATURE_DATA *DataEntry,\r
3824 OUT CHAR16 **BufferToReturn\r
3825 )\r
3826{\r
3827 UINTN Index;\r
3828 UINTN BufferIndex;\r
3829 UINTN TotalSize;\r
3830 UINTN DataSize;\r
3831 UINTN Line;\r
3832 UINTN OneLineBytes;\r
3833\r
3834 //\r
3835 // Assume that, display 8 bytes in one line.\r
3836 //\r
3837 OneLineBytes = 8;\r
3838\r
3839 if (ListEntry == NULL || DataEntry == NULL || BufferToReturn == NULL) {\r
3840 return EFI_INVALID_PARAMETER;\r
3841 }\r
3842\r
3843 DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);\r
3844 Line = (DataSize + OneLineBytes - 1) / OneLineBytes;\r
3845\r
3846 //\r
3847 // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.\r
3848 //\r
3849 TotalSize = ((DataSize + Line) * 2 * sizeof(CHAR16));\r
3850\r
3851 *BufferToReturn = AllocateZeroPool(TotalSize);\r
3852 if (*BufferToReturn == NULL) {\r
3853 return EFI_OUT_OF_RESOURCES;\r
3854 }\r
3855\r
3856 for (Index = 0, BufferIndex = 0; Index < DataSize; Index = Index + 1) {\r
3857 if ((Index > 0) && (Index % OneLineBytes == 0)) {\r
3858 BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"\n");\r
3859 }\r
3860 BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"%02x", DataEntry->SignatureData[Index]);\r
3861 }\r
3862 BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"\n");\r
3863\r
3864 return EFI_SUCCESS;\r
3865}\r
3866\r
3867/**\r
3868 Function to get the common name from the X509 format certificate.\r
3869 The buffer is callee allocated and should be freed by the caller.\r
3870\r
3871 @param[in] ListEntry The pointer point to the signature list.\r
3872 @param[in] DataEntry The signature data we are processing.\r
3873 @param[out] BufferToReturn Buffer to save the CN of X509 certificate.\r
3874\r
3875 @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.\r
3876 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
3877 @retval EFI_SUCCESS Operation success.\r
3878 @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.\r
3879**/\r
3880EFI_STATUS\r
3881GetCommonNameFromX509 (\r
3882 IN EFI_SIGNATURE_LIST *ListEntry,\r
3883 IN EFI_SIGNATURE_DATA *DataEntry,\r
3884 OUT CHAR16 **BufferToReturn\r
3885 )\r
3886{\r
3887 EFI_STATUS Status;\r
3888 CHAR8 *CNBuffer;\r
3889 UINTN CNBufferSize;\r
3890\r
3891 Status = EFI_SUCCESS;\r
3892 CNBuffer = NULL;\r
3893\r
3894 CNBuffer = AllocateZeroPool(256);\r
3895 if (CNBuffer == NULL) {\r
3896 Status = EFI_OUT_OF_RESOURCES;\r
3897 goto ON_EXIT;\r
3898 }\r
3899\r
3900 CNBufferSize = 256;\r
3901 X509GetCommonName (\r
3902 (UINT8 *)DataEntry + sizeof(EFI_GUID),\r
3903 ListEntry->SignatureSize - sizeof(EFI_GUID),\r
3904 CNBuffer,\r
3905 &CNBufferSize\r
3906 );\r
3907\r
3908 *BufferToReturn = AllocateZeroPool(256 * sizeof(CHAR16));\r
3909 if (*BufferToReturn == NULL) {\r
3910 Status = EFI_OUT_OF_RESOURCES;\r
3911 goto ON_EXIT;\r
3912 }\r
3913\r
3914 AsciiStrToUnicodeStrS (CNBuffer, *BufferToReturn, 256);\r
3915\r
3916ON_EXIT:\r
3917 SECUREBOOT_FREE_NON_NULL (CNBuffer);\r
3918\r
3919 return Status;\r
3920}\r
3921\r
3922/**\r
3923 Format the help info for the signature data, each help info contain 3 parts.\r
3924 1. Onwer Guid.\r
3925 2. Content, depends on the type of the signature list.\r
3926 3. Revocation time.\r
3927\r
3928 @param[in] PrivateData Module's private data.\r
3929 @param[in] ListEntry Point to the signature list.\r
3930 @param[in] DataEntry Point to the signature data we are processing.\r
3931 @param[out] StringId Save the string id of help info.\r
3932\r
3933 @retval EFI_SUCCESS Operation success.\r
3934 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
3935**/\r
3936EFI_STATUS\r
3937FormatHelpInfo (\r
3938 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
3939 IN EFI_SIGNATURE_LIST *ListEntry,\r
3940 IN EFI_SIGNATURE_DATA *DataEntry,\r
3941 OUT EFI_STRING_ID *StringId\r
3942 )\r
3943{\r
3944 EFI_STATUS Status;\r
3945 EFI_TIME *Time;\r
3946 EFI_STRING_ID ListTypeId;\r
3539e850 3947 EFI_STRING FormatHelpString;\r
3948 EFI_STRING FormatTypeString;\r
85974aef 3949 UINTN DataSize;\r
3950 UINTN HelpInfoIndex;\r
3951 UINTN TotalSize;\r
65c77f02 3952 CHAR16 GuidString[BUFFER_MAX_SIZE];\r
3953 CHAR16 TimeString[BUFFER_MAX_SIZE];\r
85974aef 3954 CHAR16 *DataString;\r
85974aef 3955 CHAR16 *HelpInfoString;\r
3956 BOOLEAN IsCert;\r
3957\r
3539e850 3958 Status = EFI_SUCCESS;\r
3959 Time = NULL;\r
3960 FormatTypeString = NULL;\r
3961 HelpInfoIndex = 0;\r
3962 DataString = NULL;\r
3963 HelpInfoString = NULL;\r
3964 IsCert = FALSE;\r
85974aef 3965\r
3966 if (CompareGuid(&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) {\r
3967 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256);\r
3968 DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);\r
3969 IsCert = TRUE;\r
3970 } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Guid)) {\r
3971 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509);\r
3972 DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);\r
3973 IsCert = TRUE;\r
3974 } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha1Guid)) {\r
3975 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA1);\r
3976 DataSize = 20;\r
3977 } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha256Guid)) {\r
3978 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA256);\r
3979 DataSize = 32;\r
3980 } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) {\r
3981 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA256);\r
3982 DataSize = 32;\r
3983 Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);\r
3984 } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha384Guid)) {\r
3985 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA384);\r
3986 DataSize = 48;\r
3987 Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);\r
3988 } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha512Guid)) {\r
3989 ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA512);\r
3990 DataSize = 64;\r
3991 Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);\r
3992 } else {\r
3993 Status = EFI_UNSUPPORTED;\r
3994 goto ON_EXIT;\r
3995 }\r
3996\r
3539e850 3997 FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListTypeId, NULL);\r
3998 if (FormatTypeString == NULL) {\r
3999 goto ON_EXIT;\r
4000 }\r
4001\r
85974aef 4002 TotalSize = 1024;\r
4003 HelpInfoString = AllocateZeroPool (TotalSize);\r
4004 if (HelpInfoString == NULL) {\r
4005 Status = EFI_OUT_OF_RESOURCES;\r
4006 goto ON_EXIT;\r
4007 }\r
4008\r
4009 //\r
4010 // Format GUID part.\r
4011 //\r
65c77f02 4012 ZeroMem (GuidString, sizeof (GuidString));\r
4013 GuidToString(&DataEntry->SignatureOwner, GuidString, BUFFER_MAX_SIZE);\r
3539e850 4014 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID), NULL);\r
4015 if (FormatHelpString == NULL) {\r
4016 goto ON_EXIT;\r
4017 }\r
85974aef 4018 HelpInfoIndex += UnicodeSPrint (\r
4019 &HelpInfoString[HelpInfoIndex],\r
4020 TotalSize - sizeof(CHAR16) * HelpInfoIndex,\r
3539e850 4021 FormatHelpString,\r
85974aef 4022 GuidString\r
4023 );\r
3539e850 4024 SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
4025 FormatHelpString = NULL;\r
85974aef 4026\r
4027 //\r
4028 // Format content part, it depends on the type of signature list, hash value or CN.\r
4029 //\r
4030 if (IsCert) {\r
4031 GetCommonNameFromX509 (ListEntry, DataEntry, &DataString);\r
3539e850 4032 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN), NULL);\r
85974aef 4033 } else {\r
4034 //\r
4035 // Format hash value for each signature data entry.\r
4036 //\r
4037 ParseHashValue (ListEntry, DataEntry, &DataString);\r
3539e850 4038 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH), NULL);\r
4039 }\r
4040 if (FormatHelpString == NULL) {\r
4041 goto ON_EXIT;\r
85974aef 4042 }\r
3539e850 4043 HelpInfoIndex += UnicodeSPrint (\r
4044 &HelpInfoString[HelpInfoIndex],\r
4045 TotalSize - sizeof (CHAR16) * HelpInfoIndex,\r
4046 FormatHelpString,\r
4047 FormatTypeString,\r
4048 DataSize,\r
4049 DataString\r
4050 );\r
4051 SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
4052 FormatHelpString = NULL;\r
85974aef 4053\r
4054 //\r
4055 // Format revocation time part.\r
4056 //\r
4057 if (Time != NULL) {\r
65c77f02 4058 ZeroMem (TimeString, sizeof (TimeString));\r
85974aef 4059 UnicodeSPrint (\r
4060 TimeString,\r
65c77f02 4061 sizeof (TimeString),\r
85974aef 4062 L"%d-%d-%d %d:%d:%d",\r
4063 Time->Year,\r
4064 Time->Month,\r
4065 Time->Day,\r
4066 Time->Hour,\r
4067 Time->Minute,\r
4068 Time->Second\r
4069 );\r
3539e850 4070 FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME), NULL);\r
4071 if (FormatHelpString == NULL) {\r
4072 goto ON_EXIT;\r
4073 }\r
85974aef 4074 UnicodeSPrint (\r
4075 &HelpInfoString[HelpInfoIndex],\r
4076 TotalSize - sizeof (CHAR16) * HelpInfoIndex,\r
3539e850 4077 FormatHelpString,\r
85974aef 4078 TimeString\r
4079 );\r
3539e850 4080 SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
4081 FormatHelpString = NULL;\r
85974aef 4082 }\r
4083\r
4084 *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL);\r
85974aef 4085ON_EXIT:\r
85974aef 4086 SECUREBOOT_FREE_NON_NULL (DataString);\r
85974aef 4087 SECUREBOOT_FREE_NON_NULL (HelpInfoString);\r
4088\r
3539e850 4089 SECUREBOOT_FREE_NON_NULL (FormatTypeString);\r
4090\r
85974aef 4091 return Status;\r
4092}\r
4093\r
4094/**\r
4095 This functino to load signature data under the signature list.\r
4096\r
4097 @param[in] PrivateData Module's private data.\r
4098 @param[in] LabelId Label number to insert opcodes.\r
4099 @param[in] FormId Form ID of current page.\r
4100 @param[in] QuestionIdBase Base question id of the signature list.\r
4101 @param[in] ListIndex Indicate to load which signature list.\r
4102\r
4103 @retval EFI_SUCCESS Success to update the signature list page\r
4104 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
4105**/\r
4106EFI_STATUS\r
4107LoadSignatureData (\r
4108 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
4109 IN UINT16 LabelId,\r
4110 IN EFI_FORM_ID FormId,\r
4111 IN EFI_QUESTION_ID QuestionIdBase,\r
4112 IN UINT16 ListIndex\r
4113 )\r
4114{\r
4115 EFI_STATUS Status;\r
4116 EFI_SIGNATURE_LIST *ListWalker;\r
4117 EFI_SIGNATURE_DATA *DataWalker;\r
4118 EFI_IFR_GUID_LABEL *StartLabel;\r
4119 EFI_IFR_GUID_LABEL *EndLabel;\r
4120 EFI_STRING_ID HelpStringId;\r
3539e850 4121 EFI_STRING FormatNameString;\r
85974aef 4122 VOID *StartOpCodeHandle;\r
4123 VOID *EndOpCodeHandle;\r
4124 UINTN DataSize;\r
4125 UINTN RemainingSize;\r
4126 UINT16 Index;\r
4127 UINT8 *VariableData;\r
65c77f02 4128 CHAR16 VariableName[BUFFER_MAX_SIZE];\r
4129 CHAR16 NameBuffer[BUFFER_MAX_SIZE];\r
85974aef 4130\r
4131 Status = EFI_SUCCESS;\r
3539e850 4132 FormatNameString = NULL;\r
85974aef 4133 StartOpCodeHandle = NULL;\r
4134 EndOpCodeHandle = NULL;\r
4135 Index = 0;\r
4136 VariableData = NULL;\r
85974aef 4137\r
4138 //\r
4139 // Initialize the container for dynamic opcodes.\r
4140 //\r
4141 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
4142 if (StartOpCodeHandle == NULL) {\r
4143 Status = EFI_OUT_OF_RESOURCES;\r
4144 goto ON_EXIT;\r
4145 }\r
4146\r
4147 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
4148 if (EndOpCodeHandle == NULL) {\r
4149 Status = EFI_OUT_OF_RESOURCES;\r
4150 goto ON_EXIT;\r
4151 }\r
4152\r
4153 //\r
4154 // Create Hii Extend Label OpCode.\r
4155 //\r
4156 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
4157 StartOpCodeHandle,\r
4158 &gEfiIfrTianoGuid,\r
4159 NULL,\r
4160 sizeof (EFI_IFR_GUID_LABEL)\r
4161 );\r
4162 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
4163 StartLabel->Number = LabelId;\r
4164\r
4165 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
4166 EndOpCodeHandle,\r
4167 &gEfiIfrTianoGuid,\r
4168 NULL,\r
4169 sizeof (EFI_IFR_GUID_LABEL)\r
4170 );\r
4171 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
4172 EndLabel->Number = LABEL_END;\r
4173\r
0085d619 4174 if (PrivateData->VariableName == Variable_DB) {\r
65c77f02 4175 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);\r
0085d619 4176 } else if (PrivateData->VariableName == Variable_DBX) {\r
65c77f02 4177 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);\r
0085d619 4178 } else if (PrivateData->VariableName == Variable_DBT) {\r
65c77f02 4179 UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);\r
85974aef 4180 } else {\r
4181 goto ON_EXIT;\r
4182 }\r
4183\r
4184 //\r
4185 // Read Variable, the variable name save in the PrivateData->VariableName.\r
4186 //\r
4187 DataSize = 0;\r
4188 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
4189 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
4190 goto ON_EXIT;\r
4191 }\r
4192\r
4193 VariableData = AllocateZeroPool (DataSize);\r
4194 if (VariableData == NULL) {\r
4195 Status = EFI_OUT_OF_RESOURCES;\r
4196 goto ON_EXIT;\r
4197 }\r
4198 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
4199 if (EFI_ERROR (Status)) {\r
4200 goto ON_EXIT;\r
4201 }\r
4202\r
85974aef 4203 RemainingSize = DataSize;\r
4204 ListWalker = (EFI_SIGNATURE_LIST *)VariableData;\r
4205\r
4206 //\r
4207 // Skip signature list.\r
4208 //\r
4209 while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex-- > 0) {\r
4210 RemainingSize -= ListWalker->SignatureListSize;\r
4211 ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
4212 }\r
4213\r
3539e850 4214 FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT), NULL);\r
4215 if (FormatNameString == NULL) {\r
4216 goto ON_EXIT;\r
4217 }\r
4218\r
85974aef 4219 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof(EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);\r
4220 for (Index = 0; Index < SIGNATURE_DATA_COUNTS(ListWalker); Index = Index + 1) {\r
4221 //\r
4222 // Format name buffer.\r
4223 //\r
65c77f02 4224 ZeroMem (NameBuffer, sizeof (NameBuffer));\r
3539e850 4225 UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);\r
85974aef 4226\r
4227 //\r
4228 // Format help info buffer.\r
4229 //\r
4230 Status = FormatHelpInfo (PrivateData, ListWalker, DataWalker, &HelpStringId);\r
4231 if (EFI_ERROR (Status)) {\r
4232 goto ON_EXIT;\r
4233 }\r
4234\r
4235 HiiCreateCheckBoxOpCode (\r
4236 StartOpCodeHandle,\r
4237 (EFI_QUESTION_ID)(QuestionIdBase + Index),\r
4238 0,\r
4239 0,\r
4240 HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),\r
4241 HelpStringId,\r
4242 EFI_IFR_FLAG_CALLBACK,\r
4243 0,\r
4244 NULL\r
4245 );\r
4246\r
4247 ZeroMem(NameBuffer, 100);\r
4248 DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);\r
4249 }\r
4250\r
4251 //\r
4252 // Allocate a buffer to record which signature data will be checked.\r
4253 // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.\r
4254 //\r
4255 PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker) * sizeof (BOOLEAN));\r
85974aef 4256ON_EXIT:\r
4257 HiiUpdateForm (\r
4258 PrivateData->HiiHandle,\r
4259 &gSecureBootConfigFormSetGuid,\r
4260 FormId,\r
4261 StartOpCodeHandle,\r
4262 EndOpCodeHandle\r
4263 );\r
4264\r
4265 SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);\r
4266 SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);\r
4267\r
85974aef 4268 SECUREBOOT_FREE_NON_NULL (VariableData);\r
3539e850 4269 SECUREBOOT_FREE_NON_NULL (FormatNameString);\r
85974aef 4270\r
4271 return Status;\r
4272}\r
4273\r
beda2356 4274/**\r
ecc722ad 4275 This function is called to provide results data to the driver.\r
beda2356 4276\r
4277 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
4278 @param[in] Action Specifies the type of action taken by the browser.\r
4279 @param[in] QuestionId A unique value which is sent to the original\r
4280 exporting driver so that it can identify the type\r
4281 of data to expect.\r
4282 @param[in] Type The type of value for the question.\r
4283 @param[in] Value A pointer to the data being sent to the original\r
4284 exporting driver.\r
4285 @param[out] ActionRequest On return, points to the action requested by the\r
4286 callback function.\r
4287\r
4288 @retval EFI_SUCCESS The callback successfully handled the action.\r
4289 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
4290 variable and its data.\r
4291 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
4292 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
4293 callback.\r
4294\r
4295**/\r
4296EFI_STATUS\r
4297EFIAPI\r
4298SecureBootCallback (\r
4299 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
4300 IN EFI_BROWSER_ACTION Action,\r
4301 IN EFI_QUESTION_ID QuestionId,\r
4302 IN UINT8 Type,\r
4303 IN EFI_IFR_TYPE_VALUE *Value,\r
4304 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
4305 )\r
4306{\r
ecc722ad 4307 EFI_INPUT_KEY Key;\r
20333c6d 4308 EFI_STATUS Status;\r
2a085774 4309 RETURN_STATUS RStatus;\r
ecc722ad 4310 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;\r
4311 UINTN BufferSize;\r
4312 SECUREBOOT_CONFIGURATION *IfrNvData;\r
4313 UINT16 LabelId;\r
bf4a3dbd 4314 UINT8 *SecureBootEnable;\r
126f3b1d 4315 UINT8 *Pk;\r
f71ed839 4316 UINT8 *SecureBootMode;\r
12087ff6 4317 UINT8 *SetupMode;\r
e4d7370d 4318 CHAR16 PromptString[100];\r
762d8ddb 4319 EFI_DEVICE_PATH_PROTOCOL *File;\r
4de754e1
ZC
4320 UINTN NameLength;\r
4321 UINT16 *FilePostFix;\r
4322 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
488aab25 4323 BOOLEAN GetBrowserDataResult;\r
bf4a3dbd 4324\r
96832eef 4325 Status = EFI_SUCCESS;\r
bf4a3dbd 4326 SecureBootEnable = NULL;\r
f71ed839 4327 SecureBootMode = NULL;\r
12087ff6 4328 SetupMode = NULL;\r
762d8ddb 4329 File = NULL;\r
bc0c99b3 4330\r
beda2356 4331 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
4332 return EFI_INVALID_PARAMETER;\r
4333 }\r
12087ff6 4334\r
96832eef
CZ
4335 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
4336\r
762d8ddb
DB
4337 gSecureBootPrivateData = Private;\r
4338\r
96832eef
CZ
4339 //\r
4340 // Retrieve uncommitted data from Browser\r
4341 //\r
4342 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
4343 IfrNvData = AllocateZeroPool (BufferSize);\r
4344 if (IfrNvData == NULL) {\r
4345 return EFI_OUT_OF_RESOURCES;\r
4346 }\r
4347\r
488aab25 4348 GetBrowserDataResult = HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
beda2356 4349\r
a365eed4
FS
4350 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
4351 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
02dd6af9
CZ
4352 //\r
4353 // Update secure boot strings when opening this form\r
4354 //\r
4355 Status = UpdateSecureBootString(Private);\r
4de754e1 4356 SecureBootExtractConfigFromVariable (Private, IfrNvData);\r
a365eed4 4357 mIsEnterSecureBootForm = TRUE;\r
4de754e1
ZC
4358 } else {\r
4359 //\r
4360 // When entering SecureBoot OPTION Form\r
4361 // always close opened file & free resource\r
4362 //\r
4363 if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) ||\r
4364 (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) ||\r
4365 (QuestionId == KEY_SECURE_BOOT_DB_OPTION) ||\r
4366 (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) ||\r
4367 (QuestionId == KEY_SECURE_BOOT_DBT_OPTION)) {\r
4368 CloseEnrolledFile(Private->FileContext);\r
85974aef 4369 } else if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_LIST) {\r
4370 //\r
4371 // Update ListCount field in varstore\r
4372 // Button "Delete All Signature List" is\r
4373 // enable when ListCount is greater than 0.\r
4374 //\r
4375 IfrNvData->ListCount = Private->ListCount;\r
4de754e1 4376 }\r
a365eed4 4377 }\r
96832eef 4378 goto EXIT;\r
a365eed4 4379 }\r
20333c6d 4380\r
a365eed4
FS
4381 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
4382 Status = EFI_UNSUPPORTED;\r
4383 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
4384 if (mIsEnterSecureBootForm) {\r
4385 Value->u8 = SECURE_BOOT_MODE_STANDARD;\r
4386 Status = EFI_SUCCESS;\r
4387 }\r
12087ff6 4388 } \r
96832eef 4389 goto EXIT;\r
a365eed4 4390 }\r
20333c6d 4391\r
f71ed839 4392 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
4393 (Action != EFI_BROWSER_ACTION_CHANGING) &&\r
a2f2c258 4394 (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&\r
4395 (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {\r
96832eef
CZ
4396 Status = EFI_UNSUPPORTED;\r
4397 goto EXIT;\r
beda2356 4398 }\r
bc0c99b3 4399\r
ecc722ad 4400 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
4401\r
4402 switch (QuestionId) {\r
4403 case KEY_SECURE_BOOT_ENABLE:\r
f01b91ae 4404 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
bf4a3dbd 4405 if (NULL != SecureBootEnable) {\r
f71ed839 4406 FreePool (SecureBootEnable);\r
ecc722ad 4407 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {\r
4408 CreatePopUp (\r
4409 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4410 &Key,\r
4411 L"Only Physical Presence User could disable secure boot!",\r
4412 NULL\r
4413 );\r
4414 Status = EFI_UNSUPPORTED;\r
0357efe3 4415 } else {\r
4416 CreatePopUp (\r
4417 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4418 &Key,\r
f71ed839 4419 L"Configuration changed, please reset the platform to take effect!",\r
0357efe3 4420 NULL\r
4421 );\r
ecc722ad 4422 }\r
ecc722ad 4423 }\r
4424 break;\r
4425\r
ecc722ad 4426 case KEY_SECURE_BOOT_KEK_OPTION:\r
4427 case KEY_SECURE_BOOT_DB_OPTION:\r
4428 case KEY_SECURE_BOOT_DBX_OPTION:\r
20333c6d 4429 case KEY_SECURE_BOOT_DBT_OPTION:\r
4de754e1 4430 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
ecc722ad 4431 //\r
4432 // Clear Signature GUID.\r
4433 //\r
4434 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));\r
4435 if (Private->SignatureGUID == NULL) {\r
4436 Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
4437 if (Private->SignatureGUID == NULL) {\r
4438 return EFI_OUT_OF_RESOURCES;\r
4439 }\r
4440 }\r
beda2356 4441\r
4de754e1
ZC
4442 //\r
4443 // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page\r
4444 //\r
4445 SecureBootExtractConfigFromVariable (PrivateData, IfrNvData);\r
4446\r
ecc722ad 4447 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {\r
4448 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
4449 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {\r
4450 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
20333c6d
QL
4451 } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {\r
4452 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;\r
ecc722ad 4453 } else {\r
4454 LabelId = FORMID_ENROLL_KEK_FORM;\r
4455 }\r
4456\r
4457 //\r
4458 // Refresh selected file.\r
4459 //\r
20333c6d 4460 CleanUpPage (LabelId, Private);\r
ecc722ad 4461 break;\r
762d8ddb
DB
4462 case KEY_SECURE_BOOT_PK_OPTION:\r
4463 LabelId = FORMID_ENROLL_PK_FORM;\r
4464 //\r
4465 // Refresh selected file.\r
4466 //\r
4467 CleanUpPage (LabelId, Private);\r
4468 break;\r
4469\r
4470 case FORMID_ENROLL_PK_FORM:\r
d6224153 4471 ChooseFile (NULL, NULL, UpdatePKFromFile, &File);\r
762d8ddb 4472 break;\r
20333c6d 4473\r
ecc722ad 4474 case FORMID_ENROLL_KEK_FORM:\r
d6224153 4475 ChooseFile (NULL, NULL, UpdateKEKFromFile, &File);\r
762d8ddb
DB
4476 break;\r
4477\r
ecc722ad 4478 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
d6224153 4479 ChooseFile (NULL, NULL, UpdateDBFromFile, &File);\r
762d8ddb
DB
4480 break;\r
4481\r
ecc722ad 4482 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
d6224153 4483 ChooseFile (NULL, NULL, UpdateDBXFromFile, &File);\r
4de754e1
ZC
4484\r
4485 if (Private->FileContext->FHandle != NULL) {\r
4486 //\r
4487 // Parse the file's postfix.\r
4488 //\r
4489 NameLength = StrLen (Private->FileContext->FileName);\r
4490 if (NameLength <= 4) {\r
4491 return FALSE;\r
4492 }\r
4493 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
4494\r
4495 if (IsDerEncodeCertificate (FilePostFix)) {\r
4496 //\r
4497 // Supports DER-encoded X509 certificate.\r
4498 //\r
4499 IfrNvData->FileEnrollType = X509_CERT_FILE_TYPE;\r
4500 } else if (IsAuthentication2Format(Private->FileContext->FHandle)){\r
4501 IfrNvData->FileEnrollType = AUTHENTICATION_2_FILE_TYPE;\r
4502 } else {\r
4503 IfrNvData->FileEnrollType = PE_IMAGE_FILE_TYPE;\r
4504 }\r
4505 Private->FileContext->FileType = IfrNvData->FileEnrollType;\r
4506\r
4507 //\r
4508 // Clean up Certificate Format if File type is not X509 DER\r
4509 //\r
4510 if (IfrNvData->FileEnrollType != X509_CERT_FILE_TYPE) {\r
4511 IfrNvData->CertificateFormat = HASHALG_RAW;\r
4512 }\r
4513 DEBUG((DEBUG_ERROR, "IfrNvData->FileEnrollType %d\n", Private->FileContext->FileType));\r
4514 }\r
4515\r
762d8ddb 4516 break;\r
ecc722ad 4517\r
762d8ddb 4518 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:\r
d6224153 4519 ChooseFile (NULL, NULL, UpdateDBTFromFile, &File);\r
ecc722ad 4520 break;\r
4521\r
20333c6d 4522 case KEY_SECURE_BOOT_DELETE_PK:\r
f71ed839 4523 if (Value->u8) {\r
4524 CreatePopUp (\r
4525 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4526 &Key,\r
4527 L"Are you sure you want to delete PK? Secure boot will be disabled!",\r
4528 L"Press 'Y' to delete PK and exit, 'N' to discard change and return",\r
4529 NULL\r
4530 );\r
4531 if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {\r
ecc722ad 4532 Status = DeletePlatformKey ();\r
f71ed839 4533 if (EFI_ERROR (Status)) {\r
4534 CreatePopUp (\r
4535 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4536 &Key,\r
4537 L"Only Physical Presence User could delete PK in custom mode!",\r
4538 NULL\r
4539 );\r
4540 }\r
ecc722ad 4541 }\r
f71ed839 4542 }\r
ecc722ad 4543 break;\r
4544\r
4545 case KEY_DELETE_KEK:\r
4546 UpdateDeletePage (\r
20333c6d 4547 Private,\r
ecc722ad 4548 EFI_KEY_EXCHANGE_KEY_NAME,\r
4549 &gEfiGlobalVariableGuid,\r
4550 LABEL_KEK_DELETE,\r
4551 FORMID_DELETE_KEK_FORM,\r
20333c6d 4552 OPTION_DEL_KEK_QUESTION_ID\r
ecc722ad 4553 );\r
4554 break;\r
4555\r
20333c6d 4556 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:\r
ecc722ad 4557 UpdateDeletePage (\r
4558 Private,\r
4559 EFI_IMAGE_SECURITY_DATABASE,\r
4560 &gEfiImageSecurityDatabaseGuid,\r
4561 LABEL_DB_DELETE,\r
4562 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
4563 OPTION_DEL_DB_QUESTION_ID\r
4564 );\r
4565 break;\r
4566\r
85974aef 4567 //\r
4568 // From DBX option to the level-1 form, display signature list.\r
4569 //\r
4570 case KEY_VALUE_FROM_DBX_TO_LIST_FORM:\r
0085d619 4571 Private->VariableName = Variable_DBX;\r
85974aef 4572 LoadSignatureList (\r
ecc722ad 4573 Private,\r
85974aef 4574 LABEL_SIGNATURE_LIST_START,\r
4575 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
4576 OPTION_SIGNATURE_LIST_QUESTION_ID\r
4577 );\r
4578 break;\r
4579\r
4580 //\r
4581 // Delete all signature list and reload.\r
4582 //\r
4583 case KEY_SECURE_BOOT_DELETE_ALL_LIST:\r
4584 CreatePopUp(\r
4585 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4586 &Key,\r
4587 L"Press 'Y' to delete signature list.",\r
4588 L"Press other key to cancel and exit.",\r
4589 NULL\r
4590 );\r
4591\r
4592 if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
0085d619 4593 DeleteSignatureEx (Private, Delete_Signature_List_All, IfrNvData->CheckedDataCount);\r
85974aef 4594 }\r
4595\r
4596 LoadSignatureList (\r
4597 Private,\r
4598 LABEL_SIGNATURE_LIST_START,\r
4599 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
4600 OPTION_SIGNATURE_LIST_QUESTION_ID\r
4601 );\r
4602 break;\r
ecc722ad 4603\r
85974aef 4604 //\r
4605 // Delete one signature list and reload.\r
4606 //\r
4607 case KEY_SECURE_BOOT_DELETE_ALL_DATA:\r
4608 CreatePopUp(\r
4609 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4610 &Key,\r
4611 L"Press 'Y' to delete signature data.",\r
4612 L"Press other key to cancel and exit.",\r
4613 NULL\r
4614 );\r
4615\r
4616 if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
0085d619 4617 DeleteSignatureEx (Private, Delete_Signature_List_One, IfrNvData->CheckedDataCount);\r
85974aef 4618 }\r
4619\r
4620 LoadSignatureList (\r
4621 Private,\r
4622 LABEL_SIGNATURE_LIST_START,\r
4623 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
4624 OPTION_SIGNATURE_LIST_QUESTION_ID\r
4625 );\r
4626 break;\r
4627\r
4628 //\r
4629 // Delete checked signature data and reload.\r
4630 //\r
4631 case KEY_SECURE_BOOT_DELETE_CHECK_DATA:\r
4632 CreatePopUp(\r
4633 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4634 &Key,\r
4635 L"Press 'Y' to delete signature data.",\r
4636 L"Press other key to cancel and exit.",\r
4637 NULL\r
4638 );\r
4639\r
4640 if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
0085d619 4641 DeleteSignatureEx (Private, Delete_Signature_Data, IfrNvData->CheckedDataCount);\r
85974aef 4642 }\r
4643\r
4644 LoadSignatureList (\r
4645 Private,\r
4646 LABEL_SIGNATURE_LIST_START,\r
4647 SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
4648 OPTION_SIGNATURE_LIST_QUESTION_ID\r
4649 );\r
ecc722ad 4650 break;\r
4651\r
20333c6d
QL
4652 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:\r
4653 UpdateDeletePage (\r
4654 Private,\r
4655 EFI_IMAGE_SECURITY_DATABASE2,\r
4656 &gEfiImageSecurityDatabaseGuid,\r
4657 LABEL_DBT_DELETE,\r
4658 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
4659 OPTION_DEL_DBT_QUESTION_ID\r
4660 );\r
4661\r
4662 break;\r
4663\r
ecc722ad 4664 case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
4665 Status = EnrollKeyExchangeKey (Private);\r
ee79ac8d 4666 if (EFI_ERROR (Status)) {\r
4667 CreatePopUp (\r
4668 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4669 &Key,\r
4670 L"ERROR: Unsupported file type!",\r
4671 L"Only supports DER-encoded X509 certificate",\r
4672 NULL\r
4673 );\r
4674 }\r
ecc722ad 4675 break;\r
4676\r
4677 case KEY_VALUE_SAVE_AND_EXIT_DB:\r
4678 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
ee79ac8d 4679 if (EFI_ERROR (Status)) {\r
4680 CreatePopUp (\r
4681 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4682 &Key,\r
4683 L"ERROR: Unsupported file type!",\r
4684 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
4685 NULL\r
4686 );\r
4687 }\r
ecc722ad 4688 break;\r
4689\r
4690 case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
20333c6d
QL
4691 if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {\r
4692 CreatePopUp (\r
4693 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4694 &Key,\r
4695 L"Enrollment failed! Same certificate had already been in the dbx!",\r
4696 NULL\r
4697 );\r
4de754e1
ZC
4698\r
4699 //\r
4700 // Cert already exists in DBX. Close opened file before exit.\r
4701 //\r
4702 CloseEnrolledFile(Private->FileContext);\r
4703 break;\r
20333c6d
QL
4704 }\r
4705\r
4706 if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {\r
4707 Status = EnrollX509HashtoSigDB (\r
4708 Private,\r
4709 IfrNvData->CertificateFormat,\r
4710 &IfrNvData->RevocationDate,\r
4711 &IfrNvData->RevocationTime,\r
4712 IfrNvData->AlwaysRevocation\r
4713 );\r
4de754e1 4714 IfrNvData->CertificateFormat = HASHALG_RAW;\r
20333c6d
QL
4715 } else {\r
4716 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
4717 }\r
ee79ac8d 4718 if (EFI_ERROR (Status)) {\r
4719 CreatePopUp (\r
4720 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4721 &Key,\r
4722 L"ERROR: Unsupported file type!",\r
4de754e1 4723 L"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",\r
ee79ac8d 4724 NULL\r
4725 );\r
4726 }\r
ecc722ad 4727 break;\r
4728\r
20333c6d
QL
4729 case KEY_VALUE_SAVE_AND_EXIT_DBT:\r
4730 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);\r
4731 if (EFI_ERROR (Status)) {\r
4732 CreatePopUp (\r
4733 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4734 &Key,\r
4735 L"ERROR: Unsupported file type!",\r
4736 L"Only supports DER-encoded X509 certificate.",\r
4737 NULL\r
4738 );\r
4739 }\r
4740 break;\r
762d8ddb
DB
4741 case KEY_VALUE_SAVE_AND_EXIT_PK:\r
4742 Status = EnrollPlatformKey (Private);\r
4743 if (EFI_ERROR (Status)) {\r
4744 UnicodeSPrint (\r
4745 PromptString,\r
4746 sizeof (PromptString),\r
4747 L"Only DER encoded certificate file (%s) is supported.",\r
4748 mSupportX509Suffix\r
4749 );\r
4750 CreatePopUp (\r
4751 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
4752 &Key,\r
4753 L"ERROR: Unsupported file type!",\r
4754 PromptString,\r
4755 NULL\r
4756 );\r
4757 }\r
4758 break;\r
ecc722ad 4759 default:\r
762d8ddb 4760 if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
ecc722ad 4761 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
4762 DeleteKeyExchangeKey (Private, QuestionId);\r
4763 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&\r
4764 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
4765 DeleteSignature (\r
4766 Private,\r
4767 EFI_IMAGE_SECURITY_DATABASE,\r
4768 &gEfiImageSecurityDatabaseGuid,\r
20333c6d 4769 LABEL_DB_DELETE,\r
ecc722ad 4770 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
4771 OPTION_DEL_DB_QUESTION_ID,\r
4772 QuestionId - OPTION_DEL_DB_QUESTION_ID\r
4773 );\r
85974aef 4774 } else if ((QuestionId >= OPTION_SIGNATURE_LIST_QUESTION_ID) &&\r
4775 (QuestionId < (OPTION_SIGNATURE_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
4776 LoadSignatureData (\r
ecc722ad 4777 Private,\r
85974aef 4778 LABEL_SIGNATURE_DATA_START,\r
4779 SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,\r
4780 OPTION_SIGNATURE_DATA_QUESTION_ID,\r
4781 QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID\r
4782 );\r
4783 Private->ListIndex = QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID;\r
4784 } else if ((QuestionId >= OPTION_SIGNATURE_DATA_QUESTION_ID) &&\r
4785 (QuestionId < (OPTION_SIGNATURE_DATA_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
4786 if (Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID]) {\r
4787 IfrNvData->CheckedDataCount--;\r
4788 Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = FALSE;\r
4789 } else {\r
4790 IfrNvData->CheckedDataCount++;\r
4791 Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = TRUE;\r
4792 }\r
20333c6d
QL
4793 } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&\r
4794 (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
4795 DeleteSignature (\r
4796 Private,\r
4797 EFI_IMAGE_SECURITY_DATABASE2,\r
4798 &gEfiImageSecurityDatabaseGuid,\r
4799 LABEL_DBT_DELETE,\r
4800 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
4801 OPTION_DEL_DBT_QUESTION_ID,\r
4802 QuestionId - OPTION_DEL_DBT_QUESTION_ID\r
4803 );\r
ecc722ad 4804 }\r
4805 break;\r
ecc722ad 4806\r
4807 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
4808 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
4809 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
4810 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
20333c6d 4811 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:\r
4de754e1 4812 CloseEnrolledFile(Private->FileContext);\r
20333c6d 4813\r
ecc722ad 4814 if (Private->SignatureGUID != NULL) {\r
4815 FreePool (Private->SignatureGUID);\r
4816 Private->SignatureGUID = NULL;\r
4817 }\r
ecc722ad 4818 break;\r
762d8ddb
DB
4819 }\r
4820 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
4821 switch (QuestionId) {\r
4822 case KEY_SECURE_BOOT_ENABLE:\r
4823 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
4824 break;\r
ecc722ad 4825 case KEY_SECURE_BOOT_MODE:\r
a365eed4 4826 mIsEnterSecureBootForm = FALSE;\r
ecc722ad 4827 break;\r
ecc722ad 4828 case KEY_SECURE_BOOT_KEK_GUID:\r
4829 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
4830 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
20333c6d 4831 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:\r
ecc722ad 4832 ASSERT (Private->SignatureGUID != NULL);\r
2a085774
RN
4833 RStatus = StrToGuid (IfrNvData->SignatureGuid, Private->SignatureGUID);\r
4834 if (RETURN_ERROR (RStatus) || (IfrNvData->SignatureGuid[GUID_STRING_LENGTH] != L'\0')) {\r
4835 Status = EFI_INVALID_PARAMETER;\r
ecc722ad 4836 break;\r
4837 }\r
4838\r
4839 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
4840 break;\r
ecc722ad 4841 case KEY_SECURE_BOOT_DELETE_PK:\r
12087ff6
ZC
4842 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
4843 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
f71ed839 4844 IfrNvData->DeletePk = TRUE;\r
4845 IfrNvData->HasPk = FALSE;\r
ecc722ad 4846 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
f71ed839 4847 } else {\r
4848 IfrNvData->DeletePk = FALSE;\r
4849 IfrNvData->HasPk = TRUE;\r
4850 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
4851 }\r
12087ff6
ZC
4852 if (SetupMode != NULL) {\r
4853 FreePool (SetupMode);\r
4854 }\r
c93bcb7e
ED
4855 break;\r
4856 default:\r
c93bcb7e 4857 break;\r
ecc722ad 4858 }\r
a2f2c258 4859 } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {\r
4860 if (QuestionId == KEY_HIDE_SECURE_BOOT) {\r
126f3b1d
ZC
4861 GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL);\r
4862 if (Pk == NULL) {\r
a2f2c258 4863 IfrNvData->HideSecureBoot = TRUE;\r
4864 } else {\r
126f3b1d 4865 FreePool (Pk);\r
a2f2c258 4866 IfrNvData->HideSecureBoot = FALSE;\r
4867 }\r
4868 Value->b = IfrNvData->HideSecureBoot;\r
4869 }\r
f71ed839 4870 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
4871 //\r
4872 // Force the platform back to Standard Mode once user leave the setup screen.\r
4873 //\r
4874 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
4875 if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {\r
4876 IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
4877 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);\r
4878 }\r
4879 if (SecureBootMode != NULL) {\r
4880 FreePool (SecureBootMode);\r
4881 }\r
85974aef 4882\r
4883 if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_DATA) {\r
4884 //\r
4885 // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.\r
4886 //\r
4887 SECUREBOOT_FREE_NON_NULL (Private->CheckArray);\r
4888 IfrNvData->CheckedDataCount = 0;\r
4889 }\r
ecc722ad 4890 }\r
20333c6d 4891\r
96832eef
CZ
4892EXIT:\r
4893\r
488aab25 4894 if (!EFI_ERROR (Status) && GetBrowserDataResult) {\r
ecc722ad 4895 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
742d9b3a 4896 HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
ecc722ad 4897 }\r
96832eef 4898\r
ecc722ad 4899 FreePool (IfrNvData);\r
20333c6d 4900\r
762d8ddb
DB
4901 if (File != NULL){\r
4902 FreePool(File);\r
4903 File = NULL;\r
4904 }\r
4905\r
ecc722ad 4906 return EFI_SUCCESS;\r
beda2356 4907}\r
4908\r
4909/**\r
4910 This function publish the SecureBoot configuration Form.\r
4911\r
4912 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
4913\r
ecc722ad 4914 @retval EFI_SUCCESS HII Form is installed successfully.\r
beda2356 4915 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.\r
4916 @retval Others Other errors as indicated.\r
4917\r
4918**/\r
4919EFI_STATUS\r
4920InstallSecureBootConfigForm (\r
4921 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
4922 )\r
4923{\r
4924 EFI_STATUS Status;\r
4925 EFI_HII_HANDLE HiiHandle;\r
4926 EFI_HANDLE DriverHandle;\r
beda2356 4927 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4928\r
4929 DriverHandle = NULL;\r
4930 ConfigAccess = &PrivateData->ConfigAccess;\r
4931 Status = gBS->InstallMultipleProtocolInterfaces (\r
4932 &DriverHandle,\r
4933 &gEfiDevicePathProtocolGuid,\r
4934 &mSecureBootHiiVendorDevicePath,\r
4935 &gEfiHiiConfigAccessProtocolGuid,\r
4936 ConfigAccess,\r
4937 NULL\r
4938 );\r
4939 if (EFI_ERROR (Status)) {\r
4940 return Status;\r
4941 }\r
4942\r
4943 PrivateData->DriverHandle = DriverHandle;\r
4944\r
4945 //\r
4946 // Publish the HII package list\r
4947 //\r
4948 HiiHandle = HiiAddPackages (\r
4949 &gSecureBootConfigFormSetGuid,\r
4950 DriverHandle,\r
4951 SecureBootConfigDxeStrings,\r
4952 SecureBootConfigBin,\r
4953 NULL\r
4954 );\r
4955 if (HiiHandle == NULL) {\r
4956 gBS->UninstallMultipleProtocolInterfaces (\r
4957 DriverHandle,\r
4958 &gEfiDevicePathProtocolGuid,\r
4959 &mSecureBootHiiVendorDevicePath,\r
4960 &gEfiHiiConfigAccessProtocolGuid,\r
4961 ConfigAccess,\r
4962 NULL\r
bc0c99b3 4963 );\r
beda2356 4964 return EFI_OUT_OF_RESOURCES;\r
4965 }\r
bc0c99b3 4966\r
beda2356 4967 PrivateData->HiiHandle = HiiHandle;\r
ecc722ad 4968\r
4969 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
20333c6d 4970\r
762d8ddb 4971 if (PrivateData->FileContext == NULL) {\r
ecc722ad 4972 UninstallSecureBootConfigForm (PrivateData);\r
4973 return EFI_OUT_OF_RESOURCES;\r
4974 }\r
20333c6d 4975\r
ecc722ad 4976 //\r
4977 // Init OpCode Handle and Allocate space for creation of Buffer\r
4978 //\r
4979 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
4980 if (mStartOpCodeHandle == NULL) {\r
4981 UninstallSecureBootConfigForm (PrivateData);\r
4982 return EFI_OUT_OF_RESOURCES;\r
4983 }\r
4984\r
4985 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
4986 if (mEndOpCodeHandle == NULL) {\r
4987 UninstallSecureBootConfigForm (PrivateData);\r
4988 return EFI_OUT_OF_RESOURCES;\r
4989 }\r
4990\r
4991 //\r
4992 // Create Hii Extend Label OpCode as the start opcode\r
4993 //\r
4994 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
4995 mStartOpCodeHandle,\r
4996 &gEfiIfrTianoGuid,\r
4997 NULL,\r
4998 sizeof (EFI_IFR_GUID_LABEL)\r
4999 );\r
5000 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
5001\r
5002 //\r
5003 // Create Hii Extend Label OpCode as the end opcode\r
5004 //\r
5005 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
5006 mEndOpCodeHandle,\r
5007 &gEfiIfrTianoGuid,\r
5008 NULL,\r
5009 sizeof (EFI_IFR_GUID_LABEL)\r
5010 );\r
5011 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
5012 mEndLabel->Number = LABEL_END;\r
20333c6d 5013\r
bc0c99b3 5014 return EFI_SUCCESS;\r
beda2356 5015}\r
5016\r
5017/**\r
5018 This function removes SecureBoot configuration Form.\r
5019\r
5020 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
5021\r
5022**/\r
5023VOID\r
5024UninstallSecureBootConfigForm (\r
5025 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
5026 )\r
5027{\r
5028 //\r
5029 // Uninstall HII package list\r
5030 //\r
5031 if (PrivateData->HiiHandle != NULL) {\r
5032 HiiRemovePackages (PrivateData->HiiHandle);\r
5033 PrivateData->HiiHandle = NULL;\r
5034 }\r
5035\r
5036 //\r
5037 // Uninstall HII Config Access Protocol\r
5038 //\r
5039 if (PrivateData->DriverHandle != NULL) {\r
5040 gBS->UninstallMultipleProtocolInterfaces (\r
5041 PrivateData->DriverHandle,\r
5042 &gEfiDevicePathProtocolGuid,\r
5043 &mSecureBootHiiVendorDevicePath,\r
5044 &gEfiHiiConfigAccessProtocolGuid,\r
5045 &PrivateData->ConfigAccess,\r
5046 NULL\r
5047 );\r
5048 PrivateData->DriverHandle = NULL;\r
5049 }\r
bc0c99b3 5050\r
ecc722ad 5051 if (PrivateData->SignatureGUID != NULL) {\r
5052 FreePool (PrivateData->SignatureGUID);\r
5053 }\r
5054\r
ecc722ad 5055 if (PrivateData->FileContext != NULL) {\r
5056 FreePool (PrivateData->FileContext);\r
5057 }\r
5058\r
beda2356 5059 FreePool (PrivateData);\r
ecc722ad 5060\r
ecc722ad 5061 if (mStartOpCodeHandle != NULL) {\r
5062 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
5063 }\r
5064\r
5065 if (mEndOpCodeHandle != NULL) {\r
5066 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
5067 }\r
beda2356 5068}\r