]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
Add more security check for CommBuffer+CommBufferSize.
[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
cf7409f2 350 // Parse the file's postfix. Only support DER encoded X.509 certificate files (*.cer or *.der).\r
ecc722ad 351 //\r
352 FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
cf7409f2 353 if ((CompareMem (FilePostFix, L".cer",4) != 0) && (CompareMem (FilePostFix, L".der",4) != 0)) {\r
354 DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate file (*.cer or *.der) 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
de2447dd 1019 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1020 //\r
1021 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
1022 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
1023 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1024 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1025 //\r
1026 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
1027 } else {\r
1028 //\r
1029 // Get the magic value from the PE/COFF Optional Header\r
1030 //\r
1031 Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
1032 }\r
1033 \r
ecc722ad 1034 //\r
1035 // 3. Calculate the distance from the base of the image header to the image checksum address.\r
1036 // 4. Hash the image header from its base to beginning of the image checksum.\r
1037 //\r
1038 HashBase = mImageBase;\r
1039 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1040 //\r
1041 // Use PE32 offset.\r
1042 //\r
1043 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
1044 } else {\r
1045 //\r
1046 // Use PE32+ offset.\r
1047 //\r
1048 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
1049 }\r
1050\r
1051 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1052 if (!Status) {\r
1053 goto Done;\r
1054 }\r
1055 //\r
1056 // 5. Skip over the image checksum (it occupies a single ULONG).\r
1057 // 6. Get the address of the beginning of the Cert Directory.\r
1058 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
1059 //\r
1060 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1061 //\r
1062 // Use PE32 offset.\r
1063 //\r
1064 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
1065 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1066 } else {\r
1067 //\r
1068 // Use PE32+ offset.\r
1069 // \r
1070 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
1071 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1072 }\r
1073\r
1074 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1075 if (!Status) {\r
1076 goto Done;\r
1077 }\r
1078 //\r
1079 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
1080 // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
1081 //\r
1082 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1083 //\r
1084 // Use PE32 offset\r
1085 //\r
1086 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1087 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1088 } else {\r
1089 //\r
1090 // Use PE32+ offset.\r
1091 //\r
1092 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1093 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1094 }\r
1095\r
1096 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1097 if (!Status) {\r
1098 goto Done;\r
1099 }\r
1100 //\r
1101 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
1102 //\r
1103 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1104 //\r
1105 // Use PE32 offset.\r
1106 //\r
1107 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
1108 } else {\r
1109 //\r
1110 // Use PE32+ offset\r
1111 //\r
1112 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
1113 }\r
1114\r
1115 //\r
1116 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
1117 // structures in the image. The 'NumberOfSections' field of the image\r
1118 // header indicates how big the table should be. Do not include any\r
1119 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
1120 //\r
1121 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
1122 ASSERT (SectionHeader != NULL);\r
1123 //\r
1124 // 12. Using the 'PointerToRawData' in the referenced section headers as\r
1125 // a key, arrange the elements in the table in ascending order. In other\r
1126 // words, sort the section headers according to the disk-file offset of\r
1127 // the section.\r
1128 //\r
1129 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1130 mImageBase +\r
1131 mPeCoffHeaderOffset +\r
1132 sizeof (UINT32) +\r
1133 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1134 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
1135 );\r
1136 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1137 Pos = Index;\r
1138 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
1139 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
1140 Pos--;\r
1141 }\r
1142 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
1143 Section += 1;\r
1144 }\r
1145\r
1146 //\r
1147 // 13. Walk through the sorted table, bring the corresponding section\r
1148 // into memory, and hash the entire section (using the 'SizeOfRawData'\r
1149 // field in the section header to determine the amount of data to hash).\r
1150 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
1151 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.\r
1152 //\r
1153 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1154 Section = &SectionHeader[Index];\r
1155 if (Section->SizeOfRawData == 0) {\r
1156 continue;\r
1157 }\r
1158 HashBase = mImageBase + Section->PointerToRawData;\r
1159 HashSize = (UINTN) Section->SizeOfRawData;\r
1160\r
1161 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1162 if (!Status) {\r
1163 goto Done;\r
1164 }\r
1165\r
1166 SumOfBytesHashed += HashSize;\r
1167 }\r
1168\r
1169 //\r
1170 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
1171 // data in the file that needs to be added to the hash. This data begins\r
1172 // at file offset SUM_OF_BYTES_HASHED and its length is:\r
1173 // FileSize - (CertDirectory->Size)\r
1174 //\r
1175 if (mImageSize > SumOfBytesHashed) {\r
1176 HashBase = mImageBase + SumOfBytesHashed;\r
1177 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1178 //\r
1179 // Use PE32 offset.\r
1180 //\r
1181 HashSize = (UINTN)(\r
1182 mImageSize -\r
1183 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
1184 SumOfBytesHashed);\r
1185 } else {\r
1186 //\r
1187 // Use PE32+ offset.\r
1188 //\r
1189 HashSize = (UINTN)(\r
1190 mImageSize -\r
1191 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
1192 SumOfBytesHashed); \r
1193 }\r
1194\r
1195 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1196 if (!Status) {\r
1197 goto Done;\r
1198 }\r
1199 }\r
1200\r
1201 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
1202\r
1203Done:\r
1204 if (HashCtx != NULL) {\r
1205 FreePool (HashCtx);\r
1206 }\r
1207 if (SectionHeader != NULL) {\r
1208 FreePool (SectionHeader);\r
1209 }\r
1210 return Status;\r
1211}\r
1212\r
1213/**\r
1214 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of \r
1215 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification \r
1216 8.0 Appendix A\r
1217\r
1218 @retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
1219 @retval EFI_SUCCESS Hash successfully.\r
1220\r
1221**/\r
1222EFI_STATUS \r
1223HashPeImageByType (\r
1224 VOID\r
1225 )\r
1226{\r
1227 UINT8 Index;\r
1228 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
1229\r
1230 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
1231\r
1232 for (Index = 0; Index < HASHALG_MAX; Index++) { \r
1233 //\r
1234 // Check the Hash algorithm in PE/COFF Authenticode.\r
1235 // According to PKCS#7 Definition: \r
1236 // SignedData ::= SEQUENCE {\r
1237 // version Version,\r
1238 // digestAlgorithms DigestAlgorithmIdentifiers,\r
1239 // contentInfo ContentInfo,\r
1240 // .... }\r
1241 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
1242 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
1243 // Fixed offset (+32) is calculated based on two bytes of length encoding.\r
1244 //\r
1245 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
1246 //\r
1247 // Only support two bytes of Long Form of Length Encoding.\r
1248 //\r
1249 continue;\r
1250 }\r
1251\r
1252 // \r
1253 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
1254 break;\r
1255 }\r
1256 }\r
1257\r
1258 if (Index == HASHALG_MAX) {\r
1259 return EFI_UNSUPPORTED;\r
1260 }\r
1261\r
1262 //\r
1263 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
1264 //\r
1265 if (!HashPeImage(Index)) {\r
1266 return EFI_UNSUPPORTED;\r
1267 }\r
1268\r
1269 return EFI_SUCCESS;\r
1270}\r
1271\r
1272/**\r
1273 Enroll a new executable's signature into Signature Database. \r
1274\r
1275 @param[in] PrivateData The module's private data.\r
1276 @param[in] VariableName Variable name of signature database, must be \r
1277 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
1278\r
1279 @retval EFI_SUCCESS New signature is enrolled successfully.\r
1280 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1281 @retval EFI_UNSUPPORTED Unsupported command.\r
1282 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
1283\r
1284**/\r
1285EFI_STATUS\r
1286EnrollImageSignatureToSigDB (\r
1287 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1288 IN CHAR16 *VariableName\r
1289 )\r
1290{\r
1291 EFI_STATUS Status;\r
1292 EFI_SIGNATURE_LIST *SigDBCert;\r
1293 EFI_SIGNATURE_DATA *SigDBCertData;\r
1294 VOID *Data;\r
1295 UINTN DataSize;\r
1296 UINTN SigDBSize;\r
1297 UINT32 Attr;\r
1298 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;\r
1299\r
1300 Data = NULL;\r
1301 GuidCertData = NULL;\r
ecc722ad 1302\r
1303 //\r
1304 // Form the SigDB certificate list.\r
1305 // Format the data item into EFI_SIGNATURE_LIST type.\r
1306 //\r
1307 // We need to parse executable's signature data from specified signed executable file.\r
1308 // In current implementation, we simply trust the pass-in signed executable file.\r
1309 // In reality, it's OS's responsibility to verify the signed executable file.\r
1310 //\r
1311\r
1312 //\r
1313 // Read the whole file content\r
1314 //\r
1315 Status = ReadFileContent(\r
1316 Private->FileContext->FHandle,\r
1317 (VOID **) &mImageBase, \r
1318 &mImageSize, \r
1319 0\r
1320 );\r
1321 if (EFI_ERROR (Status)) {\r
1322 goto ON_EXIT;\r
1323 } \r
ba57d4fd 1324 ASSERT (mImageBase != NULL);\r
ecc722ad 1325\r
1326 Status = LoadPeImage ();\r
1327 if (EFI_ERROR (Status)) {\r
1328 goto ON_EXIT;\r
1329 }\r
1330\r
1331 if (mSecDataDir->SizeOfCert == 0) {\r
1332 if (!HashPeImage (HASHALG_SHA256)) {\r
1333 Status = EFI_SECURITY_VIOLATION;\r
1334 goto ON_EXIT;\r
1335 }\r
1336 } else {\r
1337 \r
1338 //\r
1339 // Read the certificate data\r
1340 //\r
1341 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
1342\r
1343 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
1344 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
1345 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
1346 Status = EFI_ABORTED;\r
1347 goto ON_EXIT;\r
1348 }\r
1349\r
1350 if (!HashPeImage (HASHALG_SHA256)) {\r
1351 Status = EFI_ABORTED;\r
1352 goto ON_EXIT;;\r
1353 }\r
1354 \r
1355 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
1356\r
1357 Status = HashPeImageByType ();\r
1358 if (EFI_ERROR (Status)) {\r
1359 goto ON_EXIT;;\r
1360 }\r
1361 } else {\r
1362 Status = EFI_ABORTED;\r
1363 goto ON_EXIT;\r
1364 }\r
1365 }\r
1366\r
1367 //\r
1368 // Create a new SigDB entry.\r
1369 //\r
1370 SigDBSize = sizeof(EFI_SIGNATURE_LIST) \r
1371 + sizeof(EFI_SIGNATURE_DATA) - 1\r
1372 + (UINT32) mImageDigestSize;\r
1373\r
1374 Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
1375 if (Data == NULL) {\r
1376 Status = EFI_OUT_OF_RESOURCES;\r
1377 goto ON_EXIT;\r
1378 }\r
1379 \r
1380 //\r
1381 // Adjust the Certificate Database parameters.\r
1382 // \r
1383 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
1384 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
1385 SigDBCert->SignatureHeaderSize = 0;\r
1386 SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
1387 CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
1388\r
1389 SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
1390 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
1391 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
1392\r
8c1babfd 1393 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
1394 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
1395 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
1396 if (EFI_ERROR (Status)) {\r
1397 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
1398 goto ON_EXIT;\r
1399 }\r
1400 \r
ecc722ad 1401 //\r
1402 // Check if SigDB variable has been already existed. \r
1403 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
1404 // new signature data to original variable\r
1405 // \r
1406 DataSize = 0;\r
1407 Status = gRT->GetVariable(\r
1408 VariableName, \r
1409 &gEfiImageSecurityDatabaseGuid, \r
1410 NULL, \r
1411 &DataSize, \r
1412 NULL\r
1413 );\r
1414 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1415 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
1416 } else if (Status != EFI_NOT_FOUND) {\r
1417 goto ON_EXIT;\r
1418 } \r
1419\r
1420 //\r
1421 // Enroll the variable.\r
1422 //\r
1423 Status = gRT->SetVariable(\r
1424 VariableName, \r
1425 &gEfiImageSecurityDatabaseGuid, \r
1426 Attr, \r
1427 SigDBSize, \r
1428 Data\r
1429 );\r
1430 if (EFI_ERROR (Status)) {\r
1431 goto ON_EXIT;\r
1432 }\r
1433\r
1434ON_EXIT:\r
1435\r
1436 CloseFile (Private->FileContext->FHandle);\r
1437 Private->FileContext->FHandle = NULL;\r
1438 Private->FileContext->FileName = NULL;\r
1439\r
1440 if (Private->SignatureGUID != NULL) {\r
1441 FreePool (Private->SignatureGUID);\r
1442 Private->SignatureGUID = NULL;\r
1443 }\r
1444\r
1445 if (Data != NULL) {\r
1446 FreePool (Data);\r
1447 }\r
1448\r
1449 if (mImageBase != NULL) {\r
1450 FreePool (mImageBase);\r
1451 mImageBase = NULL;\r
1452 }\r
1453\r
1454 return Status;\r
1455}\r
1456\r
1457/**\r
1458 Enroll signature into DB/DBX without KEK's authentication.\r
1459 The SignatureOwner GUID will be Private->SignatureGUID.\r
1460 \r
1461 @param[in] PrivateData The module's private data.\r
1462 @param[in] VariableName Variable name of signature database, must be \r
1463 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
1464 \r
1465 @retval EFI_SUCCESS New signature enrolled successfully.\r
1466 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1467 @retval others Fail to enroll signature data.\r
1468 \r
1469**/\r
1470EFI_STATUS\r
1471EnrollSignatureDatabase (\r
1472 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1473 IN CHAR16 *VariableName\r
1474 ) \r
1475{\r
1476 UINT16* FilePostFix;\r
1477\r
1478 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
1479 return EFI_INVALID_PARAMETER;\r
1480 }\r
1481\r
1482 //\r
1483 // Parse the file's postfix. \r
1484 //\r
1485 FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
1486 if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {\r
1487 //\r
1488 // Supports .cer and .der file as X509 certificate.\r
1489 //\r
1490 return EnrollX509toSigDB (Private, VariableName);\r
1491 }\r
1492\r
1493 return EnrollImageSignatureToSigDB (Private, VariableName);\r
1494}\r
1495\r
1496/**\r
1497 List all signatures in specified signature database (e.g. KEK/DB/DBX)\r
1498 by GUID in the page for user to select and delete as needed.\r
1499\r
1500 @param[in] PrivateData Module's private data.\r
1501 @param[in] VariableName The variable name of the vendor's signature database.\r
1502 @param[in] VendorGuid A unique identifier for the vendor.\r
1503 @param[in] LabelNumber Label number to insert opcodes.\r
1504 @param[in] FormId Form ID of current page.\r
1505 @param[in] QuestionIdBase Base question id of the signature list.\r
1506\r
1507 @retval EFI_SUCCESS Success to update the signature list page\r
1508 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
1509 \r
1510**/\r
1511EFI_STATUS\r
1512UpdateDeletePage (\r
1513 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
1514 IN CHAR16 *VariableName,\r
1515 IN EFI_GUID *VendorGuid,\r
1516 IN UINT16 LabelNumber,\r
1517 IN EFI_FORM_ID FormId,\r
1518 IN EFI_QUESTION_ID QuestionIdBase\r
1519 )\r
1520{\r
1521 EFI_STATUS Status;\r
1522 UINT32 Index;\r
1523 UINTN CertCount;\r
1524 UINTN GuidIndex;\r
1525 VOID *StartOpCodeHandle;\r
1526 VOID *EndOpCodeHandle;\r
1527 EFI_IFR_GUID_LABEL *StartLabel;\r
1528 EFI_IFR_GUID_LABEL *EndLabel; \r
1529 UINTN DataSize;\r
1530 UINT8 *Data;\r
1531 EFI_SIGNATURE_LIST *CertList;\r
1532 EFI_SIGNATURE_DATA *Cert;\r
1533 UINT32 ItemDataSize;\r
1534 CHAR16 *GuidStr;\r
1535 EFI_STRING_ID GuidID;\r
1536 EFI_STRING_ID Help;\r
1537\r
1538 Data = NULL;\r
1539 CertList = NULL;\r
1540 Cert = NULL;\r
1541 GuidStr = NULL;\r
1542 StartOpCodeHandle = NULL;\r
1543 EndOpCodeHandle = NULL;\r
1544 \r
1545 //\r
1546 // Initialize the container for dynamic opcodes.\r
1547 //\r
1548 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1549 if (StartOpCodeHandle == NULL) {\r
1550 Status = EFI_OUT_OF_RESOURCES;\r
1551 goto ON_EXIT; \r
1552 }\r
1553\r
1554 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1555 if (EndOpCodeHandle == NULL) {\r
1556 Status = EFI_OUT_OF_RESOURCES;\r
1557 goto ON_EXIT; \r
1558 }\r
1559\r
1560 //\r
1561 // Create Hii Extend Label OpCode.\r
1562 //\r
1563 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
1564 StartOpCodeHandle,\r
1565 &gEfiIfrTianoGuid,\r
1566 NULL,\r
1567 sizeof (EFI_IFR_GUID_LABEL)\r
1568 );\r
1569 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1570 StartLabel->Number = LabelNumber;\r
1571\r
1572 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
1573 EndOpCodeHandle,\r
1574 &gEfiIfrTianoGuid,\r
1575 NULL,\r
1576 sizeof (EFI_IFR_GUID_LABEL)\r
1577 );\r
1578 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1579 EndLabel->Number = LABEL_END;\r
1580\r
1581 //\r
1582 // Read Variable.\r
1583 //\r
1584 DataSize = 0;\r
1585 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); \r
1586 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
1587 goto ON_EXIT;\r
1588 }\r
1589\r
1590 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1591 if (Data == NULL) {\r
1592 Status = EFI_OUT_OF_RESOURCES;\r
1593 goto ON_EXIT;\r
1594 }\r
1595\r
1596 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
1597 if (EFI_ERROR (Status)) {\r
1598 goto ON_EXIT;\r
1599 }\r
1600\r
1601 GuidStr = AllocateZeroPool (100);\r
1602 if (GuidStr == NULL) {\r
1603 Status = EFI_OUT_OF_RESOURCES;\r
1604 goto ON_EXIT;\r
1605 }\r
1606\r
1607 //\r
1608 // Enumerate all KEK pub data.\r
1609 //\r
1610 ItemDataSize = (UINT32) DataSize;\r
1611 CertList = (EFI_SIGNATURE_LIST *) Data;\r
1612 GuidIndex = 0;\r
1613\r
1614 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
1615\r
1616 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
1617 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
1618 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
1619 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
1620 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
1621 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
1622 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
1623 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
1624 } else {\r
1625 //\r
1626 // The signature type is not supported in current implementation.\r
1627 //\r
1628 continue;\r
1629 }\r
1630\r
1631 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1632 for (Index = 0; Index < CertCount; Index++) {\r
1633 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList \r
1634 + sizeof (EFI_SIGNATURE_LIST) \r
1635 + CertList->SignatureHeaderSize \r
1636 + Index * CertList->SignatureSize);\r
1637 //\r
1638 // Display GUID and help \r
1639 //\r
1640 GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
1641 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
1642 HiiCreateCheckBoxOpCode (\r
1643 StartOpCodeHandle,\r
1644 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
1645 0, \r
1646 0, \r
1647 GuidID, \r
1648 Help,\r
1649 EFI_IFR_FLAG_CALLBACK,\r
1650 0,\r
1651 NULL\r
1652 ); \r
1653 }\r
1654\r
1655 ItemDataSize -= CertList->SignatureListSize;\r
1656 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1657 }\r
1658\r
1659ON_EXIT:\r
1660 HiiUpdateForm (\r
1661 PrivateData->HiiHandle,\r
1662 &gSecureBootConfigFormSetGuid,\r
1663 FormId,\r
1664 StartOpCodeHandle,\r
1665 EndOpCodeHandle\r
1666 );\r
1667\r
1668 if (StartOpCodeHandle != NULL) {\r
1669 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1670 }\r
1671\r
1672 if (EndOpCodeHandle != NULL) {\r
1673 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1674 }\r
1675 \r
1676 if (Data != NULL) {\r
1677 FreePool (Data);\r
1678 }\r
1679\r
1680 if (GuidStr != NULL) {\r
1681 FreePool (GuidStr);\r
1682 }\r
1683\r
1684 return EFI_SUCCESS;\r
1685}\r
1686\r
beda2356 1687/**\r
ecc722ad 1688 Delete a KEK entry from KEK database. \r
beda2356 1689\r
ecc722ad 1690 @param[in] PrivateData Module's private data.\r
1691 @param[in] QuestionId Question id of the KEK item to delete.\r
beda2356 1692\r
ecc722ad 1693 @retval EFI_SUCCESS Delete kek item successfully.\r
1694 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
1695 \r
1696**/\r
1697EFI_STATUS\r
1698DeleteKeyExchangeKey (\r
1699 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
1700 IN EFI_QUESTION_ID QuestionId\r
1701 )\r
1702{\r
1703 EFI_STATUS Status;\r
1704 UINTN DataSize;\r
1705 UINT8 *Data;\r
1706 UINT8 *OldData;\r
1707 UINT32 Attr;\r
1708 UINT32 Index;\r
1709 EFI_SIGNATURE_LIST *CertList;\r
1710 EFI_SIGNATURE_LIST *NewCertList;\r
1711 EFI_SIGNATURE_DATA *Cert;\r
1712 UINTN CertCount;\r
1713 UINT32 Offset;\r
1714 BOOLEAN IsKEKItemFound;\r
1715 UINT32 KekDataSize;\r
1716 UINTN DeleteKekIndex;\r
1717 UINTN GuidIndex;\r
1718\r
1719 Data = NULL;\r
1720 OldData = NULL;\r
1721 CertList = NULL;\r
1722 Cert = NULL;\r
1723 Attr = 0; \r
1724 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
1725 \r
1726 //\r
1727 // Get original KEK variable.\r
1728 // \r
1729 DataSize = 0; \r
1730 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
1731 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
1732 goto ON_EXIT;\r
1733 }\r
1734\r
1735 OldData = (UINT8*)AllocateZeroPool(DataSize);\r
1736 if (OldData == NULL) {\r
1737 Status = EFI_OUT_OF_RESOURCES; \r
1738 goto ON_EXIT;\r
1739 }\r
1740\r
1741 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
1742 if (EFI_ERROR(Status)) {\r
1743 goto ON_EXIT;\r
1744 }\r
1745\r
1746 //\r
1747 // Allocate space for new variable. \r
1748 //\r
1749 Data = (UINT8*) AllocateZeroPool (DataSize);\r
1750 if (Data == NULL) {\r
1751 Status = EFI_OUT_OF_RESOURCES;\r
1752 goto ON_EXIT;\r
1753 }\r
1754\r
1755 //\r
1756 // Enumerate all KEK pub data and erasing the target item.\r
1757 //\r
1758 IsKEKItemFound = FALSE;\r
1759 KekDataSize = (UINT32) DataSize;\r
1760 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
1761 Offset = 0;\r
1762 GuidIndex = 0;\r
1763 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
1764 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
1765 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
1766 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
1767 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
1768 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1769 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1770 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1771 for (Index = 0; Index < CertCount; Index++) {\r
1772 if (GuidIndex == DeleteKekIndex ) {\r
1773 //\r
1774 // Find it! Skip it!\r
1775 //\r
1776 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
1777 IsKEKItemFound = TRUE; \r
1778 } else {\r
1779 //\r
1780 // This item doesn't match. Copy it to the Data buffer.\r
1781 //\r
1782 CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
1783 Offset += CertList->SignatureSize;\r
1784 }\r
1785 GuidIndex++;\r
1786 Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
1787 }\r
1788 } else {\r
1789 //\r
1790 // This List doesn't match. Copy it to the Data buffer.\r
1791 //\r
1792 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
1793 Offset += CertList->SignatureListSize;\r
1794 }\r
1795 \r
1796 KekDataSize -= CertList->SignatureListSize;\r
1797 CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
1798 }\r
1799\r
1800 if (!IsKEKItemFound) {\r
1801 //\r
1802 // Doesn't find the Kek Item!\r
1803 //\r
1804 Status = EFI_NOT_FOUND;\r
1805 goto ON_EXIT;\r
1806 }\r
1807\r
1808 //\r
1809 // Delete the Signature header if there is no signature in the list.\r
1810 //\r
1811 KekDataSize = Offset;\r
1812 CertList = (EFI_SIGNATURE_LIST*) Data;\r
1813 Offset = 0;\r
1814 ZeroMem (OldData, KekDataSize);\r
1815 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
1816 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1817 DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount));\r
1818 if (CertCount != 0) {\r
1819 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
1820 Offset += CertList->SignatureListSize;\r
1821 } \r
1822 KekDataSize -= CertList->SignatureListSize;\r
1823 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1824 }\r
1825\r
ecc722ad 1826 DataSize = Offset;\r
8c1babfd 1827 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
1828 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
1829 if (EFI_ERROR (Status)) {\r
1830 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
1831 goto ON_EXIT;\r
1832 }\r
1833 }\r
ecc722ad 1834\r
1835 Status = gRT->SetVariable(\r
1836 EFI_KEY_EXCHANGE_KEY_NAME, \r
1837 &gEfiGlobalVariableGuid, \r
1838 Attr, \r
1839 DataSize, \r
1840 OldData\r
1841 );\r
1842 if (EFI_ERROR (Status)) {\r
1843 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
1844 goto ON_EXIT;\r
1845 }\r
1846 \r
1847ON_EXIT:\r
1848 if (Data != NULL) {\r
1849 FreePool(Data);\r
1850 }\r
1851\r
1852 if (OldData != NULL) {\r
1853 FreePool(OldData);\r
1854 }\r
1855\r
1856 return UpdateDeletePage (\r
1857 PrivateData, \r
1858 EFI_KEY_EXCHANGE_KEY_NAME,\r
1859 &gEfiGlobalVariableGuid,\r
1860 LABEL_KEK_DELETE,\r
1861 FORMID_DELETE_KEK_FORM,\r
1862 OPTION_DEL_KEK_QUESTION_ID\r
1863 );\r
1864}\r
1865\r
1866/**\r
1867 Delete a signature entry from siganture database.\r
beda2356 1868\r
ecc722ad 1869 @param[in] PrivateData Module's private data.\r
1870 @param[in] VariableName The variable name of the vendor's signature database.\r
1871 @param[in] VendorGuid A unique identifier for the vendor.\r
1872 @param[in] LabelNumber Label number to insert opcodes.\r
1873 @param[in] FormId Form ID of current page.\r
1874 @param[in] QuestionIdBase Base question id of the signature list.\r
1875 @param[in] DeleteIndex Signature index to delete.\r
1876 \r
1877 @retval EFI_SUCCESS Delete siganture successfully.\r
1878 @retval EFI_NOT_FOUND Can't find the signature item,\r
1879 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
beda2356 1880**/\r
1881EFI_STATUS\r
ecc722ad 1882DeleteSignature (\r
1883 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
1884 IN CHAR16 *VariableName,\r
1885 IN EFI_GUID *VendorGuid,\r
1886 IN UINT16 LabelNumber,\r
1887 IN EFI_FORM_ID FormId,\r
1888 IN EFI_QUESTION_ID QuestionIdBase,\r
1889 IN UINTN DeleteIndex\r
beda2356 1890 )\r
1891{\r
ecc722ad 1892 EFI_STATUS Status;\r
1893 UINTN DataSize;\r
1894 UINT8 *Data;\r
1895 UINT8 *OldData;\r
1896 UINT32 Attr;\r
1897 UINT32 Index;\r
1898 EFI_SIGNATURE_LIST *CertList;\r
1899 EFI_SIGNATURE_LIST *NewCertList;\r
1900 EFI_SIGNATURE_DATA *Cert;\r
1901 UINTN CertCount;\r
1902 UINT32 Offset;\r
1903 BOOLEAN IsItemFound;\r
1904 UINT32 ItemDataSize;\r
1905 UINTN GuidIndex;\r
bc0c99b3 1906\r
ecc722ad 1907 Data = NULL;\r
1908 OldData = NULL;\r
1909 CertList = NULL;\r
1910 Cert = NULL;\r
1911 Attr = 0; \r
1912\r
1913 //\r
1914 // Get original signature list data.\r
1915 // \r
1916 DataSize = 0;\r
1917 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
1918 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
1919 goto ON_EXIT;\r
1920 }\r
1921\r
1922 OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
1923 if (OldData == NULL) {\r
1924 Status = EFI_OUT_OF_RESOURCES; \r
1925 goto ON_EXIT;\r
1926 }\r
1927\r
1928 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
1929 if (EFI_ERROR(Status)) {\r
1930 goto ON_EXIT;\r
1931 } \r
1932\r
1933 //\r
1934 // Allocate space for new variable. \r
1935 //\r
1936 Data = (UINT8*) AllocateZeroPool (DataSize);\r
1937 if (Data == NULL) {\r
1938 Status = EFI_OUT_OF_RESOURCES;\r
1939 goto ON_EXIT;\r
1940 }\r
1941\r
1942 //\r
1943 // Enumerate all signature data and erasing the target item.\r
1944 //\r
1945 IsItemFound = FALSE;\r
1946 ItemDataSize = (UINT32) DataSize;\r
1947 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
1948 Offset = 0;\r
1949 GuidIndex = 0;\r
1950 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
1951 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
1952 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
1953 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
1954 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)\r
1955 ) {\r
1956 //\r
1957 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
1958 //\r
1959 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
1960 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
1961 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1962 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1963 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1964 for (Index = 0; Index < CertCount; Index++) {\r
1965 if (GuidIndex == DeleteIndex) {\r
1966 //\r
1967 // Find it! Skip it!\r
1968 //\r
1969 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
1970 IsItemFound = TRUE; \r
1971 } else {\r
1972 //\r
1973 // This item doesn't match. Copy it to the Data buffer.\r
1974 //\r
1975 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
1976 Offset += CertList->SignatureSize;\r
1977 }\r
1978 GuidIndex++;\r
1979 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
1980 }\r
1981 } else {\r
1982 //\r
1983 // This List doesn't match. Just copy it to the Data buffer.\r
1984 //\r
1985 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
1986 Offset += CertList->SignatureListSize;\r
1987 }\r
1988 \r
1989 ItemDataSize -= CertList->SignatureListSize;\r
1990 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1991 }\r
1992\r
1993 if (!IsItemFound) {\r
1994 //\r
1995 // Doesn't find the signature Item!\r
1996 //\r
1997 Status = EFI_NOT_FOUND;\r
1998 goto ON_EXIT;\r
1999 }\r
2000\r
2001 //\r
2002 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
2003 //\r
2004 ItemDataSize = Offset;\r
2005 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2006 Offset = 0;\r
2007 ZeroMem (OldData, ItemDataSize);\r
2008 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2009 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2010 DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount));\r
2011 if (CertCount != 0) {\r
2012 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2013 Offset += CertList->SignatureListSize;\r
2014 } \r
2015 ItemDataSize -= CertList->SignatureListSize;\r
2016 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2017 }\r
2018\r
ecc722ad 2019 DataSize = Offset;\r
8c1babfd 2020 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2021 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2022 if (EFI_ERROR (Status)) {\r
2023 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2024 goto ON_EXIT;\r
2025 }\r
2026 }\r
ecc722ad 2027\r
2028 Status = gRT->SetVariable(\r
2029 VariableName, \r
2030 VendorGuid, \r
2031 Attr, \r
2032 DataSize, \r
2033 OldData\r
2034 );\r
beda2356 2035 if (EFI_ERROR (Status)) {\r
ecc722ad 2036 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2037 goto ON_EXIT;\r
beda2356 2038 }\r
ecc722ad 2039 \r
2040ON_EXIT:\r
2041 if (Data != NULL) {\r
2042 FreePool(Data);\r
2043 }\r
2044\r
2045 if (OldData != NULL) {\r
2046 FreePool(OldData);\r
2047 }\r
2048\r
2049 return UpdateDeletePage (\r
2050 PrivateData, \r
2051 VariableName,\r
2052 VendorGuid,\r
2053 LabelNumber,\r
2054 FormId,\r
2055 QuestionIdBase\r
2056 );\r
2057}\r
2058\r
2059/**\r
2060 This function extracts configuration from variable.\r
2061 \r
2062 @param[in, out] ConfigData Point to SecureBoot configuration private data.\r
2063\r
2064**/\r
2065VOID\r
2066SecureBootExtractConfigFromVariable (\r
2067 IN OUT SECUREBOOT_CONFIGURATION *ConfigData\r
2068 ) \r
2069{\r
2070 UINT8 *SecureBootEnable;\r
2071 UINT8 *SetupMode;\r
8f8ca22e 2072 UINT8 *SecureBoot;\r
ecc722ad 2073 UINT8 *SecureBootMode;\r
2074\r
2075 SecureBootEnable = NULL;\r
2076 SetupMode = NULL;\r
8f8ca22e 2077 SecureBoot = NULL;\r
ecc722ad 2078 SecureBootMode = NULL;\r
2079 \r
ecc722ad 2080 //\r
2081 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
2082 // Checkbox.\r
2083 //\r
8f8ca22e 2084 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
ecc722ad 2085 if (SecureBootEnable == NULL) {\r
2086 ConfigData->HideSecureBoot = TRUE;\r
2087 } else {\r
2088 ConfigData->HideSecureBoot = FALSE;\r
ecc722ad 2089 }\r
8f8ca22e 2090 \r
ecc722ad 2091 //\r
2092 // If it is Physical Presence User, set the PhysicalPresent to true.\r
2093 //\r
2094 if (UserPhysicalPresent()) {\r
2095 ConfigData->PhysicalPresent = TRUE;\r
2096 } else {\r
2097 ConfigData->PhysicalPresent = FALSE;\r
2098 }\r
2099 \r
2100 //\r
2101 // If there is no PK then the Delete Pk button will be gray.\r
2102 //\r
f01b91ae 2103 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
8f8ca22e 2104 if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
ecc722ad 2105 ConfigData->HasPk = FALSE;\r
2106 } else {\r
2107 ConfigData->HasPk = TRUE;\r
2108 }\r
8f8ca22e 2109 \r
2110 //\r
2111 // If the value of SecureBoot variable is 1, the platform is operating in secure boot mode.\r
2112 //\r
2113 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
2114 if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
2115 ConfigData->SecureBootState = TRUE;\r
2116 } else {\r
2117 ConfigData->SecureBootState = FALSE;\r
2118 }\r
ecc722ad 2119\r
2120 //\r
2121 // Get the SecureBootMode from CustomMode variable.\r
2122 //\r
f01b91ae 2123 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
ecc722ad 2124 if (SecureBootMode == NULL) {\r
2125 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
2126 } else {\r
2127 ConfigData->SecureBootMode = *(SecureBootMode);\r
2128 }\r
2129 \r
beda2356 2130}\r
2131\r
2132/**\r
2133 This function allows a caller to extract the current configuration for one\r
2134 or more named elements from the target driver.\r
2135\r
2136 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2137 @param[in] Request A null-terminated Unicode string in\r
2138 <ConfigRequest> format.\r
2139 @param[out] Progress On return, points to a character in the Request\r
2140 string. Points to the string's null terminator if\r
2141 request was successful. Points to the most recent\r
2142 '&' before the first failing name/value pair (or\r
2143 the beginning of the string if the failure is in\r
2144 the first name/value pair) if the request was not\r
2145 successful.\r
2146 @param[out] Results A null-terminated Unicode string in\r
2147 <ConfigAltResp> format which has all values filled\r
2148 in for the names in the Request string. String to\r
2149 be allocated by the called function.\r
2150\r
2151 @retval EFI_SUCCESS The Results is filled with the requested values.\r
2152 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
2153 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
2154 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
2155 driver.\r
2156\r
2157**/\r
2158EFI_STATUS\r
2159EFIAPI\r
2160SecureBootExtractConfig (\r
2161 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2162 IN CONST EFI_STRING Request,\r
2163 OUT EFI_STRING *Progress,\r
2164 OUT EFI_STRING *Results\r
2165 )\r
2166{\r
2167 EFI_STATUS Status;\r
2168 UINTN BufferSize;\r
bc0c99b3 2169 UINTN Size;\r
beda2356 2170 SECUREBOOT_CONFIGURATION Configuration;\r
beda2356 2171 EFI_STRING ConfigRequest;\r
bc0c99b3 2172 EFI_STRING ConfigRequestHdr;\r
bc0c99b3 2173 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
2174 BOOLEAN AllocatedRequest;\r
2175\r
beda2356 2176 if (Progress == NULL || Results == NULL) {\r
2177 return EFI_INVALID_PARAMETER;\r
2178 }\r
ecc722ad 2179 \r
bc0c99b3 2180 AllocatedRequest = FALSE;\r
2181 ConfigRequestHdr = NULL;\r
2182 ConfigRequest = NULL;\r
2183 Size = 0;\r
2184 \r
ea71453f 2185 ZeroMem (&Configuration, sizeof (Configuration));\r
bc0c99b3 2186 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
2187 *Progress = Request;\r
2188 \r
beda2356 2189 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
2190 return EFI_NOT_FOUND;\r
2191 }\r
2192\r
beda2356 2193 //\r
ecc722ad 2194 // Get Configuration from Variable.\r
beda2356 2195 //\r
ecc722ad 2196 SecureBootExtractConfigFromVariable (&Configuration);\r
beda2356 2197 \r
bc0c99b3 2198 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
beda2356 2199 ConfigRequest = Request;\r
bc0c99b3 2200 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
2201 //\r
2202 // Request is set to NULL or OFFSET is NULL, construct full request string.\r
bc0c99b3 2203 //\r
2204 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
2205 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
2206 //\r
2207 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
2208 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
2209 ConfigRequest = AllocateZeroPool (Size);\r
2210 ASSERT (ConfigRequest != NULL);\r
2211 AllocatedRequest = TRUE;\r
2212 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
2213 FreePool (ConfigRequestHdr);\r
2214 ConfigRequestHdr = NULL;\r
2215 }\r
beda2356 2216\r
2217 Status = gHiiConfigRouting->BlockToConfig (\r
2218 gHiiConfigRouting,\r
2219 ConfigRequest,\r
2220 (UINT8 *) &Configuration,\r
2221 BufferSize,\r
2222 Results,\r
2223 Progress\r
2224 );\r
bc0c99b3 2225\r
2226 //\r
2227 // Free the allocated config request string.\r
2228 //\r
2229 if (AllocatedRequest) {\r
2230 FreePool (ConfigRequest);\r
2231 }\r
2232\r
beda2356 2233 //\r
2234 // Set Progress string to the original request string.\r
2235 //\r
2236 if (Request == NULL) {\r
2237 *Progress = NULL;\r
2238 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
2239 *Progress = Request + StrLen (Request);\r
2240 }\r
2241\r
2242 return Status;\r
2243}\r
2244\r
2245/**\r
2246 This function processes the results of changes in configuration.\r
2247\r
2248 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2249 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>\r
2250 format.\r
2251 @param[out] Progress A pointer to a string filled in with the offset of\r
2252 the most recent '&' before the first failing\r
2253 name/value pair (or the beginning of the string if\r
2254 the failure is in the first name/value pair) or\r
2255 the terminating NULL if all was successful.\r
2256\r
2257 @retval EFI_SUCCESS The Results is processed successfully.\r
2258 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
2259 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
2260 driver.\r
2261\r
2262**/\r
2263EFI_STATUS\r
2264EFIAPI\r
2265SecureBootRouteConfig (\r
2266 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2267 IN CONST EFI_STRING Configuration,\r
2268 OUT EFI_STRING *Progress\r
2269 )\r
2270{\r
beda2356 2271 if (Configuration == NULL || Progress == NULL) {\r
2272 return EFI_INVALID_PARAMETER;\r
2273 }\r
2274\r
2275 *Progress = Configuration;\r
2276 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
2277 return EFI_NOT_FOUND;\r
2278 }\r
2279\r
ecc722ad 2280 *Progress = Configuration + StrLen (Configuration);\r
beda2356 2281 return EFI_SUCCESS;\r
2282}\r
2283\r
2284/**\r
ecc722ad 2285 This function is called to provide results data to the driver.\r
beda2356 2286\r
2287 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2288 @param[in] Action Specifies the type of action taken by the browser.\r
2289 @param[in] QuestionId A unique value which is sent to the original\r
2290 exporting driver so that it can identify the type\r
2291 of data to expect.\r
2292 @param[in] Type The type of value for the question.\r
2293 @param[in] Value A pointer to the data being sent to the original\r
2294 exporting driver.\r
2295 @param[out] ActionRequest On return, points to the action requested by the\r
2296 callback function.\r
2297\r
2298 @retval EFI_SUCCESS The callback successfully handled the action.\r
2299 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
2300 variable and its data.\r
2301 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
2302 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
2303 callback.\r
2304\r
2305**/\r
2306EFI_STATUS\r
2307EFIAPI\r
2308SecureBootCallback (\r
2309 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2310 IN EFI_BROWSER_ACTION Action,\r
2311 IN EFI_QUESTION_ID QuestionId,\r
2312 IN UINT8 Type,\r
2313 IN EFI_IFR_TYPE_VALUE *Value,\r
2314 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
2315 )\r
2316{\r
ecc722ad 2317 EFI_INPUT_KEY Key;\r
2318 EFI_STATUS Status; \r
2319 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;\r
2320 UINTN BufferSize;\r
2321 SECUREBOOT_CONFIGURATION *IfrNvData;\r
2322 UINT16 LabelId;\r
bf4a3dbd
ED
2323 UINT8 *SecureBootEnable;\r
2324\r
2325 SecureBootEnable = NULL;\r
bc0c99b3 2326\r
beda2356 2327 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
2328 return EFI_INVALID_PARAMETER;\r
2329 }\r
2330\r
ecc722ad 2331 if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) {\r
beda2356 2332 return EFI_UNSUPPORTED;\r
2333 }\r
ecc722ad 2334 \r
2335 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
bc0c99b3 2336\r
ecc722ad 2337 //\r
2338 // Retrieve uncommitted data from Browser\r
2339 //\r
2340 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
2341 IfrNvData = AllocateZeroPool (BufferSize);\r
2342 if (IfrNvData == NULL) {\r
2343 return EFI_OUT_OF_RESOURCES;\r
beda2356 2344 }\r
bc0c99b3 2345\r
ecc722ad 2346 Status = EFI_SUCCESS;\r
2347\r
2348 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);\r
2349 \r
2350 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2351\r
2352 switch (QuestionId) {\r
2353 case KEY_SECURE_BOOT_ENABLE:\r
f01b91ae 2354 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
bf4a3dbd 2355 if (NULL != SecureBootEnable) {\r
ecc722ad 2356 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {\r
2357 CreatePopUp (\r
2358 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2359 &Key,\r
2360 L"Only Physical Presence User could disable secure boot!",\r
2361 NULL\r
2362 );\r
2363 Status = EFI_UNSUPPORTED;\r
2364 }\r
2365 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; \r
2366 }\r
2367 break;\r
2368\r
2369 case KEY_SECURE_BOOT_OPTION:\r
2370 FreeMenu (&DirectoryMenu);\r
2371 FreeMenu (&FsOptionMenu);\r
2372 break;\r
2373\r
2374 case KEY_SECURE_BOOT_KEK_OPTION:\r
2375 case KEY_SECURE_BOOT_DB_OPTION:\r
2376 case KEY_SECURE_BOOT_DBX_OPTION:\r
2377 //\r
2378 // Clear Signature GUID.\r
2379 //\r
2380 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));\r
2381 if (Private->SignatureGUID == NULL) {\r
2382 Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
2383 if (Private->SignatureGUID == NULL) {\r
2384 return EFI_OUT_OF_RESOURCES;\r
2385 }\r
2386 }\r
beda2356 2387\r
ecc722ad 2388 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {\r
2389 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
2390 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {\r
2391 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
2392 } else {\r
2393 LabelId = FORMID_ENROLL_KEK_FORM;\r
2394 }\r
2395\r
2396 //\r
2397 // Refresh selected file.\r
2398 //\r
2399 CleanUpPage (LabelId, Private); \r
2400 break;\r
2401 \r
2402 case SECUREBOOT_ADD_PK_FILE_FORM_ID:\r
2403 case FORMID_ENROLL_KEK_FORM:\r
2404 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
2405 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
2406 if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {\r
2407 Private->FeCurrentState = FileExplorerStateEnrollPkFile;\r
2408 } else if (QuestionId == FORMID_ENROLL_KEK_FORM) {\r
2409 Private->FeCurrentState = FileExplorerStateEnrollKekFile;\r
2410 } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {\r
2411 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;\r
2412 } else {\r
2413 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;\r
2414 }\r
2415\r
2416 Private->FeDisplayContext = FileExplorerDisplayUnknown;\r
2417 CleanUpPage (FORM_FILE_EXPLORER_ID, Private);\r
2418 UpdateFileExplorer (Private, 0);\r
2419 break;\r
2420\r
2421 case KEY_SECURE_BOOT_DELETE_PK: \r
2422 if (Value->u8) {\r
2423 Status = DeletePlatformKey ();\r
2424 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2425 }\r
2426 break;\r
2427\r
2428 case KEY_DELETE_KEK:\r
2429 UpdateDeletePage (\r
2430 Private, \r
2431 EFI_KEY_EXCHANGE_KEY_NAME,\r
2432 &gEfiGlobalVariableGuid,\r
2433 LABEL_KEK_DELETE,\r
2434 FORMID_DELETE_KEK_FORM,\r
2435 OPTION_DEL_KEK_QUESTION_ID \r
2436 );\r
2437 break;\r
2438\r
2439 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB: \r
2440 UpdateDeletePage (\r
2441 Private,\r
2442 EFI_IMAGE_SECURITY_DATABASE,\r
2443 &gEfiImageSecurityDatabaseGuid,\r
2444 LABEL_DB_DELETE,\r
2445 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
2446 OPTION_DEL_DB_QUESTION_ID\r
2447 );\r
2448 break;\r
2449\r
2450 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:\r
2451 UpdateDeletePage (\r
2452 Private,\r
2453 EFI_IMAGE_SECURITY_DATABASE1,\r
2454 &gEfiImageSecurityDatabaseGuid,\r
2455 LABEL_DBX_DELETE,\r
2456 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
2457 OPTION_DEL_DBX_QUESTION_ID\r
2458 );\r
2459\r
2460 break;\r
2461\r
2462 case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
2463 Status = EnrollKeyExchangeKey (Private);\r
2464 break;\r
2465\r
2466 case KEY_VALUE_SAVE_AND_EXIT_DB:\r
2467 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
2468 break;\r
2469\r
2470 case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
2471 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
2472 break;\r
2473\r
2474 default:\r
2475 if (QuestionId >= FILE_OPTION_OFFSET) {\r
2476 UpdateFileExplorer (Private, QuestionId);\r
2477 } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
2478 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
2479 DeleteKeyExchangeKey (Private, QuestionId);\r
2480 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&\r
2481 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
2482 DeleteSignature (\r
2483 Private,\r
2484 EFI_IMAGE_SECURITY_DATABASE,\r
2485 &gEfiImageSecurityDatabaseGuid,\r
2486 LABEL_DB_DELETE, \r
2487 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
2488 OPTION_DEL_DB_QUESTION_ID,\r
2489 QuestionId - OPTION_DEL_DB_QUESTION_ID\r
2490 );\r
2491 } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&\r
2492 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
2493 DeleteSignature (\r
2494 Private,\r
2495 EFI_IMAGE_SECURITY_DATABASE1,\r
2496 &gEfiImageSecurityDatabaseGuid,\r
2497 LABEL_DBX_DELETE, \r
2498 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
2499 OPTION_DEL_DBX_QUESTION_ID,\r
2500 QuestionId - OPTION_DEL_DBX_QUESTION_ID\r
2501 );\r
2502 }\r
2503 break;\r
2504 }\r
2505 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2506 switch (QuestionId) {\r
2507 case KEY_SECURE_BOOT_ENABLE:\r
2508 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; \r
2509 break; \r
2510 case KEY_VALUE_SAVE_AND_EXIT_PK:\r
2511 Status = EnrollPlatformKey (Private);\r
2512 if (EFI_ERROR (Status)) {\r
2513 CreatePopUp (\r
2514 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2515 &Key,\r
cf7409f2 2516 L"ERROR: Unsupported file type, only DER encoded certificate file (*.cer or *.der) is supported!",\r
ecc722ad 2517 NULL\r
2518 );\r
2519 } else {\r
0fb450fb 2520 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; \r
ecc722ad 2521 } \r
2522 break;\r
2523\r
2524 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
2525 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
2526 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
2527 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
2528 if (Private->FileContext->FHandle != NULL) {\r
2529 CloseFile (Private->FileContext->FHandle);\r
2530 Private->FileContext->FHandle = NULL;\r
2531 Private->FileContext->FileName = NULL;\r
2532 }\r
2533 \r
2534 if (Private->SignatureGUID != NULL) {\r
2535 FreePool (Private->SignatureGUID);\r
2536 Private->SignatureGUID = NULL;\r
2537 }\r
2538 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
2539 break;\r
2540 \r
2541 case KEY_SECURE_BOOT_MODE:\r
f01b91ae 2542 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootEnable, NULL);\r
bf4a3dbd 2543 if (NULL != SecureBootEnable) {\r
ecc722ad 2544 Status = gRT->SetVariable ( \r
2545 EFI_CUSTOM_MODE_NAME,\r
2546 &gEfiCustomModeEnableGuid,\r
2547 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
2548 sizeof (UINT8),\r
2549 &Value->u8\r
2550 );\r
2551 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2552 IfrNvData->SecureBootMode = Value->u8;\r
2553 } \r
2554 break;\r
2555\r
2556 case KEY_SECURE_BOOT_KEK_GUID:\r
2557 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
2558 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
2559 ASSERT (Private->SignatureGUID != NULL);\r
2560 Status = StringToGuid (\r
2561 IfrNvData->SignatureGuid,\r
2562 StrLen (IfrNvData->SignatureGuid),\r
2563 Private->SignatureGUID\r
2564 );\r
2565 if (EFI_ERROR (Status)) {\r
2566 break;\r
2567 }\r
2568\r
2569 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2570 break;\r
2571\r
2572 case KEY_SECURE_BOOT_DELETE_PK:\r
2573 if (Value->u8) {\r
2574 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
2575 }\r
2576 break; \r
2577 }\r
2578 }\r
2579 \r
2580 if (!EFI_ERROR (Status)) {\r
2581 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
2582 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8*) IfrNvData, NULL);\r
2583 }\r
2584 FreePool (IfrNvData);\r
2585 \r
2586 return EFI_SUCCESS;\r
beda2356 2587}\r
2588\r
2589/**\r
2590 This function publish the SecureBoot configuration Form.\r
2591\r
2592 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
2593\r
ecc722ad 2594 @retval EFI_SUCCESS HII Form is installed successfully.\r
beda2356 2595 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.\r
2596 @retval Others Other errors as indicated.\r
2597\r
2598**/\r
2599EFI_STATUS\r
2600InstallSecureBootConfigForm (\r
2601 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
2602 )\r
2603{\r
2604 EFI_STATUS Status;\r
2605 EFI_HII_HANDLE HiiHandle;\r
2606 EFI_HANDLE DriverHandle;\r
beda2356 2607 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2608\r
2609 DriverHandle = NULL;\r
2610 ConfigAccess = &PrivateData->ConfigAccess;\r
2611 Status = gBS->InstallMultipleProtocolInterfaces (\r
2612 &DriverHandle,\r
2613 &gEfiDevicePathProtocolGuid,\r
2614 &mSecureBootHiiVendorDevicePath,\r
2615 &gEfiHiiConfigAccessProtocolGuid,\r
2616 ConfigAccess,\r
2617 NULL\r
2618 );\r
2619 if (EFI_ERROR (Status)) {\r
2620 return Status;\r
2621 }\r
2622\r
2623 PrivateData->DriverHandle = DriverHandle;\r
2624\r
2625 //\r
2626 // Publish the HII package list\r
2627 //\r
2628 HiiHandle = HiiAddPackages (\r
2629 &gSecureBootConfigFormSetGuid,\r
2630 DriverHandle,\r
2631 SecureBootConfigDxeStrings,\r
2632 SecureBootConfigBin,\r
2633 NULL\r
2634 );\r
2635 if (HiiHandle == NULL) {\r
2636 gBS->UninstallMultipleProtocolInterfaces (\r
2637 DriverHandle,\r
2638 &gEfiDevicePathProtocolGuid,\r
2639 &mSecureBootHiiVendorDevicePath,\r
2640 &gEfiHiiConfigAccessProtocolGuid,\r
2641 ConfigAccess,\r
2642 NULL\r
bc0c99b3 2643 );\r
beda2356 2644 return EFI_OUT_OF_RESOURCES;\r
2645 }\r
bc0c99b3 2646\r
beda2356 2647 PrivateData->HiiHandle = HiiHandle;\r
ecc722ad 2648\r
2649 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
2650 PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));\r
2651 \r
2652 if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) {\r
2653 UninstallSecureBootConfigForm (PrivateData);\r
2654 return EFI_OUT_OF_RESOURCES;\r
2655 }\r
2656 \r
2657 PrivateData->FeCurrentState = FileExplorerStateInActive;\r
2658 PrivateData->FeDisplayContext = FileExplorerDisplayUnknown;\r
2659 \r
2660 InitializeListHead (&FsOptionMenu.Head);\r
2661 InitializeListHead (&DirectoryMenu.Head);\r
2662\r
2663 //\r
2664 // Init OpCode Handle and Allocate space for creation of Buffer\r
2665 //\r
2666 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2667 if (mStartOpCodeHandle == NULL) {\r
2668 UninstallSecureBootConfigForm (PrivateData);\r
2669 return EFI_OUT_OF_RESOURCES;\r
2670 }\r
2671\r
2672 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2673 if (mEndOpCodeHandle == NULL) {\r
2674 UninstallSecureBootConfigForm (PrivateData);\r
2675 return EFI_OUT_OF_RESOURCES;\r
2676 }\r
2677\r
2678 //\r
2679 // Create Hii Extend Label OpCode as the start opcode\r
2680 //\r
2681 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2682 mStartOpCodeHandle,\r
2683 &gEfiIfrTianoGuid,\r
2684 NULL,\r
2685 sizeof (EFI_IFR_GUID_LABEL)\r
2686 );\r
2687 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2688\r
2689 //\r
2690 // Create Hii Extend Label OpCode as the end opcode\r
2691 //\r
2692 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2693 mEndOpCodeHandle,\r
2694 &gEfiIfrTianoGuid,\r
2695 NULL,\r
2696 sizeof (EFI_IFR_GUID_LABEL)\r
2697 );\r
2698 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2699 mEndLabel->Number = LABEL_END;\r
2700 \r
bc0c99b3 2701 return EFI_SUCCESS;\r
beda2356 2702}\r
2703\r
2704/**\r
2705 This function removes SecureBoot configuration Form.\r
2706\r
2707 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
2708\r
2709**/\r
2710VOID\r
2711UninstallSecureBootConfigForm (\r
2712 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
2713 )\r
2714{\r
2715 //\r
2716 // Uninstall HII package list\r
2717 //\r
2718 if (PrivateData->HiiHandle != NULL) {\r
2719 HiiRemovePackages (PrivateData->HiiHandle);\r
2720 PrivateData->HiiHandle = NULL;\r
2721 }\r
2722\r
2723 //\r
2724 // Uninstall HII Config Access Protocol\r
2725 //\r
2726 if (PrivateData->DriverHandle != NULL) {\r
2727 gBS->UninstallMultipleProtocolInterfaces (\r
2728 PrivateData->DriverHandle,\r
2729 &gEfiDevicePathProtocolGuid,\r
2730 &mSecureBootHiiVendorDevicePath,\r
2731 &gEfiHiiConfigAccessProtocolGuid,\r
2732 &PrivateData->ConfigAccess,\r
2733 NULL\r
2734 );\r
2735 PrivateData->DriverHandle = NULL;\r
2736 }\r
bc0c99b3 2737\r
ecc722ad 2738 if (PrivateData->SignatureGUID != NULL) {\r
2739 FreePool (PrivateData->SignatureGUID);\r
2740 }\r
2741\r
2742 if (PrivateData->MenuEntry != NULL) {\r
2743 FreePool (PrivateData->MenuEntry);\r
2744 }\r
2745\r
2746 if (PrivateData->FileContext != NULL) {\r
2747 FreePool (PrivateData->FileContext);\r
2748 }\r
2749\r
beda2356 2750 FreePool (PrivateData);\r
ecc722ad 2751\r
2752 FreeMenu (&DirectoryMenu);\r
2753 FreeMenu (&FsOptionMenu);\r
2754\r
2755 if (mStartOpCodeHandle != NULL) {\r
2756 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
2757 }\r
2758\r
2759 if (mEndOpCodeHandle != NULL) {\r
2760 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
2761 }\r
beda2356 2762}\r