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