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