]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
Refine the Secure Boot UI driver to input the GUID and varstroe name when using HiiSe...
[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
f71ed839 4Copyright (c) 2011 - 2013, 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
ecc722ad 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
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, NULL, NULL, NULL, NULL },\r
70 { L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL }\r
71};\r
72\r
e4d7370d 73//\r
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
98/**\r
99 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.\r
100\r
101 @param[in] FileSuffix The suffix of the input certificate file\r
102\r
103 @retval TRUE It's a DER-encoded certificate.\r
104 @retval FALSE It's NOT a DER-encoded certificate.\r
105\r
106**/\r
107BOOLEAN\r
108IsDerEncodeCertificate (\r
109 IN CONST CHAR16 *FileSuffix\r
110)\r
111{\r
112 UINTN Index; \r
113 for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {\r
114 if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {\r
115 return TRUE;\r
116 }\r
117 }\r
118 return FALSE;\r
119}\r
ecc722ad 120\r
121/**\r
122 Set Secure Boot option into variable space.\r
123\r
124 @param[in] VarValue The option of Secure Boot.\r
125\r
126 @retval EFI_SUCCESS The operation is finished successfully.\r
127 @retval Others Other errors as indicated.\r
128\r
129**/\r
130EFI_STATUS\r
131SaveSecureBootVariable (\r
132 IN UINT8 VarValue\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136\r
137 Status = gRT->SetVariable (\r
138 EFI_SECURE_BOOT_ENABLE_NAME,\r
139 &gEfiSecureBootEnableDisableGuid,\r
140 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
141 sizeof (UINT8),\r
142 &VarValue\r
143 );\r
144 return Status;\r
145}\r
146\r
8c1babfd 147/**\r
148 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2\r
149 descriptor with the input data. NO authentication is required in this function.\r
150 \r
151 @param[in, out] DataSize On input, the size of Data buffer in bytes.\r
152 On output, the size of data returned in Data\r
153 buffer in bytes.\r
154 @param[in, out] Data On input, Pointer to data buffer to be wrapped or \r
155 pointer to NULL to wrap an empty payload.\r
156 On output, Pointer to the new payload date buffer allocated from pool,\r
157 it's caller's responsibility to free the memory when finish using it. \r
158\r
159 @retval EFI_SUCCESS Create time based payload successfully.\r
160 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.\r
161 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
162 @retval Others Unexpected error happens.\r
163\r
164**/\r
165EFI_STATUS\r
166CreateTimeBasedPayload (\r
167 IN OUT UINTN *DataSize,\r
168 IN OUT UINT8 **Data\r
169 )\r
170{\r
171 EFI_STATUS Status;\r
172 UINT8 *NewData;\r
173 UINT8 *Payload;\r
174 UINTN PayloadSize;\r
175 EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;\r
176 UINTN DescriptorSize;\r
177 EFI_TIME Time;\r
178 \r
179 if (Data == NULL || DataSize == NULL) {\r
180 return EFI_INVALID_PARAMETER;\r
181 }\r
182 \r
183 //\r
184 // In Setup mode or Custom mode, the variable does not need to be signed but the \r
185 // parameters to the SetVariable() call still need to be prepared as authenticated\r
186 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate\r
187 // data in it.\r
188 //\r
189 Payload = *Data;\r
190 PayloadSize = *DataSize;\r
191 \r
192 DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
193 NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);\r
194 if (NewData == NULL) {\r
195 return EFI_OUT_OF_RESOURCES;\r
196 }\r
197\r
198 if ((Payload != NULL) && (PayloadSize != 0)) {\r
199 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
200 }\r
201\r
202 DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);\r
203\r
204 ZeroMem (&Time, sizeof (EFI_TIME));\r
205 Status = gRT->GetTime (&Time, NULL);\r
206 if (EFI_ERROR (Status)) {\r
207 FreePool(NewData);\r
208 return Status;\r
209 }\r
210 Time.Pad1 = 0;\r
211 Time.Nanosecond = 0;\r
212 Time.TimeZone = 0;\r
213 Time.Daylight = 0;\r
214 Time.Pad2 = 0;\r
215 CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\r
216 \r
217 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
218 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;\r
219 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
220 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);\r
221 \r
222 if (Payload != NULL) {\r
223 FreePool(Payload);\r
224 }\r
225 \r
226 *DataSize = DescriptorSize + PayloadSize;\r
227 *Data = NewData;\r
228 return EFI_SUCCESS;\r
229}\r
230\r
ecc722ad 231/**\r
232 Internal helper function to delete a Variable given its name and GUID, NO authentication\r
233 required.\r
234\r
235 @param[in] VariableName Name of the Variable.\r
236 @param[in] VendorGuid GUID of the Variable.\r
237\r
238 @retval EFI_SUCCESS Variable deleted successfully.\r
239 @retval Others The driver failed to start the device.\r
240\r
241**/\r
242EFI_STATUS\r
243DeleteVariable (\r
244 IN CHAR16 *VariableName,\r
245 IN EFI_GUID *VendorGuid\r
246 )\r
247{\r
248 EFI_STATUS Status;\r
249 VOID* Variable;\r
8c1babfd 250 UINT8 *Data;\r
251 UINTN DataSize;\r
252 UINT32 Attr;\r
ecc722ad 253\r
bf4a3dbd 254 GetVariable2 (VariableName, VendorGuid, &Variable, NULL);\r
ecc722ad 255 if (Variable == NULL) {\r
256 return EFI_SUCCESS;\r
257 }\r
f71ed839 258 FreePool (Variable);\r
ecc722ad 259\r
8c1babfd 260 Data = NULL;\r
261 DataSize = 0;\r
262 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
263 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
ecc722ad 264\r
8c1babfd 265 Status = CreateTimeBasedPayload (&DataSize, &Data);\r
266 if (EFI_ERROR (Status)) {\r
267 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
268 return Status;\r
ecc722ad 269 }\r
270\r
8c1babfd 271 Status = gRT->SetVariable (\r
272 VariableName,\r
273 VendorGuid,\r
274 Attr,\r
275 DataSize,\r
276 Data\r
277 );\r
278 if (Data != NULL) {\r
279 FreePool (Data);\r
ecc722ad 280 }\r
ecc722ad 281 return Status;\r
282}\r
283\r
f71ed839 284/**\r
285\r
286 Set the platform secure boot mode into "Custom" or "Standard" mode.\r
287\r
288 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or\r
289 CUSTOM_SECURE_BOOT_MODE.\r
290 \r
291 @return EFI_SUCCESS The platform has switched to the special mode successfully.\r
292 @return other Fail to operate the secure boot mode.\r
293 \r
294**/\r
295EFI_STATUS\r
296SetSecureBootMode (\r
297 IN UINT8 SecureBootMode\r
298 )\r
299{\r
300 return gRT->SetVariable ( \r
301 EFI_CUSTOM_MODE_NAME,\r
302 &gEfiCustomModeEnableGuid,\r
303 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
304 sizeof (UINT8),\r
305 &SecureBootMode\r
306 );\r
307}\r
308\r
ecc722ad 309/**\r
310 Generate the PK signature list from the X509 Certificate storing file (.cer)\r
311\r
312 @param[in] X509File FileHandle of X509 Certificate storing file.\r
313 @param[out] PkCert Point to the data buffer to store the signature list.\r
314 \r
315 @return EFI_UNSUPPORTED Unsupported Key Length.\r
316 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.\r
317 \r
318**/\r
319EFI_STATUS\r
320CreatePkX509SignatureList (\r
321 IN EFI_FILE_HANDLE X509File, \r
322 OUT EFI_SIGNATURE_LIST **PkCert \r
323 )\r
324{\r
325 EFI_STATUS Status; \r
326 UINT8 *X509Data;\r
327 UINTN X509DataSize;\r
328 EFI_SIGNATURE_DATA *PkCertData;\r
329\r
330 X509Data = NULL;\r
331 PkCertData = NULL;\r
332 X509DataSize = 0; \r
333 \r
4adc12bf 334 Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);\r
ecc722ad 335 if (EFI_ERROR (Status)) {\r
336 goto ON_EXIT;\r
337 }\r
ba57d4fd 338 ASSERT (X509Data != NULL);\r
ecc722ad 339\r
340 //\r
341 // Allocate space for PK certificate list and initialize it.\r
342 // Create PK database entry with SignatureHeaderSize equals 0.\r
343 //\r
344 *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (\r
345 sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1\r
346 + X509DataSize\r
347 );\r
348 if (*PkCert == NULL) {\r
349 Status = EFI_OUT_OF_RESOURCES;\r
350 goto ON_EXIT;\r
351 }\r
352\r
353 (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST) \r
354 + sizeof(EFI_SIGNATURE_DATA) - 1\r
355 + X509DataSize);\r
356 (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
357 (*PkCert)->SignatureHeaderSize = 0;\r
358 CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);\r
359 PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert) \r
360 + sizeof(EFI_SIGNATURE_LIST)\r
361 + (*PkCert)->SignatureHeaderSize);\r
362 CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid); \r
363 //\r
364 // Fill the PK database with PKpub data from X509 certificate file.\r
365 // \r
366 CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);\r
367 \r
368ON_EXIT:\r
369 \r
370 if (X509Data != NULL) {\r
371 FreePool (X509Data);\r
372 }\r
373 \r
374 if (EFI_ERROR(Status) && *PkCert != NULL) {\r
375 FreePool (*PkCert);\r
376 *PkCert = NULL;\r
377 }\r
378 \r
379 return Status;\r
380}\r
381\r
382/**\r
383 Enroll new PK into the System without original PK's authentication.\r
384\r
385 The SignatureOwner GUID will be the same with PK's vendorguid.\r
386\r
387 @param[in] PrivateData The module's private data.\r
388\r
389 @retval EFI_SUCCESS New PK enrolled successfully.\r
390 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
391 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
392 \r
393**/\r
394EFI_STATUS\r
395EnrollPlatformKey (\r
396 IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private\r
397 ) \r
398{\r
399 EFI_STATUS Status;\r
400 UINT32 Attr;\r
401 UINTN DataSize;\r
402 EFI_SIGNATURE_LIST *PkCert;\r
403 UINT16* FilePostFix;\r
fd64f84f 404 UINTN NameLength;\r
ecc722ad 405 \r
406 if (Private->FileContext->FileName == NULL) {\r
407 return EFI_INVALID_PARAMETER;\r
408 }\r
409\r
410 PkCert = NULL;\r
411\r
f71ed839 412 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
413 if (EFI_ERROR (Status)) {\r
414 return Status;\r
415 }\r
416\r
ecc722ad 417 //\r
e4d7370d 418 // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
ecc722ad 419 //\r
fd64f84f
GCPL
420 NameLength = StrLen (Private->FileContext->FileName);\r
421 if (NameLength <= 4) {\r
422 return EFI_INVALID_PARAMETER;\r
423 }\r
424 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
e4d7370d 425 if (!IsDerEncodeCertificate(FilePostFix)) {\r
426 DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));\r
ecc722ad 427 return EFI_INVALID_PARAMETER;\r
428 }\r
429 DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));\r
430 DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));\r
431\r
432 //\r
433 // Prase the selected PK file and generature PK certificate list.\r
434 //\r
8c1babfd 435 Status = CreatePkX509SignatureList (\r
436 Private->FileContext->FHandle, \r
437 &PkCert \r
438 );\r
439 if (EFI_ERROR (Status)) {\r
440 goto ON_EXIT;\r
ecc722ad 441 }\r
ba57d4fd 442 ASSERT (PkCert != NULL);\r
ecc722ad 443 \r
444 //\r
445 // Set Platform Key variable.\r
446 // \r
447 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
8c1babfd 448 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
ecc722ad 449 DataSize = PkCert->SignatureListSize;\r
8c1babfd 450 Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);\r
451 if (EFI_ERROR (Status)) {\r
452 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
453 goto ON_EXIT;\r
454 }\r
455 \r
ecc722ad 456 Status = gRT->SetVariable(\r
457 EFI_PLATFORM_KEY_NAME, \r
458 &gEfiGlobalVariableGuid, \r
459 Attr, \r
460 DataSize, \r
461 PkCert\r
462 );\r
463 if (EFI_ERROR (Status)) {\r
464 if (Status == EFI_OUT_OF_RESOURCES) {\r
465 DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));\r
466 }\r
467 goto ON_EXIT;\r
468 }\r
469 \r
470ON_EXIT:\r
471\r
472 if (PkCert != NULL) {\r
473 FreePool(PkCert);\r
474 }\r
475 \r
476 if (Private->FileContext->FHandle != NULL) {\r
477 CloseFile (Private->FileContext->FHandle);\r
478 Private->FileContext->FHandle = NULL;\r
479 }\r
480\r
481 return Status;\r
482}\r
483\r
484/**\r
485 Remove the PK variable.\r
486\r
487 @retval EFI_SUCCESS Delete PK successfully.\r
488 @retval Others Could not allow to delete PK.\r
489 \r
490**/\r
491EFI_STATUS\r
492DeletePlatformKey (\r
493 VOID\r
494)\r
495{\r
496 EFI_STATUS Status;\r
497\r
f71ed839 498 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
499 if (EFI_ERROR (Status)) {\r
500 return Status;\r
501 }\r
502\r
8c1babfd 503 Status = DeleteVariable (\r
504 EFI_PLATFORM_KEY_NAME,\r
505 &gEfiGlobalVariableGuid\r
506 );\r
ecc722ad 507 return Status;\r
508}\r
509\r
510/**\r
511 Enroll a new KEK item from public key storing file (*.pbk).\r
512\r
513 @param[in] PrivateData The module's private data.\r
514\r
515 @retval EFI_SUCCESS New KEK enrolled successfully.\r
516 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
517 @retval EFI_UNSUPPORTED Unsupported command.\r
518 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
519\r
520**/\r
521EFI_STATUS\r
522EnrollRsa2048ToKek (\r
523 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
524 )\r
525{\r
526 EFI_STATUS Status;\r
527 UINT32 Attr;\r
528 UINTN DataSize;\r
529 EFI_SIGNATURE_LIST *KekSigList;\r
530 UINTN KeyBlobSize;\r
531 UINT8 *KeyBlob;\r
532 CPL_KEY_INFO *KeyInfo;\r
533 EFI_SIGNATURE_DATA *KEKSigData;\r
534 UINTN KekSigListSize;\r
535 UINT8 *KeyBuffer; \r
536 UINTN KeyLenInBytes;\r
537\r
538 Attr = 0;\r
539 DataSize = 0;\r
540 KeyBuffer = NULL;\r
541 KeyBlobSize = 0;\r
542 KeyBlob = NULL;\r
543 KeyInfo = NULL;\r
544 KEKSigData = NULL;\r
545 KekSigList = NULL;\r
546 KekSigListSize = 0;\r
547 \r
548 //\r
549 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.\r
550 // First, We have to parse out public key data from the pbk key file.\r
551 // \r
552 Status = ReadFileContent (\r
553 Private->FileContext->FHandle,\r
4adc12bf 554 (VOID**) &KeyBlob,\r
ecc722ad 555 &KeyBlobSize,\r
556 0\r
557 );\r
558 if (EFI_ERROR (Status)) {\r
559 goto ON_EXIT;\r
560 }\r
ba57d4fd 561 ASSERT (KeyBlob != NULL);\r
ecc722ad 562 KeyInfo = (CPL_KEY_INFO *) KeyBlob;\r
563 if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {\r
564 DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));\r
565 Status = EFI_UNSUPPORTED;\r
566 goto ON_EXIT;\r
567 }\r
568 \r
569 //\r
570 // Convert the Public key to fix octet string format represented in RSA PKCS#1.\r
571 // \r
572 KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;\r
573 KeyBuffer = AllocateZeroPool (KeyLenInBytes);\r
574 if (KeyBuffer == NULL) {\r
575 Status = EFI_OUT_OF_RESOURCES;\r
576 goto ON_EXIT;\r
577 }\r
578 Int2OctStr (\r
579 (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)), \r
580 KeyLenInBytes / sizeof (UINTN), \r
581 KeyBuffer, \r
582 KeyLenInBytes\r
583 );\r
584 CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);\r
585 \r
586 //\r
587 // Form an new EFI_SIGNATURE_LIST.\r
588 //\r
589 KekSigListSize = sizeof(EFI_SIGNATURE_LIST)\r
590 + sizeof(EFI_SIGNATURE_DATA) - 1\r
591 + WIN_CERT_UEFI_RSA2048_SIZE;\r
592\r
593 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
594 if (KekSigList == NULL) {\r
595 Status = EFI_OUT_OF_RESOURCES;\r
596 goto ON_EXIT;\r
597 }\r
598\r
599 KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST)\r
600 + sizeof(EFI_SIGNATURE_DATA) - 1\r
601 + WIN_CERT_UEFI_RSA2048_SIZE;\r
602 KekSigList->SignatureHeaderSize = 0;\r
603 KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;\r
604 CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);\r
605 \r
606 KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));\r
607 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
608 CopyMem (\r
609 KEKSigData->SignatureData,\r
610 KeyBlob + sizeof(CPL_KEY_INFO),\r
611 WIN_CERT_UEFI_RSA2048_SIZE\r
612 );\r
613 \r
614 //\r
615 // Check if KEK entry has been already existed. \r
616 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
617 // new KEK to original variable.\r
618 // \r
8c1babfd 619 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
620 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
621 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
622 if (EFI_ERROR (Status)) {\r
623 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
624 goto ON_EXIT;\r
625 }\r
626\r
ecc722ad 627 Status = gRT->GetVariable(\r
628 EFI_KEY_EXCHANGE_KEY_NAME, \r
629 &gEfiGlobalVariableGuid, \r
630 NULL, \r
631 &DataSize, \r
632 NULL\r
633 );\r
634 if (Status == EFI_BUFFER_TOO_SMALL) {\r
635 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
636 } else if (Status != EFI_NOT_FOUND) {\r
637 goto ON_EXIT;\r
638 }\r
639 \r
640 //\r
641 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,\r
642 // \r
643 Status = gRT->SetVariable(\r
644 EFI_KEY_EXCHANGE_KEY_NAME, \r
645 &gEfiGlobalVariableGuid, \r
646 Attr, \r
647 KekSigListSize, \r
648 KekSigList\r
649 );\r
650 if (EFI_ERROR (Status)) {\r
651 goto ON_EXIT;\r
652 }\r
653 \r
654ON_EXIT:\r
655\r
656 CloseFile (Private->FileContext->FHandle);\r
657 Private->FileContext->FHandle = NULL;\r
658 Private->FileContext->FileName = NULL;\r
659\r
660 if (Private->SignatureGUID != NULL) {\r
661 FreePool (Private->SignatureGUID);\r
662 Private->SignatureGUID = NULL;\r
663 }\r
664\r
665 if (KeyBlob != NULL) {\r
666 FreePool (KeyBlob);\r
667 }\r
668 if (KeyBuffer != NULL) {\r
669 FreePool (KeyBuffer);\r
670 }\r
671 if (KekSigList != NULL) {\r
672 FreePool (KekSigList);\r
673 }\r
674 \r
675 return Status;\r
676}\r
677\r
678/**\r
679 Enroll a new KEK item from X509 certificate file.\r
680\r
681 @param[in] PrivateData The module's private data.\r
682\r
683 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
684 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
685 @retval EFI_UNSUPPORTED Unsupported command.\r
686 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
687\r
688**/\r
689EFI_STATUS\r
690EnrollX509ToKek (\r
691 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
692 ) \r
693{\r
694 EFI_STATUS Status;\r
695 UINTN X509DataSize;\r
696 VOID *X509Data;\r
697 EFI_SIGNATURE_DATA *KEKSigData;\r
698 EFI_SIGNATURE_LIST *KekSigList;\r
699 UINTN DataSize;\r
700 UINTN KekSigListSize;\r
701 UINT32 Attr;\r
702\r
703 X509Data = NULL;\r
704 X509DataSize = 0;\r
705 KekSigList = NULL;\r
706 KekSigListSize = 0;\r
707 DataSize = 0;\r
708 KEKSigData = NULL;\r
709\r
710 Status = ReadFileContent (\r
711 Private->FileContext->FHandle,\r
712 &X509Data,\r
713 &X509DataSize,\r
714 0\r
715 );\r
716 if (EFI_ERROR (Status)) {\r
717 goto ON_EXIT;\r
718 }\r
ba57d4fd 719 ASSERT (X509Data != NULL);\r
ecc722ad 720\r
721 KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
722 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
723 if (KekSigList == NULL) {\r
724 Status = EFI_OUT_OF_RESOURCES;\r
725 goto ON_EXIT;\r
726 }\r
727\r
728 //\r
729 // Fill Certificate Database parameters.\r
730 // \r
731 KekSigList->SignatureListSize = (UINT32) KekSigListSize;\r
732 KekSigList->SignatureHeaderSize = 0;\r
733 KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
734 CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);\r
735\r
736 KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));\r
737 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
738 CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);\r
739\r
740 //\r
741 // Check if KEK been already existed. \r
742 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
743 // new kek to original variable\r
744 // \r
745 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
8c1babfd 746 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
747 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
748 if (EFI_ERROR (Status)) {\r
749 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
750 goto ON_EXIT;\r
751 }\r
752 \r
ecc722ad 753 Status = gRT->GetVariable(\r
754 EFI_KEY_EXCHANGE_KEY_NAME, \r
755 &gEfiGlobalVariableGuid, \r
756 NULL, \r
757 &DataSize, \r
758 NULL\r
759 );\r
760 if (Status == EFI_BUFFER_TOO_SMALL) {\r
761 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
762 } else if (Status != EFI_NOT_FOUND) {\r
763 goto ON_EXIT;\r
764 } \r
765\r
766 Status = gRT->SetVariable(\r
767 EFI_KEY_EXCHANGE_KEY_NAME, \r
768 &gEfiGlobalVariableGuid, \r
769 Attr, \r
770 KekSigListSize,\r
771 KekSigList\r
772 );\r
773 if (EFI_ERROR (Status)) {\r
774 goto ON_EXIT;\r
775 }\r
776\r
777ON_EXIT:\r
778\r
779 CloseFile (Private->FileContext->FHandle);\r
780 Private->FileContext->FileName = NULL;\r
781 Private->FileContext->FHandle = NULL;\r
782\r
783 if (Private->SignatureGUID != NULL) {\r
784 FreePool (Private->SignatureGUID);\r
785 Private->SignatureGUID = NULL;\r
786 }\r
787\r
788 if (KekSigList != NULL) {\r
789 FreePool (KekSigList);\r
790 }\r
791\r
792 return Status;\r
793}\r
794\r
795/**\r
796 Enroll new KEK into the System without PK's authentication.\r
797 The SignatureOwner GUID will be Private->SignatureGUID.\r
798 \r
799 @param[in] PrivateData The module's private data.\r
800 \r
801 @retval EFI_SUCCESS New KEK enrolled successful.\r
802 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
803 @retval others Fail to enroll KEK data.\r
804 \r
805**/\r
806EFI_STATUS\r
807EnrollKeyExchangeKey (\r
808 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
809 ) \r
810{\r
811 UINT16* FilePostFix;\r
f71ed839 812 EFI_STATUS Status;\r
fd64f84f 813 UINTN NameLength;\r
ecc722ad 814 \r
815 if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {\r
816 return EFI_INVALID_PARAMETER;\r
817 }\r
818\r
f71ed839 819 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
820 if (EFI_ERROR (Status)) {\r
821 return Status;\r
822 }\r
823\r
ecc722ad 824 //\r
e4d7370d 825 // Parse the file's postfix. Supports DER-encoded X509 certificate, \r
ecc722ad 826 // and .pbk as RSA public key file.\r
827 //\r
fd64f84f
GCPL
828 NameLength = StrLen (Private->FileContext->FileName);\r
829 if (NameLength <= 4) {\r
830 return EFI_INVALID_PARAMETER;\r
831 }\r
832 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
e4d7370d 833 if (IsDerEncodeCertificate(FilePostFix)) {\r
ecc722ad 834 return EnrollX509ToKek (Private);\r
835 } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {\r
836 return EnrollRsa2048ToKek (Private);\r
837 } else {\r
838 return EFI_INVALID_PARAMETER;\r
839 }\r
840}\r
841\r
842/**\r
843 Enroll a new X509 certificate into Signature Database (DB or DBX) without\r
844 KEK's authentication.\r
845\r
846 @param[in] PrivateData The module's private data.\r
847 @param[in] VariableName Variable name of signature database, must be \r
848 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
849 \r
850 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
851 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
852\r
853**/\r
854EFI_STATUS\r
855EnrollX509toSigDB (\r
856 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
857 IN CHAR16 *VariableName\r
858 ) \r
859{\r
860 EFI_STATUS Status;\r
861 UINTN X509DataSize;\r
862 VOID *X509Data;\r
863 EFI_SIGNATURE_LIST *SigDBCert;\r
864 EFI_SIGNATURE_DATA *SigDBCertData;\r
865 VOID *Data;\r
866 UINTN DataSize;\r
867 UINTN SigDBSize;\r
868 UINT32 Attr;\r
869\r
870 X509DataSize = 0;\r
871 SigDBSize = 0;\r
872 DataSize = 0;\r
873 X509Data = NULL;\r
874 SigDBCert = NULL;\r
875 SigDBCertData = NULL;\r
876 Data = NULL;\r
877\r
878 Status = ReadFileContent (\r
879 Private->FileContext->FHandle,\r
880 &X509Data,\r
881 &X509DataSize,\r
882 0\r
883 );\r
884 if (EFI_ERROR (Status)) {\r
885 goto ON_EXIT;\r
886 }\r
ba57d4fd 887 ASSERT (X509Data != NULL);\r
ecc722ad 888\r
889 SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
890\r
891 Data = AllocateZeroPool (SigDBSize);\r
892 if (Data == NULL) {\r
893 Status = EFI_OUT_OF_RESOURCES;\r
894 goto ON_EXIT;\r
895 }\r
896\r
897 //\r
898 // Fill Certificate Database parameters.\r
899 // \r
900 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
901 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
902 SigDBCert->SignatureHeaderSize = 0;\r
903 SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
904 CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);\r
905\r
906 SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));\r
907 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
908 CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);\r
909\r
910 //\r
911 // Check if signature database entry has been already existed. \r
912 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
913 // new signature data to original variable\r
914 // \r
915 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
8c1babfd 916 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
917 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
918 if (EFI_ERROR (Status)) {\r
919 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
920 goto ON_EXIT;\r
921 }\r
ecc722ad 922\r
923 Status = gRT->GetVariable(\r
924 VariableName, \r
925 &gEfiImageSecurityDatabaseGuid, \r
926 NULL, \r
927 &DataSize, \r
928 NULL\r
929 );\r
930 if (Status == EFI_BUFFER_TOO_SMALL) {\r
931 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
932 } else if (Status != EFI_NOT_FOUND) {\r
933 goto ON_EXIT;\r
934 } \r
935\r
936 Status = gRT->SetVariable(\r
937 VariableName, \r
938 &gEfiImageSecurityDatabaseGuid, \r
939 Attr, \r
940 SigDBSize,\r
941 Data\r
942 );\r
943 if (EFI_ERROR (Status)) {\r
944 goto ON_EXIT;\r
945 }\r
946\r
947ON_EXIT:\r
948\r
949 CloseFile (Private->FileContext->FHandle);\r
950 Private->FileContext->FileName = NULL;\r
951 Private->FileContext->FHandle = NULL;\r
952\r
953 if (Private->SignatureGUID != NULL) {\r
954 FreePool (Private->SignatureGUID);\r
955 Private->SignatureGUID = NULL;\r
956 }\r
957\r
958 if (Data != NULL) {\r
959 FreePool (Data);\r
960 }\r
961\r
962 if (X509Data != NULL) {\r
963 FreePool (X509Data);\r
964 }\r
965\r
966 return Status;\r
967}\r
968\r
969/**\r
970 Load PE/COFF image information into internal buffer and check its validity.\r
971\r
972 @retval EFI_SUCCESS Successful\r
973 @retval EFI_UNSUPPORTED Invalid PE/COFF file\r
974 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.\r
975\r
976**/\r
977EFI_STATUS\r
978LoadPeImage (\r
979 VOID \r
980 ) \r
981{\r
982 EFI_IMAGE_DOS_HEADER *DosHdr;\r
983 EFI_IMAGE_NT_HEADERS32 *NtHeader32;\r
984 EFI_IMAGE_NT_HEADERS64 *NtHeader64;\r
985\r
986 NtHeader32 = NULL;\r
987 NtHeader64 = NULL;\r
988 //\r
989 // Read the Dos header\r
990 //\r
991 DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);\r
992 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)\r
993 {\r
994 //\r
995 // DOS image header is present, \r
996 // So read the PE header after the DOS image header\r
997 //\r
998 mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
999 }\r
1000 else\r
1001 {\r
1002 mPeCoffHeaderOffset = 0;\r
1003 }\r
1004\r
1005 //\r
1006 // Read PE header and check the signature validity and machine compatibility\r
1007 //\r
1008 NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);\r
1009 if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)\r
1010 {\r
1011 return EFI_UNSUPPORTED;\r
1012 }\r
1013\r
1014 mNtHeader.Pe32 = NtHeader32;\r
1015\r
1016 //\r
1017 // Check the architecture field of PE header and get the Certificate Data Directory data\r
1018 // Note the size of FileHeader field is constant for both IA32 and X64 arch\r
1019 //\r
1020 if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) \r
1021 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) {\r
1022 //\r
1023 // IA-32 Architecture\r
1024 //\r
1025 mImageType = ImageType_IA32;\r
1026 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
1027 }\r
1028 else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
1029 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) {\r
1030 //\r
1031 // 64-bits Architecture\r
1032 //\r
1033 mImageType = ImageType_X64;\r
1034 NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);\r
1035 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
1036 } else {\r
1037 return EFI_UNSUPPORTED;\r
1038 }\r
1039\r
1040 return EFI_SUCCESS;\r
1041}\r
1042\r
1043/**\r
1044 Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
1045 PE/COFF Specification 8.0 Appendix A\r
1046\r
1047 @param[in] HashAlg Hash algorithm type.\r
1048 \r
1049 @retval TRUE Successfully hash image.\r
1050 @retval FALSE Fail in hash image.\r
1051\r
1052**/\r
1053BOOLEAN \r
1054HashPeImage (\r
1055 IN UINT32 HashAlg\r
1056 )\r
1057{\r
1058 BOOLEAN Status;\r
1059 UINT16 Magic;\r
1060 EFI_IMAGE_SECTION_HEADER *Section;\r
1061 VOID *HashCtx;\r
1062 UINTN CtxSize;\r
1063 UINT8 *HashBase;\r
1064 UINTN HashSize;\r
1065 UINTN SumOfBytesHashed;\r
1066 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1067 UINTN Index;\r
1068 UINTN Pos;\r
1069\r
1070 HashCtx = NULL;\r
1071 SectionHeader = NULL;\r
1072 Status = FALSE;\r
1073\r
1074 if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
1075 return FALSE;\r
1076 }\r
1077 \r
1078 //\r
1079 // Initialize context of hash.\r
1080 //\r
1081 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
1082\r
1083 if (HashAlg == HASHALG_SHA1) {\r
1084 mImageDigestSize = SHA1_DIGEST_SIZE;\r
1085 mCertType = gEfiCertSha1Guid; \r
1086 } else if (HashAlg == HASHALG_SHA256) {\r
1087 mImageDigestSize = SHA256_DIGEST_SIZE;\r
1088 mCertType = gEfiCertSha256Guid;\r
1089 }\r
1090\r
1091 CtxSize = mHash[HashAlg].GetContextSize();\r
1092 \r
1093 HashCtx = AllocatePool (CtxSize);\r
1094 ASSERT (HashCtx != NULL);\r
1095\r
1096 // 1. Load the image header into memory.\r
1097\r
1098 // 2. Initialize a SHA hash context.\r
1099 Status = mHash[HashAlg].HashInit(HashCtx);\r
1100 if (!Status) {\r
1101 goto Done;\r
1102 }\r
1103 //\r
1104 // Measuring PE/COFF Image Header;\r
1105 // But CheckSum field and SECURITY data directory (certificate) are excluded\r
1106 //\r
de2447dd 1107 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1108 //\r
1109 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
1110 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
1111 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1112 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1113 //\r
1114 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
1115 } else {\r
1116 //\r
1117 // Get the magic value from the PE/COFF Optional Header\r
1118 //\r
1119 Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
1120 }\r
1121 \r
ecc722ad 1122 //\r
1123 // 3. Calculate the distance from the base of the image header to the image checksum address.\r
1124 // 4. Hash the image header from its base to beginning of the image checksum.\r
1125 //\r
1126 HashBase = mImageBase;\r
1127 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1128 //\r
1129 // Use PE32 offset.\r
1130 //\r
1131 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
1132 } else {\r
1133 //\r
1134 // Use PE32+ offset.\r
1135 //\r
1136 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
1137 }\r
1138\r
1139 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1140 if (!Status) {\r
1141 goto Done;\r
1142 }\r
1143 //\r
1144 // 5. Skip over the image checksum (it occupies a single ULONG).\r
1145 // 6. Get the address of the beginning of the Cert Directory.\r
1146 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
1147 //\r
1148 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1149 //\r
1150 // Use PE32 offset.\r
1151 //\r
1152 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
1153 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1154 } else {\r
1155 //\r
1156 // Use PE32+ offset.\r
1157 // \r
1158 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
1159 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1160 }\r
1161\r
1162 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1163 if (!Status) {\r
1164 goto Done;\r
1165 }\r
1166 //\r
1167 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
1168 // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
1169 //\r
1170 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1171 //\r
1172 // Use PE32 offset\r
1173 //\r
1174 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1175 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1176 } else {\r
1177 //\r
1178 // Use PE32+ offset.\r
1179 //\r
1180 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1181 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1182 }\r
1183\r
1184 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1185 if (!Status) {\r
1186 goto Done;\r
1187 }\r
1188 //\r
1189 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
1190 //\r
1191 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1192 //\r
1193 // Use PE32 offset.\r
1194 //\r
1195 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
1196 } else {\r
1197 //\r
1198 // Use PE32+ offset\r
1199 //\r
1200 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
1201 }\r
1202\r
1203 //\r
1204 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
1205 // structures in the image. The 'NumberOfSections' field of the image\r
1206 // header indicates how big the table should be. Do not include any\r
1207 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
1208 //\r
1209 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
1210 ASSERT (SectionHeader != NULL);\r
1211 //\r
1212 // 12. Using the 'PointerToRawData' in the referenced section headers as\r
1213 // a key, arrange the elements in the table in ascending order. In other\r
1214 // words, sort the section headers according to the disk-file offset of\r
1215 // the section.\r
1216 //\r
1217 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1218 mImageBase +\r
1219 mPeCoffHeaderOffset +\r
1220 sizeof (UINT32) +\r
1221 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1222 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
1223 );\r
1224 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1225 Pos = Index;\r
1226 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
1227 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
1228 Pos--;\r
1229 }\r
1230 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
1231 Section += 1;\r
1232 }\r
1233\r
1234 //\r
1235 // 13. Walk through the sorted table, bring the corresponding section\r
1236 // into memory, and hash the entire section (using the 'SizeOfRawData'\r
1237 // field in the section header to determine the amount of data to hash).\r
1238 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
1239 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.\r
1240 //\r
1241 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1242 Section = &SectionHeader[Index];\r
1243 if (Section->SizeOfRawData == 0) {\r
1244 continue;\r
1245 }\r
1246 HashBase = mImageBase + Section->PointerToRawData;\r
1247 HashSize = (UINTN) Section->SizeOfRawData;\r
1248\r
1249 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1250 if (!Status) {\r
1251 goto Done;\r
1252 }\r
1253\r
1254 SumOfBytesHashed += HashSize;\r
1255 }\r
1256\r
1257 //\r
1258 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
1259 // data in the file that needs to be added to the hash. This data begins\r
1260 // at file offset SUM_OF_BYTES_HASHED and its length is:\r
1261 // FileSize - (CertDirectory->Size)\r
1262 //\r
1263 if (mImageSize > SumOfBytesHashed) {\r
1264 HashBase = mImageBase + SumOfBytesHashed;\r
1265 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1266 //\r
1267 // Use PE32 offset.\r
1268 //\r
1269 HashSize = (UINTN)(\r
1270 mImageSize -\r
1271 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
1272 SumOfBytesHashed);\r
1273 } else {\r
1274 //\r
1275 // Use PE32+ offset.\r
1276 //\r
1277 HashSize = (UINTN)(\r
1278 mImageSize -\r
1279 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
1280 SumOfBytesHashed); \r
1281 }\r
1282\r
1283 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1284 if (!Status) {\r
1285 goto Done;\r
1286 }\r
1287 }\r
1288\r
1289 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
1290\r
1291Done:\r
1292 if (HashCtx != NULL) {\r
1293 FreePool (HashCtx);\r
1294 }\r
1295 if (SectionHeader != NULL) {\r
1296 FreePool (SectionHeader);\r
1297 }\r
1298 return Status;\r
1299}\r
1300\r
1301/**\r
1302 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of \r
1303 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification \r
1304 8.0 Appendix A\r
1305\r
1306 @retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
1307 @retval EFI_SUCCESS Hash successfully.\r
1308\r
1309**/\r
1310EFI_STATUS \r
1311HashPeImageByType (\r
1312 VOID\r
1313 )\r
1314{\r
1315 UINT8 Index;\r
1316 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
1317\r
1318 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
1319\r
1320 for (Index = 0; Index < HASHALG_MAX; Index++) { \r
1321 //\r
1322 // Check the Hash algorithm in PE/COFF Authenticode.\r
1323 // According to PKCS#7 Definition: \r
1324 // SignedData ::= SEQUENCE {\r
1325 // version Version,\r
1326 // digestAlgorithms DigestAlgorithmIdentifiers,\r
1327 // contentInfo ContentInfo,\r
1328 // .... }\r
1329 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
1330 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
1331 // Fixed offset (+32) is calculated based on two bytes of length encoding.\r
1332 //\r
1333 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
1334 //\r
1335 // Only support two bytes of Long Form of Length Encoding.\r
1336 //\r
1337 continue;\r
1338 }\r
1339\r
1340 // \r
1341 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
1342 break;\r
1343 }\r
1344 }\r
1345\r
1346 if (Index == HASHALG_MAX) {\r
1347 return EFI_UNSUPPORTED;\r
1348 }\r
1349\r
1350 //\r
1351 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
1352 //\r
1353 if (!HashPeImage(Index)) {\r
1354 return EFI_UNSUPPORTED;\r
1355 }\r
1356\r
1357 return EFI_SUCCESS;\r
1358}\r
1359\r
1360/**\r
1361 Enroll a new executable's signature into Signature Database. \r
1362\r
1363 @param[in] PrivateData The module's private data.\r
1364 @param[in] VariableName Variable name of signature database, must be \r
1365 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
1366\r
1367 @retval EFI_SUCCESS New signature is enrolled successfully.\r
1368 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1369 @retval EFI_UNSUPPORTED Unsupported command.\r
1370 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
1371\r
1372**/\r
1373EFI_STATUS\r
1374EnrollImageSignatureToSigDB (\r
1375 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1376 IN CHAR16 *VariableName\r
1377 )\r
1378{\r
1379 EFI_STATUS Status;\r
1380 EFI_SIGNATURE_LIST *SigDBCert;\r
1381 EFI_SIGNATURE_DATA *SigDBCertData;\r
1382 VOID *Data;\r
1383 UINTN DataSize;\r
1384 UINTN SigDBSize;\r
1385 UINT32 Attr;\r
1386 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;\r
1387\r
1388 Data = NULL;\r
1389 GuidCertData = NULL;\r
ecc722ad 1390\r
1391 //\r
1392 // Form the SigDB certificate list.\r
1393 // Format the data item into EFI_SIGNATURE_LIST type.\r
1394 //\r
1395 // We need to parse executable's signature data from specified signed executable file.\r
1396 // In current implementation, we simply trust the pass-in signed executable file.\r
1397 // In reality, it's OS's responsibility to verify the signed executable file.\r
1398 //\r
1399\r
1400 //\r
1401 // Read the whole file content\r
1402 //\r
1403 Status = ReadFileContent(\r
1404 Private->FileContext->FHandle,\r
1405 (VOID **) &mImageBase, \r
1406 &mImageSize, \r
1407 0\r
1408 );\r
1409 if (EFI_ERROR (Status)) {\r
1410 goto ON_EXIT;\r
1411 } \r
ba57d4fd 1412 ASSERT (mImageBase != NULL);\r
ecc722ad 1413\r
1414 Status = LoadPeImage ();\r
1415 if (EFI_ERROR (Status)) {\r
1416 goto ON_EXIT;\r
1417 }\r
1418\r
1419 if (mSecDataDir->SizeOfCert == 0) {\r
1420 if (!HashPeImage (HASHALG_SHA256)) {\r
1421 Status = EFI_SECURITY_VIOLATION;\r
1422 goto ON_EXIT;\r
1423 }\r
1424 } else {\r
1425 \r
1426 //\r
1427 // Read the certificate data\r
1428 //\r
1429 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
1430\r
1431 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
1432 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
1433 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
1434 Status = EFI_ABORTED;\r
1435 goto ON_EXIT;\r
1436 }\r
1437\r
1438 if (!HashPeImage (HASHALG_SHA256)) {\r
1439 Status = EFI_ABORTED;\r
1440 goto ON_EXIT;;\r
1441 }\r
1442 \r
1443 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
1444\r
1445 Status = HashPeImageByType ();\r
1446 if (EFI_ERROR (Status)) {\r
1447 goto ON_EXIT;;\r
1448 }\r
1449 } else {\r
1450 Status = EFI_ABORTED;\r
1451 goto ON_EXIT;\r
1452 }\r
1453 }\r
1454\r
1455 //\r
1456 // Create a new SigDB entry.\r
1457 //\r
1458 SigDBSize = sizeof(EFI_SIGNATURE_LIST) \r
1459 + sizeof(EFI_SIGNATURE_DATA) - 1\r
1460 + (UINT32) mImageDigestSize;\r
1461\r
1462 Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
1463 if (Data == NULL) {\r
1464 Status = EFI_OUT_OF_RESOURCES;\r
1465 goto ON_EXIT;\r
1466 }\r
1467 \r
1468 //\r
1469 // Adjust the Certificate Database parameters.\r
1470 // \r
1471 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
1472 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
1473 SigDBCert->SignatureHeaderSize = 0;\r
1474 SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
1475 CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
1476\r
1477 SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
1478 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
1479 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
1480\r
8c1babfd 1481 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
1482 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
1483 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
1484 if (EFI_ERROR (Status)) {\r
1485 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
1486 goto ON_EXIT;\r
1487 }\r
1488 \r
ecc722ad 1489 //\r
1490 // Check if SigDB variable has been already existed. \r
1491 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
1492 // new signature data to original variable\r
1493 // \r
1494 DataSize = 0;\r
1495 Status = gRT->GetVariable(\r
1496 VariableName, \r
1497 &gEfiImageSecurityDatabaseGuid, \r
1498 NULL, \r
1499 &DataSize, \r
1500 NULL\r
1501 );\r
1502 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1503 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
1504 } else if (Status != EFI_NOT_FOUND) {\r
1505 goto ON_EXIT;\r
1506 } \r
1507\r
1508 //\r
1509 // Enroll the variable.\r
1510 //\r
1511 Status = gRT->SetVariable(\r
1512 VariableName, \r
1513 &gEfiImageSecurityDatabaseGuid, \r
1514 Attr, \r
1515 SigDBSize, \r
1516 Data\r
1517 );\r
1518 if (EFI_ERROR (Status)) {\r
1519 goto ON_EXIT;\r
1520 }\r
1521\r
1522ON_EXIT:\r
1523\r
1524 CloseFile (Private->FileContext->FHandle);\r
1525 Private->FileContext->FHandle = NULL;\r
1526 Private->FileContext->FileName = NULL;\r
1527\r
1528 if (Private->SignatureGUID != NULL) {\r
1529 FreePool (Private->SignatureGUID);\r
1530 Private->SignatureGUID = NULL;\r
1531 }\r
1532\r
1533 if (Data != NULL) {\r
1534 FreePool (Data);\r
1535 }\r
1536\r
1537 if (mImageBase != NULL) {\r
1538 FreePool (mImageBase);\r
1539 mImageBase = NULL;\r
1540 }\r
1541\r
1542 return Status;\r
1543}\r
1544\r
1545/**\r
1546 Enroll signature into DB/DBX without KEK's authentication.\r
1547 The SignatureOwner GUID will be Private->SignatureGUID.\r
1548 \r
1549 @param[in] PrivateData The module's private data.\r
1550 @param[in] VariableName Variable name of signature database, must be \r
1551 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
1552 \r
1553 @retval EFI_SUCCESS New signature enrolled successfully.\r
1554 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1555 @retval others Fail to enroll signature data.\r
1556 \r
1557**/\r
1558EFI_STATUS\r
1559EnrollSignatureDatabase (\r
1560 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1561 IN CHAR16 *VariableName\r
1562 ) \r
1563{\r
1564 UINT16* FilePostFix;\r
f71ed839 1565 EFI_STATUS Status;\r
fd64f84f 1566 UINTN NameLength;\r
ecc722ad 1567\r
1568 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
1569 return EFI_INVALID_PARAMETER;\r
1570 }\r
1571\r
f71ed839 1572 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
1573 if (EFI_ERROR (Status)) {\r
1574 return Status;\r
1575 }\r
1576 \r
ecc722ad 1577 //\r
1578 // Parse the file's postfix. \r
1579 //\r
fd64f84f
GCPL
1580 NameLength = StrLen (Private->FileContext->FileName);\r
1581 if (NameLength <= 4) {\r
1582 return EFI_INVALID_PARAMETER;\r
1583 }\r
1584 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
e4d7370d 1585 if (IsDerEncodeCertificate(FilePostFix)) {\r
ecc722ad 1586 //\r
e4d7370d 1587 // Supports DER-encoded X509 certificate.\r
ecc722ad 1588 //\r
1589 return EnrollX509toSigDB (Private, VariableName);\r
1590 }\r
1591\r
1592 return EnrollImageSignatureToSigDB (Private, VariableName);\r
1593}\r
1594\r
1595/**\r
1596 List all signatures in specified signature database (e.g. KEK/DB/DBX)\r
1597 by GUID in the page for user to select and delete as needed.\r
1598\r
1599 @param[in] PrivateData Module's private data.\r
1600 @param[in] VariableName The variable name of the vendor's signature database.\r
1601 @param[in] VendorGuid A unique identifier for the vendor.\r
1602 @param[in] LabelNumber Label number to insert opcodes.\r
1603 @param[in] FormId Form ID of current page.\r
1604 @param[in] QuestionIdBase Base question id of the signature list.\r
1605\r
1606 @retval EFI_SUCCESS Success to update the signature list page\r
1607 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
1608 \r
1609**/\r
1610EFI_STATUS\r
1611UpdateDeletePage (\r
1612 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
1613 IN CHAR16 *VariableName,\r
1614 IN EFI_GUID *VendorGuid,\r
1615 IN UINT16 LabelNumber,\r
1616 IN EFI_FORM_ID FormId,\r
1617 IN EFI_QUESTION_ID QuestionIdBase\r
1618 )\r
1619{\r
1620 EFI_STATUS Status;\r
1621 UINT32 Index;\r
1622 UINTN CertCount;\r
1623 UINTN GuidIndex;\r
1624 VOID *StartOpCodeHandle;\r
1625 VOID *EndOpCodeHandle;\r
1626 EFI_IFR_GUID_LABEL *StartLabel;\r
1627 EFI_IFR_GUID_LABEL *EndLabel; \r
1628 UINTN DataSize;\r
1629 UINT8 *Data;\r
1630 EFI_SIGNATURE_LIST *CertList;\r
1631 EFI_SIGNATURE_DATA *Cert;\r
1632 UINT32 ItemDataSize;\r
1633 CHAR16 *GuidStr;\r
1634 EFI_STRING_ID GuidID;\r
1635 EFI_STRING_ID Help;\r
1636\r
1637 Data = NULL;\r
1638 CertList = NULL;\r
1639 Cert = NULL;\r
1640 GuidStr = NULL;\r
1641 StartOpCodeHandle = NULL;\r
1642 EndOpCodeHandle = NULL;\r
1643 \r
1644 //\r
1645 // Initialize the container for dynamic opcodes.\r
1646 //\r
1647 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1648 if (StartOpCodeHandle == NULL) {\r
1649 Status = EFI_OUT_OF_RESOURCES;\r
1650 goto ON_EXIT; \r
1651 }\r
1652\r
1653 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1654 if (EndOpCodeHandle == NULL) {\r
1655 Status = EFI_OUT_OF_RESOURCES;\r
1656 goto ON_EXIT; \r
1657 }\r
1658\r
1659 //\r
1660 // Create Hii Extend Label OpCode.\r
1661 //\r
1662 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
1663 StartOpCodeHandle,\r
1664 &gEfiIfrTianoGuid,\r
1665 NULL,\r
1666 sizeof (EFI_IFR_GUID_LABEL)\r
1667 );\r
1668 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1669 StartLabel->Number = LabelNumber;\r
1670\r
1671 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
1672 EndOpCodeHandle,\r
1673 &gEfiIfrTianoGuid,\r
1674 NULL,\r
1675 sizeof (EFI_IFR_GUID_LABEL)\r
1676 );\r
1677 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1678 EndLabel->Number = LABEL_END;\r
1679\r
1680 //\r
1681 // Read Variable.\r
1682 //\r
1683 DataSize = 0;\r
1684 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); \r
1685 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
1686 goto ON_EXIT;\r
1687 }\r
1688\r
1689 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1690 if (Data == NULL) {\r
1691 Status = EFI_OUT_OF_RESOURCES;\r
1692 goto ON_EXIT;\r
1693 }\r
1694\r
1695 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
1696 if (EFI_ERROR (Status)) {\r
1697 goto ON_EXIT;\r
1698 }\r
1699\r
1700 GuidStr = AllocateZeroPool (100);\r
1701 if (GuidStr == NULL) {\r
1702 Status = EFI_OUT_OF_RESOURCES;\r
1703 goto ON_EXIT;\r
1704 }\r
1705\r
1706 //\r
1707 // Enumerate all KEK pub data.\r
1708 //\r
1709 ItemDataSize = (UINT32) DataSize;\r
1710 CertList = (EFI_SIGNATURE_LIST *) Data;\r
1711 GuidIndex = 0;\r
1712\r
1713 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
1714\r
1715 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
1716 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
1717 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
1718 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
1719 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
1720 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
1721 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
1722 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
1723 } else {\r
1724 //\r
1725 // The signature type is not supported in current implementation.\r
1726 //\r
b7d269ea 1727 ItemDataSize -= CertList->SignatureListSize;\r
1728 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
ecc722ad 1729 continue;\r
1730 }\r
1731\r
1732 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1733 for (Index = 0; Index < CertCount; Index++) {\r
1734 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList \r
1735 + sizeof (EFI_SIGNATURE_LIST) \r
1736 + CertList->SignatureHeaderSize \r
1737 + Index * CertList->SignatureSize);\r
1738 //\r
1739 // Display GUID and help \r
1740 //\r
1741 GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
1742 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
1743 HiiCreateCheckBoxOpCode (\r
1744 StartOpCodeHandle,\r
1745 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
1746 0, \r
1747 0, \r
1748 GuidID, \r
1749 Help,\r
1750 EFI_IFR_FLAG_CALLBACK,\r
1751 0,\r
1752 NULL\r
1753 ); \r
1754 }\r
1755\r
1756 ItemDataSize -= CertList->SignatureListSize;\r
1757 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1758 }\r
1759\r
1760ON_EXIT:\r
1761 HiiUpdateForm (\r
1762 PrivateData->HiiHandle,\r
1763 &gSecureBootConfigFormSetGuid,\r
1764 FormId,\r
1765 StartOpCodeHandle,\r
1766 EndOpCodeHandle\r
1767 );\r
1768\r
1769 if (StartOpCodeHandle != NULL) {\r
1770 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1771 }\r
1772\r
1773 if (EndOpCodeHandle != NULL) {\r
1774 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1775 }\r
1776 \r
1777 if (Data != NULL) {\r
1778 FreePool (Data);\r
1779 }\r
1780\r
1781 if (GuidStr != NULL) {\r
1782 FreePool (GuidStr);\r
1783 }\r
1784\r
1785 return EFI_SUCCESS;\r
1786}\r
1787\r
beda2356 1788/**\r
ecc722ad 1789 Delete a KEK entry from KEK database. \r
beda2356 1790\r
ecc722ad 1791 @param[in] PrivateData Module's private data.\r
1792 @param[in] QuestionId Question id of the KEK item to delete.\r
beda2356 1793\r
ecc722ad 1794 @retval EFI_SUCCESS Delete kek item successfully.\r
1795 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
1796 \r
1797**/\r
1798EFI_STATUS\r
1799DeleteKeyExchangeKey (\r
1800 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
1801 IN EFI_QUESTION_ID QuestionId\r
1802 )\r
1803{\r
1804 EFI_STATUS Status;\r
1805 UINTN DataSize;\r
1806 UINT8 *Data;\r
1807 UINT8 *OldData;\r
1808 UINT32 Attr;\r
1809 UINT32 Index;\r
1810 EFI_SIGNATURE_LIST *CertList;\r
1811 EFI_SIGNATURE_LIST *NewCertList;\r
1812 EFI_SIGNATURE_DATA *Cert;\r
1813 UINTN CertCount;\r
1814 UINT32 Offset;\r
1815 BOOLEAN IsKEKItemFound;\r
1816 UINT32 KekDataSize;\r
1817 UINTN DeleteKekIndex;\r
1818 UINTN GuidIndex;\r
1819\r
1820 Data = NULL;\r
1821 OldData = NULL;\r
1822 CertList = NULL;\r
1823 Cert = NULL;\r
1824 Attr = 0; \r
1825 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
f71ed839 1826\r
1827 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
1828 if (EFI_ERROR (Status)) {\r
1829 return Status;\r
1830 }\r
ecc722ad 1831 \r
1832 //\r
1833 // Get original KEK variable.\r
1834 // \r
1835 DataSize = 0; \r
1836 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
1837 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
1838 goto ON_EXIT;\r
1839 }\r
1840\r
1841 OldData = (UINT8*)AllocateZeroPool(DataSize);\r
1842 if (OldData == NULL) {\r
1843 Status = EFI_OUT_OF_RESOURCES; \r
1844 goto ON_EXIT;\r
1845 }\r
1846\r
1847 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
1848 if (EFI_ERROR(Status)) {\r
1849 goto ON_EXIT;\r
1850 }\r
1851\r
1852 //\r
1853 // Allocate space for new variable. \r
1854 //\r
1855 Data = (UINT8*) AllocateZeroPool (DataSize);\r
1856 if (Data == NULL) {\r
1857 Status = EFI_OUT_OF_RESOURCES;\r
1858 goto ON_EXIT;\r
1859 }\r
1860\r
1861 //\r
1862 // Enumerate all KEK pub data and erasing the target item.\r
1863 //\r
1864 IsKEKItemFound = FALSE;\r
1865 KekDataSize = (UINT32) DataSize;\r
1866 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
1867 Offset = 0;\r
1868 GuidIndex = 0;\r
1869 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
1870 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
1871 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
1872 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
1873 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
1874 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1875 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1876 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1877 for (Index = 0; Index < CertCount; Index++) {\r
1878 if (GuidIndex == DeleteKekIndex ) {\r
1879 //\r
1880 // Find it! Skip it!\r
1881 //\r
1882 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
1883 IsKEKItemFound = TRUE; \r
1884 } else {\r
1885 //\r
1886 // This item doesn't match. Copy it to the Data buffer.\r
1887 //\r
1888 CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
1889 Offset += CertList->SignatureSize;\r
1890 }\r
1891 GuidIndex++;\r
1892 Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
1893 }\r
1894 } else {\r
1895 //\r
1896 // This List doesn't match. Copy it to the Data buffer.\r
1897 //\r
1898 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
1899 Offset += CertList->SignatureListSize;\r
1900 }\r
1901 \r
1902 KekDataSize -= CertList->SignatureListSize;\r
1903 CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
1904 }\r
1905\r
1906 if (!IsKEKItemFound) {\r
1907 //\r
1908 // Doesn't find the Kek Item!\r
1909 //\r
1910 Status = EFI_NOT_FOUND;\r
1911 goto ON_EXIT;\r
1912 }\r
1913\r
1914 //\r
1915 // Delete the Signature header if there is no signature in the list.\r
1916 //\r
1917 KekDataSize = Offset;\r
1918 CertList = (EFI_SIGNATURE_LIST*) Data;\r
1919 Offset = 0;\r
1920 ZeroMem (OldData, KekDataSize);\r
1921 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
1922 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1923 DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount));\r
1924 if (CertCount != 0) {\r
1925 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
1926 Offset += CertList->SignatureListSize;\r
1927 } \r
1928 KekDataSize -= CertList->SignatureListSize;\r
1929 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1930 }\r
1931\r
ecc722ad 1932 DataSize = Offset;\r
8c1babfd 1933 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
1934 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
1935 if (EFI_ERROR (Status)) {\r
1936 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
1937 goto ON_EXIT;\r
1938 }\r
1939 }\r
ecc722ad 1940\r
1941 Status = gRT->SetVariable(\r
1942 EFI_KEY_EXCHANGE_KEY_NAME, \r
1943 &gEfiGlobalVariableGuid, \r
1944 Attr, \r
1945 DataSize, \r
1946 OldData\r
1947 );\r
1948 if (EFI_ERROR (Status)) {\r
1949 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
1950 goto ON_EXIT;\r
1951 }\r
1952 \r
1953ON_EXIT:\r
1954 if (Data != NULL) {\r
1955 FreePool(Data);\r
1956 }\r
1957\r
1958 if (OldData != NULL) {\r
1959 FreePool(OldData);\r
1960 }\r
1961\r
1962 return UpdateDeletePage (\r
1963 PrivateData, \r
1964 EFI_KEY_EXCHANGE_KEY_NAME,\r
1965 &gEfiGlobalVariableGuid,\r
1966 LABEL_KEK_DELETE,\r
1967 FORMID_DELETE_KEK_FORM,\r
1968 OPTION_DEL_KEK_QUESTION_ID\r
1969 );\r
1970}\r
1971\r
1972/**\r
1973 Delete a signature entry from siganture database.\r
beda2356 1974\r
ecc722ad 1975 @param[in] PrivateData Module's private data.\r
1976 @param[in] VariableName The variable name of the vendor's signature database.\r
1977 @param[in] VendorGuid A unique identifier for the vendor.\r
1978 @param[in] LabelNumber Label number to insert opcodes.\r
1979 @param[in] FormId Form ID of current page.\r
1980 @param[in] QuestionIdBase Base question id of the signature list.\r
1981 @param[in] DeleteIndex Signature index to delete.\r
1982 \r
1983 @retval EFI_SUCCESS Delete siganture successfully.\r
1984 @retval EFI_NOT_FOUND Can't find the signature item,\r
1985 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
beda2356 1986**/\r
1987EFI_STATUS\r
ecc722ad 1988DeleteSignature (\r
1989 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
1990 IN CHAR16 *VariableName,\r
1991 IN EFI_GUID *VendorGuid,\r
1992 IN UINT16 LabelNumber,\r
1993 IN EFI_FORM_ID FormId,\r
1994 IN EFI_QUESTION_ID QuestionIdBase,\r
1995 IN UINTN DeleteIndex\r
beda2356 1996 )\r
1997{\r
ecc722ad 1998 EFI_STATUS Status;\r
1999 UINTN DataSize;\r
2000 UINT8 *Data;\r
2001 UINT8 *OldData;\r
2002 UINT32 Attr;\r
2003 UINT32 Index;\r
2004 EFI_SIGNATURE_LIST *CertList;\r
2005 EFI_SIGNATURE_LIST *NewCertList;\r
2006 EFI_SIGNATURE_DATA *Cert;\r
2007 UINTN CertCount;\r
2008 UINT32 Offset;\r
2009 BOOLEAN IsItemFound;\r
2010 UINT32 ItemDataSize;\r
2011 UINTN GuidIndex;\r
bc0c99b3 2012\r
ecc722ad 2013 Data = NULL;\r
2014 OldData = NULL;\r
2015 CertList = NULL;\r
2016 Cert = NULL;\r
2017 Attr = 0; \r
2018\r
f71ed839 2019 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2020 if (EFI_ERROR (Status)) {\r
2021 return Status;\r
2022 }\r
2023\r
ecc722ad 2024 //\r
2025 // Get original signature list data.\r
2026 // \r
2027 DataSize = 0;\r
2028 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
2029 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2030 goto ON_EXIT;\r
2031 }\r
2032\r
2033 OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
2034 if (OldData == NULL) {\r
2035 Status = EFI_OUT_OF_RESOURCES; \r
2036 goto ON_EXIT;\r
2037 }\r
2038\r
2039 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
2040 if (EFI_ERROR(Status)) {\r
2041 goto ON_EXIT;\r
2042 } \r
2043\r
2044 //\r
2045 // Allocate space for new variable. \r
2046 //\r
2047 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2048 if (Data == NULL) {\r
2049 Status = EFI_OUT_OF_RESOURCES;\r
2050 goto ON_EXIT;\r
2051 }\r
2052\r
2053 //\r
2054 // Enumerate all signature data and erasing the target item.\r
2055 //\r
2056 IsItemFound = FALSE;\r
2057 ItemDataSize = (UINT32) DataSize;\r
2058 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2059 Offset = 0;\r
2060 GuidIndex = 0;\r
2061 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2062 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2063 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
2064 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
2065 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)\r
2066 ) {\r
2067 //\r
2068 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
2069 //\r
2070 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2071 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
2072 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2073 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2074 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2075 for (Index = 0; Index < CertCount; Index++) {\r
2076 if (GuidIndex == DeleteIndex) {\r
2077 //\r
2078 // Find it! Skip it!\r
2079 //\r
2080 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
2081 IsItemFound = TRUE; \r
2082 } else {\r
2083 //\r
2084 // This item doesn't match. Copy it to the Data buffer.\r
2085 //\r
2086 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
2087 Offset += CertList->SignatureSize;\r
2088 }\r
2089 GuidIndex++;\r
2090 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
2091 }\r
2092 } else {\r
2093 //\r
2094 // This List doesn't match. Just copy it to the Data buffer.\r
2095 //\r
2096 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2097 Offset += CertList->SignatureListSize;\r
2098 }\r
2099 \r
2100 ItemDataSize -= CertList->SignatureListSize;\r
2101 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2102 }\r
2103\r
2104 if (!IsItemFound) {\r
2105 //\r
2106 // Doesn't find the signature Item!\r
2107 //\r
2108 Status = EFI_NOT_FOUND;\r
2109 goto ON_EXIT;\r
2110 }\r
2111\r
2112 //\r
2113 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
2114 //\r
2115 ItemDataSize = Offset;\r
2116 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2117 Offset = 0;\r
2118 ZeroMem (OldData, ItemDataSize);\r
2119 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2120 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2121 DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount));\r
2122 if (CertCount != 0) {\r
2123 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2124 Offset += CertList->SignatureListSize;\r
2125 } \r
2126 ItemDataSize -= CertList->SignatureListSize;\r
2127 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2128 }\r
2129\r
ecc722ad 2130 DataSize = Offset;\r
8c1babfd 2131 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2132 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2133 if (EFI_ERROR (Status)) {\r
2134 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2135 goto ON_EXIT;\r
2136 }\r
2137 }\r
ecc722ad 2138\r
2139 Status = gRT->SetVariable(\r
2140 VariableName, \r
2141 VendorGuid, \r
2142 Attr, \r
2143 DataSize, \r
2144 OldData\r
2145 );\r
beda2356 2146 if (EFI_ERROR (Status)) {\r
ecc722ad 2147 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2148 goto ON_EXIT;\r
beda2356 2149 }\r
ecc722ad 2150 \r
2151ON_EXIT:\r
2152 if (Data != NULL) {\r
2153 FreePool(Data);\r
2154 }\r
2155\r
2156 if (OldData != NULL) {\r
2157 FreePool(OldData);\r
2158 }\r
2159\r
2160 return UpdateDeletePage (\r
2161 PrivateData, \r
2162 VariableName,\r
2163 VendorGuid,\r
2164 LabelNumber,\r
2165 FormId,\r
2166 QuestionIdBase\r
2167 );\r
2168}\r
2169\r
2170/**\r
2171 This function extracts configuration from variable.\r
2172 \r
2173 @param[in, out] ConfigData Point to SecureBoot configuration private data.\r
2174\r
2175**/\r
2176VOID\r
2177SecureBootExtractConfigFromVariable (\r
2178 IN OUT SECUREBOOT_CONFIGURATION *ConfigData\r
2179 ) \r
2180{\r
2181 UINT8 *SecureBootEnable;\r
2182 UINT8 *SetupMode;\r
2183 UINT8 *SecureBootMode;\r
2184\r
2185 SecureBootEnable = NULL;\r
2186 SetupMode = NULL;\r
2187 SecureBootMode = NULL;\r
2188 \r
ecc722ad 2189 //\r
2190 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
2191 // Checkbox.\r
2192 //\r
f71ed839 2193 ConfigData->AttemptSecureBoot = FALSE;\r
8f8ca22e 2194 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
ecc722ad 2195 if (SecureBootEnable == NULL) {\r
2196 ConfigData->HideSecureBoot = TRUE;\r
2197 } else {\r
2198 ConfigData->HideSecureBoot = FALSE;\r
f71ed839 2199 if ((*SecureBootEnable) == SECURE_BOOT_ENABLE) {\r
2200 ConfigData->AttemptSecureBoot = TRUE;\r
2201 }\r
ecc722ad 2202 }\r
8f8ca22e 2203 \r
ecc722ad 2204 //\r
2205 // If it is Physical Presence User, set the PhysicalPresent to true.\r
2206 //\r
2207 if (UserPhysicalPresent()) {\r
2208 ConfigData->PhysicalPresent = TRUE;\r
2209 } else {\r
2210 ConfigData->PhysicalPresent = FALSE;\r
2211 }\r
2212 \r
2213 //\r
2214 // If there is no PK then the Delete Pk button will be gray.\r
2215 //\r
f01b91ae 2216 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
8f8ca22e 2217 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
ecc722ad 2218 ConfigData->HasPk = FALSE;\r
2219 } else {\r
2220 ConfigData->HasPk = TRUE;\r
2221 }\r
2222\r
2223 //\r
2224 // Get the SecureBootMode from CustomMode variable.\r
2225 //\r
f01b91ae 2226 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
ecc722ad 2227 if (SecureBootMode == NULL) {\r
2228 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
2229 } else {\r
2230 ConfigData->SecureBootMode = *(SecureBootMode);\r
2231 }\r
f71ed839 2232\r
2233 if (SecureBootEnable != NULL) {\r
2234 FreePool (SecureBootEnable);\r
2235 }\r
2236 if (SetupMode != NULL) {\r
2237 FreePool (SetupMode);\r
2238 }\r
2239 if (SecureBootMode != NULL) {\r
2240 FreePool (SecureBootMode);\r
2241 }\r
beda2356 2242}\r
2243\r
2244/**\r
2245 This function allows a caller to extract the current configuration for one\r
2246 or more named elements from the target driver.\r
2247\r
2248 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2249 @param[in] Request A null-terminated Unicode string in\r
2250 <ConfigRequest> format.\r
2251 @param[out] Progress On return, points to a character in the Request\r
2252 string. Points to the string's null terminator if\r
2253 request was successful. Points to the most recent\r
2254 '&' before the first failing name/value pair (or\r
2255 the beginning of the string if the failure is in\r
2256 the first name/value pair) if the request was not\r
2257 successful.\r
2258 @param[out] Results A null-terminated Unicode string in\r
2259 <ConfigAltResp> format which has all values filled\r
2260 in for the names in the Request string. String to\r
2261 be allocated by the called function.\r
2262\r
2263 @retval EFI_SUCCESS The Results is filled with the requested values.\r
2264 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
2265 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
2266 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
2267 driver.\r
2268\r
2269**/\r
2270EFI_STATUS\r
2271EFIAPI\r
2272SecureBootExtractConfig (\r
2273 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2274 IN CONST EFI_STRING Request,\r
2275 OUT EFI_STRING *Progress,\r
2276 OUT EFI_STRING *Results\r
2277 )\r
2278{\r
2279 EFI_STATUS Status;\r
2280 UINTN BufferSize;\r
bc0c99b3 2281 UINTN Size;\r
beda2356 2282 SECUREBOOT_CONFIGURATION Configuration;\r
beda2356 2283 EFI_STRING ConfigRequest;\r
bc0c99b3 2284 EFI_STRING ConfigRequestHdr;\r
bc0c99b3 2285 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
2286 BOOLEAN AllocatedRequest;\r
f71ed839 2287 UINT8 *SecureBoot;\r
bc0c99b3 2288\r
beda2356 2289 if (Progress == NULL || Results == NULL) {\r
2290 return EFI_INVALID_PARAMETER;\r
2291 }\r
ecc722ad 2292 \r
bc0c99b3 2293 AllocatedRequest = FALSE;\r
2294 ConfigRequestHdr = NULL;\r
2295 ConfigRequest = NULL;\r
2296 Size = 0;\r
f71ed839 2297 SecureBoot = NULL;\r
bc0c99b3 2298 \r
ea71453f 2299 ZeroMem (&Configuration, sizeof (Configuration));\r
bc0c99b3 2300 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
2301 *Progress = Request;\r
2302 \r
beda2356 2303 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
2304 return EFI_NOT_FOUND;\r
2305 }\r
2306\r
beda2356 2307 //\r
ecc722ad 2308 // Get Configuration from Variable.\r
beda2356 2309 //\r
ecc722ad 2310 SecureBootExtractConfigFromVariable (&Configuration);\r
f71ed839 2311\r
2312 //\r
2313 // Update current secure boot state.\r
2314 //\r
2315 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
2316 if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
2317 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
2318 } else {\r
2319 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
2320 }\r
2321 if (SecureBoot != NULL) {\r
2322 FreePool (SecureBoot);\r
2323 }\r
beda2356 2324 \r
bc0c99b3 2325 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
beda2356 2326 ConfigRequest = Request;\r
bc0c99b3 2327 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
2328 //\r
2329 // Request is set to NULL or OFFSET is NULL, construct full request string.\r
bc0c99b3 2330 //\r
2331 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
2332 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
2333 //\r
2334 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
2335 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
2336 ConfigRequest = AllocateZeroPool (Size);\r
2337 ASSERT (ConfigRequest != NULL);\r
2338 AllocatedRequest = TRUE;\r
2339 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
2340 FreePool (ConfigRequestHdr);\r
2341 ConfigRequestHdr = NULL;\r
2342 }\r
beda2356 2343\r
2344 Status = gHiiConfigRouting->BlockToConfig (\r
2345 gHiiConfigRouting,\r
2346 ConfigRequest,\r
2347 (UINT8 *) &Configuration,\r
2348 BufferSize,\r
2349 Results,\r
2350 Progress\r
2351 );\r
bc0c99b3 2352\r
2353 //\r
2354 // Free the allocated config request string.\r
2355 //\r
2356 if (AllocatedRequest) {\r
2357 FreePool (ConfigRequest);\r
2358 }\r
2359\r
beda2356 2360 //\r
2361 // Set Progress string to the original request string.\r
2362 //\r
2363 if (Request == NULL) {\r
2364 *Progress = NULL;\r
2365 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
2366 *Progress = Request + StrLen (Request);\r
2367 }\r
2368\r
2369 return Status;\r
2370}\r
2371\r
2372/**\r
2373 This function processes the results of changes in configuration.\r
2374\r
2375 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2376 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>\r
2377 format.\r
2378 @param[out] Progress A pointer to a string filled in with the offset of\r
2379 the most recent '&' before the first failing\r
2380 name/value pair (or the beginning of the string if\r
2381 the failure is in the first name/value pair) or\r
2382 the terminating NULL if all was successful.\r
2383\r
2384 @retval EFI_SUCCESS The Results is processed successfully.\r
2385 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
2386 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
2387 driver.\r
2388\r
2389**/\r
2390EFI_STATUS\r
2391EFIAPI\r
2392SecureBootRouteConfig (\r
2393 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2394 IN CONST EFI_STRING Configuration,\r
2395 OUT EFI_STRING *Progress\r
2396 )\r
2397{\r
a2f2c258 2398 UINT8 *SecureBootEnable;\r
2399 SECUREBOOT_CONFIGURATION IfrNvData;\r
2400 UINTN BufferSize;\r
2401 EFI_STATUS Status;\r
2402 \r
beda2356 2403 if (Configuration == NULL || Progress == NULL) {\r
2404 return EFI_INVALID_PARAMETER;\r
2405 }\r
2406\r
2407 *Progress = Configuration;\r
2408 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
2409 return EFI_NOT_FOUND;\r
2410 }\r
2411\r
a365eed4
FS
2412 //\r
2413 // Get Configuration from Variable.\r
2414 //\r
2415 SecureBootExtractConfigFromVariable (&IfrNvData);\r
2416\r
2417 //\r
2418 // Map the Configuration to the configuration block.\r
2419 //\r
a2f2c258 2420 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
2421 Status = gHiiConfigRouting->ConfigToBlock (\r
2422 gHiiConfigRouting,\r
2423 Configuration,\r
2424 (UINT8 *)&IfrNvData,\r
2425 &BufferSize,\r
2426 Progress\r
2427 );\r
2428 if (EFI_ERROR (Status)) {\r
2429 return Status;\r
2430 }\r
2431\r
2432 //\r
2433 // Store Buffer Storage back to EFI variable if needed\r
2434 //\r
2435 SecureBootEnable = NULL;\r
2436 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
2437 if (NULL != SecureBootEnable) {\r
2438 FreePool (SecureBootEnable);\r
2439 Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);\r
2440 if (EFI_ERROR (Status)) {\r
2441 return Status;\r
2442 }\r
2443 }\r
2444\r
ecc722ad 2445 *Progress = Configuration + StrLen (Configuration);\r
beda2356 2446 return EFI_SUCCESS;\r
2447}\r
2448\r
2449/**\r
ecc722ad 2450 This function is called to provide results data to the driver.\r
beda2356 2451\r
2452 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2453 @param[in] Action Specifies the type of action taken by the browser.\r
2454 @param[in] QuestionId A unique value which is sent to the original\r
2455 exporting driver so that it can identify the type\r
2456 of data to expect.\r
2457 @param[in] Type The type of value for the question.\r
2458 @param[in] Value A pointer to the data being sent to the original\r
2459 exporting driver.\r
2460 @param[out] ActionRequest On return, points to the action requested by the\r
2461 callback function.\r
2462\r
2463 @retval EFI_SUCCESS The callback successfully handled the action.\r
2464 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
2465 variable and its data.\r
2466 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
2467 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
2468 callback.\r
2469\r
2470**/\r
2471EFI_STATUS\r
2472EFIAPI\r
2473SecureBootCallback (\r
2474 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2475 IN EFI_BROWSER_ACTION Action,\r
2476 IN EFI_QUESTION_ID QuestionId,\r
2477 IN UINT8 Type,\r
2478 IN EFI_IFR_TYPE_VALUE *Value,\r
2479 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
2480 )\r
2481{\r
ecc722ad 2482 EFI_INPUT_KEY Key;\r
2483 EFI_STATUS Status; \r
2484 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;\r
2485 UINTN BufferSize;\r
2486 SECUREBOOT_CONFIGURATION *IfrNvData;\r
2487 UINT16 LabelId;\r
bf4a3dbd 2488 UINT8 *SecureBootEnable;\r
f71ed839 2489 UINT8 *SecureBootMode;\r
2490 UINT8 *SetupMode;\r
e4d7370d 2491 CHAR16 PromptString[100];\r
bf4a3dbd
ED
2492\r
2493 SecureBootEnable = NULL;\r
f71ed839 2494 SecureBootMode = NULL;\r
2495 SetupMode = NULL;\r
bc0c99b3 2496\r
beda2356 2497 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
2498 return EFI_INVALID_PARAMETER;\r
2499 }\r
2500\r
a365eed4
FS
2501 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
2502 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
2503 mIsEnterSecureBootForm = TRUE;\r
2504 }\r
2505\r
2506 return EFI_SUCCESS;\r
2507 }\r
2508 \r
2509 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
2510 Status = EFI_UNSUPPORTED;\r
2511 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
2512 if (mIsEnterSecureBootForm) {\r
2513 Value->u8 = SECURE_BOOT_MODE_STANDARD;\r
2514 Status = EFI_SUCCESS;\r
2515 }\r
2516 }\r
2517 return Status;\r
2518 }\r
2519 \r
f71ed839 2520 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
2521 (Action != EFI_BROWSER_ACTION_CHANGING) &&\r
a2f2c258 2522 (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&\r
2523 (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {\r
beda2356 2524 return EFI_UNSUPPORTED;\r
2525 }\r
ecc722ad 2526 \r
2527 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
bc0c99b3 2528\r
ecc722ad 2529 //\r
2530 // Retrieve uncommitted data from Browser\r
2531 //\r
2532 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
2533 IfrNvData = AllocateZeroPool (BufferSize);\r
2534 if (IfrNvData == NULL) {\r
2535 return EFI_OUT_OF_RESOURCES;\r
beda2356 2536 }\r
bc0c99b3 2537\r
ecc722ad 2538 Status = EFI_SUCCESS;\r
2539\r
742d9b3a 2540 HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
ecc722ad 2541 \r
2542 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2543\r
2544 switch (QuestionId) {\r
2545 case KEY_SECURE_BOOT_ENABLE:\r
f01b91ae 2546 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
bf4a3dbd 2547 if (NULL != SecureBootEnable) {\r
f71ed839 2548 FreePool (SecureBootEnable);\r
ecc722ad 2549 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {\r
2550 CreatePopUp (\r
2551 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2552 &Key,\r
2553 L"Only Physical Presence User could disable secure boot!",\r
2554 NULL\r
2555 );\r
2556 Status = EFI_UNSUPPORTED;\r
0357efe3 2557 } else {\r
2558 CreatePopUp (\r
2559 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2560 &Key,\r
f71ed839 2561 L"Configuration changed, please reset the platform to take effect!",\r
0357efe3 2562 NULL\r
2563 );\r
ecc722ad 2564 }\r
ecc722ad 2565 }\r
2566 break;\r
2567\r
2568 case KEY_SECURE_BOOT_OPTION:\r
2569 FreeMenu (&DirectoryMenu);\r
2570 FreeMenu (&FsOptionMenu);\r
2571 break;\r
2572\r
2573 case KEY_SECURE_BOOT_KEK_OPTION:\r
2574 case KEY_SECURE_BOOT_DB_OPTION:\r
2575 case KEY_SECURE_BOOT_DBX_OPTION:\r
2576 //\r
2577 // Clear Signature GUID.\r
2578 //\r
2579 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));\r
2580 if (Private->SignatureGUID == NULL) {\r
2581 Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
2582 if (Private->SignatureGUID == NULL) {\r
2583 return EFI_OUT_OF_RESOURCES;\r
2584 }\r
2585 }\r
beda2356 2586\r
ecc722ad 2587 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {\r
2588 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
2589 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {\r
2590 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
2591 } else {\r
2592 LabelId = FORMID_ENROLL_KEK_FORM;\r
2593 }\r
2594\r
2595 //\r
2596 // Refresh selected file.\r
2597 //\r
2598 CleanUpPage (LabelId, Private); \r
2599 break;\r
2600 \r
2601 case SECUREBOOT_ADD_PK_FILE_FORM_ID:\r
2602 case FORMID_ENROLL_KEK_FORM:\r
2603 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
2604 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
2605 if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {\r
2606 Private->FeCurrentState = FileExplorerStateEnrollPkFile;\r
2607 } else if (QuestionId == FORMID_ENROLL_KEK_FORM) {\r
2608 Private->FeCurrentState = FileExplorerStateEnrollKekFile;\r
2609 } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {\r
2610 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;\r
2611 } else {\r
2612 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;\r
2613 }\r
2614\r
2615 Private->FeDisplayContext = FileExplorerDisplayUnknown;\r
2616 CleanUpPage (FORM_FILE_EXPLORER_ID, Private);\r
2617 UpdateFileExplorer (Private, 0);\r
2618 break;\r
2619\r
2620 case KEY_SECURE_BOOT_DELETE_PK: \r
f71ed839 2621 if (Value->u8) {\r
2622 CreatePopUp (\r
2623 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2624 &Key,\r
2625 L"Are you sure you want to delete PK? Secure boot will be disabled!",\r
2626 L"Press 'Y' to delete PK and exit, 'N' to discard change and return",\r
2627 NULL\r
2628 );\r
2629 if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {\r
ecc722ad 2630 Status = DeletePlatformKey ();\r
f71ed839 2631 if (EFI_ERROR (Status)) {\r
2632 CreatePopUp (\r
2633 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2634 &Key,\r
2635 L"Only Physical Presence User could delete PK in custom mode!",\r
2636 NULL\r
2637 );\r
2638 }\r
ecc722ad 2639 }\r
f71ed839 2640 }\r
ecc722ad 2641 break;\r
2642\r
2643 case KEY_DELETE_KEK:\r
2644 UpdateDeletePage (\r
2645 Private, \r
2646 EFI_KEY_EXCHANGE_KEY_NAME,\r
2647 &gEfiGlobalVariableGuid,\r
2648 LABEL_KEK_DELETE,\r
2649 FORMID_DELETE_KEK_FORM,\r
2650 OPTION_DEL_KEK_QUESTION_ID \r
2651 );\r
2652 break;\r
2653\r
2654 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB: \r
2655 UpdateDeletePage (\r
2656 Private,\r
2657 EFI_IMAGE_SECURITY_DATABASE,\r
2658 &gEfiImageSecurityDatabaseGuid,\r
2659 LABEL_DB_DELETE,\r
2660 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
2661 OPTION_DEL_DB_QUESTION_ID\r
2662 );\r
2663 break;\r
2664\r
2665 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:\r
2666 UpdateDeletePage (\r
2667 Private,\r
2668 EFI_IMAGE_SECURITY_DATABASE1,\r
2669 &gEfiImageSecurityDatabaseGuid,\r
2670 LABEL_DBX_DELETE,\r
2671 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
2672 OPTION_DEL_DBX_QUESTION_ID\r
2673 );\r
2674\r
2675 break;\r
2676\r
2677 case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
2678 Status = EnrollKeyExchangeKey (Private);\r
ee79ac8d 2679 if (EFI_ERROR (Status)) {\r
2680 CreatePopUp (\r
2681 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2682 &Key,\r
2683 L"ERROR: Unsupported file type!",\r
2684 L"Only supports DER-encoded X509 certificate",\r
2685 NULL\r
2686 );\r
2687 }\r
ecc722ad 2688 break;\r
2689\r
2690 case KEY_VALUE_SAVE_AND_EXIT_DB:\r
2691 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
ee79ac8d 2692 if (EFI_ERROR (Status)) {\r
2693 CreatePopUp (\r
2694 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2695 &Key,\r
2696 L"ERROR: Unsupported file type!",\r
2697 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
2698 NULL\r
2699 );\r
2700 }\r
ecc722ad 2701 break;\r
2702\r
2703 case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
2704 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
ee79ac8d 2705 if (EFI_ERROR (Status)) {\r
2706 CreatePopUp (\r
2707 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2708 &Key,\r
2709 L"ERROR: Unsupported file type!",\r
2710 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
2711 NULL\r
2712 );\r
2713 }\r
ecc722ad 2714 break;\r
2715\r
2716 default:\r
2717 if (QuestionId >= FILE_OPTION_OFFSET) {\r
2718 UpdateFileExplorer (Private, QuestionId);\r
2719 } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
2720 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
2721 DeleteKeyExchangeKey (Private, QuestionId);\r
2722 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&\r
2723 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
2724 DeleteSignature (\r
2725 Private,\r
2726 EFI_IMAGE_SECURITY_DATABASE,\r
2727 &gEfiImageSecurityDatabaseGuid,\r
2728 LABEL_DB_DELETE, \r
2729 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
2730 OPTION_DEL_DB_QUESTION_ID,\r
2731 QuestionId - OPTION_DEL_DB_QUESTION_ID\r
2732 );\r
2733 } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&\r
2734 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
2735 DeleteSignature (\r
2736 Private,\r
2737 EFI_IMAGE_SECURITY_DATABASE1,\r
2738 &gEfiImageSecurityDatabaseGuid,\r
2739 LABEL_DBX_DELETE, \r
2740 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
2741 OPTION_DEL_DBX_QUESTION_ID,\r
2742 QuestionId - OPTION_DEL_DBX_QUESTION_ID\r
2743 );\r
2744 }\r
2745 break;\r
2746 }\r
2747 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2748 switch (QuestionId) {\r
2749 case KEY_SECURE_BOOT_ENABLE:\r
f71ed839 2750 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
ecc722ad 2751 break; \r
2752 case KEY_VALUE_SAVE_AND_EXIT_PK:\r
2753 Status = EnrollPlatformKey (Private);\r
2754 if (EFI_ERROR (Status)) {\r
ee79ac8d 2755 UnicodeSPrint (\r
2756 PromptString,\r
2757 sizeof (PromptString),\r
2758 L"Only DER encoded certificate file (%s) is supported.",\r
2759 mSupportX509Suffix\r
2760 );\r
ecc722ad 2761 CreatePopUp (\r
2762 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2763 &Key,\r
e4d7370d 2764 L"ERROR: Unsupported file type!",\r
2765 PromptString,\r
ecc722ad 2766 NULL\r
2767 );\r
2768 } else {\r
0fb450fb 2769 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; \r
ecc722ad 2770 } \r
2771 break;\r
2772\r
2773 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
2774 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
2775 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
2776 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
2777 if (Private->FileContext->FHandle != NULL) {\r
2778 CloseFile (Private->FileContext->FHandle);\r
2779 Private->FileContext->FHandle = NULL;\r
2780 Private->FileContext->FileName = NULL;\r
2781 }\r
2782 \r
2783 if (Private->SignatureGUID != NULL) {\r
2784 FreePool (Private->SignatureGUID);\r
2785 Private->SignatureGUID = NULL;\r
2786 }\r
2787 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
2788 break;\r
2789 \r
2790 case KEY_SECURE_BOOT_MODE:\r
a365eed4 2791 mIsEnterSecureBootForm = FALSE;\r
ecc722ad 2792 break;\r
2793\r
2794 case KEY_SECURE_BOOT_KEK_GUID:\r
2795 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
2796 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
2797 ASSERT (Private->SignatureGUID != NULL);\r
2798 Status = StringToGuid (\r
2799 IfrNvData->SignatureGuid,\r
2800 StrLen (IfrNvData->SignatureGuid),\r
2801 Private->SignatureGUID\r
2802 );\r
2803 if (EFI_ERROR (Status)) {\r
2804 break;\r
2805 }\r
2806\r
2807 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2808 break;\r
2809\r
2810 case KEY_SECURE_BOOT_DELETE_PK:\r
f71ed839 2811 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
2812 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
2813 IfrNvData->DeletePk = TRUE;\r
2814 IfrNvData->HasPk = FALSE;\r
ecc722ad 2815 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
f71ed839 2816 } else {\r
2817 IfrNvData->DeletePk = FALSE;\r
2818 IfrNvData->HasPk = TRUE;\r
2819 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2820 }\r
2821 if (SetupMode != NULL) {\r
2822 FreePool (SetupMode);\r
ecc722ad 2823 }\r
2824 break; \r
2825 }\r
a2f2c258 2826 } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {\r
2827 if (QuestionId == KEY_HIDE_SECURE_BOOT) {\r
2828 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
2829 if (SecureBootEnable == NULL) {\r
2830 IfrNvData->HideSecureBoot = TRUE;\r
2831 } else {\r
2832 FreePool (SecureBootEnable);\r
2833 IfrNvData->HideSecureBoot = FALSE;\r
2834 }\r
2835 Value->b = IfrNvData->HideSecureBoot;\r
2836 }\r
f71ed839 2837 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
2838 //\r
2839 // Force the platform back to Standard Mode once user leave the setup screen.\r
2840 //\r
2841 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
2842 if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {\r
2843 IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
2844 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);\r
2845 }\r
2846 if (SecureBootMode != NULL) {\r
2847 FreePool (SecureBootMode);\r
2848 }\r
ecc722ad 2849 }\r
2850 \r
2851 if (!EFI_ERROR (Status)) {\r
2852 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
742d9b3a 2853 HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
ecc722ad 2854 }\r
2855 FreePool (IfrNvData);\r
2856 \r
2857 return EFI_SUCCESS;\r
beda2356 2858}\r
2859\r
2860/**\r
2861 This function publish the SecureBoot configuration Form.\r
2862\r
2863 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
2864\r
ecc722ad 2865 @retval EFI_SUCCESS HII Form is installed successfully.\r
beda2356 2866 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.\r
2867 @retval Others Other errors as indicated.\r
2868\r
2869**/\r
2870EFI_STATUS\r
2871InstallSecureBootConfigForm (\r
2872 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
2873 )\r
2874{\r
2875 EFI_STATUS Status;\r
2876 EFI_HII_HANDLE HiiHandle;\r
2877 EFI_HANDLE DriverHandle;\r
beda2356 2878 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2879\r
2880 DriverHandle = NULL;\r
2881 ConfigAccess = &PrivateData->ConfigAccess;\r
2882 Status = gBS->InstallMultipleProtocolInterfaces (\r
2883 &DriverHandle,\r
2884 &gEfiDevicePathProtocolGuid,\r
2885 &mSecureBootHiiVendorDevicePath,\r
2886 &gEfiHiiConfigAccessProtocolGuid,\r
2887 ConfigAccess,\r
2888 NULL\r
2889 );\r
2890 if (EFI_ERROR (Status)) {\r
2891 return Status;\r
2892 }\r
2893\r
2894 PrivateData->DriverHandle = DriverHandle;\r
2895\r
2896 //\r
2897 // Publish the HII package list\r
2898 //\r
2899 HiiHandle = HiiAddPackages (\r
2900 &gSecureBootConfigFormSetGuid,\r
2901 DriverHandle,\r
2902 SecureBootConfigDxeStrings,\r
2903 SecureBootConfigBin,\r
2904 NULL\r
2905 );\r
2906 if (HiiHandle == NULL) {\r
2907 gBS->UninstallMultipleProtocolInterfaces (\r
2908 DriverHandle,\r
2909 &gEfiDevicePathProtocolGuid,\r
2910 &mSecureBootHiiVendorDevicePath,\r
2911 &gEfiHiiConfigAccessProtocolGuid,\r
2912 ConfigAccess,\r
2913 NULL\r
bc0c99b3 2914 );\r
beda2356 2915 return EFI_OUT_OF_RESOURCES;\r
2916 }\r
bc0c99b3 2917\r
beda2356 2918 PrivateData->HiiHandle = HiiHandle;\r
ecc722ad 2919\r
2920 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
2921 PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));\r
2922 \r
2923 if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) {\r
2924 UninstallSecureBootConfigForm (PrivateData);\r
2925 return EFI_OUT_OF_RESOURCES;\r
2926 }\r
2927 \r
2928 PrivateData->FeCurrentState = FileExplorerStateInActive;\r
2929 PrivateData->FeDisplayContext = FileExplorerDisplayUnknown;\r
2930 \r
2931 InitializeListHead (&FsOptionMenu.Head);\r
2932 InitializeListHead (&DirectoryMenu.Head);\r
2933\r
2934 //\r
2935 // Init OpCode Handle and Allocate space for creation of Buffer\r
2936 //\r
2937 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2938 if (mStartOpCodeHandle == NULL) {\r
2939 UninstallSecureBootConfigForm (PrivateData);\r
2940 return EFI_OUT_OF_RESOURCES;\r
2941 }\r
2942\r
2943 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2944 if (mEndOpCodeHandle == NULL) {\r
2945 UninstallSecureBootConfigForm (PrivateData);\r
2946 return EFI_OUT_OF_RESOURCES;\r
2947 }\r
2948\r
2949 //\r
2950 // Create Hii Extend Label OpCode as the start opcode\r
2951 //\r
2952 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2953 mStartOpCodeHandle,\r
2954 &gEfiIfrTianoGuid,\r
2955 NULL,\r
2956 sizeof (EFI_IFR_GUID_LABEL)\r
2957 );\r
2958 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2959\r
2960 //\r
2961 // Create Hii Extend Label OpCode as the end opcode\r
2962 //\r
2963 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2964 mEndOpCodeHandle,\r
2965 &gEfiIfrTianoGuid,\r
2966 NULL,\r
2967 sizeof (EFI_IFR_GUID_LABEL)\r
2968 );\r
2969 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2970 mEndLabel->Number = LABEL_END;\r
2971 \r
bc0c99b3 2972 return EFI_SUCCESS;\r
beda2356 2973}\r
2974\r
2975/**\r
2976 This function removes SecureBoot configuration Form.\r
2977\r
2978 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
2979\r
2980**/\r
2981VOID\r
2982UninstallSecureBootConfigForm (\r
2983 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
2984 )\r
2985{\r
2986 //\r
2987 // Uninstall HII package list\r
2988 //\r
2989 if (PrivateData->HiiHandle != NULL) {\r
2990 HiiRemovePackages (PrivateData->HiiHandle);\r
2991 PrivateData->HiiHandle = NULL;\r
2992 }\r
2993\r
2994 //\r
2995 // Uninstall HII Config Access Protocol\r
2996 //\r
2997 if (PrivateData->DriverHandle != NULL) {\r
2998 gBS->UninstallMultipleProtocolInterfaces (\r
2999 PrivateData->DriverHandle,\r
3000 &gEfiDevicePathProtocolGuid,\r
3001 &mSecureBootHiiVendorDevicePath,\r
3002 &gEfiHiiConfigAccessProtocolGuid,\r
3003 &PrivateData->ConfigAccess,\r
3004 NULL\r
3005 );\r
3006 PrivateData->DriverHandle = NULL;\r
3007 }\r
bc0c99b3 3008\r
ecc722ad 3009 if (PrivateData->SignatureGUID != NULL) {\r
3010 FreePool (PrivateData->SignatureGUID);\r
3011 }\r
3012\r
3013 if (PrivateData->MenuEntry != NULL) {\r
3014 FreePool (PrivateData->MenuEntry);\r
3015 }\r
3016\r
3017 if (PrivateData->FileContext != NULL) {\r
3018 FreePool (PrivateData->FileContext);\r
3019 }\r
3020\r
beda2356 3021 FreePool (PrivateData);\r
ecc722ad 3022\r
3023 FreeMenu (&DirectoryMenu);\r
3024 FreeMenu (&FsOptionMenu);\r
3025\r
3026 if (mStartOpCodeHandle != NULL) {\r
3027 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
3028 }\r
3029\r
3030 if (mEndOpCodeHandle != NULL) {\r
3031 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
3032 }\r
beda2356 3033}\r