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