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