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