]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
IntelFsp2WrapperPkg: Remove unused header files from Fspm and Fsps WrapperPeim
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigImpl.c
CommitLineData
beda2356 1/** @file\r
2 HII Config Access protocol implementation of SecureBoot configuration module.\r
3\r
02dd6af9 4Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
bc0c99b3 5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
beda2356 8http://opensource.org/licenses/bsd-license.php\r
9\r
bc0c99b3 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
beda2356 11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "SecureBootConfigImpl.h"\r
16\r
ecc722ad 17CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
beda2356 18\r
19SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = {\r
20333c6d 20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,\r
beda2356 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
bc0c99b3 43 {\r
beda2356 44 (UINT8) (END_DEVICE_PATH_LENGTH),\r
45 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
46 }\r
47 }\r
48};\r
49\r
ecc722ad 50\r
a365eed4
FS
51BOOLEAN mIsEnterSecureBootForm = FALSE;\r
52\r
ecc722ad 53//\r
54// OID ASN.1 Value for Hash Algorithms\r
55//\r
56UINT8 mHashOidValue[] = {\r
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5\r
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1\r
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224\r
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256\r
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384\r
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512\r
63 };\r
64\r
65HASH_TABLE mHash[] = {\r
20333c6d
QL
66 { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },\r
67 { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },\r
68 { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},\r
69 { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},\r
70 { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
ecc722ad 71};\r
72\r
e4d7370d 73//\r
20333c6d
QL
74// Variable Definitions\r
75//\r
ecc722ad 76UINT32 mPeCoffHeaderOffset = 0;\r
77WIN_CERTIFICATE *mCertificate = NULL;\r
78IMAGE_TYPE mImageType;\r
79UINT8 *mImageBase = NULL;\r
80UINTN mImageSize = 0;\r
81UINT8 mImageDigest[MAX_DIGEST_SIZE];\r
82UINTN mImageDigestSize;\r
83EFI_GUID mCertType;\r
84EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL;\r
85EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
86\r
e4d7370d 87//\r
88// Possible DER-encoded certificate file suffixes, end with NULL pointer.\r
89//\r
90CHAR16* mDerEncodedSuffix[] = {\r
91 L".cer",\r
92 L".der",\r
93 L".crt",\r
94 NULL\r
95};\r
96CHAR16* mSupportX509Suffix = L"*.cer/der/crt";\r
97\r
762d8ddb
DB
98SECUREBOOT_CONFIG_PRIVATE_DATA *gSecureBootPrivateData = NULL;\r
99\r
e4d7370d 100/**\r
101 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.\r
102\r
103 @param[in] FileSuffix The suffix of the input certificate file\r
104\r
105 @retval TRUE It's a DER-encoded certificate.\r
106 @retval FALSE It's NOT a DER-encoded certificate.\r
107\r
108**/\r
109BOOLEAN\r
110IsDerEncodeCertificate (\r
111 IN CONST CHAR16 *FileSuffix\r
112)\r
113{\r
20333c6d 114 UINTN Index;\r
e4d7370d 115 for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {\r
116 if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {\r
117 return TRUE;\r
118 }\r
119 }\r
120 return FALSE;\r
121}\r
ecc722ad 122\r
123/**\r
124 Set Secure Boot option into variable space.\r
125\r
126 @param[in] VarValue The option of Secure Boot.\r
127\r
128 @retval EFI_SUCCESS The operation is finished successfully.\r
129 @retval Others Other errors as indicated.\r
130\r
131**/\r
132EFI_STATUS\r
133SaveSecureBootVariable (\r
134 IN UINT8 VarValue\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138\r
139 Status = gRT->SetVariable (\r
140 EFI_SECURE_BOOT_ENABLE_NAME,\r
141 &gEfiSecureBootEnableDisableGuid,\r
142 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
143 sizeof (UINT8),\r
144 &VarValue\r
145 );\r
146 return Status;\r
147}\r
148\r
8c1babfd 149/**\r
150 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2\r
151 descriptor with the input data. NO authentication is required in this function.\r
20333c6d 152\r
8c1babfd 153 @param[in, out] DataSize On input, the size of Data buffer in bytes.\r
154 On output, the size of data returned in Data\r
155 buffer in bytes.\r
20333c6d 156 @param[in, out] Data On input, Pointer to data buffer to be wrapped or\r
8c1babfd 157 pointer to NULL to wrap an empty payload.\r
158 On output, Pointer to the new payload date buffer allocated from pool,\r
20333c6d 159 it's caller's responsibility to free the memory when finish using it.\r
8c1babfd 160\r
161 @retval EFI_SUCCESS Create time based payload successfully.\r
162 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.\r
163 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
164 @retval Others Unexpected error happens.\r
165\r
166**/\r
167EFI_STATUS\r
168CreateTimeBasedPayload (\r
169 IN OUT UINTN *DataSize,\r
170 IN OUT UINT8 **Data\r
171 )\r
172{\r
173 EFI_STATUS Status;\r
174 UINT8 *NewData;\r
175 UINT8 *Payload;\r
176 UINTN PayloadSize;\r
177 EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;\r
178 UINTN DescriptorSize;\r
179 EFI_TIME Time;\r
20333c6d 180\r
8c1babfd 181 if (Data == NULL || DataSize == NULL) {\r
182 return EFI_INVALID_PARAMETER;\r
183 }\r
20333c6d 184\r
8c1babfd 185 //\r
20333c6d 186 // In Setup mode or Custom mode, the variable does not need to be signed but the\r
8c1babfd 187 // parameters to the SetVariable() call still need to be prepared as authenticated\r
188 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate\r
189 // data in it.\r
190 //\r
191 Payload = *Data;\r
192 PayloadSize = *DataSize;\r
20333c6d 193\r
8c1babfd 194 DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
195 NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);\r
196 if (NewData == NULL) {\r
197 return EFI_OUT_OF_RESOURCES;\r
198 }\r
199\r
200 if ((Payload != NULL) && (PayloadSize != 0)) {\r
201 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
202 }\r
203\r
204 DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);\r
205\r
206 ZeroMem (&Time, sizeof (EFI_TIME));\r
207 Status = gRT->GetTime (&Time, NULL);\r
208 if (EFI_ERROR (Status)) {\r
209 FreePool(NewData);\r
210 return Status;\r
211 }\r
212 Time.Pad1 = 0;\r
213 Time.Nanosecond = 0;\r
214 Time.TimeZone = 0;\r
215 Time.Daylight = 0;\r
216 Time.Pad2 = 0;\r
217 CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\r
20333c6d 218\r
8c1babfd 219 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
220 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;\r
221 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
222 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);\r
20333c6d 223\r
8c1babfd 224 if (Payload != NULL) {\r
225 FreePool(Payload);\r
226 }\r
20333c6d 227\r
8c1babfd 228 *DataSize = DescriptorSize + PayloadSize;\r
229 *Data = NewData;\r
230 return EFI_SUCCESS;\r
231}\r
232\r
ecc722ad 233/**\r
234 Internal helper function to delete a Variable given its name and GUID, NO authentication\r
235 required.\r
236\r
237 @param[in] VariableName Name of the Variable.\r
238 @param[in] VendorGuid GUID of the Variable.\r
239\r
240 @retval EFI_SUCCESS Variable deleted successfully.\r
241 @retval Others The driver failed to start the device.\r
242\r
243**/\r
244EFI_STATUS\r
245DeleteVariable (\r
246 IN CHAR16 *VariableName,\r
247 IN EFI_GUID *VendorGuid\r
248 )\r
249{\r
250 EFI_STATUS Status;\r
251 VOID* Variable;\r
8c1babfd 252 UINT8 *Data;\r
253 UINTN DataSize;\r
254 UINT32 Attr;\r
ecc722ad 255\r
bf4a3dbd 256 GetVariable2 (VariableName, VendorGuid, &Variable, NULL);\r
ecc722ad 257 if (Variable == NULL) {\r
258 return EFI_SUCCESS;\r
259 }\r
f71ed839 260 FreePool (Variable);\r
ecc722ad 261\r
8c1babfd 262 Data = NULL;\r
263 DataSize = 0;\r
264 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
265 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
ecc722ad 266\r
8c1babfd 267 Status = CreateTimeBasedPayload (&DataSize, &Data);\r
268 if (EFI_ERROR (Status)) {\r
269 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
270 return Status;\r
ecc722ad 271 }\r
272\r
8c1babfd 273 Status = gRT->SetVariable (\r
274 VariableName,\r
275 VendorGuid,\r
276 Attr,\r
277 DataSize,\r
278 Data\r
279 );\r
280 if (Data != NULL) {\r
281 FreePool (Data);\r
ecc722ad 282 }\r
ecc722ad 283 return Status;\r
284}\r
285\r
f71ed839 286/**\r
287\r
288 Set the platform secure boot mode into "Custom" or "Standard" mode.\r
289\r
290 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or\r
291 CUSTOM_SECURE_BOOT_MODE.\r
20333c6d 292\r
f71ed839 293 @return EFI_SUCCESS The platform has switched to the special mode successfully.\r
294 @return other Fail to operate the secure boot mode.\r
20333c6d 295\r
f71ed839 296**/\r
297EFI_STATUS\r
298SetSecureBootMode (\r
299 IN UINT8 SecureBootMode\r
300 )\r
301{\r
20333c6d 302 return gRT->SetVariable (\r
f71ed839 303 EFI_CUSTOM_MODE_NAME,\r
304 &gEfiCustomModeEnableGuid,\r
305 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
306 sizeof (UINT8),\r
307 &SecureBootMode\r
308 );\r
309}\r
310\r
ecc722ad 311/**\r
312 Generate the PK signature list from the X509 Certificate storing file (.cer)\r
313\r
314 @param[in] X509File FileHandle of X509 Certificate storing file.\r
315 @param[out] PkCert Point to the data buffer to store the signature list.\r
20333c6d 316\r
ecc722ad 317 @return EFI_UNSUPPORTED Unsupported Key Length.\r
318 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.\r
20333c6d 319\r
ecc722ad 320**/\r
321EFI_STATUS\r
322CreatePkX509SignatureList (\r
20333c6d
QL
323 IN EFI_FILE_HANDLE X509File,\r
324 OUT EFI_SIGNATURE_LIST **PkCert\r
ecc722ad 325 )\r
326{\r
20333c6d 327 EFI_STATUS Status;\r
ecc722ad 328 UINT8 *X509Data;\r
329 UINTN X509DataSize;\r
330 EFI_SIGNATURE_DATA *PkCertData;\r
331\r
332 X509Data = NULL;\r
333 PkCertData = NULL;\r
20333c6d
QL
334 X509DataSize = 0;\r
335\r
4adc12bf 336 Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);\r
ecc722ad 337 if (EFI_ERROR (Status)) {\r
338 goto ON_EXIT;\r
339 }\r
ba57d4fd 340 ASSERT (X509Data != NULL);\r
ecc722ad 341\r
342 //\r
343 // Allocate space for PK certificate list and initialize it.\r
344 // Create PK database entry with SignatureHeaderSize equals 0.\r
345 //\r
346 *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (\r
347 sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1\r
348 + X509DataSize\r
349 );\r
350 if (*PkCert == NULL) {\r
351 Status = EFI_OUT_OF_RESOURCES;\r
352 goto ON_EXIT;\r
353 }\r
354\r
20333c6d 355 (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST)\r
ecc722ad 356 + sizeof(EFI_SIGNATURE_DATA) - 1\r
357 + X509DataSize);\r
358 (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
359 (*PkCert)->SignatureHeaderSize = 0;\r
360 CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);\r
20333c6d 361 PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert)\r
ecc722ad 362 + sizeof(EFI_SIGNATURE_LIST)\r
363 + (*PkCert)->SignatureHeaderSize);\r
20333c6d 364 CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);\r
ecc722ad 365 //\r
366 // Fill the PK database with PKpub data from X509 certificate file.\r
20333c6d 367 //\r
ecc722ad 368 CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);\r
20333c6d 369\r
ecc722ad 370ON_EXIT:\r
20333c6d 371\r
ecc722ad 372 if (X509Data != NULL) {\r
373 FreePool (X509Data);\r
374 }\r
20333c6d 375\r
ecc722ad 376 if (EFI_ERROR(Status) && *PkCert != NULL) {\r
377 FreePool (*PkCert);\r
378 *PkCert = NULL;\r
379 }\r
20333c6d 380\r
ecc722ad 381 return Status;\r
382}\r
383\r
384/**\r
385 Enroll new PK into the System without original PK's authentication.\r
386\r
387 The SignatureOwner GUID will be the same with PK's vendorguid.\r
388\r
389 @param[in] PrivateData The module's private data.\r
390\r
391 @retval EFI_SUCCESS New PK enrolled successfully.\r
392 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
393 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
20333c6d 394\r
ecc722ad 395**/\r
396EFI_STATUS\r
397EnrollPlatformKey (\r
398 IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private\r
20333c6d 399 )\r
ecc722ad 400{\r
401 EFI_STATUS Status;\r
402 UINT32 Attr;\r
403 UINTN DataSize;\r
404 EFI_SIGNATURE_LIST *PkCert;\r
405 UINT16* FilePostFix;\r
fd64f84f 406 UINTN NameLength;\r
20333c6d 407\r
ecc722ad 408 if (Private->FileContext->FileName == NULL) {\r
409 return EFI_INVALID_PARAMETER;\r
410 }\r
411\r
412 PkCert = NULL;\r
413\r
f71ed839 414 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
415 if (EFI_ERROR (Status)) {\r
416 return Status;\r
417 }\r
418\r
ecc722ad 419 //\r
e4d7370d 420 // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
ecc722ad 421 //\r
fd64f84f
GCPL
422 NameLength = StrLen (Private->FileContext->FileName);\r
423 if (NameLength <= 4) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
426 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
e4d7370d 427 if (!IsDerEncodeCertificate(FilePostFix)) {\r
428 DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));\r
ecc722ad 429 return EFI_INVALID_PARAMETER;\r
430 }\r
431 DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));\r
432 DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));\r
433\r
434 //\r
435 // Prase the selected PK file and generature PK certificate list.\r
436 //\r
8c1babfd 437 Status = CreatePkX509SignatureList (\r
20333c6d
QL
438 Private->FileContext->FHandle,\r
439 &PkCert\r
8c1babfd 440 );\r
441 if (EFI_ERROR (Status)) {\r
442 goto ON_EXIT;\r
ecc722ad 443 }\r
ba57d4fd 444 ASSERT (PkCert != NULL);\r
20333c6d 445\r
ecc722ad 446 //\r
447 // Set Platform Key variable.\r
20333c6d
QL
448 //\r
449 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 450 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
ecc722ad 451 DataSize = PkCert->SignatureListSize;\r
8c1babfd 452 Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);\r
453 if (EFI_ERROR (Status)) {\r
454 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
455 goto ON_EXIT;\r
456 }\r
20333c6d 457\r
ecc722ad 458 Status = gRT->SetVariable(\r
20333c6d
QL
459 EFI_PLATFORM_KEY_NAME,\r
460 &gEfiGlobalVariableGuid,\r
461 Attr,\r
462 DataSize,\r
ecc722ad 463 PkCert\r
464 );\r
465 if (EFI_ERROR (Status)) {\r
466 if (Status == EFI_OUT_OF_RESOURCES) {\r
467 DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));\r
468 }\r
469 goto ON_EXIT;\r
470 }\r
20333c6d 471\r
ecc722ad 472ON_EXIT:\r
473\r
474 if (PkCert != NULL) {\r
475 FreePool(PkCert);\r
476 }\r
20333c6d 477\r
ecc722ad 478 if (Private->FileContext->FHandle != NULL) {\r
479 CloseFile (Private->FileContext->FHandle);\r
480 Private->FileContext->FHandle = NULL;\r
481 }\r
482\r
483 return Status;\r
484}\r
485\r
486/**\r
487 Remove the PK variable.\r
488\r
489 @retval EFI_SUCCESS Delete PK successfully.\r
490 @retval Others Could not allow to delete PK.\r
20333c6d 491\r
ecc722ad 492**/\r
493EFI_STATUS\r
494DeletePlatformKey (\r
495 VOID\r
496)\r
497{\r
498 EFI_STATUS Status;\r
499\r
f71ed839 500 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
501 if (EFI_ERROR (Status)) {\r
502 return Status;\r
503 }\r
504\r
8c1babfd 505 Status = DeleteVariable (\r
506 EFI_PLATFORM_KEY_NAME,\r
507 &gEfiGlobalVariableGuid\r
508 );\r
ecc722ad 509 return Status;\r
510}\r
511\r
512/**\r
513 Enroll a new KEK item from public key storing file (*.pbk).\r
514\r
515 @param[in] PrivateData The module's private data.\r
516\r
517 @retval EFI_SUCCESS New KEK enrolled successfully.\r
518 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
519 @retval EFI_UNSUPPORTED Unsupported command.\r
520 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
521\r
522**/\r
523EFI_STATUS\r
524EnrollRsa2048ToKek (\r
525 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
526 )\r
527{\r
528 EFI_STATUS Status;\r
529 UINT32 Attr;\r
530 UINTN DataSize;\r
531 EFI_SIGNATURE_LIST *KekSigList;\r
532 UINTN KeyBlobSize;\r
533 UINT8 *KeyBlob;\r
534 CPL_KEY_INFO *KeyInfo;\r
535 EFI_SIGNATURE_DATA *KEKSigData;\r
536 UINTN KekSigListSize;\r
20333c6d 537 UINT8 *KeyBuffer;\r
ecc722ad 538 UINTN KeyLenInBytes;\r
539\r
540 Attr = 0;\r
541 DataSize = 0;\r
542 KeyBuffer = NULL;\r
543 KeyBlobSize = 0;\r
544 KeyBlob = NULL;\r
545 KeyInfo = NULL;\r
546 KEKSigData = NULL;\r
547 KekSigList = NULL;\r
548 KekSigListSize = 0;\r
20333c6d 549\r
ecc722ad 550 //\r
551 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.\r
552 // First, We have to parse out public key data from the pbk key file.\r
20333c6d 553 //\r
ecc722ad 554 Status = ReadFileContent (\r
555 Private->FileContext->FHandle,\r
4adc12bf 556 (VOID**) &KeyBlob,\r
ecc722ad 557 &KeyBlobSize,\r
558 0\r
559 );\r
560 if (EFI_ERROR (Status)) {\r
561 goto ON_EXIT;\r
562 }\r
ba57d4fd 563 ASSERT (KeyBlob != NULL);\r
ecc722ad 564 KeyInfo = (CPL_KEY_INFO *) KeyBlob;\r
565 if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {\r
566 DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));\r
567 Status = EFI_UNSUPPORTED;\r
568 goto ON_EXIT;\r
569 }\r
20333c6d 570\r
ecc722ad 571 //\r
572 // Convert the Public key to fix octet string format represented in RSA PKCS#1.\r
20333c6d 573 //\r
ecc722ad 574 KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;\r
575 KeyBuffer = AllocateZeroPool (KeyLenInBytes);\r
576 if (KeyBuffer == NULL) {\r
577 Status = EFI_OUT_OF_RESOURCES;\r
578 goto ON_EXIT;\r
579 }\r
580 Int2OctStr (\r
20333c6d
QL
581 (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),\r
582 KeyLenInBytes / sizeof (UINTN),\r
583 KeyBuffer,\r
ecc722ad 584 KeyLenInBytes\r
585 );\r
586 CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);\r
20333c6d 587\r
ecc722ad 588 //\r
589 // Form an new EFI_SIGNATURE_LIST.\r
590 //\r
591 KekSigListSize = sizeof(EFI_SIGNATURE_LIST)\r
592 + sizeof(EFI_SIGNATURE_DATA) - 1\r
593 + WIN_CERT_UEFI_RSA2048_SIZE;\r
594\r
595 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
596 if (KekSigList == NULL) {\r
597 Status = EFI_OUT_OF_RESOURCES;\r
598 goto ON_EXIT;\r
599 }\r
600\r
601 KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST)\r
602 + sizeof(EFI_SIGNATURE_DATA) - 1\r
603 + WIN_CERT_UEFI_RSA2048_SIZE;\r
604 KekSigList->SignatureHeaderSize = 0;\r
605 KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;\r
606 CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);\r
20333c6d 607\r
ecc722ad 608 KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));\r
609 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
610 CopyMem (\r
611 KEKSigData->SignatureData,\r
612 KeyBlob + sizeof(CPL_KEY_INFO),\r
613 WIN_CERT_UEFI_RSA2048_SIZE\r
614 );\r
20333c6d 615\r
ecc722ad 616 //\r
20333c6d
QL
617 // Check if KEK entry has been already existed.\r
618 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 619 // new KEK to original variable.\r
20333c6d
QL
620 //\r
621 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 622 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
623 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
624 if (EFI_ERROR (Status)) {\r
625 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
626 goto ON_EXIT;\r
627 }\r
628\r
ecc722ad 629 Status = gRT->GetVariable(\r
20333c6d
QL
630 EFI_KEY_EXCHANGE_KEY_NAME,\r
631 &gEfiGlobalVariableGuid,\r
632 NULL,\r
633 &DataSize,\r
ecc722ad 634 NULL\r
635 );\r
636 if (Status == EFI_BUFFER_TOO_SMALL) {\r
637 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
638 } else if (Status != EFI_NOT_FOUND) {\r
639 goto ON_EXIT;\r
640 }\r
20333c6d 641\r
ecc722ad 642 //\r
643 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,\r
20333c6d 644 //\r
ecc722ad 645 Status = gRT->SetVariable(\r
20333c6d
QL
646 EFI_KEY_EXCHANGE_KEY_NAME,\r
647 &gEfiGlobalVariableGuid,\r
648 Attr,\r
649 KekSigListSize,\r
ecc722ad 650 KekSigList\r
651 );\r
652 if (EFI_ERROR (Status)) {\r
653 goto ON_EXIT;\r
654 }\r
20333c6d 655\r
ecc722ad 656ON_EXIT:\r
657\r
658 CloseFile (Private->FileContext->FHandle);\r
659 Private->FileContext->FHandle = NULL;\r
762d8ddb
DB
660\r
661 if (Private->FileContext->FileName != NULL){\r
662 FreePool(Private->FileContext->FileName);\r
663 Private->FileContext->FileName = NULL;\r
664 }\r
ecc722ad 665\r
666 if (Private->SignatureGUID != NULL) {\r
667 FreePool (Private->SignatureGUID);\r
668 Private->SignatureGUID = NULL;\r
669 }\r
670\r
671 if (KeyBlob != NULL) {\r
672 FreePool (KeyBlob);\r
673 }\r
674 if (KeyBuffer != NULL) {\r
675 FreePool (KeyBuffer);\r
676 }\r
677 if (KekSigList != NULL) {\r
678 FreePool (KekSigList);\r
679 }\r
20333c6d 680\r
ecc722ad 681 return Status;\r
682}\r
683\r
684/**\r
685 Enroll a new KEK item from X509 certificate file.\r
686\r
687 @param[in] PrivateData The module's private data.\r
688\r
689 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
690 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
691 @retval EFI_UNSUPPORTED Unsupported command.\r
692 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
693\r
694**/\r
695EFI_STATUS\r
696EnrollX509ToKek (\r
697 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
20333c6d 698 )\r
ecc722ad 699{\r
700 EFI_STATUS Status;\r
701 UINTN X509DataSize;\r
702 VOID *X509Data;\r
703 EFI_SIGNATURE_DATA *KEKSigData;\r
704 EFI_SIGNATURE_LIST *KekSigList;\r
705 UINTN DataSize;\r
706 UINTN KekSigListSize;\r
707 UINT32 Attr;\r
708\r
709 X509Data = NULL;\r
710 X509DataSize = 0;\r
711 KekSigList = NULL;\r
712 KekSigListSize = 0;\r
713 DataSize = 0;\r
714 KEKSigData = NULL;\r
715\r
716 Status = ReadFileContent (\r
717 Private->FileContext->FHandle,\r
718 &X509Data,\r
719 &X509DataSize,\r
720 0\r
721 );\r
722 if (EFI_ERROR (Status)) {\r
723 goto ON_EXIT;\r
724 }\r
ba57d4fd 725 ASSERT (X509Data != NULL);\r
ecc722ad 726\r
727 KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
728 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
729 if (KekSigList == NULL) {\r
730 Status = EFI_OUT_OF_RESOURCES;\r
731 goto ON_EXIT;\r
732 }\r
733\r
734 //\r
735 // Fill Certificate Database parameters.\r
20333c6d 736 //\r
ecc722ad 737 KekSigList->SignatureListSize = (UINT32) KekSigListSize;\r
738 KekSigList->SignatureHeaderSize = 0;\r
739 KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
740 CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);\r
741\r
742 KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));\r
743 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
744 CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);\r
745\r
746 //\r
20333c6d
QL
747 // Check if KEK been already existed.\r
748 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 749 // new kek to original variable\r
20333c6d
QL
750 //\r
751 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 752 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
753 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
754 if (EFI_ERROR (Status)) {\r
755 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
756 goto ON_EXIT;\r
757 }\r
20333c6d 758\r
ecc722ad 759 Status = gRT->GetVariable(\r
20333c6d
QL
760 EFI_KEY_EXCHANGE_KEY_NAME,\r
761 &gEfiGlobalVariableGuid,\r
762 NULL,\r
763 &DataSize,\r
ecc722ad 764 NULL\r
765 );\r
766 if (Status == EFI_BUFFER_TOO_SMALL) {\r
767 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
768 } else if (Status != EFI_NOT_FOUND) {\r
769 goto ON_EXIT;\r
20333c6d 770 }\r
ecc722ad 771\r
772 Status = gRT->SetVariable(\r
20333c6d
QL
773 EFI_KEY_EXCHANGE_KEY_NAME,\r
774 &gEfiGlobalVariableGuid,\r
775 Attr,\r
ecc722ad 776 KekSigListSize,\r
777 KekSigList\r
778 );\r
779 if (EFI_ERROR (Status)) {\r
780 goto ON_EXIT;\r
781 }\r
782\r
783ON_EXIT:\r
20333c6d
QL
784\r
785 CloseFile (Private->FileContext->FHandle);\r
762d8ddb
DB
786 if (Private->FileContext->FileName != NULL){\r
787 FreePool(Private->FileContext->FileName);\r
788 Private->FileContext->FileName = NULL;\r
789 }\r
790\r
20333c6d
QL
791 Private->FileContext->FHandle = NULL;\r
792\r
793 if (Private->SignatureGUID != NULL) {\r
794 FreePool (Private->SignatureGUID);\r
795 Private->SignatureGUID = NULL;\r
796 }\r
797\r
798 if (KekSigList != NULL) {\r
799 FreePool (KekSigList);\r
800 }\r
801\r
802 return Status;\r
803}\r
804\r
805/**\r
806 Enroll new KEK into the System without PK's authentication.\r
807 The SignatureOwner GUID will be Private->SignatureGUID.\r
808\r
809 @param[in] PrivateData The module's private data.\r
810\r
811 @retval EFI_SUCCESS New KEK enrolled successful.\r
812 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
813 @retval others Fail to enroll KEK data.\r
814\r
815**/\r
816EFI_STATUS\r
817EnrollKeyExchangeKey (\r
818 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
819 )\r
820{\r
821 UINT16* FilePostFix;\r
822 EFI_STATUS Status;\r
823 UINTN NameLength;\r
824\r
825 if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {\r
826 return EFI_INVALID_PARAMETER;\r
827 }\r
828\r
829 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
830 if (EFI_ERROR (Status)) {\r
831 return Status;\r
832 }\r
833\r
834 //\r
835 // Parse the file's postfix. Supports DER-encoded X509 certificate,\r
836 // and .pbk as RSA public key file.\r
837 //\r
838 NameLength = StrLen (Private->FileContext->FileName);\r
839 if (NameLength <= 4) {\r
840 return EFI_INVALID_PARAMETER;\r
841 }\r
842 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
843 if (IsDerEncodeCertificate(FilePostFix)) {\r
844 return EnrollX509ToKek (Private);\r
845 } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {\r
846 return EnrollRsa2048ToKek (Private);\r
847 } else {\r
848 return EFI_INVALID_PARAMETER;\r
849 }\r
850}\r
851\r
852/**\r
853 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without\r
854 KEK's authentication.\r
855\r
856 @param[in] PrivateData The module's private data.\r
857 @param[in] VariableName Variable name of signature database, must be\r
858 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
859\r
860 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
861 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
862\r
863**/\r
864EFI_STATUS\r
865EnrollX509toSigDB (\r
866 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
867 IN CHAR16 *VariableName\r
868 )\r
869{\r
870 EFI_STATUS Status;\r
871 UINTN X509DataSize;\r
872 VOID *X509Data;\r
873 EFI_SIGNATURE_LIST *SigDBCert;\r
874 EFI_SIGNATURE_DATA *SigDBCertData;\r
875 VOID *Data;\r
876 UINTN DataSize;\r
877 UINTN SigDBSize;\r
878 UINT32 Attr;\r
879\r
880 X509DataSize = 0;\r
881 SigDBSize = 0;\r
882 DataSize = 0;\r
883 X509Data = NULL;\r
884 SigDBCert = NULL;\r
885 SigDBCertData = NULL;\r
886 Data = NULL;\r
887\r
888 Status = ReadFileContent (\r
889 Private->FileContext->FHandle,\r
890 &X509Data,\r
891 &X509DataSize,\r
892 0\r
893 );\r
894 if (EFI_ERROR (Status)) {\r
895 goto ON_EXIT;\r
896 }\r
897 ASSERT (X509Data != NULL);\r
898\r
899 SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
900\r
901 Data = AllocateZeroPool (SigDBSize);\r
902 if (Data == NULL) {\r
903 Status = EFI_OUT_OF_RESOURCES;\r
904 goto ON_EXIT;\r
905 }\r
906\r
907 //\r
908 // Fill Certificate Database parameters.\r
909 //\r
910 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
911 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
912 SigDBCert->SignatureHeaderSize = 0;\r
913 SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
914 CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);\r
915\r
916 SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));\r
917 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
918 CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);\r
919\r
920 //\r
921 // Check if signature database entry has been already existed.\r
922 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
923 // new signature data to original variable\r
924 //\r
925 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
926 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
927 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
928 if (EFI_ERROR (Status)) {\r
929 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
930 goto ON_EXIT;\r
931 }\r
932\r
933 Status = gRT->GetVariable(\r
934 VariableName,\r
935 &gEfiImageSecurityDatabaseGuid,\r
936 NULL,\r
937 &DataSize,\r
938 NULL\r
939 );\r
940 if (Status == EFI_BUFFER_TOO_SMALL) {\r
941 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
942 } else if (Status != EFI_NOT_FOUND) {\r
943 goto ON_EXIT;\r
944 }\r
945\r
946 Status = gRT->SetVariable(\r
947 VariableName,\r
948 &gEfiImageSecurityDatabaseGuid,\r
949 Attr,\r
950 SigDBSize,\r
951 Data\r
952 );\r
953 if (EFI_ERROR (Status)) {\r
954 goto ON_EXIT;\r
955 }\r
956\r
957ON_EXIT:\r
958\r
959 CloseFile (Private->FileContext->FHandle);\r
762d8ddb
DB
960 if (Private->FileContext->FileName != NULL){\r
961 FreePool(Private->FileContext->FileName);\r
962 Private->FileContext->FileName = NULL;\r
963 }\r
964\r
20333c6d
QL
965 Private->FileContext->FHandle = NULL;\r
966\r
967 if (Private->SignatureGUID != NULL) {\r
968 FreePool (Private->SignatureGUID);\r
969 Private->SignatureGUID = NULL;\r
970 }\r
971\r
972 if (Data != NULL) {\r
973 FreePool (Data);\r
974 }\r
975\r
976 if (X509Data != NULL) {\r
977 FreePool (X509Data);\r
978 }\r
979\r
980 return Status;\r
981}\r
982\r
983/**\r
984 Check whether signature is in specified database.\r
985\r
986 @param[in] VariableName Name of database variable that is searched in.\r
987 @param[in] Signature Pointer to signature that is searched for.\r
988 @param[in] SignatureSize Size of Signature.\r
989\r
990 @return TRUE Found the signature in the variable database.\r
991 @return FALSE Not found the signature in the variable database.\r
992\r
993**/\r
994BOOLEAN\r
995IsSignatureFoundInDatabase (\r
996 IN CHAR16 *VariableName,\r
997 IN UINT8 *Signature,\r
998 IN UINTN SignatureSize\r
999 )\r
1000{\r
1001 EFI_STATUS Status;\r
1002 EFI_SIGNATURE_LIST *CertList;\r
1003 EFI_SIGNATURE_DATA *Cert;\r
1004 UINTN DataSize;\r
1005 UINT8 *Data;\r
1006 UINTN Index;\r
1007 UINTN CertCount;\r
1008 BOOLEAN IsFound;\r
1009\r
1010 //\r
1011 // Read signature database variable.\r
1012 //\r
1013 IsFound = FALSE;\r
1014 Data = NULL;\r
1015 DataSize = 0;\r
1016 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
1017 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1018 return FALSE;\r
1019 }\r
1020\r
1021 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1022 if (Data == NULL) {\r
1023 return FALSE;\r
1024 }\r
1025\r
1026 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
1027 if (EFI_ERROR (Status)) {\r
1028 goto Done;\r
1029 }\r
1030\r
1031 //\r
1032 // Enumerate all signature data in SigDB to check if executable's signature exists.\r
1033 //\r
1034 CertList = (EFI_SIGNATURE_LIST *) Data;\r
1035 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
1036 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1037 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1038 if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) {\r
1039 for (Index = 0; Index < CertCount; Index++) {\r
1040 if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {\r
1041 //\r
1042 // Find the signature in database.\r
1043 //\r
1044 IsFound = TRUE;\r
1045 break;\r
1046 }\r
1047 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
1048 }\r
1049\r
1050 if (IsFound) {\r
1051 break;\r
1052 }\r
1053 }\r
1054\r
1055 DataSize -= CertList->SignatureListSize;\r
1056 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1057 }\r
1058\r
1059Done:\r
1060 if (Data != NULL) {\r
1061 FreePool (Data);\r
1062 }\r
1063\r
1064 return IsFound;\r
1065}\r
1066\r
1067/**\r
1068 Calculate the hash of a certificate data with the specified hash algorithm.\r
1069\r
1070 @param[in] CertData The certificate data to be hashed.\r
1071 @param[in] CertSize The certificate size in bytes.\r
1072 @param[in] HashAlg The specified hash algorithm.\r
1073 @param[out] CertHash The output digest of the certificate\r
1074\r
1075 @retval TRUE Successfully got the hash of the CertData.\r
1076 @retval FALSE Failed to get the hash of CertData.\r
1077\r
1078**/\r
1079BOOLEAN\r
1080CalculateCertHash (\r
1081 IN UINT8 *CertData,\r
1082 IN UINTN CertSize,\r
1083 IN UINT32 HashAlg,\r
1084 OUT UINT8 *CertHash\r
1085 )\r
1086{\r
1087 BOOLEAN Status;\r
1088 VOID *HashCtx;\r
1089 UINTN CtxSize;\r
12d95665
LQ
1090 UINT8 *TBSCert;\r
1091 UINTN TBSCertSize;\r
20333c6d
QL
1092\r
1093 HashCtx = NULL;\r
1094 Status = FALSE;\r
1095\r
1096 if (HashAlg >= HASHALG_MAX) {\r
1097 return FALSE;\r
1098 }\r
1099\r
12d95665
LQ
1100 //\r
1101 // Retrieve the TBSCertificate for Hash Calculation.\r
1102 //\r
1103 if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {\r
1104 return FALSE;\r
1105 }\r
1106\r
20333c6d
QL
1107 //\r
1108 // 1. Initialize context of hash.\r
1109 //\r
1110 CtxSize = mHash[HashAlg].GetContextSize ();\r
1111 HashCtx = AllocatePool (CtxSize);\r
1112 ASSERT (HashCtx != NULL);\r
1113\r
1114 //\r
1115 // 2. Initialize a hash context.\r
1116 //\r
1117 Status = mHash[HashAlg].HashInit (HashCtx);\r
1118 if (!Status) {\r
1119 goto Done;\r
1120 }\r
1121\r
1122 //\r
1123 // 3. Calculate the hash.\r
1124 //\r
12d95665 1125 Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
20333c6d
QL
1126 if (!Status) {\r
1127 goto Done;\r
1128 }\r
1129\r
1130 //\r
1131 // 4. Get the hash result.\r
1132 //\r
1133 ZeroMem (CertHash, mHash[HashAlg].DigestLength);\r
1134 Status = mHash[HashAlg].HashFinal (HashCtx, CertHash);\r
1135\r
1136Done:\r
1137 if (HashCtx != NULL) {\r
1138 FreePool (HashCtx);\r
1139 }\r
1140\r
1141 return Status;\r
1142}\r
1143\r
1144/**\r
1145 Check whether the hash of an X.509 certificate is in forbidden database (DBX).\r
1146\r
1147 @param[in] Certificate Pointer to X.509 Certificate that is searched for.\r
1148 @param[in] CertSize Size of X.509 Certificate.\r
1149\r
1150 @return TRUE Found the certificate hash in the forbidden database.\r
1151 @return FALSE Certificate hash is Not found in the forbidden database.\r
1152\r
1153**/\r
1154BOOLEAN\r
1155IsCertHashFoundInDbx (\r
1156 IN UINT8 *Certificate,\r
1157 IN UINTN CertSize\r
1158 )\r
1159{\r
1160 BOOLEAN IsFound;\r
1161 EFI_STATUS Status;\r
1162 EFI_SIGNATURE_LIST *DbxList;\r
1163 EFI_SIGNATURE_DATA *CertHash;\r
1164 UINTN CertHashCount;\r
1165 UINTN Index;\r
1166 UINT32 HashAlg;\r
1167 UINT8 CertDigest[MAX_DIGEST_SIZE];\r
1168 UINT8 *DbxCertHash;\r
1169 UINTN SiglistHeaderSize;\r
1170 UINT8 *Data;\r
1171 UINTN DataSize;\r
1172\r
1173 IsFound = FALSE;\r
1174 HashAlg = HASHALG_MAX;\r
1175 Data = NULL;\r
1176\r
1177 //\r
1178 // Read signature database variable.\r
1179 //\r
1180 DataSize = 0;\r
1181 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
1182 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1183 return FALSE;\r
1184 }\r
1185\r
1186 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1187 if (Data == NULL) {\r
1188 return FALSE;\r
1189 }\r
1190\r
1191 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
1192 if (EFI_ERROR (Status)) {\r
1193 goto Done;\r
1194 }\r
1195\r
1196 //\r
1197 // Check whether the certificate hash exists in the forbidden database.\r
1198 //\r
1199 DbxList = (EFI_SIGNATURE_LIST *) Data;\r
1200 while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {\r
1201 //\r
1202 // Determine Hash Algorithm of Certificate in the forbidden database.\r
1203 //\r
1204 if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
1205 HashAlg = HASHALG_SHA256;\r
1206 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
1207 HashAlg = HASHALG_SHA384;\r
1208 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
1209 HashAlg = HASHALG_SHA512;\r
1210 } else {\r
1211 DataSize -= DbxList->SignatureListSize;\r
1212 DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
1213 continue;\r
1214 }\r
1215\r
1216 //\r
1217 // Calculate the hash value of current db certificate for comparision.\r
1218 //\r
1219 if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {\r
1220 goto Done;\r
1221 }\r
1222\r
1223 SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;\r
1224 CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);\r
1225 CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;\r
1226 for (Index = 0; Index < CertHashCount; Index++) {\r
1227 //\r
1228 // Iterate each Signature Data Node within this CertList for verify.\r
1229 //\r
1230 DbxCertHash = CertHash->SignatureData;\r
1231 if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {\r
1232 //\r
1233 // Hash of Certificate is found in forbidden database.\r
1234 //\r
1235 IsFound = TRUE;\r
1236 goto Done;\r
1237 }\r
1238 CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);\r
1239 }\r
1240\r
1241 DataSize -= DbxList->SignatureListSize;\r
1242 DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
1243 }\r
1244\r
1245Done:\r
1246 if (Data != NULL) {\r
1247 FreePool (Data);\r
1248 }\r
1249\r
1250 return IsFound;\r
1251}\r
1252\r
1253/**\r
1254 Check whether the signature list exists in given variable data.\r
1255\r
1256 It searches the signature list for the ceritificate hash by CertType.\r
1257 If the signature list is found, get the offset of Database for the\r
1258 next hash of a certificate.\r
1259\r
1260 @param[in] Database Variable data to save signature list.\r
1261 @param[in] DatabaseSize Variable size.\r
1262 @param[in] SignatureType The type of the signature.\r
1263 @param[out] Offset The offset to save a new hash of certificate.\r
1264\r
1265 @return TRUE The signature list is found in the forbidden database.\r
1266 @return FALSE The signature list is not found in the forbidden database.\r
1267**/\r
1268BOOLEAN\r
1269GetSignaturelistOffset (\r
1270 IN EFI_SIGNATURE_LIST *Database,\r
1271 IN UINTN DatabaseSize,\r
1272 IN EFI_GUID *SignatureType,\r
1273 OUT UINTN *Offset\r
1274 )\r
1275{\r
1276 EFI_SIGNATURE_LIST *SigList;\r
1277 UINTN SiglistSize;\r
1278\r
1279 if ((Database == NULL) || (DatabaseSize == 0)) {\r
1280 *Offset = 0;\r
1281 return FALSE;\r
1282 }\r
1283\r
1284 SigList = Database;\r
1285 SiglistSize = DatabaseSize;\r
1286 while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {\r
1287 if (CompareGuid (&SigList->SignatureType, SignatureType)) {\r
1288 *Offset = DatabaseSize - SiglistSize;\r
1289 return TRUE;\r
1290 }\r
1291 SiglistSize -= SigList->SignatureListSize;\r
1292 SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);\r
1293 }\r
1294 *Offset = 0;\r
1295 return FALSE;\r
1296}\r
1297\r
1298/**\r
1299 Enroll a new X509 certificate hash into Signature Database (dbx) without\r
1300 KEK's authentication.\r
1301\r
1302 @param[in] PrivateData The module's private data.\r
1303 @param[in] HashAlg The hash algorithm to enroll the certificate.\r
1304 @param[in] RevocationDate The revocation date of the certificate.\r
1305 @param[in] RevocationTime The revocation time of the certificate.\r
1306 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.\r
1307\r
1308 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
1309 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1310 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
1311\r
1312**/\r
1313EFI_STATUS\r
1314EnrollX509HashtoSigDB (\r
1315 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1316 IN UINT32 HashAlg,\r
1317 IN EFI_HII_DATE *RevocationDate,\r
1318 IN EFI_HII_TIME *RevocationTime,\r
1319 IN BOOLEAN AlwaysRevocation\r
1320 )\r
1321{\r
1322 EFI_STATUS Status;\r
1323 UINTN X509DataSize;\r
1324 VOID *X509Data;\r
1325 EFI_SIGNATURE_LIST *SignatureList;\r
1326 UINTN SignatureListSize;\r
1327 UINT8 *Data;\r
1328 UINT8 *NewData;\r
1329 UINTN DataSize;\r
1330 UINTN DbSize;\r
1331 UINT32 Attr;\r
1332 EFI_SIGNATURE_DATA *SignatureData;\r
1333 UINTN SignatureSize;\r
1334 EFI_GUID SignatureType;\r
1335 UINTN Offset;\r
1336 UINT8 CertHash[MAX_DIGEST_SIZE];\r
1337 UINT16* FilePostFix;\r
1338 UINTN NameLength;\r
1339 EFI_TIME *Time;\r
1340\r
1341 X509DataSize = 0;\r
1342 DbSize = 0;\r
1343 X509Data = NULL;\r
1344 SignatureData = NULL;\r
1345 SignatureList = NULL;\r
1346 Data = NULL;\r
1347 NewData = NULL;\r
1348\r
1349 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
1350 return EFI_INVALID_PARAMETER;\r
1351 }\r
1352\r
1353 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
1354 if (EFI_ERROR (Status)) {\r
1355 return Status;\r
1356 }\r
1357\r
1358 //\r
1359 // Parse the file's postfix.\r
1360 //\r
1361 NameLength = StrLen (Private->FileContext->FileName);\r
1362 if (NameLength <= 4) {\r
1363 return EFI_INVALID_PARAMETER;\r
1364 }\r
1365 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
1366 if (!IsDerEncodeCertificate(FilePostFix)) {\r
1367 //\r
1368 // Only supports DER-encoded X509 certificate.\r
1369 //\r
1370 return EFI_INVALID_PARAMETER;\r
1371 }\r
1372\r
1373 //\r
1374 // Get the certificate from file and calculate its hash.\r
1375 //\r
1376 Status = ReadFileContent (\r
1377 Private->FileContext->FHandle,\r
1378 &X509Data,\r
1379 &X509DataSize,\r
1380 0\r
1381 );\r
1382 if (EFI_ERROR (Status)) {\r
1383 goto ON_EXIT;\r
1384 }\r
1385 ASSERT (X509Data != NULL);\r
1386\r
1387 if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {\r
1388 goto ON_EXIT;\r
1389 }\r
1390\r
1391 //\r
1392 // Get the variable for enrollment.\r
1393 //\r
1394 DataSize = 0;\r
1395 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
1396 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1397 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1398 if (Data == NULL) {\r
1399 return EFI_OUT_OF_RESOURCES;\r
1400 }\r
1401\r
1402 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
1403 if (EFI_ERROR (Status)) {\r
1404 goto ON_EXIT;\r
1405 }\r
1406 }\r
1407\r
1408 //\r
1409 // Allocate memory for Signature and fill the Signature\r
1410 //\r
1411 SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;\r
1412 SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize);\r
1413 if (SignatureData == NULL) {\r
1414 return EFI_OUT_OF_RESOURCES;\r
1415 }\r
1416 CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);\r
1417 CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);\r
1418\r
1419 //\r
1420 // Fill the time.\r
1421 //\r
1422 if (!AlwaysRevocation) {\r
1423 Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);\r
1424 Time->Year = RevocationDate->Year;\r
1425 Time->Month = RevocationDate->Month;\r
1426 Time->Day = RevocationDate->Day;\r
1427 Time->Hour = RevocationTime->Hour;\r
1428 Time->Minute = RevocationTime->Minute;\r
1429 Time->Second = RevocationTime->Second;\r
1430 }\r
1431\r
1432 //\r
1433 // Determine the GUID for certificate hash.\r
1434 //\r
1435 switch (HashAlg) {\r
1436 case HASHALG_SHA256:\r
1437 SignatureType = gEfiCertX509Sha256Guid;\r
1438 break;\r
1439 case HASHALG_SHA384:\r
1440 SignatureType = gEfiCertX509Sha384Guid;\r
1441 break;\r
1442 case HASHALG_SHA512:\r
1443 SignatureType = gEfiCertX509Sha512Guid;\r
1444 break;\r
1445 default:\r
1446 return FALSE;\r
1447 }\r
1448\r
1449 //\r
1450 // Add signature into the new variable data buffer\r
1451 //\r
1452 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {\r
1453 //\r
1454 // Add the signature to the found signaturelist.\r
1455 //\r
1456 DbSize = DataSize + SignatureSize;\r
1457 NewData = AllocateZeroPool (DbSize);\r
1458 if (NewData == NULL) {\r
1459 Status = EFI_OUT_OF_RESOURCES;\r
1460 goto ON_EXIT;\r
1461 }\r
1462\r
1463 SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
1464 SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);\r
1465 CopyMem (NewData, Data, Offset + SignatureListSize);\r
1466\r
1467 SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);\r
1468 WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));\r
1469\r
1470 Offset += SignatureListSize;\r
1471 CopyMem (NewData + Offset, SignatureData, SignatureSize);\r
1472 CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);\r
1473\r
1474 FreePool (Data);\r
1475 Data = NewData;\r
1476 DataSize = DbSize;\r
1477 } else {\r
1478 //\r
1479 // Create a new signaturelist, and add the signature into the signaturelist.\r
1480 //\r
1481 DbSize = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize;\r
1482 NewData = AllocateZeroPool (DbSize);\r
1483 if (NewData == NULL) {\r
1484 Status = EFI_OUT_OF_RESOURCES;\r
1485 goto ON_EXIT;\r
1486 }\r
1487 //\r
1488 // Fill Certificate Database parameters.\r
1489 //\r
1490 SignatureList = (EFI_SIGNATURE_LIST*) (NewData + DataSize);\r
1491 SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize;\r
1492 WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize);\r
1493 WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize);\r
1494 CopyGuid (&SignatureList->SignatureType, &SignatureType);\r
1495 CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);\r
1496 if ((DataSize != 0) && (Data != NULL)) {\r
1497 CopyMem (NewData, Data, DataSize);\r
1498 FreePool (Data);\r
1499 }\r
1500 Data = NewData;\r
1501 DataSize = DbSize;\r
1502 }\r
1503\r
1504 Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data);\r
1505 if (EFI_ERROR (Status)) {\r
1506 goto ON_EXIT;\r
1507 }\r
1508\r
1509 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
1510 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
1511 Status = gRT->SetVariable(\r
1512 EFI_IMAGE_SECURITY_DATABASE1,\r
1513 &gEfiImageSecurityDatabaseGuid,\r
1514 Attr,\r
1515 DataSize,\r
1516 Data\r
1517 );\r
1518 if (EFI_ERROR (Status)) {\r
1519 goto ON_EXIT;\r
1520 }\r
1521\r
1522ON_EXIT:\r
ecc722ad 1523 CloseFile (Private->FileContext->FHandle);\r
762d8ddb
DB
1524 if (Private->FileContext->FileName != NULL){\r
1525 FreePool(Private->FileContext->FileName);\r
1526 Private->FileContext->FileName = NULL;\r
1527 }\r
1528\r
ecc722ad 1529 Private->FileContext->FHandle = NULL;\r
1530\r
1531 if (Private->SignatureGUID != NULL) {\r
1532 FreePool (Private->SignatureGUID);\r
1533 Private->SignatureGUID = NULL;\r
1534 }\r
1535\r
20333c6d
QL
1536 if (Data != NULL) {\r
1537 FreePool (Data);\r
ecc722ad 1538 }\r
1539\r
20333c6d
QL
1540 if (SignatureData != NULL) {\r
1541 FreePool (SignatureData);\r
ecc722ad 1542 }\r
1543\r
20333c6d
QL
1544 if (X509Data != NULL) {\r
1545 FreePool (X509Data);\r
f71ed839 1546 }\r
1547\r
20333c6d 1548 return Status;\r
ecc722ad 1549}\r
1550\r
1551/**\r
20333c6d 1552 Check whether a certificate from a file exists in dbx.\r
ecc722ad 1553\r
1554 @param[in] PrivateData The module's private data.\r
20333c6d
QL
1555 @param[in] VariableName Variable name of signature database, must be\r
1556 EFI_IMAGE_SECURITY_DATABASE1.\r
ecc722ad 1557\r
20333c6d
QL
1558 @retval TRUE The X509 certificate is found in dbx successfully.\r
1559 @retval FALSE The X509 certificate is not found in dbx.\r
ecc722ad 1560**/\r
20333c6d
QL
1561BOOLEAN\r
1562IsX509CertInDbx (\r
ecc722ad 1563 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1564 IN CHAR16 *VariableName\r
20333c6d 1565 )\r
ecc722ad 1566{\r
20333c6d
QL
1567 EFI_STATUS Status;\r
1568 UINTN X509DataSize;\r
1569 VOID *X509Data;\r
1570 BOOLEAN IsFound;\r
ecc722ad 1571\r
20333c6d
QL
1572 //\r
1573 // Read the certificate from file\r
1574 //\r
ecc722ad 1575 X509DataSize = 0;\r
ecc722ad 1576 X509Data = NULL;\r
ecc722ad 1577 Status = ReadFileContent (\r
1578 Private->FileContext->FHandle,\r
1579 &X509Data,\r
1580 &X509DataSize,\r
1581 0\r
1582 );\r
1583 if (EFI_ERROR (Status)) {\r
20333c6d 1584 return FALSE;\r
ecc722ad 1585 }\r
1586\r
1587 //\r
20333c6d 1588 // Check the raw certificate.\r
ecc722ad 1589 //\r
20333c6d
QL
1590 IsFound = FALSE;\r
1591 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {\r
1592 IsFound = TRUE;\r
8c1babfd 1593 goto ON_EXIT;\r
1594 }\r
ecc722ad 1595\r
20333c6d
QL
1596 //\r
1597 // Check the hash of certificate.\r
1598 //\r
1599 if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {\r
1600 IsFound = TRUE;\r
ecc722ad 1601 goto ON_EXIT;\r
1602 }\r
1603\r
1604ON_EXIT:\r
ecc722ad 1605 if (X509Data != NULL) {\r
1606 FreePool (X509Data);\r
1607 }\r
1608\r
20333c6d 1609 return IsFound;\r
ecc722ad 1610}\r
1611\r
1612/**\r
1613 Load PE/COFF image information into internal buffer and check its validity.\r
1614\r
1615 @retval EFI_SUCCESS Successful\r
1616 @retval EFI_UNSUPPORTED Invalid PE/COFF file\r
1617 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.\r
1618\r
1619**/\r
1620EFI_STATUS\r
1621LoadPeImage (\r
20333c6d
QL
1622 VOID\r
1623 )\r
ecc722ad 1624{\r
1625 EFI_IMAGE_DOS_HEADER *DosHdr;\r
1626 EFI_IMAGE_NT_HEADERS32 *NtHeader32;\r
1627 EFI_IMAGE_NT_HEADERS64 *NtHeader64;\r
1628\r
1629 NtHeader32 = NULL;\r
1630 NtHeader64 = NULL;\r
1631 //\r
1632 // Read the Dos header\r
1633 //\r
1634 DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);\r
1635 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)\r
1636 {\r
1637 //\r
20333c6d 1638 // DOS image header is present,\r
ecc722ad 1639 // So read the PE header after the DOS image header\r
1640 //\r
1641 mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
1642 }\r
1643 else\r
1644 {\r
1645 mPeCoffHeaderOffset = 0;\r
1646 }\r
1647\r
1648 //\r
1649 // Read PE header and check the signature validity and machine compatibility\r
1650 //\r
1651 NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);\r
1652 if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)\r
1653 {\r
1654 return EFI_UNSUPPORTED;\r
1655 }\r
1656\r
1657 mNtHeader.Pe32 = NtHeader32;\r
1658\r
1659 //\r
1660 // Check the architecture field of PE header and get the Certificate Data Directory data\r
1661 // Note the size of FileHeader field is constant for both IA32 and X64 arch\r
1662 //\r
20333c6d 1663 if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)\r
a16170a1
AB
1664 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)\r
1665 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) {\r
ecc722ad 1666 //\r
a16170a1 1667 // 32-bits Architecture\r
ecc722ad 1668 //\r
1669 mImageType = ImageType_IA32;\r
1670 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
1671 }\r
1672 else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
a16170a1
AB
1673 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)\r
1674 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) {\r
ecc722ad 1675 //\r
1676 // 64-bits Architecture\r
1677 //\r
1678 mImageType = ImageType_X64;\r
1679 NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);\r
1680 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
1681 } else {\r
1682 return EFI_UNSUPPORTED;\r
1683 }\r
1684\r
1685 return EFI_SUCCESS;\r
1686}\r
1687\r
1688/**\r
1689 Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
1690 PE/COFF Specification 8.0 Appendix A\r
1691\r
1692 @param[in] HashAlg Hash algorithm type.\r
20333c6d 1693\r
ecc722ad 1694 @retval TRUE Successfully hash image.\r
1695 @retval FALSE Fail in hash image.\r
1696\r
1697**/\r
20333c6d 1698BOOLEAN\r
ecc722ad 1699HashPeImage (\r
1700 IN UINT32 HashAlg\r
1701 )\r
1702{\r
1703 BOOLEAN Status;\r
1704 UINT16 Magic;\r
1705 EFI_IMAGE_SECTION_HEADER *Section;\r
1706 VOID *HashCtx;\r
1707 UINTN CtxSize;\r
1708 UINT8 *HashBase;\r
1709 UINTN HashSize;\r
1710 UINTN SumOfBytesHashed;\r
1711 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1712 UINTN Index;\r
1713 UINTN Pos;\r
1714\r
1715 HashCtx = NULL;\r
1716 SectionHeader = NULL;\r
1717 Status = FALSE;\r
1718\r
1719 if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
1720 return FALSE;\r
1721 }\r
20333c6d 1722\r
ecc722ad 1723 //\r
1724 // Initialize context of hash.\r
1725 //\r
1726 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
1727\r
1728 if (HashAlg == HASHALG_SHA1) {\r
1729 mImageDigestSize = SHA1_DIGEST_SIZE;\r
20333c6d 1730 mCertType = gEfiCertSha1Guid;\r
ecc722ad 1731 } else if (HashAlg == HASHALG_SHA256) {\r
1732 mImageDigestSize = SHA256_DIGEST_SIZE;\r
1733 mCertType = gEfiCertSha256Guid;\r
1734 }\r
1735\r
1736 CtxSize = mHash[HashAlg].GetContextSize();\r
20333c6d 1737\r
ecc722ad 1738 HashCtx = AllocatePool (CtxSize);\r
1739 ASSERT (HashCtx != NULL);\r
1740\r
1741 // 1. Load the image header into memory.\r
1742\r
1743 // 2. Initialize a SHA hash context.\r
1744 Status = mHash[HashAlg].HashInit(HashCtx);\r
1745 if (!Status) {\r
1746 goto Done;\r
1747 }\r
1748 //\r
1749 // Measuring PE/COFF Image Header;\r
1750 // But CheckSum field and SECURITY data directory (certificate) are excluded\r
1751 //\r
de2447dd 1752 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1753 //\r
20333c6d
QL
1754 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
1755 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
de2447dd 1756 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1757 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1758 //\r
1759 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
1760 } else {\r
1761 //\r
1762 // Get the magic value from the PE/COFF Optional Header\r
1763 //\r
1764 Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
1765 }\r
20333c6d 1766\r
ecc722ad 1767 //\r
1768 // 3. Calculate the distance from the base of the image header to the image checksum address.\r
1769 // 4. Hash the image header from its base to beginning of the image checksum.\r
1770 //\r
1771 HashBase = mImageBase;\r
1772 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1773 //\r
1774 // Use PE32 offset.\r
1775 //\r
1776 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
1777 } else {\r
1778 //\r
1779 // Use PE32+ offset.\r
1780 //\r
1781 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
1782 }\r
1783\r
1784 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1785 if (!Status) {\r
1786 goto Done;\r
1787 }\r
1788 //\r
1789 // 5. Skip over the image checksum (it occupies a single ULONG).\r
1790 // 6. Get the address of the beginning of the Cert Directory.\r
1791 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
1792 //\r
1793 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1794 //\r
1795 // Use PE32 offset.\r
1796 //\r
1797 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
1798 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1799 } else {\r
1800 //\r
1801 // Use PE32+ offset.\r
20333c6d 1802 //\r
ecc722ad 1803 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
1804 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1805 }\r
1806\r
1807 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1808 if (!Status) {\r
1809 goto Done;\r
1810 }\r
1811 //\r
1812 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
1813 // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
1814 //\r
1815 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1816 //\r
1817 // Use PE32 offset\r
1818 //\r
1819 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1820 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1821 } else {\r
1822 //\r
1823 // Use PE32+ offset.\r
1824 //\r
1825 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1826 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1827 }\r
1828\r
1829 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1830 if (!Status) {\r
1831 goto Done;\r
1832 }\r
1833 //\r
1834 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
1835 //\r
1836 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1837 //\r
1838 // Use PE32 offset.\r
1839 //\r
1840 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
1841 } else {\r
1842 //\r
1843 // Use PE32+ offset\r
1844 //\r
1845 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
1846 }\r
1847\r
1848 //\r
1849 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
1850 // structures in the image. The 'NumberOfSections' field of the image\r
1851 // header indicates how big the table should be. Do not include any\r
1852 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
1853 //\r
1854 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
1855 ASSERT (SectionHeader != NULL);\r
1856 //\r
1857 // 12. Using the 'PointerToRawData' in the referenced section headers as\r
1858 // a key, arrange the elements in the table in ascending order. In other\r
1859 // words, sort the section headers according to the disk-file offset of\r
1860 // the section.\r
1861 //\r
1862 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1863 mImageBase +\r
1864 mPeCoffHeaderOffset +\r
1865 sizeof (UINT32) +\r
1866 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1867 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
1868 );\r
1869 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1870 Pos = Index;\r
1871 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
1872 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
1873 Pos--;\r
1874 }\r
1875 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
1876 Section += 1;\r
1877 }\r
1878\r
1879 //\r
1880 // 13. Walk through the sorted table, bring the corresponding section\r
1881 // into memory, and hash the entire section (using the 'SizeOfRawData'\r
1882 // field in the section header to determine the amount of data to hash).\r
1883 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
1884 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.\r
1885 //\r
1886 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1887 Section = &SectionHeader[Index];\r
1888 if (Section->SizeOfRawData == 0) {\r
1889 continue;\r
1890 }\r
1891 HashBase = mImageBase + Section->PointerToRawData;\r
1892 HashSize = (UINTN) Section->SizeOfRawData;\r
1893\r
1894 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1895 if (!Status) {\r
1896 goto Done;\r
1897 }\r
1898\r
1899 SumOfBytesHashed += HashSize;\r
1900 }\r
1901\r
1902 //\r
1903 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
1904 // data in the file that needs to be added to the hash. This data begins\r
1905 // at file offset SUM_OF_BYTES_HASHED and its length is:\r
1906 // FileSize - (CertDirectory->Size)\r
1907 //\r
1908 if (mImageSize > SumOfBytesHashed) {\r
1909 HashBase = mImageBase + SumOfBytesHashed;\r
1910 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1911 //\r
1912 // Use PE32 offset.\r
1913 //\r
1914 HashSize = (UINTN)(\r
1915 mImageSize -\r
1916 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
1917 SumOfBytesHashed);\r
1918 } else {\r
1919 //\r
1920 // Use PE32+ offset.\r
1921 //\r
1922 HashSize = (UINTN)(\r
1923 mImageSize -\r
1924 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
20333c6d 1925 SumOfBytesHashed);\r
ecc722ad 1926 }\r
1927\r
1928 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1929 if (!Status) {\r
1930 goto Done;\r
1931 }\r
1932 }\r
1933\r
1934 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
1935\r
1936Done:\r
1937 if (HashCtx != NULL) {\r
1938 FreePool (HashCtx);\r
1939 }\r
1940 if (SectionHeader != NULL) {\r
1941 FreePool (SectionHeader);\r
1942 }\r
1943 return Status;\r
1944}\r
1945\r
1946/**\r
69f8bb52 1947 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of\r
20333c6d 1948 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification\r
ecc722ad 1949 8.0 Appendix A\r
1950\r
1951 @retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
1952 @retval EFI_SUCCESS Hash successfully.\r
1953\r
1954**/\r
20333c6d 1955EFI_STATUS\r
ecc722ad 1956HashPeImageByType (\r
1957 VOID\r
1958 )\r
1959{\r
1960 UINT8 Index;\r
1961 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
1962\r
1963 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
1964\r
20333c6d 1965 for (Index = 0; Index < HASHALG_MAX; Index++) {\r
ecc722ad 1966 //\r
1967 // Check the Hash algorithm in PE/COFF Authenticode.\r
20333c6d 1968 // According to PKCS#7 Definition:\r
ecc722ad 1969 // SignedData ::= SEQUENCE {\r
1970 // version Version,\r
1971 // digestAlgorithms DigestAlgorithmIdentifiers,\r
1972 // contentInfo ContentInfo,\r
1973 // .... }\r
1974 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
1975 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
1976 // Fixed offset (+32) is calculated based on two bytes of length encoding.\r
1977 //\r
1978 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
1979 //\r
1980 // Only support two bytes of Long Form of Length Encoding.\r
1981 //\r
1982 continue;\r
1983 }\r
1984\r
20333c6d 1985 //\r
ecc722ad 1986 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
1987 break;\r
1988 }\r
1989 }\r
1990\r
1991 if (Index == HASHALG_MAX) {\r
1992 return EFI_UNSUPPORTED;\r
1993 }\r
1994\r
1995 //\r
1996 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
1997 //\r
1998 if (!HashPeImage(Index)) {\r
1999 return EFI_UNSUPPORTED;\r
2000 }\r
2001\r
2002 return EFI_SUCCESS;\r
2003}\r
2004\r
2005/**\r
20333c6d 2006 Enroll a new executable's signature into Signature Database.\r
ecc722ad 2007\r
2008 @param[in] PrivateData The module's private data.\r
20333c6d
QL
2009 @param[in] VariableName Variable name of signature database, must be\r
2010 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1\r
2011 or EFI_IMAGE_SECURITY_DATABASE2.\r
ecc722ad 2012\r
2013 @retval EFI_SUCCESS New signature is enrolled successfully.\r
2014 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2015 @retval EFI_UNSUPPORTED Unsupported command.\r
2016 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
2017\r
2018**/\r
2019EFI_STATUS\r
2020EnrollImageSignatureToSigDB (\r
2021 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2022 IN CHAR16 *VariableName\r
2023 )\r
2024{\r
2025 EFI_STATUS Status;\r
2026 EFI_SIGNATURE_LIST *SigDBCert;\r
2027 EFI_SIGNATURE_DATA *SigDBCertData;\r
2028 VOID *Data;\r
2029 UINTN DataSize;\r
2030 UINTN SigDBSize;\r
2031 UINT32 Attr;\r
2032 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;\r
2033\r
2034 Data = NULL;\r
2035 GuidCertData = NULL;\r
ecc722ad 2036\r
20333c6d
QL
2037 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {\r
2038 return EFI_UNSUPPORTED;\r
2039 }\r
2040\r
ecc722ad 2041 //\r
2042 // Form the SigDB certificate list.\r
2043 // Format the data item into EFI_SIGNATURE_LIST type.\r
2044 //\r
2045 // We need to parse executable's signature data from specified signed executable file.\r
2046 // In current implementation, we simply trust the pass-in signed executable file.\r
2047 // In reality, it's OS's responsibility to verify the signed executable file.\r
2048 //\r
2049\r
2050 //\r
2051 // Read the whole file content\r
2052 //\r
2053 Status = ReadFileContent(\r
2054 Private->FileContext->FHandle,\r
20333c6d
QL
2055 (VOID **) &mImageBase,\r
2056 &mImageSize,\r
ecc722ad 2057 0\r
2058 );\r
2059 if (EFI_ERROR (Status)) {\r
2060 goto ON_EXIT;\r
20333c6d 2061 }\r
ba57d4fd 2062 ASSERT (mImageBase != NULL);\r
ecc722ad 2063\r
2064 Status = LoadPeImage ();\r
2065 if (EFI_ERROR (Status)) {\r
2066 goto ON_EXIT;\r
2067 }\r
2068\r
2069 if (mSecDataDir->SizeOfCert == 0) {\r
2070 if (!HashPeImage (HASHALG_SHA256)) {\r
2071 Status = EFI_SECURITY_VIOLATION;\r
2072 goto ON_EXIT;\r
2073 }\r
2074 } else {\r
20333c6d 2075\r
ecc722ad 2076 //\r
2077 // Read the certificate data\r
2078 //\r
2079 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
2080\r
2081 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
2082 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
2083 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
2084 Status = EFI_ABORTED;\r
2085 goto ON_EXIT;\r
2086 }\r
2087\r
2088 if (!HashPeImage (HASHALG_SHA256)) {\r
2089 Status = EFI_ABORTED;\r
2090 goto ON_EXIT;;\r
2091 }\r
20333c6d 2092\r
ecc722ad 2093 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
2094\r
2095 Status = HashPeImageByType ();\r
2096 if (EFI_ERROR (Status)) {\r
2097 goto ON_EXIT;;\r
2098 }\r
2099 } else {\r
2100 Status = EFI_ABORTED;\r
2101 goto ON_EXIT;\r
2102 }\r
2103 }\r
2104\r
2105 //\r
2106 // Create a new SigDB entry.\r
2107 //\r
20333c6d 2108 SigDBSize = sizeof(EFI_SIGNATURE_LIST)\r
ecc722ad 2109 + sizeof(EFI_SIGNATURE_DATA) - 1\r
2110 + (UINT32) mImageDigestSize;\r
2111\r
2112 Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
2113 if (Data == NULL) {\r
2114 Status = EFI_OUT_OF_RESOURCES;\r
2115 goto ON_EXIT;\r
2116 }\r
20333c6d 2117\r
ecc722ad 2118 //\r
2119 // Adjust the Certificate Database parameters.\r
20333c6d 2120 //\r
ecc722ad 2121 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
2122 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
2123 SigDBCert->SignatureHeaderSize = 0;\r
2124 SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
2125 CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
2126\r
2127 SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
2128 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
2129 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
2130\r
20333c6d 2131 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 2132 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
2133 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
2134 if (EFI_ERROR (Status)) {\r
2135 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2136 goto ON_EXIT;\r
2137 }\r
20333c6d 2138\r
ecc722ad 2139 //\r
20333c6d
QL
2140 // Check if SigDB variable has been already existed.\r
2141 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 2142 // new signature data to original variable\r
20333c6d 2143 //\r
ecc722ad 2144 DataSize = 0;\r
2145 Status = gRT->GetVariable(\r
20333c6d
QL
2146 VariableName,\r
2147 &gEfiImageSecurityDatabaseGuid,\r
2148 NULL,\r
2149 &DataSize,\r
ecc722ad 2150 NULL\r
2151 );\r
2152 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2153 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
2154 } else if (Status != EFI_NOT_FOUND) {\r
2155 goto ON_EXIT;\r
20333c6d 2156 }\r
ecc722ad 2157\r
2158 //\r
2159 // Enroll the variable.\r
2160 //\r
2161 Status = gRT->SetVariable(\r
20333c6d
QL
2162 VariableName,\r
2163 &gEfiImageSecurityDatabaseGuid,\r
2164 Attr,\r
2165 SigDBSize,\r
ecc722ad 2166 Data\r
2167 );\r
2168 if (EFI_ERROR (Status)) {\r
2169 goto ON_EXIT;\r
2170 }\r
2171\r
2172ON_EXIT:\r
2173\r
2174 CloseFile (Private->FileContext->FHandle);\r
2175 Private->FileContext->FHandle = NULL;\r
762d8ddb
DB
2176\r
2177 if (Private->FileContext->FileName != NULL){\r
2178 FreePool(Private->FileContext->FileName);\r
2179 Private->FileContext->FileName = NULL;\r
2180 }\r
ecc722ad 2181\r
2182 if (Private->SignatureGUID != NULL) {\r
2183 FreePool (Private->SignatureGUID);\r
2184 Private->SignatureGUID = NULL;\r
2185 }\r
2186\r
2187 if (Data != NULL) {\r
2188 FreePool (Data);\r
2189 }\r
2190\r
2191 if (mImageBase != NULL) {\r
2192 FreePool (mImageBase);\r
2193 mImageBase = NULL;\r
2194 }\r
2195\r
2196 return Status;\r
2197}\r
2198\r
2199/**\r
20333c6d 2200 Enroll signature into DB/DBX/DBT without KEK's authentication.\r
ecc722ad 2201 The SignatureOwner GUID will be Private->SignatureGUID.\r
20333c6d 2202\r
ecc722ad 2203 @param[in] PrivateData The module's private data.\r
20333c6d 2204 @param[in] VariableName Variable name of signature database, must be\r
ecc722ad 2205 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
20333c6d 2206\r
ecc722ad 2207 @retval EFI_SUCCESS New signature enrolled successfully.\r
2208 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2209 @retval others Fail to enroll signature data.\r
20333c6d 2210\r
ecc722ad 2211**/\r
2212EFI_STATUS\r
2213EnrollSignatureDatabase (\r
2214 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2215 IN CHAR16 *VariableName\r
20333c6d 2216 )\r
ecc722ad 2217{\r
2218 UINT16* FilePostFix;\r
f71ed839 2219 EFI_STATUS Status;\r
fd64f84f 2220 UINTN NameLength;\r
ecc722ad 2221\r
2222 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
2223 return EFI_INVALID_PARAMETER;\r
2224 }\r
2225\r
20333c6d 2226 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
f71ed839 2227 if (EFI_ERROR (Status)) {\r
2228 return Status;\r
2229 }\r
20333c6d 2230\r
ecc722ad 2231 //\r
20333c6d 2232 // Parse the file's postfix.\r
ecc722ad 2233 //\r
fd64f84f
GCPL
2234 NameLength = StrLen (Private->FileContext->FileName);\r
2235 if (NameLength <= 4) {\r
2236 return EFI_INVALID_PARAMETER;\r
2237 }\r
2238 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
20333c6d 2239 if (IsDerEncodeCertificate (FilePostFix)) {\r
ecc722ad 2240 //\r
e4d7370d 2241 // Supports DER-encoded X509 certificate.\r
ecc722ad 2242 //\r
2243 return EnrollX509toSigDB (Private, VariableName);\r
2244 }\r
2245\r
2246 return EnrollImageSignatureToSigDB (Private, VariableName);\r
2247}\r
2248\r
2249/**\r
20333c6d 2250 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)\r
ecc722ad 2251 by GUID in the page for user to select and delete as needed.\r
2252\r
2253 @param[in] PrivateData Module's private data.\r
2254 @param[in] VariableName The variable name of the vendor's signature database.\r
2255 @param[in] VendorGuid A unique identifier for the vendor.\r
2256 @param[in] LabelNumber Label number to insert opcodes.\r
2257 @param[in] FormId Form ID of current page.\r
2258 @param[in] QuestionIdBase Base question id of the signature list.\r
2259\r
2260 @retval EFI_SUCCESS Success to update the signature list page\r
2261 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
20333c6d 2262\r
ecc722ad 2263**/\r
2264EFI_STATUS\r
2265UpdateDeletePage (\r
2266 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2267 IN CHAR16 *VariableName,\r
2268 IN EFI_GUID *VendorGuid,\r
2269 IN UINT16 LabelNumber,\r
2270 IN EFI_FORM_ID FormId,\r
2271 IN EFI_QUESTION_ID QuestionIdBase\r
2272 )\r
2273{\r
2274 EFI_STATUS Status;\r
2275 UINT32 Index;\r
2276 UINTN CertCount;\r
2277 UINTN GuidIndex;\r
2278 VOID *StartOpCodeHandle;\r
2279 VOID *EndOpCodeHandle;\r
2280 EFI_IFR_GUID_LABEL *StartLabel;\r
20333c6d 2281 EFI_IFR_GUID_LABEL *EndLabel;\r
ecc722ad 2282 UINTN DataSize;\r
2283 UINT8 *Data;\r
2284 EFI_SIGNATURE_LIST *CertList;\r
2285 EFI_SIGNATURE_DATA *Cert;\r
2286 UINT32 ItemDataSize;\r
2287 CHAR16 *GuidStr;\r
2288 EFI_STRING_ID GuidID;\r
2289 EFI_STRING_ID Help;\r
2290\r
2291 Data = NULL;\r
2292 CertList = NULL;\r
2293 Cert = NULL;\r
2294 GuidStr = NULL;\r
2295 StartOpCodeHandle = NULL;\r
2296 EndOpCodeHandle = NULL;\r
20333c6d 2297\r
ecc722ad 2298 //\r
2299 // Initialize the container for dynamic opcodes.\r
2300 //\r
2301 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2302 if (StartOpCodeHandle == NULL) {\r
2303 Status = EFI_OUT_OF_RESOURCES;\r
20333c6d 2304 goto ON_EXIT;\r
ecc722ad 2305 }\r
2306\r
2307 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2308 if (EndOpCodeHandle == NULL) {\r
2309 Status = EFI_OUT_OF_RESOURCES;\r
20333c6d 2310 goto ON_EXIT;\r
ecc722ad 2311 }\r
2312\r
2313 //\r
2314 // Create Hii Extend Label OpCode.\r
2315 //\r
2316 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2317 StartOpCodeHandle,\r
2318 &gEfiIfrTianoGuid,\r
2319 NULL,\r
2320 sizeof (EFI_IFR_GUID_LABEL)\r
2321 );\r
2322 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2323 StartLabel->Number = LabelNumber;\r
2324\r
2325 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2326 EndOpCodeHandle,\r
2327 &gEfiIfrTianoGuid,\r
2328 NULL,\r
2329 sizeof (EFI_IFR_GUID_LABEL)\r
2330 );\r
2331 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2332 EndLabel->Number = LABEL_END;\r
2333\r
2334 //\r
2335 // Read Variable.\r
2336 //\r
2337 DataSize = 0;\r
20333c6d 2338 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
ecc722ad 2339 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2340 goto ON_EXIT;\r
2341 }\r
2342\r
2343 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
2344 if (Data == NULL) {\r
2345 Status = EFI_OUT_OF_RESOURCES;\r
2346 goto ON_EXIT;\r
2347 }\r
2348\r
2349 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
2350 if (EFI_ERROR (Status)) {\r
2351 goto ON_EXIT;\r
2352 }\r
2353\r
2354 GuidStr = AllocateZeroPool (100);\r
2355 if (GuidStr == NULL) {\r
2356 Status = EFI_OUT_OF_RESOURCES;\r
2357 goto ON_EXIT;\r
2358 }\r
2359\r
2360 //\r
2361 // Enumerate all KEK pub data.\r
2362 //\r
2363 ItemDataSize = (UINT32) DataSize;\r
2364 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2365 GuidIndex = 0;\r
2366\r
2367 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2368\r
2369 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
2370 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
2371 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
2372 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
2373 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
2374 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
2375 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
2376 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
20333c6d
QL
2377 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
2378 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);\r
2379 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
2380 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);\r
2381 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
2382 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);\r
ecc722ad 2383 } else {\r
2384 //\r
2385 // The signature type is not supported in current implementation.\r
2386 //\r
b7d269ea 2387 ItemDataSize -= CertList->SignatureListSize;\r
2388 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
ecc722ad 2389 continue;\r
2390 }\r
2391\r
2392 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2393 for (Index = 0; Index < CertCount; Index++) {\r
20333c6d
QL
2394 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList\r
2395 + sizeof (EFI_SIGNATURE_LIST)\r
2396 + CertList->SignatureHeaderSize\r
ecc722ad 2397 + Index * CertList->SignatureSize);\r
2398 //\r
20333c6d 2399 // Display GUID and help\r
ecc722ad 2400 //\r
2401 GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
2402 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
2403 HiiCreateCheckBoxOpCode (\r
2404 StartOpCodeHandle,\r
2405 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
20333c6d
QL
2406 0,\r
2407 0,\r
2408 GuidID,\r
ecc722ad 2409 Help,\r
2410 EFI_IFR_FLAG_CALLBACK,\r
2411 0,\r
2412 NULL\r
20333c6d 2413 );\r
ecc722ad 2414 }\r
2415\r
2416 ItemDataSize -= CertList->SignatureListSize;\r
2417 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2418 }\r
2419\r
2420ON_EXIT:\r
2421 HiiUpdateForm (\r
2422 PrivateData->HiiHandle,\r
2423 &gSecureBootConfigFormSetGuid,\r
2424 FormId,\r
2425 StartOpCodeHandle,\r
2426 EndOpCodeHandle\r
2427 );\r
2428\r
2429 if (StartOpCodeHandle != NULL) {\r
2430 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2431 }\r
2432\r
2433 if (EndOpCodeHandle != NULL) {\r
2434 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2435 }\r
20333c6d 2436\r
ecc722ad 2437 if (Data != NULL) {\r
2438 FreePool (Data);\r
2439 }\r
2440\r
2441 if (GuidStr != NULL) {\r
2442 FreePool (GuidStr);\r
2443 }\r
2444\r
2445 return EFI_SUCCESS;\r
2446}\r
2447\r
beda2356 2448/**\r
20333c6d 2449 Delete a KEK entry from KEK database.\r
beda2356 2450\r
ecc722ad 2451 @param[in] PrivateData Module's private data.\r
2452 @param[in] QuestionId Question id of the KEK item to delete.\r
beda2356 2453\r
ecc722ad 2454 @retval EFI_SUCCESS Delete kek item successfully.\r
2455 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
20333c6d 2456\r
ecc722ad 2457**/\r
2458EFI_STATUS\r
2459DeleteKeyExchangeKey (\r
2460 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2461 IN EFI_QUESTION_ID QuestionId\r
2462 )\r
2463{\r
2464 EFI_STATUS Status;\r
2465 UINTN DataSize;\r
2466 UINT8 *Data;\r
2467 UINT8 *OldData;\r
2468 UINT32 Attr;\r
2469 UINT32 Index;\r
2470 EFI_SIGNATURE_LIST *CertList;\r
2471 EFI_SIGNATURE_LIST *NewCertList;\r
2472 EFI_SIGNATURE_DATA *Cert;\r
2473 UINTN CertCount;\r
2474 UINT32 Offset;\r
2475 BOOLEAN IsKEKItemFound;\r
2476 UINT32 KekDataSize;\r
2477 UINTN DeleteKekIndex;\r
2478 UINTN GuidIndex;\r
2479\r
2480 Data = NULL;\r
2481 OldData = NULL;\r
2482 CertList = NULL;\r
2483 Cert = NULL;\r
20333c6d 2484 Attr = 0;\r
ecc722ad 2485 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
f71ed839 2486\r
2487 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2488 if (EFI_ERROR (Status)) {\r
2489 return Status;\r
2490 }\r
20333c6d 2491\r
ecc722ad 2492 //\r
2493 // Get original KEK variable.\r
20333c6d
QL
2494 //\r
2495 DataSize = 0;\r
ecc722ad 2496 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
2497 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2498 goto ON_EXIT;\r
2499 }\r
2500\r
2501 OldData = (UINT8*)AllocateZeroPool(DataSize);\r
2502 if (OldData == NULL) {\r
20333c6d 2503 Status = EFI_OUT_OF_RESOURCES;\r
ecc722ad 2504 goto ON_EXIT;\r
2505 }\r
2506\r
2507 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
2508 if (EFI_ERROR(Status)) {\r
2509 goto ON_EXIT;\r
2510 }\r
2511\r
2512 //\r
20333c6d 2513 // Allocate space for new variable.\r
ecc722ad 2514 //\r
2515 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2516 if (Data == NULL) {\r
2517 Status = EFI_OUT_OF_RESOURCES;\r
2518 goto ON_EXIT;\r
2519 }\r
2520\r
2521 //\r
2522 // Enumerate all KEK pub data and erasing the target item.\r
2523 //\r
2524 IsKEKItemFound = FALSE;\r
2525 KekDataSize = (UINT32) DataSize;\r
2526 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2527 Offset = 0;\r
2528 GuidIndex = 0;\r
2529 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
2530 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2531 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
2532 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2533 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
2534 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2535 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2536 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2537 for (Index = 0; Index < CertCount; Index++) {\r
2538 if (GuidIndex == DeleteKekIndex ) {\r
2539 //\r
2540 // Find it! Skip it!\r
2541 //\r
2542 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
20333c6d 2543 IsKEKItemFound = TRUE;\r
ecc722ad 2544 } else {\r
2545 //\r
2546 // This item doesn't match. Copy it to the Data buffer.\r
2547 //\r
2548 CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
2549 Offset += CertList->SignatureSize;\r
2550 }\r
2551 GuidIndex++;\r
2552 Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
2553 }\r
2554 } else {\r
2555 //\r
2556 // This List doesn't match. Copy it to the Data buffer.\r
2557 //\r
2558 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
2559 Offset += CertList->SignatureListSize;\r
2560 }\r
20333c6d 2561\r
ecc722ad 2562 KekDataSize -= CertList->SignatureListSize;\r
2563 CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
2564 }\r
2565\r
2566 if (!IsKEKItemFound) {\r
2567 //\r
2568 // Doesn't find the Kek Item!\r
2569 //\r
2570 Status = EFI_NOT_FOUND;\r
2571 goto ON_EXIT;\r
2572 }\r
2573\r
2574 //\r
2575 // Delete the Signature header if there is no signature in the list.\r
2576 //\r
2577 KekDataSize = Offset;\r
2578 CertList = (EFI_SIGNATURE_LIST*) Data;\r
2579 Offset = 0;\r
2580 ZeroMem (OldData, KekDataSize);\r
2581 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
2582 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
33985e3b 2583 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));\r
ecc722ad 2584 if (CertCount != 0) {\r
2585 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
2586 Offset += CertList->SignatureListSize;\r
20333c6d 2587 }\r
ecc722ad 2588 KekDataSize -= CertList->SignatureListSize;\r
2589 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2590 }\r
2591\r
ecc722ad 2592 DataSize = Offset;\r
8c1babfd 2593 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2594 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2595 if (EFI_ERROR (Status)) {\r
2596 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2597 goto ON_EXIT;\r
2598 }\r
2599 }\r
ecc722ad 2600\r
2601 Status = gRT->SetVariable(\r
20333c6d
QL
2602 EFI_KEY_EXCHANGE_KEY_NAME,\r
2603 &gEfiGlobalVariableGuid,\r
2604 Attr,\r
2605 DataSize,\r
ecc722ad 2606 OldData\r
2607 );\r
2608 if (EFI_ERROR (Status)) {\r
2609 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2610 goto ON_EXIT;\r
2611 }\r
20333c6d 2612\r
ecc722ad 2613ON_EXIT:\r
2614 if (Data != NULL) {\r
2615 FreePool(Data);\r
2616 }\r
2617\r
2618 if (OldData != NULL) {\r
2619 FreePool(OldData);\r
2620 }\r
2621\r
2622 return UpdateDeletePage (\r
20333c6d 2623 PrivateData,\r
ecc722ad 2624 EFI_KEY_EXCHANGE_KEY_NAME,\r
2625 &gEfiGlobalVariableGuid,\r
2626 LABEL_KEK_DELETE,\r
2627 FORMID_DELETE_KEK_FORM,\r
2628 OPTION_DEL_KEK_QUESTION_ID\r
2629 );\r
2630}\r
2631\r
2632/**\r
2633 Delete a signature entry from siganture database.\r
beda2356 2634\r
ecc722ad 2635 @param[in] PrivateData Module's private data.\r
2636 @param[in] VariableName The variable name of the vendor's signature database.\r
2637 @param[in] VendorGuid A unique identifier for the vendor.\r
2638 @param[in] LabelNumber Label number to insert opcodes.\r
2639 @param[in] FormId Form ID of current page.\r
2640 @param[in] QuestionIdBase Base question id of the signature list.\r
2641 @param[in] DeleteIndex Signature index to delete.\r
20333c6d 2642\r
ecc722ad 2643 @retval EFI_SUCCESS Delete siganture successfully.\r
2644 @retval EFI_NOT_FOUND Can't find the signature item,\r
2645 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
beda2356 2646**/\r
2647EFI_STATUS\r
ecc722ad 2648DeleteSignature (\r
2649 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2650 IN CHAR16 *VariableName,\r
2651 IN EFI_GUID *VendorGuid,\r
2652 IN UINT16 LabelNumber,\r
2653 IN EFI_FORM_ID FormId,\r
2654 IN EFI_QUESTION_ID QuestionIdBase,\r
2655 IN UINTN DeleteIndex\r
beda2356 2656 )\r
2657{\r
ecc722ad 2658 EFI_STATUS Status;\r
2659 UINTN DataSize;\r
2660 UINT8 *Data;\r
2661 UINT8 *OldData;\r
2662 UINT32 Attr;\r
2663 UINT32 Index;\r
2664 EFI_SIGNATURE_LIST *CertList;\r
2665 EFI_SIGNATURE_LIST *NewCertList;\r
2666 EFI_SIGNATURE_DATA *Cert;\r
2667 UINTN CertCount;\r
2668 UINT32 Offset;\r
2669 BOOLEAN IsItemFound;\r
2670 UINT32 ItemDataSize;\r
2671 UINTN GuidIndex;\r
bc0c99b3 2672\r
ecc722ad 2673 Data = NULL;\r
2674 OldData = NULL;\r
2675 CertList = NULL;\r
2676 Cert = NULL;\r
20333c6d 2677 Attr = 0;\r
ecc722ad 2678\r
f71ed839 2679 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2680 if (EFI_ERROR (Status)) {\r
2681 return Status;\r
2682 }\r
2683\r
ecc722ad 2684 //\r
2685 // Get original signature list data.\r
20333c6d 2686 //\r
ecc722ad 2687 DataSize = 0;\r
2688 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
2689 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2690 goto ON_EXIT;\r
2691 }\r
2692\r
2693 OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
2694 if (OldData == NULL) {\r
20333c6d 2695 Status = EFI_OUT_OF_RESOURCES;\r
ecc722ad 2696 goto ON_EXIT;\r
2697 }\r
2698\r
2699 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
2700 if (EFI_ERROR(Status)) {\r
2701 goto ON_EXIT;\r
20333c6d 2702 }\r
ecc722ad 2703\r
2704 //\r
20333c6d 2705 // Allocate space for new variable.\r
ecc722ad 2706 //\r
2707 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2708 if (Data == NULL) {\r
2709 Status = EFI_OUT_OF_RESOURCES;\r
2710 goto ON_EXIT;\r
2711 }\r
2712\r
2713 //\r
2714 // Enumerate all signature data and erasing the target item.\r
2715 //\r
2716 IsItemFound = FALSE;\r
2717 ItemDataSize = (UINT32) DataSize;\r
2718 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2719 Offset = 0;\r
2720 GuidIndex = 0;\r
2721 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2722 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2723 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
2724 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
20333c6d
QL
2725 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||\r
2726 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||\r
2727 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||\r
2728 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)\r
ecc722ad 2729 ) {\r
2730 //\r
2731 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
2732 //\r
2733 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2734 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
2735 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2736 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2737 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2738 for (Index = 0; Index < CertCount; Index++) {\r
2739 if (GuidIndex == DeleteIndex) {\r
2740 //\r
2741 // Find it! Skip it!\r
2742 //\r
2743 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
20333c6d 2744 IsItemFound = TRUE;\r
ecc722ad 2745 } else {\r
2746 //\r
2747 // This item doesn't match. Copy it to the Data buffer.\r
2748 //\r
2749 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
2750 Offset += CertList->SignatureSize;\r
2751 }\r
2752 GuidIndex++;\r
2753 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
2754 }\r
2755 } else {\r
2756 //\r
2757 // This List doesn't match. Just copy it to the Data buffer.\r
2758 //\r
2759 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2760 Offset += CertList->SignatureListSize;\r
2761 }\r
20333c6d 2762\r
ecc722ad 2763 ItemDataSize -= CertList->SignatureListSize;\r
2764 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2765 }\r
2766\r
2767 if (!IsItemFound) {\r
2768 //\r
2769 // Doesn't find the signature Item!\r
2770 //\r
2771 Status = EFI_NOT_FOUND;\r
2772 goto ON_EXIT;\r
2773 }\r
2774\r
2775 //\r
2776 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
2777 //\r
2778 ItemDataSize = Offset;\r
2779 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2780 Offset = 0;\r
2781 ZeroMem (OldData, ItemDataSize);\r
2782 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2783 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
33985e3b 2784 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));\r
ecc722ad 2785 if (CertCount != 0) {\r
2786 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2787 Offset += CertList->SignatureListSize;\r
20333c6d 2788 }\r
ecc722ad 2789 ItemDataSize -= CertList->SignatureListSize;\r
2790 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2791 }\r
2792\r
ecc722ad 2793 DataSize = Offset;\r
8c1babfd 2794 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2795 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2796 if (EFI_ERROR (Status)) {\r
2797 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2798 goto ON_EXIT;\r
2799 }\r
2800 }\r
ecc722ad 2801\r
2802 Status = gRT->SetVariable(\r
20333c6d
QL
2803 VariableName,\r
2804 VendorGuid,\r
2805 Attr,\r
2806 DataSize,\r
ecc722ad 2807 OldData\r
2808 );\r
beda2356 2809 if (EFI_ERROR (Status)) {\r
ecc722ad 2810 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2811 goto ON_EXIT;\r
beda2356 2812 }\r
20333c6d 2813\r
ecc722ad 2814ON_EXIT:\r
2815 if (Data != NULL) {\r
2816 FreePool(Data);\r
2817 }\r
2818\r
2819 if (OldData != NULL) {\r
2820 FreePool(OldData);\r
2821 }\r
2822\r
2823 return UpdateDeletePage (\r
20333c6d 2824 PrivateData,\r
ecc722ad 2825 VariableName,\r
2826 VendorGuid,\r
2827 LabelNumber,\r
2828 FormId,\r
2829 QuestionIdBase\r
2830 );\r
2831}\r
2832\r
02dd6af9
CZ
2833/**\r
2834\r
2835 Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT\r
2836 and STR_CUR_SECURE_BOOT_MODE_CONTENT.\r
2837\r
2838 @param[in] PrivateData Module's private data.\r
2839\r
2840 @return EFI_SUCCESS Update secure boot strings successfully.\r
2841 @return other Fail to update secure boot strings.\r
2842\r
2843**/\r
2844EFI_STATUS\r
2845UpdateSecureBootString(\r
2846 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
abffadf0
ZC
2847 )\r
2848{\r
02dd6af9
CZ
2849 UINT8 *SecureBoot;\r
2850\r
e8cd9b80
CZ
2851 SecureBoot = NULL;\r
2852\r
02dd6af9
CZ
2853 //\r
2854 // Get current secure boot state.\r
2855 //\r
e8cd9b80
CZ
2856 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
2857 if (SecureBoot == NULL) {\r
2858 return EFI_NOT_FOUND;\r
02dd6af9
CZ
2859 }\r
2860\r
2861 if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
2862 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
2863 } else {\r
2864 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
2865 }\r
02dd6af9
CZ
2866\r
2867 FreePool(SecureBoot);\r
2868\r
2869 return EFI_SUCCESS;\r
2870}\r
2871\r
ecc722ad 2872/**\r
2873 This function extracts configuration from variable.\r
20333c6d 2874\r
ecc722ad 2875 @param[in, out] ConfigData Point to SecureBoot configuration private data.\r
2876\r
2877**/\r
2878VOID\r
2879SecureBootExtractConfigFromVariable (\r
2880 IN OUT SECUREBOOT_CONFIGURATION *ConfigData\r
20333c6d 2881 )\r
ecc722ad 2882{\r
20333c6d 2883 UINT8 *SecureBootEnable;\r
12087ff6 2884 UINT8 *SetupMode;\r
20333c6d
QL
2885 UINT8 *SecureBootMode;\r
2886 EFI_TIME CurrTime;\r
ecc722ad 2887\r
2888 SecureBootEnable = NULL;\r
12087ff6 2889 SetupMode = NULL;\r
ecc722ad 2890 SecureBootMode = NULL;\r
20333c6d
QL
2891\r
2892 //\r
2893 // Initilize the Date and Time using system time.\r
2894 //\r
2895 ConfigData->CertificateFormat = HASHALG_RAW;\r
2896 ConfigData->AlwaysRevocation = TRUE;\r
2897 gRT->GetTime (&CurrTime, NULL);\r
2898 ConfigData->RevocationDate.Year = CurrTime.Year;\r
2899 ConfigData->RevocationDate.Month = CurrTime.Month;\r
2900 ConfigData->RevocationDate.Day = CurrTime.Day;\r
2901 ConfigData->RevocationTime.Hour = CurrTime.Hour;\r
2902 ConfigData->RevocationTime.Minute = CurrTime.Minute;\r
2903 ConfigData->RevocationTime.Second = 0;\r
2904\r
20333c6d 2905\r
ecc722ad 2906 //\r
2907 // If it is Physical Presence User, set the PhysicalPresent to true.\r
2908 //\r
2909 if (UserPhysicalPresent()) {\r
2910 ConfigData->PhysicalPresent = TRUE;\r
2911 } else {\r
2912 ConfigData->PhysicalPresent = FALSE;\r
2913 }\r
20333c6d 2914\r
96832eef
CZ
2915 //\r
2916 // If there is no PK then the Delete Pk button will be gray.\r
2917 //\r
12087ff6
ZC
2918 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
2919 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
96832eef
CZ
2920 ConfigData->HasPk = FALSE;\r
2921 } else {\r
2922 ConfigData->HasPk = TRUE;\r
2923 }\r
2924\r
126f3b1d
ZC
2925 //\r
2926 // Check SecureBootEnable & Pk status, fix the inconsistence. \r
2927 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
2928 // Checkbox.\r
2929 //\r
2930 ConfigData->AttemptSecureBoot = FALSE;\r
2931 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); \r
2932\r
2933 //\r
2934 // Fix Pk, SecureBootEnable inconsistence\r
2935 //\r
f1005559 2936 if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) {\r
126f3b1d
ZC
2937 ConfigData->HideSecureBoot = FALSE;\r
2938 if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) {\r
2939 ConfigData->AttemptSecureBoot = TRUE;\r
2940 }\r
2941 } else {\r
2942 ConfigData->HideSecureBoot = TRUE;\r
2943 }\r
2944\r
12087ff6
ZC
2945 //\r
2946 // Get the SecureBootMode from CustomMode variable.\r
2947 //\r
2948 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
2949 if (SecureBootMode == NULL) {\r
2950 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
2951 } else {\r
2952 ConfigData->SecureBootMode = *(SecureBootMode);\r
2953 }\r
2954\r
f71ed839 2955 if (SecureBootEnable != NULL) {\r
2956 FreePool (SecureBootEnable);\r
2957 }\r
12087ff6
ZC
2958 if (SetupMode != NULL) {\r
2959 FreePool (SetupMode);\r
2960 }\r
f71ed839 2961 if (SecureBootMode != NULL) {\r
2962 FreePool (SecureBootMode);\r
2963 }\r
beda2356 2964}\r
2965\r
2966/**\r
2967 This function allows a caller to extract the current configuration for one\r
2968 or more named elements from the target driver.\r
2969\r
2970 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2971 @param[in] Request A null-terminated Unicode string in\r
2972 <ConfigRequest> format.\r
2973 @param[out] Progress On return, points to a character in the Request\r
2974 string. Points to the string's null terminator if\r
2975 request was successful. Points to the most recent\r
2976 '&' before the first failing name/value pair (or\r
2977 the beginning of the string if the failure is in\r
2978 the first name/value pair) if the request was not\r
2979 successful.\r
2980 @param[out] Results A null-terminated Unicode string in\r
2981 <ConfigAltResp> format which has all values filled\r
2982 in for the names in the Request string. String to\r
2983 be allocated by the called function.\r
2984\r
2985 @retval EFI_SUCCESS The Results is filled with the requested values.\r
2986 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
2987 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
2988 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
2989 driver.\r
2990\r
2991**/\r
2992EFI_STATUS\r
2993EFIAPI\r
2994SecureBootExtractConfig (\r
2995 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2996 IN CONST EFI_STRING Request,\r
2997 OUT EFI_STRING *Progress,\r
2998 OUT EFI_STRING *Results\r
2999 )\r
3000{\r
3001 EFI_STATUS Status;\r
3002 UINTN BufferSize;\r
bc0c99b3 3003 UINTN Size;\r
beda2356 3004 SECUREBOOT_CONFIGURATION Configuration;\r
beda2356 3005 EFI_STRING ConfigRequest;\r
bc0c99b3 3006 EFI_STRING ConfigRequestHdr;\r
bc0c99b3 3007 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
3008 BOOLEAN AllocatedRequest;\r
3009\r
beda2356 3010 if (Progress == NULL || Results == NULL) {\r
3011 return EFI_INVALID_PARAMETER;\r
3012 }\r
20333c6d 3013\r
bc0c99b3 3014 AllocatedRequest = FALSE;\r
3015 ConfigRequestHdr = NULL;\r
3016 ConfigRequest = NULL;\r
3017 Size = 0;\r
20333c6d 3018\r
ea71453f 3019 ZeroMem (&Configuration, sizeof (Configuration));\r
bc0c99b3 3020 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
3021 *Progress = Request;\r
20333c6d 3022\r
beda2356 3023 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
3024 return EFI_NOT_FOUND;\r
3025 }\r
3026\r
beda2356 3027 //\r
ecc722ad 3028 // Get Configuration from Variable.\r
beda2356 3029 //\r
ecc722ad 3030 SecureBootExtractConfigFromVariable (&Configuration);\r
f71ed839 3031\r
bc0c99b3 3032 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
beda2356 3033 ConfigRequest = Request;\r
bc0c99b3 3034 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
3035 //\r
3036 // Request is set to NULL or OFFSET is NULL, construct full request string.\r
bc0c99b3 3037 //\r
3038 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
3039 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
3040 //\r
3041 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
3042 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
3043 ConfigRequest = AllocateZeroPool (Size);\r
3044 ASSERT (ConfigRequest != NULL);\r
3045 AllocatedRequest = TRUE;\r
3046 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
3047 FreePool (ConfigRequestHdr);\r
3048 ConfigRequestHdr = NULL;\r
3049 }\r
beda2356 3050\r
3051 Status = gHiiConfigRouting->BlockToConfig (\r
3052 gHiiConfigRouting,\r
3053 ConfigRequest,\r
3054 (UINT8 *) &Configuration,\r
3055 BufferSize,\r
3056 Results,\r
3057 Progress\r
3058 );\r
bc0c99b3 3059\r
3060 //\r
3061 // Free the allocated config request string.\r
3062 //\r
3063 if (AllocatedRequest) {\r
3064 FreePool (ConfigRequest);\r
3065 }\r
3066\r
beda2356 3067 //\r
3068 // Set Progress string to the original request string.\r
3069 //\r
3070 if (Request == NULL) {\r
3071 *Progress = NULL;\r
3072 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
3073 *Progress = Request + StrLen (Request);\r
3074 }\r
3075\r
3076 return Status;\r
3077}\r
3078\r
3079/**\r
3080 This function processes the results of changes in configuration.\r
3081\r
3082 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3083 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>\r
3084 format.\r
3085 @param[out] Progress A pointer to a string filled in with the offset of\r
3086 the most recent '&' before the first failing\r
3087 name/value pair (or the beginning of the string if\r
3088 the failure is in the first name/value pair) or\r
3089 the terminating NULL if all was successful.\r
3090\r
3091 @retval EFI_SUCCESS The Results is processed successfully.\r
3092 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
3093 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
3094 driver.\r
3095\r
3096**/\r
3097EFI_STATUS\r
3098EFIAPI\r
3099SecureBootRouteConfig (\r
3100 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3101 IN CONST EFI_STRING Configuration,\r
3102 OUT EFI_STRING *Progress\r
3103 )\r
3104{\r
a2f2c258 3105 SECUREBOOT_CONFIGURATION IfrNvData;\r
3106 UINTN BufferSize;\r
3107 EFI_STATUS Status;\r
20333c6d 3108\r
beda2356 3109 if (Configuration == NULL || Progress == NULL) {\r
3110 return EFI_INVALID_PARAMETER;\r
3111 }\r
3112\r
3113 *Progress = Configuration;\r
3114 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
3115 return EFI_NOT_FOUND;\r
3116 }\r
3117\r
a365eed4
FS
3118 //\r
3119 // Get Configuration from Variable.\r
3120 //\r
3121 SecureBootExtractConfigFromVariable (&IfrNvData);\r
3122\r
3123 //\r
3124 // Map the Configuration to the configuration block.\r
3125 //\r
a2f2c258 3126 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
3127 Status = gHiiConfigRouting->ConfigToBlock (\r
3128 gHiiConfigRouting,\r
3129 Configuration,\r
3130 (UINT8 *)&IfrNvData,\r
3131 &BufferSize,\r
3132 Progress\r
3133 );\r
3134 if (EFI_ERROR (Status)) {\r
3135 return Status;\r
3136 }\r
3137\r
3138 //\r
3139 // Store Buffer Storage back to EFI variable if needed\r
3140 //\r
126f3b1d 3141 if (!IfrNvData.HideSecureBoot) {\r
a2f2c258 3142 Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);\r
3143 if (EFI_ERROR (Status)) {\r
3144 return Status;\r
3145 }\r
3146 }\r
3147\r
ecc722ad 3148 *Progress = Configuration + StrLen (Configuration);\r
beda2356 3149 return EFI_SUCCESS;\r
3150}\r
3151\r
3152/**\r
ecc722ad 3153 This function is called to provide results data to the driver.\r
beda2356 3154\r
3155 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3156 @param[in] Action Specifies the type of action taken by the browser.\r
3157 @param[in] QuestionId A unique value which is sent to the original\r
3158 exporting driver so that it can identify the type\r
3159 of data to expect.\r
3160 @param[in] Type The type of value for the question.\r
3161 @param[in] Value A pointer to the data being sent to the original\r
3162 exporting driver.\r
3163 @param[out] ActionRequest On return, points to the action requested by the\r
3164 callback function.\r
3165\r
3166 @retval EFI_SUCCESS The callback successfully handled the action.\r
3167 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
3168 variable and its data.\r
3169 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
3170 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
3171 callback.\r
3172\r
3173**/\r
3174EFI_STATUS\r
3175EFIAPI\r
3176SecureBootCallback (\r
3177 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3178 IN EFI_BROWSER_ACTION Action,\r
3179 IN EFI_QUESTION_ID QuestionId,\r
3180 IN UINT8 Type,\r
3181 IN EFI_IFR_TYPE_VALUE *Value,\r
3182 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
3183 )\r
3184{\r
ecc722ad 3185 EFI_INPUT_KEY Key;\r
20333c6d 3186 EFI_STATUS Status;\r
ecc722ad 3187 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;\r
3188 UINTN BufferSize;\r
3189 SECUREBOOT_CONFIGURATION *IfrNvData;\r
3190 UINT16 LabelId;\r
bf4a3dbd 3191 UINT8 *SecureBootEnable;\r
126f3b1d 3192 UINT8 *Pk;\r
f71ed839 3193 UINT8 *SecureBootMode;\r
12087ff6 3194 UINT8 *SetupMode;\r
e4d7370d 3195 CHAR16 PromptString[100];\r
762d8ddb 3196 EFI_DEVICE_PATH_PROTOCOL *File;\r
bf4a3dbd 3197\r
96832eef 3198 Status = EFI_SUCCESS;\r
bf4a3dbd 3199 SecureBootEnable = NULL;\r
f71ed839 3200 SecureBootMode = NULL;\r
12087ff6 3201 SetupMode = NULL;\r
762d8ddb 3202 File = NULL;\r
bc0c99b3 3203\r
beda2356 3204 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
3205 return EFI_INVALID_PARAMETER;\r
3206 }\r
12087ff6 3207\r
96832eef
CZ
3208 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
3209\r
762d8ddb
DB
3210 gSecureBootPrivateData = Private;\r
3211\r
96832eef
CZ
3212 //\r
3213 // Retrieve uncommitted data from Browser\r
3214 //\r
3215 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
3216 IfrNvData = AllocateZeroPool (BufferSize);\r
3217 if (IfrNvData == NULL) {\r
3218 return EFI_OUT_OF_RESOURCES;\r
3219 }\r
3220\r
3221 HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
beda2356 3222\r
a365eed4
FS
3223 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
3224 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
02dd6af9
CZ
3225 //\r
3226 // Update secure boot strings when opening this form\r
3227 //\r
3228 Status = UpdateSecureBootString(Private);\r
762d8ddb 3229 SecureBootExtractConfigFromVariable (IfrNvData);\r
a365eed4
FS
3230 mIsEnterSecureBootForm = TRUE;\r
3231 }\r
96832eef 3232 goto EXIT;\r
a365eed4 3233 }\r
20333c6d 3234\r
a365eed4
FS
3235 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
3236 Status = EFI_UNSUPPORTED;\r
3237 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
3238 if (mIsEnterSecureBootForm) {\r
3239 Value->u8 = SECURE_BOOT_MODE_STANDARD;\r
3240 Status = EFI_SUCCESS;\r
3241 }\r
12087ff6 3242 } \r
96832eef 3243 goto EXIT;\r
a365eed4 3244 }\r
20333c6d 3245\r
f71ed839 3246 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
3247 (Action != EFI_BROWSER_ACTION_CHANGING) &&\r
a2f2c258 3248 (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&\r
3249 (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {\r
96832eef
CZ
3250 Status = EFI_UNSUPPORTED;\r
3251 goto EXIT;\r
beda2356 3252 }\r
bc0c99b3 3253\r
ecc722ad 3254 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
3255\r
3256 switch (QuestionId) {\r
3257 case KEY_SECURE_BOOT_ENABLE:\r
f01b91ae 3258 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
bf4a3dbd 3259 if (NULL != SecureBootEnable) {\r
f71ed839 3260 FreePool (SecureBootEnable);\r
ecc722ad 3261 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {\r
3262 CreatePopUp (\r
3263 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3264 &Key,\r
3265 L"Only Physical Presence User could disable secure boot!",\r
3266 NULL\r
3267 );\r
3268 Status = EFI_UNSUPPORTED;\r
0357efe3 3269 } else {\r
3270 CreatePopUp (\r
3271 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3272 &Key,\r
f71ed839 3273 L"Configuration changed, please reset the platform to take effect!",\r
0357efe3 3274 NULL\r
3275 );\r
ecc722ad 3276 }\r
ecc722ad 3277 }\r
3278 break;\r
3279\r
ecc722ad 3280 case KEY_SECURE_BOOT_KEK_OPTION:\r
3281 case KEY_SECURE_BOOT_DB_OPTION:\r
3282 case KEY_SECURE_BOOT_DBX_OPTION:\r
20333c6d 3283 case KEY_SECURE_BOOT_DBT_OPTION:\r
ecc722ad 3284 //\r
3285 // Clear Signature GUID.\r
3286 //\r
3287 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));\r
3288 if (Private->SignatureGUID == NULL) {\r
3289 Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
3290 if (Private->SignatureGUID == NULL) {\r
3291 return EFI_OUT_OF_RESOURCES;\r
3292 }\r
3293 }\r
beda2356 3294\r
ecc722ad 3295 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {\r
3296 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
3297 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {\r
3298 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
20333c6d
QL
3299 } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {\r
3300 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;\r
ecc722ad 3301 } else {\r
3302 LabelId = FORMID_ENROLL_KEK_FORM;\r
3303 }\r
3304\r
3305 //\r
3306 // Refresh selected file.\r
3307 //\r
20333c6d 3308 CleanUpPage (LabelId, Private);\r
ecc722ad 3309 break;\r
762d8ddb
DB
3310 case KEY_SECURE_BOOT_PK_OPTION:\r
3311 LabelId = FORMID_ENROLL_PK_FORM;\r
3312 //\r
3313 // Refresh selected file.\r
3314 //\r
3315 CleanUpPage (LabelId, Private);\r
3316 break;\r
3317\r
3318 case FORMID_ENROLL_PK_FORM:\r
d6224153 3319 ChooseFile (NULL, NULL, UpdatePKFromFile, &File);\r
762d8ddb 3320 break;\r
20333c6d 3321\r
ecc722ad 3322 case FORMID_ENROLL_KEK_FORM:\r
d6224153 3323 ChooseFile (NULL, NULL, UpdateKEKFromFile, &File);\r
762d8ddb
DB
3324 break;\r
3325\r
ecc722ad 3326 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
d6224153 3327 ChooseFile (NULL, NULL, UpdateDBFromFile, &File);\r
762d8ddb
DB
3328 break;\r
3329\r
ecc722ad 3330 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
d6224153 3331 ChooseFile (NULL, NULL, UpdateDBXFromFile, &File);\r
762d8ddb 3332 break;\r
ecc722ad 3333\r
762d8ddb 3334 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:\r
d6224153 3335 ChooseFile (NULL, NULL, UpdateDBTFromFile, &File);\r
ecc722ad 3336 break;\r
3337\r
20333c6d 3338 case KEY_SECURE_BOOT_DELETE_PK:\r
f71ed839 3339 if (Value->u8) {\r
3340 CreatePopUp (\r
3341 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3342 &Key,\r
3343 L"Are you sure you want to delete PK? Secure boot will be disabled!",\r
3344 L"Press 'Y' to delete PK and exit, 'N' to discard change and return",\r
3345 NULL\r
3346 );\r
3347 if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {\r
ecc722ad 3348 Status = DeletePlatformKey ();\r
f71ed839 3349 if (EFI_ERROR (Status)) {\r
3350 CreatePopUp (\r
3351 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3352 &Key,\r
3353 L"Only Physical Presence User could delete PK in custom mode!",\r
3354 NULL\r
3355 );\r
3356 }\r
ecc722ad 3357 }\r
f71ed839 3358 }\r
ecc722ad 3359 break;\r
3360\r
3361 case KEY_DELETE_KEK:\r
3362 UpdateDeletePage (\r
20333c6d 3363 Private,\r
ecc722ad 3364 EFI_KEY_EXCHANGE_KEY_NAME,\r
3365 &gEfiGlobalVariableGuid,\r
3366 LABEL_KEK_DELETE,\r
3367 FORMID_DELETE_KEK_FORM,\r
20333c6d 3368 OPTION_DEL_KEK_QUESTION_ID\r
ecc722ad 3369 );\r
3370 break;\r
3371\r
20333c6d 3372 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:\r
ecc722ad 3373 UpdateDeletePage (\r
3374 Private,\r
3375 EFI_IMAGE_SECURITY_DATABASE,\r
3376 &gEfiImageSecurityDatabaseGuid,\r
3377 LABEL_DB_DELETE,\r
3378 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
3379 OPTION_DEL_DB_QUESTION_ID\r
3380 );\r
3381 break;\r
3382\r
3383 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:\r
3384 UpdateDeletePage (\r
3385 Private,\r
3386 EFI_IMAGE_SECURITY_DATABASE1,\r
3387 &gEfiImageSecurityDatabaseGuid,\r
3388 LABEL_DBX_DELETE,\r
3389 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
3390 OPTION_DEL_DBX_QUESTION_ID\r
3391 );\r
3392\r
3393 break;\r
3394\r
20333c6d
QL
3395 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:\r
3396 UpdateDeletePage (\r
3397 Private,\r
3398 EFI_IMAGE_SECURITY_DATABASE2,\r
3399 &gEfiImageSecurityDatabaseGuid,\r
3400 LABEL_DBT_DELETE,\r
3401 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
3402 OPTION_DEL_DBT_QUESTION_ID\r
3403 );\r
3404\r
3405 break;\r
3406\r
ecc722ad 3407 case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
3408 Status = EnrollKeyExchangeKey (Private);\r
ee79ac8d 3409 if (EFI_ERROR (Status)) {\r
3410 CreatePopUp (\r
3411 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3412 &Key,\r
3413 L"ERROR: Unsupported file type!",\r
3414 L"Only supports DER-encoded X509 certificate",\r
3415 NULL\r
3416 );\r
3417 }\r
ecc722ad 3418 break;\r
3419\r
3420 case KEY_VALUE_SAVE_AND_EXIT_DB:\r
3421 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
ee79ac8d 3422 if (EFI_ERROR (Status)) {\r
3423 CreatePopUp (\r
3424 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3425 &Key,\r
3426 L"ERROR: Unsupported file type!",\r
3427 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
3428 NULL\r
3429 );\r
3430 }\r
ecc722ad 3431 break;\r
3432\r
3433 case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
20333c6d
QL
3434 if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {\r
3435 CreatePopUp (\r
3436 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3437 &Key,\r
3438 L"Enrollment failed! Same certificate had already been in the dbx!",\r
3439 NULL\r
3440 );\r
3441 break;\r
3442 }\r
3443\r
3444 if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {\r
3445 Status = EnrollX509HashtoSigDB (\r
3446 Private,\r
3447 IfrNvData->CertificateFormat,\r
3448 &IfrNvData->RevocationDate,\r
3449 &IfrNvData->RevocationTime,\r
3450 IfrNvData->AlwaysRevocation\r
3451 );\r
3452 } else {\r
3453 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
3454 }\r
ee79ac8d 3455 if (EFI_ERROR (Status)) {\r
3456 CreatePopUp (\r
3457 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3458 &Key,\r
3459 L"ERROR: Unsupported file type!",\r
3460 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
3461 NULL\r
3462 );\r
3463 }\r
ecc722ad 3464 break;\r
3465\r
20333c6d
QL
3466 case KEY_VALUE_SAVE_AND_EXIT_DBT:\r
3467 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);\r
3468 if (EFI_ERROR (Status)) {\r
3469 CreatePopUp (\r
3470 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3471 &Key,\r
3472 L"ERROR: Unsupported file type!",\r
3473 L"Only supports DER-encoded X509 certificate.",\r
3474 NULL\r
3475 );\r
3476 }\r
3477 break;\r
762d8ddb
DB
3478 case KEY_VALUE_SAVE_AND_EXIT_PK:\r
3479 Status = EnrollPlatformKey (Private);\r
3480 if (EFI_ERROR (Status)) {\r
3481 UnicodeSPrint (\r
3482 PromptString,\r
3483 sizeof (PromptString),\r
3484 L"Only DER encoded certificate file (%s) is supported.",\r
3485 mSupportX509Suffix\r
3486 );\r
3487 CreatePopUp (\r
3488 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3489 &Key,\r
3490 L"ERROR: Unsupported file type!",\r
3491 PromptString,\r
3492 NULL\r
3493 );\r
3494 }\r
3495 break;\r
ecc722ad 3496 default:\r
762d8ddb 3497 if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
ecc722ad 3498 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3499 DeleteKeyExchangeKey (Private, QuestionId);\r
3500 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&\r
3501 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3502 DeleteSignature (\r
3503 Private,\r
3504 EFI_IMAGE_SECURITY_DATABASE,\r
3505 &gEfiImageSecurityDatabaseGuid,\r
20333c6d 3506 LABEL_DB_DELETE,\r
ecc722ad 3507 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
3508 OPTION_DEL_DB_QUESTION_ID,\r
3509 QuestionId - OPTION_DEL_DB_QUESTION_ID\r
3510 );\r
3511 } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&\r
3512 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3513 DeleteSignature (\r
3514 Private,\r
3515 EFI_IMAGE_SECURITY_DATABASE1,\r
3516 &gEfiImageSecurityDatabaseGuid,\r
20333c6d 3517 LABEL_DBX_DELETE,\r
ecc722ad 3518 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
3519 OPTION_DEL_DBX_QUESTION_ID,\r
3520 QuestionId - OPTION_DEL_DBX_QUESTION_ID\r
3521 );\r
20333c6d
QL
3522 } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&\r
3523 (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3524 DeleteSignature (\r
3525 Private,\r
3526 EFI_IMAGE_SECURITY_DATABASE2,\r
3527 &gEfiImageSecurityDatabaseGuid,\r
3528 LABEL_DBT_DELETE,\r
3529 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
3530 OPTION_DEL_DBT_QUESTION_ID,\r
3531 QuestionId - OPTION_DEL_DBT_QUESTION_ID\r
3532 );\r
ecc722ad 3533 }\r
3534 break;\r
ecc722ad 3535\r
3536 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
3537 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
3538 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
3539 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
20333c6d 3540 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:\r
ecc722ad 3541 if (Private->FileContext->FHandle != NULL) {\r
3542 CloseFile (Private->FileContext->FHandle);\r
3543 Private->FileContext->FHandle = NULL;\r
762d8ddb
DB
3544 if (Private->FileContext->FileName!= NULL){\r
3545 FreePool(Private->FileContext->FileName);\r
3546 Private->FileContext->FileName = NULL;\r
3547 }\r
ecc722ad 3548 }\r
20333c6d 3549\r
ecc722ad 3550 if (Private->SignatureGUID != NULL) {\r
3551 FreePool (Private->SignatureGUID);\r
3552 Private->SignatureGUID = NULL;\r
3553 }\r
ecc722ad 3554 break;\r
762d8ddb
DB
3555 }\r
3556 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
3557 switch (QuestionId) {\r
3558 case KEY_SECURE_BOOT_ENABLE:\r
3559 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
3560 break;\r
ecc722ad 3561 case KEY_SECURE_BOOT_MODE:\r
a365eed4 3562 mIsEnterSecureBootForm = FALSE;\r
ecc722ad 3563 break;\r
ecc722ad 3564 case KEY_SECURE_BOOT_KEK_GUID:\r
3565 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
3566 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
20333c6d 3567 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:\r
ecc722ad 3568 ASSERT (Private->SignatureGUID != NULL);\r
3569 Status = StringToGuid (\r
3570 IfrNvData->SignatureGuid,\r
3571 StrLen (IfrNvData->SignatureGuid),\r
3572 Private->SignatureGUID\r
3573 );\r
3574 if (EFI_ERROR (Status)) {\r
3575 break;\r
3576 }\r
3577\r
3578 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
3579 break;\r
3580\r
3581 case KEY_SECURE_BOOT_DELETE_PK:\r
12087ff6
ZC
3582 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
3583 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
f71ed839 3584 IfrNvData->DeletePk = TRUE;\r
3585 IfrNvData->HasPk = FALSE;\r
ecc722ad 3586 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
f71ed839 3587 } else {\r
3588 IfrNvData->DeletePk = FALSE;\r
3589 IfrNvData->HasPk = TRUE;\r
3590 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
3591 }\r
12087ff6
ZC
3592 if (SetupMode != NULL) {\r
3593 FreePool (SetupMode);\r
3594 }\r
c93bcb7e
ED
3595 break;\r
3596 default:\r
c93bcb7e 3597 break;\r
ecc722ad 3598 }\r
a2f2c258 3599 } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {\r
3600 if (QuestionId == KEY_HIDE_SECURE_BOOT) {\r
126f3b1d
ZC
3601 GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL);\r
3602 if (Pk == NULL) {\r
a2f2c258 3603 IfrNvData->HideSecureBoot = TRUE;\r
3604 } else {\r
126f3b1d 3605 FreePool (Pk);\r
a2f2c258 3606 IfrNvData->HideSecureBoot = FALSE;\r
3607 }\r
3608 Value->b = IfrNvData->HideSecureBoot;\r
3609 }\r
f71ed839 3610 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
3611 //\r
3612 // Force the platform back to Standard Mode once user leave the setup screen.\r
3613 //\r
3614 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
3615 if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {\r
3616 IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
3617 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);\r
3618 }\r
3619 if (SecureBootMode != NULL) {\r
3620 FreePool (SecureBootMode);\r
3621 }\r
ecc722ad 3622 }\r
20333c6d 3623\r
96832eef
CZ
3624EXIT:\r
3625\r
ecc722ad 3626 if (!EFI_ERROR (Status)) {\r
3627 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
742d9b3a 3628 HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
ecc722ad 3629 }\r
96832eef 3630\r
ecc722ad 3631 FreePool (IfrNvData);\r
20333c6d 3632\r
762d8ddb
DB
3633 if (File != NULL){\r
3634 FreePool(File);\r
3635 File = NULL;\r
3636 }\r
3637\r
ecc722ad 3638 return EFI_SUCCESS;\r
beda2356 3639}\r
3640\r
3641/**\r
3642 This function publish the SecureBoot configuration Form.\r
3643\r
3644 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
3645\r
ecc722ad 3646 @retval EFI_SUCCESS HII Form is installed successfully.\r
beda2356 3647 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.\r
3648 @retval Others Other errors as indicated.\r
3649\r
3650**/\r
3651EFI_STATUS\r
3652InstallSecureBootConfigForm (\r
3653 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
3654 )\r
3655{\r
3656 EFI_STATUS Status;\r
3657 EFI_HII_HANDLE HiiHandle;\r
3658 EFI_HANDLE DriverHandle;\r
beda2356 3659 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3660\r
3661 DriverHandle = NULL;\r
3662 ConfigAccess = &PrivateData->ConfigAccess;\r
3663 Status = gBS->InstallMultipleProtocolInterfaces (\r
3664 &DriverHandle,\r
3665 &gEfiDevicePathProtocolGuid,\r
3666 &mSecureBootHiiVendorDevicePath,\r
3667 &gEfiHiiConfigAccessProtocolGuid,\r
3668 ConfigAccess,\r
3669 NULL\r
3670 );\r
3671 if (EFI_ERROR (Status)) {\r
3672 return Status;\r
3673 }\r
3674\r
3675 PrivateData->DriverHandle = DriverHandle;\r
3676\r
3677 //\r
3678 // Publish the HII package list\r
3679 //\r
3680 HiiHandle = HiiAddPackages (\r
3681 &gSecureBootConfigFormSetGuid,\r
3682 DriverHandle,\r
3683 SecureBootConfigDxeStrings,\r
3684 SecureBootConfigBin,\r
3685 NULL\r
3686 );\r
3687 if (HiiHandle == NULL) {\r
3688 gBS->UninstallMultipleProtocolInterfaces (\r
3689 DriverHandle,\r
3690 &gEfiDevicePathProtocolGuid,\r
3691 &mSecureBootHiiVendorDevicePath,\r
3692 &gEfiHiiConfigAccessProtocolGuid,\r
3693 ConfigAccess,\r
3694 NULL\r
bc0c99b3 3695 );\r
beda2356 3696 return EFI_OUT_OF_RESOURCES;\r
3697 }\r
bc0c99b3 3698\r
beda2356 3699 PrivateData->HiiHandle = HiiHandle;\r
ecc722ad 3700\r
3701 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
20333c6d 3702\r
762d8ddb 3703 if (PrivateData->FileContext == NULL) {\r
ecc722ad 3704 UninstallSecureBootConfigForm (PrivateData);\r
3705 return EFI_OUT_OF_RESOURCES;\r
3706 }\r
20333c6d 3707\r
ecc722ad 3708 //\r
3709 // Init OpCode Handle and Allocate space for creation of Buffer\r
3710 //\r
3711 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
3712 if (mStartOpCodeHandle == NULL) {\r
3713 UninstallSecureBootConfigForm (PrivateData);\r
3714 return EFI_OUT_OF_RESOURCES;\r
3715 }\r
3716\r
3717 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
3718 if (mEndOpCodeHandle == NULL) {\r
3719 UninstallSecureBootConfigForm (PrivateData);\r
3720 return EFI_OUT_OF_RESOURCES;\r
3721 }\r
3722\r
3723 //\r
3724 // Create Hii Extend Label OpCode as the start opcode\r
3725 //\r
3726 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
3727 mStartOpCodeHandle,\r
3728 &gEfiIfrTianoGuid,\r
3729 NULL,\r
3730 sizeof (EFI_IFR_GUID_LABEL)\r
3731 );\r
3732 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3733\r
3734 //\r
3735 // Create Hii Extend Label OpCode as the end opcode\r
3736 //\r
3737 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
3738 mEndOpCodeHandle,\r
3739 &gEfiIfrTianoGuid,\r
3740 NULL,\r
3741 sizeof (EFI_IFR_GUID_LABEL)\r
3742 );\r
3743 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3744 mEndLabel->Number = LABEL_END;\r
20333c6d 3745\r
bc0c99b3 3746 return EFI_SUCCESS;\r
beda2356 3747}\r
3748\r
3749/**\r
3750 This function removes SecureBoot configuration Form.\r
3751\r
3752 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
3753\r
3754**/\r
3755VOID\r
3756UninstallSecureBootConfigForm (\r
3757 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
3758 )\r
3759{\r
3760 //\r
3761 // Uninstall HII package list\r
3762 //\r
3763 if (PrivateData->HiiHandle != NULL) {\r
3764 HiiRemovePackages (PrivateData->HiiHandle);\r
3765 PrivateData->HiiHandle = NULL;\r
3766 }\r
3767\r
3768 //\r
3769 // Uninstall HII Config Access Protocol\r
3770 //\r
3771 if (PrivateData->DriverHandle != NULL) {\r
3772 gBS->UninstallMultipleProtocolInterfaces (\r
3773 PrivateData->DriverHandle,\r
3774 &gEfiDevicePathProtocolGuid,\r
3775 &mSecureBootHiiVendorDevicePath,\r
3776 &gEfiHiiConfigAccessProtocolGuid,\r
3777 &PrivateData->ConfigAccess,\r
3778 NULL\r
3779 );\r
3780 PrivateData->DriverHandle = NULL;\r
3781 }\r
bc0c99b3 3782\r
ecc722ad 3783 if (PrivateData->SignatureGUID != NULL) {\r
3784 FreePool (PrivateData->SignatureGUID);\r
3785 }\r
3786\r
ecc722ad 3787 if (PrivateData->FileContext != NULL) {\r
3788 FreePool (PrivateData->FileContext);\r
3789 }\r
3790\r
beda2356 3791 FreePool (PrivateData);\r
ecc722ad 3792\r
ecc722ad 3793 if (mStartOpCodeHandle != NULL) {\r
3794 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
3795 }\r
3796\r
3797 if (mEndOpCodeHandle != NULL) {\r
3798 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
3799 }\r
beda2356 3800}\r