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