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