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