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