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