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