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