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