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