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