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