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