]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
SecurityPkg: SecureBootConfigDxe: SecureBoot UI for Customized SecureBoot Mode
[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
69f8bb52 4Copyright (c) 2011 - 2015, 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
20333c6d 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
a365eed4 51BOOLEAN mIsEnterSecureBootForm = FALSE;\r
96832eef
CZ
52BOOLEAN mIsSelectedSecureBootModeForm = FALSE;\r
53BOOLEAN mIsSecureBootModeChanged = FALSE;\r
a365eed4 54\r
ecc722ad 55//\r
56// OID ASN.1 Value for Hash Algorithms\r
57//\r
58UINT8 mHashOidValue[] = {\r
59 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5\r
60 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1\r
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224\r
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256\r
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384\r
64 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512\r
65 };\r
66\r
67HASH_TABLE mHash[] = {\r
20333c6d
QL
68 { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },\r
69 { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },\r
70 { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},\r
71 { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},\r
72 { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
ecc722ad 73};\r
74\r
e4d7370d 75//\r
20333c6d
QL
76// Variable Definitions\r
77//\r
ecc722ad 78UINT32 mPeCoffHeaderOffset = 0;\r
79WIN_CERTIFICATE *mCertificate = NULL;\r
80IMAGE_TYPE mImageType;\r
81UINT8 *mImageBase = NULL;\r
82UINTN mImageSize = 0;\r
83UINT8 mImageDigest[MAX_DIGEST_SIZE];\r
84UINTN mImageDigestSize;\r
85EFI_GUID mCertType;\r
86EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL;\r
87EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
88\r
e4d7370d 89//\r
90// Possible DER-encoded certificate file suffixes, end with NULL pointer.\r
91//\r
92CHAR16* mDerEncodedSuffix[] = {\r
93 L".cer",\r
94 L".der",\r
95 L".crt",\r
96 NULL\r
97};\r
98CHAR16* mSupportX509Suffix = L"*.cer/der/crt";\r
99\r
100/**\r
101 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.\r
102\r
103 @param[in] FileSuffix The suffix of the input certificate file\r
104\r
105 @retval TRUE It's a DER-encoded certificate.\r
106 @retval FALSE It's NOT a DER-encoded certificate.\r
107\r
108**/\r
109BOOLEAN\r
110IsDerEncodeCertificate (\r
111 IN CONST CHAR16 *FileSuffix\r
112)\r
113{\r
20333c6d 114 UINTN Index;\r
e4d7370d 115 for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {\r
116 if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {\r
117 return TRUE;\r
118 }\r
119 }\r
120 return FALSE;\r
121}\r
ecc722ad 122\r
123/**\r
124 Set Secure Boot option into variable space.\r
125\r
126 @param[in] VarValue The option of Secure Boot.\r
127\r
128 @retval EFI_SUCCESS The operation is finished successfully.\r
129 @retval Others Other errors as indicated.\r
130\r
131**/\r
132EFI_STATUS\r
133SaveSecureBootVariable (\r
134 IN UINT8 VarValue\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138\r
139 Status = gRT->SetVariable (\r
140 EFI_SECURE_BOOT_ENABLE_NAME,\r
141 &gEfiSecureBootEnableDisableGuid,\r
142 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
143 sizeof (UINT8),\r
144 &VarValue\r
145 );\r
146 return Status;\r
147}\r
148\r
8c1babfd 149/**\r
150 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2\r
151 descriptor with the input data. NO authentication is required in this function.\r
20333c6d 152\r
8c1babfd 153 @param[in, out] DataSize On input, the size of Data buffer in bytes.\r
154 On output, the size of data returned in Data\r
155 buffer in bytes.\r
20333c6d 156 @param[in, out] Data On input, Pointer to data buffer to be wrapped or\r
8c1babfd 157 pointer to NULL to wrap an empty payload.\r
158 On output, Pointer to the new payload date buffer allocated from pool,\r
20333c6d 159 it's caller's responsibility to free the memory when finish using it.\r
8c1babfd 160\r
161 @retval EFI_SUCCESS Create time based payload successfully.\r
162 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.\r
163 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
164 @retval Others Unexpected error happens.\r
165\r
166**/\r
167EFI_STATUS\r
168CreateTimeBasedPayload (\r
169 IN OUT UINTN *DataSize,\r
170 IN OUT UINT8 **Data\r
171 )\r
172{\r
173 EFI_STATUS Status;\r
174 UINT8 *NewData;\r
175 UINT8 *Payload;\r
176 UINTN PayloadSize;\r
177 EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;\r
178 UINTN DescriptorSize;\r
179 EFI_TIME Time;\r
20333c6d 180\r
8c1babfd 181 if (Data == NULL || DataSize == NULL) {\r
182 return EFI_INVALID_PARAMETER;\r
183 }\r
20333c6d 184\r
8c1babfd 185 //\r
20333c6d 186 // In Setup mode or Custom mode, the variable does not need to be signed but the\r
8c1babfd 187 // parameters to the SetVariable() call still need to be prepared as authenticated\r
188 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate\r
189 // data in it.\r
190 //\r
191 Payload = *Data;\r
192 PayloadSize = *DataSize;\r
20333c6d 193\r
8c1babfd 194 DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
195 NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);\r
196 if (NewData == NULL) {\r
197 return EFI_OUT_OF_RESOURCES;\r
198 }\r
199\r
200 if ((Payload != NULL) && (PayloadSize != 0)) {\r
201 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
202 }\r
203\r
204 DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);\r
205\r
206 ZeroMem (&Time, sizeof (EFI_TIME));\r
207 Status = gRT->GetTime (&Time, NULL);\r
208 if (EFI_ERROR (Status)) {\r
209 FreePool(NewData);\r
210 return Status;\r
211 }\r
212 Time.Pad1 = 0;\r
213 Time.Nanosecond = 0;\r
214 Time.TimeZone = 0;\r
215 Time.Daylight = 0;\r
216 Time.Pad2 = 0;\r
217 CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\r
20333c6d 218\r
8c1babfd 219 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
220 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;\r
221 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
222 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);\r
20333c6d 223\r
8c1babfd 224 if (Payload != NULL) {\r
225 FreePool(Payload);\r
226 }\r
20333c6d 227\r
8c1babfd 228 *DataSize = DescriptorSize + PayloadSize;\r
229 *Data = NewData;\r
230 return EFI_SUCCESS;\r
231}\r
232\r
ecc722ad 233/**\r
234 Internal helper function to delete a Variable given its name and GUID, NO authentication\r
235 required.\r
236\r
237 @param[in] VariableName Name of the Variable.\r
238 @param[in] VendorGuid GUID of the Variable.\r
239\r
240 @retval EFI_SUCCESS Variable deleted successfully.\r
241 @retval Others The driver failed to start the device.\r
242\r
243**/\r
244EFI_STATUS\r
245DeleteVariable (\r
246 IN CHAR16 *VariableName,\r
247 IN EFI_GUID *VendorGuid\r
248 )\r
249{\r
250 EFI_STATUS Status;\r
251 VOID* Variable;\r
8c1babfd 252 UINT8 *Data;\r
253 UINTN DataSize;\r
254 UINT32 Attr;\r
ecc722ad 255\r
bf4a3dbd 256 GetVariable2 (VariableName, VendorGuid, &Variable, NULL);\r
ecc722ad 257 if (Variable == NULL) {\r
258 return EFI_SUCCESS;\r
259 }\r
f71ed839 260 FreePool (Variable);\r
ecc722ad 261\r
8c1babfd 262 Data = NULL;\r
263 DataSize = 0;\r
264 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
265 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
ecc722ad 266\r
8c1babfd 267 Status = CreateTimeBasedPayload (&DataSize, &Data);\r
268 if (EFI_ERROR (Status)) {\r
269 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
270 return Status;\r
ecc722ad 271 }\r
272\r
8c1babfd 273 Status = gRT->SetVariable (\r
274 VariableName,\r
275 VendorGuid,\r
276 Attr,\r
277 DataSize,\r
278 Data\r
279 );\r
280 if (Data != NULL) {\r
281 FreePool (Data);\r
ecc722ad 282 }\r
ecc722ad 283 return Status;\r
284}\r
285\r
f71ed839 286/**\r
287\r
288 Set the platform secure boot mode into "Custom" or "Standard" mode.\r
289\r
290 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or\r
291 CUSTOM_SECURE_BOOT_MODE.\r
20333c6d 292\r
f71ed839 293 @return EFI_SUCCESS The platform has switched to the special mode successfully.\r
294 @return other Fail to operate the secure boot mode.\r
20333c6d 295\r
f71ed839 296**/\r
297EFI_STATUS\r
298SetSecureBootMode (\r
299 IN UINT8 SecureBootMode\r
300 )\r
301{\r
20333c6d 302 return gRT->SetVariable (\r
f71ed839 303 EFI_CUSTOM_MODE_NAME,\r
304 &gEfiCustomModeEnableGuid,\r
305 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
306 sizeof (UINT8),\r
307 &SecureBootMode\r
308 );\r
309}\r
310\r
ecc722ad 311/**\r
312 Generate the PK signature list from the X509 Certificate storing file (.cer)\r
313\r
314 @param[in] X509File FileHandle of X509 Certificate storing file.\r
315 @param[out] PkCert Point to the data buffer to store the signature list.\r
20333c6d 316\r
ecc722ad 317 @return EFI_UNSUPPORTED Unsupported Key Length.\r
318 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.\r
20333c6d 319\r
ecc722ad 320**/\r
321EFI_STATUS\r
322CreatePkX509SignatureList (\r
20333c6d
QL
323 IN EFI_FILE_HANDLE X509File,\r
324 OUT EFI_SIGNATURE_LIST **PkCert\r
ecc722ad 325 )\r
326{\r
20333c6d 327 EFI_STATUS Status;\r
ecc722ad 328 UINT8 *X509Data;\r
329 UINTN X509DataSize;\r
330 EFI_SIGNATURE_DATA *PkCertData;\r
331\r
332 X509Data = NULL;\r
333 PkCertData = NULL;\r
20333c6d
QL
334 X509DataSize = 0;\r
335\r
4adc12bf 336 Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);\r
ecc722ad 337 if (EFI_ERROR (Status)) {\r
338 goto ON_EXIT;\r
339 }\r
ba57d4fd 340 ASSERT (X509Data != NULL);\r
ecc722ad 341\r
342 //\r
343 // Allocate space for PK certificate list and initialize it.\r
344 // Create PK database entry with SignatureHeaderSize equals 0.\r
345 //\r
346 *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (\r
347 sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1\r
348 + X509DataSize\r
349 );\r
350 if (*PkCert == NULL) {\r
351 Status = EFI_OUT_OF_RESOURCES;\r
352 goto ON_EXIT;\r
353 }\r
354\r
20333c6d 355 (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST)\r
ecc722ad 356 + sizeof(EFI_SIGNATURE_DATA) - 1\r
357 + X509DataSize);\r
358 (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
359 (*PkCert)->SignatureHeaderSize = 0;\r
360 CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);\r
20333c6d 361 PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert)\r
ecc722ad 362 + sizeof(EFI_SIGNATURE_LIST)\r
363 + (*PkCert)->SignatureHeaderSize);\r
20333c6d 364 CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);\r
ecc722ad 365 //\r
366 // Fill the PK database with PKpub data from X509 certificate file.\r
20333c6d 367 //\r
ecc722ad 368 CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);\r
20333c6d 369\r
ecc722ad 370ON_EXIT:\r
20333c6d 371\r
ecc722ad 372 if (X509Data != NULL) {\r
373 FreePool (X509Data);\r
374 }\r
20333c6d 375\r
ecc722ad 376 if (EFI_ERROR(Status) && *PkCert != NULL) {\r
377 FreePool (*PkCert);\r
378 *PkCert = NULL;\r
379 }\r
20333c6d 380\r
ecc722ad 381 return Status;\r
382}\r
383\r
384/**\r
385 Enroll new PK into the System without original PK's authentication.\r
386\r
387 The SignatureOwner GUID will be the same with PK's vendorguid.\r
388\r
389 @param[in] PrivateData The module's private data.\r
390\r
391 @retval EFI_SUCCESS New PK enrolled successfully.\r
392 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
393 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
20333c6d 394\r
ecc722ad 395**/\r
396EFI_STATUS\r
397EnrollPlatformKey (\r
398 IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private\r
20333c6d 399 )\r
ecc722ad 400{\r
401 EFI_STATUS Status;\r
402 UINT32 Attr;\r
403 UINTN DataSize;\r
404 EFI_SIGNATURE_LIST *PkCert;\r
405 UINT16* FilePostFix;\r
fd64f84f 406 UINTN NameLength;\r
20333c6d 407\r
ecc722ad 408 if (Private->FileContext->FileName == NULL) {\r
409 return EFI_INVALID_PARAMETER;\r
410 }\r
411\r
412 PkCert = NULL;\r
413\r
f71ed839 414 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
415 if (EFI_ERROR (Status)) {\r
416 return Status;\r
417 }\r
418\r
ecc722ad 419 //\r
e4d7370d 420 // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
ecc722ad 421 //\r
fd64f84f
GCPL
422 NameLength = StrLen (Private->FileContext->FileName);\r
423 if (NameLength <= 4) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
426 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
e4d7370d 427 if (!IsDerEncodeCertificate(FilePostFix)) {\r
428 DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));\r
ecc722ad 429 return EFI_INVALID_PARAMETER;\r
430 }\r
431 DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));\r
432 DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));\r
433\r
434 //\r
435 // Prase the selected PK file and generature PK certificate list.\r
436 //\r
8c1babfd 437 Status = CreatePkX509SignatureList (\r
20333c6d
QL
438 Private->FileContext->FHandle,\r
439 &PkCert\r
8c1babfd 440 );\r
441 if (EFI_ERROR (Status)) {\r
442 goto ON_EXIT;\r
ecc722ad 443 }\r
ba57d4fd 444 ASSERT (PkCert != NULL);\r
20333c6d 445\r
ecc722ad 446 //\r
447 // Set Platform Key variable.\r
20333c6d
QL
448 //\r
449 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 450 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
ecc722ad 451 DataSize = PkCert->SignatureListSize;\r
8c1babfd 452 Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);\r
453 if (EFI_ERROR (Status)) {\r
454 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
455 goto ON_EXIT;\r
456 }\r
20333c6d 457\r
ecc722ad 458 Status = gRT->SetVariable(\r
20333c6d
QL
459 EFI_PLATFORM_KEY_NAME,\r
460 &gEfiGlobalVariableGuid,\r
461 Attr,\r
462 DataSize,\r
ecc722ad 463 PkCert\r
464 );\r
465 if (EFI_ERROR (Status)) {\r
466 if (Status == EFI_OUT_OF_RESOURCES) {\r
467 DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));\r
468 }\r
469 goto ON_EXIT;\r
470 }\r
20333c6d 471\r
ecc722ad 472ON_EXIT:\r
473\r
474 if (PkCert != NULL) {\r
475 FreePool(PkCert);\r
476 }\r
20333c6d 477\r
ecc722ad 478 if (Private->FileContext->FHandle != NULL) {\r
479 CloseFile (Private->FileContext->FHandle);\r
480 Private->FileContext->FHandle = NULL;\r
481 }\r
482\r
483 return Status;\r
484}\r
485\r
486/**\r
487 Remove the PK variable.\r
488\r
489 @retval EFI_SUCCESS Delete PK successfully.\r
490 @retval Others Could not allow to delete PK.\r
20333c6d 491\r
ecc722ad 492**/\r
493EFI_STATUS\r
494DeletePlatformKey (\r
495 VOID\r
496)\r
497{\r
498 EFI_STATUS Status;\r
499\r
f71ed839 500 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
501 if (EFI_ERROR (Status)) {\r
502 return Status;\r
503 }\r
504\r
8c1babfd 505 Status = DeleteVariable (\r
506 EFI_PLATFORM_KEY_NAME,\r
507 &gEfiGlobalVariableGuid\r
508 );\r
ecc722ad 509 return Status;\r
510}\r
511\r
512/**\r
513 Enroll a new KEK item from public key storing file (*.pbk).\r
514\r
515 @param[in] PrivateData The module's private data.\r
516\r
517 @retval EFI_SUCCESS New KEK enrolled successfully.\r
518 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
519 @retval EFI_UNSUPPORTED Unsupported command.\r
520 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
521\r
522**/\r
523EFI_STATUS\r
524EnrollRsa2048ToKek (\r
525 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
526 )\r
527{\r
528 EFI_STATUS Status;\r
529 UINT32 Attr;\r
530 UINTN DataSize;\r
531 EFI_SIGNATURE_LIST *KekSigList;\r
532 UINTN KeyBlobSize;\r
533 UINT8 *KeyBlob;\r
534 CPL_KEY_INFO *KeyInfo;\r
535 EFI_SIGNATURE_DATA *KEKSigData;\r
536 UINTN KekSigListSize;\r
20333c6d 537 UINT8 *KeyBuffer;\r
ecc722ad 538 UINTN KeyLenInBytes;\r
539\r
540 Attr = 0;\r
541 DataSize = 0;\r
542 KeyBuffer = NULL;\r
543 KeyBlobSize = 0;\r
544 KeyBlob = NULL;\r
545 KeyInfo = NULL;\r
546 KEKSigData = NULL;\r
547 KekSigList = NULL;\r
548 KekSigListSize = 0;\r
20333c6d 549\r
ecc722ad 550 //\r
551 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.\r
552 // First, We have to parse out public key data from the pbk key file.\r
20333c6d 553 //\r
ecc722ad 554 Status = ReadFileContent (\r
555 Private->FileContext->FHandle,\r
4adc12bf 556 (VOID**) &KeyBlob,\r
ecc722ad 557 &KeyBlobSize,\r
558 0\r
559 );\r
560 if (EFI_ERROR (Status)) {\r
561 goto ON_EXIT;\r
562 }\r
ba57d4fd 563 ASSERT (KeyBlob != NULL);\r
ecc722ad 564 KeyInfo = (CPL_KEY_INFO *) KeyBlob;\r
565 if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {\r
566 DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));\r
567 Status = EFI_UNSUPPORTED;\r
568 goto ON_EXIT;\r
569 }\r
20333c6d 570\r
ecc722ad 571 //\r
572 // Convert the Public key to fix octet string format represented in RSA PKCS#1.\r
20333c6d 573 //\r
ecc722ad 574 KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;\r
575 KeyBuffer = AllocateZeroPool (KeyLenInBytes);\r
576 if (KeyBuffer == NULL) {\r
577 Status = EFI_OUT_OF_RESOURCES;\r
578 goto ON_EXIT;\r
579 }\r
580 Int2OctStr (\r
20333c6d
QL
581 (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),\r
582 KeyLenInBytes / sizeof (UINTN),\r
583 KeyBuffer,\r
ecc722ad 584 KeyLenInBytes\r
585 );\r
586 CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);\r
20333c6d 587\r
ecc722ad 588 //\r
589 // Form an new EFI_SIGNATURE_LIST.\r
590 //\r
591 KekSigListSize = sizeof(EFI_SIGNATURE_LIST)\r
592 + sizeof(EFI_SIGNATURE_DATA) - 1\r
593 + WIN_CERT_UEFI_RSA2048_SIZE;\r
594\r
595 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
596 if (KekSigList == NULL) {\r
597 Status = EFI_OUT_OF_RESOURCES;\r
598 goto ON_EXIT;\r
599 }\r
600\r
601 KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST)\r
602 + sizeof(EFI_SIGNATURE_DATA) - 1\r
603 + WIN_CERT_UEFI_RSA2048_SIZE;\r
604 KekSigList->SignatureHeaderSize = 0;\r
605 KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;\r
606 CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);\r
20333c6d 607\r
ecc722ad 608 KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));\r
609 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
610 CopyMem (\r
611 KEKSigData->SignatureData,\r
612 KeyBlob + sizeof(CPL_KEY_INFO),\r
613 WIN_CERT_UEFI_RSA2048_SIZE\r
614 );\r
20333c6d 615\r
ecc722ad 616 //\r
20333c6d
QL
617 // Check if KEK entry has been already existed.\r
618 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 619 // new KEK to original variable.\r
20333c6d
QL
620 //\r
621 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 622 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
623 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
624 if (EFI_ERROR (Status)) {\r
625 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
626 goto ON_EXIT;\r
627 }\r
628\r
ecc722ad 629 Status = gRT->GetVariable(\r
20333c6d
QL
630 EFI_KEY_EXCHANGE_KEY_NAME,\r
631 &gEfiGlobalVariableGuid,\r
632 NULL,\r
633 &DataSize,\r
ecc722ad 634 NULL\r
635 );\r
636 if (Status == EFI_BUFFER_TOO_SMALL) {\r
637 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
638 } else if (Status != EFI_NOT_FOUND) {\r
639 goto ON_EXIT;\r
640 }\r
20333c6d 641\r
ecc722ad 642 //\r
643 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,\r
20333c6d 644 //\r
ecc722ad 645 Status = gRT->SetVariable(\r
20333c6d
QL
646 EFI_KEY_EXCHANGE_KEY_NAME,\r
647 &gEfiGlobalVariableGuid,\r
648 Attr,\r
649 KekSigListSize,\r
ecc722ad 650 KekSigList\r
651 );\r
652 if (EFI_ERROR (Status)) {\r
653 goto ON_EXIT;\r
654 }\r
20333c6d 655\r
ecc722ad 656ON_EXIT:\r
657\r
658 CloseFile (Private->FileContext->FHandle);\r
659 Private->FileContext->FHandle = NULL;\r
660 Private->FileContext->FileName = NULL;\r
661\r
662 if (Private->SignatureGUID != NULL) {\r
663 FreePool (Private->SignatureGUID);\r
664 Private->SignatureGUID = NULL;\r
665 }\r
666\r
667 if (KeyBlob != NULL) {\r
668 FreePool (KeyBlob);\r
669 }\r
670 if (KeyBuffer != NULL) {\r
671 FreePool (KeyBuffer);\r
672 }\r
673 if (KekSigList != NULL) {\r
674 FreePool (KekSigList);\r
675 }\r
20333c6d 676\r
ecc722ad 677 return Status;\r
678}\r
679\r
680/**\r
681 Enroll a new KEK item from X509 certificate file.\r
682\r
683 @param[in] PrivateData The module's private data.\r
684\r
685 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
686 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
687 @retval EFI_UNSUPPORTED Unsupported command.\r
688 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
689\r
690**/\r
691EFI_STATUS\r
692EnrollX509ToKek (\r
693 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
20333c6d 694 )\r
ecc722ad 695{\r
696 EFI_STATUS Status;\r
697 UINTN X509DataSize;\r
698 VOID *X509Data;\r
699 EFI_SIGNATURE_DATA *KEKSigData;\r
700 EFI_SIGNATURE_LIST *KekSigList;\r
701 UINTN DataSize;\r
702 UINTN KekSigListSize;\r
703 UINT32 Attr;\r
704\r
705 X509Data = NULL;\r
706 X509DataSize = 0;\r
707 KekSigList = NULL;\r
708 KekSigListSize = 0;\r
709 DataSize = 0;\r
710 KEKSigData = NULL;\r
711\r
712 Status = ReadFileContent (\r
713 Private->FileContext->FHandle,\r
714 &X509Data,\r
715 &X509DataSize,\r
716 0\r
717 );\r
718 if (EFI_ERROR (Status)) {\r
719 goto ON_EXIT;\r
720 }\r
ba57d4fd 721 ASSERT (X509Data != NULL);\r
ecc722ad 722\r
723 KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
724 KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
725 if (KekSigList == NULL) {\r
726 Status = EFI_OUT_OF_RESOURCES;\r
727 goto ON_EXIT;\r
728 }\r
729\r
730 //\r
731 // Fill Certificate Database parameters.\r
20333c6d 732 //\r
ecc722ad 733 KekSigList->SignatureListSize = (UINT32) KekSigListSize;\r
734 KekSigList->SignatureHeaderSize = 0;\r
735 KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
736 CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);\r
737\r
738 KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));\r
739 CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
740 CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);\r
741\r
742 //\r
20333c6d
QL
743 // Check if KEK been already existed.\r
744 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 745 // new kek to original variable\r
20333c6d
QL
746 //\r
747 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 748 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
749 Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
750 if (EFI_ERROR (Status)) {\r
751 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
752 goto ON_EXIT;\r
753 }\r
20333c6d 754\r
ecc722ad 755 Status = gRT->GetVariable(\r
20333c6d
QL
756 EFI_KEY_EXCHANGE_KEY_NAME,\r
757 &gEfiGlobalVariableGuid,\r
758 NULL,\r
759 &DataSize,\r
ecc722ad 760 NULL\r
761 );\r
762 if (Status == EFI_BUFFER_TOO_SMALL) {\r
763 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
764 } else if (Status != EFI_NOT_FOUND) {\r
765 goto ON_EXIT;\r
20333c6d 766 }\r
ecc722ad 767\r
768 Status = gRT->SetVariable(\r
20333c6d
QL
769 EFI_KEY_EXCHANGE_KEY_NAME,\r
770 &gEfiGlobalVariableGuid,\r
771 Attr,\r
ecc722ad 772 KekSigListSize,\r
773 KekSigList\r
774 );\r
775 if (EFI_ERROR (Status)) {\r
776 goto ON_EXIT;\r
777 }\r
778\r
779ON_EXIT:\r
20333c6d
QL
780\r
781 CloseFile (Private->FileContext->FHandle);\r
782 Private->FileContext->FileName = NULL;\r
783 Private->FileContext->FHandle = NULL;\r
784\r
785 if (Private->SignatureGUID != NULL) {\r
786 FreePool (Private->SignatureGUID);\r
787 Private->SignatureGUID = NULL;\r
788 }\r
789\r
790 if (KekSigList != NULL) {\r
791 FreePool (KekSigList);\r
792 }\r
793\r
794 return Status;\r
795}\r
796\r
797/**\r
798 Enroll new KEK into the System without PK's authentication.\r
799 The SignatureOwner GUID will be Private->SignatureGUID.\r
800\r
801 @param[in] PrivateData The module's private data.\r
802\r
803 @retval EFI_SUCCESS New KEK enrolled successful.\r
804 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
805 @retval others Fail to enroll KEK data.\r
806\r
807**/\r
808EFI_STATUS\r
809EnrollKeyExchangeKey (\r
810 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
811 )\r
812{\r
813 UINT16* FilePostFix;\r
814 EFI_STATUS Status;\r
815 UINTN NameLength;\r
816\r
817 if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {\r
818 return EFI_INVALID_PARAMETER;\r
819 }\r
820\r
821 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
822 if (EFI_ERROR (Status)) {\r
823 return Status;\r
824 }\r
825\r
826 //\r
827 // Parse the file's postfix. Supports DER-encoded X509 certificate,\r
828 // and .pbk as RSA public key file.\r
829 //\r
830 NameLength = StrLen (Private->FileContext->FileName);\r
831 if (NameLength <= 4) {\r
832 return EFI_INVALID_PARAMETER;\r
833 }\r
834 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
835 if (IsDerEncodeCertificate(FilePostFix)) {\r
836 return EnrollX509ToKek (Private);\r
837 } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {\r
838 return EnrollRsa2048ToKek (Private);\r
839 } else {\r
840 return EFI_INVALID_PARAMETER;\r
841 }\r
842}\r
843\r
844/**\r
845 Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without\r
846 KEK's authentication.\r
847\r
848 @param[in] PrivateData The module's private data.\r
849 @param[in] VariableName Variable name of signature database, must be\r
850 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
851\r
852 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
853 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
854\r
855**/\r
856EFI_STATUS\r
857EnrollX509toSigDB (\r
858 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
859 IN CHAR16 *VariableName\r
860 )\r
861{\r
862 EFI_STATUS Status;\r
863 UINTN X509DataSize;\r
864 VOID *X509Data;\r
865 EFI_SIGNATURE_LIST *SigDBCert;\r
866 EFI_SIGNATURE_DATA *SigDBCertData;\r
867 VOID *Data;\r
868 UINTN DataSize;\r
869 UINTN SigDBSize;\r
870 UINT32 Attr;\r
871\r
872 X509DataSize = 0;\r
873 SigDBSize = 0;\r
874 DataSize = 0;\r
875 X509Data = NULL;\r
876 SigDBCert = NULL;\r
877 SigDBCertData = NULL;\r
878 Data = NULL;\r
879\r
880 Status = ReadFileContent (\r
881 Private->FileContext->FHandle,\r
882 &X509Data,\r
883 &X509DataSize,\r
884 0\r
885 );\r
886 if (EFI_ERROR (Status)) {\r
887 goto ON_EXIT;\r
888 }\r
889 ASSERT (X509Data != NULL);\r
890\r
891 SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
892\r
893 Data = AllocateZeroPool (SigDBSize);\r
894 if (Data == NULL) {\r
895 Status = EFI_OUT_OF_RESOURCES;\r
896 goto ON_EXIT;\r
897 }\r
898\r
899 //\r
900 // Fill Certificate Database parameters.\r
901 //\r
902 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
903 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
904 SigDBCert->SignatureHeaderSize = 0;\r
905 SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
906 CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);\r
907\r
908 SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));\r
909 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
910 CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);\r
911\r
912 //\r
913 // Check if signature database entry has been already existed.\r
914 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
915 // new signature data to original variable\r
916 //\r
917 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
918 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
919 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
920 if (EFI_ERROR (Status)) {\r
921 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
922 goto ON_EXIT;\r
923 }\r
924\r
925 Status = gRT->GetVariable(\r
926 VariableName,\r
927 &gEfiImageSecurityDatabaseGuid,\r
928 NULL,\r
929 &DataSize,\r
930 NULL\r
931 );\r
932 if (Status == EFI_BUFFER_TOO_SMALL) {\r
933 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
934 } else if (Status != EFI_NOT_FOUND) {\r
935 goto ON_EXIT;\r
936 }\r
937\r
938 Status = gRT->SetVariable(\r
939 VariableName,\r
940 &gEfiImageSecurityDatabaseGuid,\r
941 Attr,\r
942 SigDBSize,\r
943 Data\r
944 );\r
945 if (EFI_ERROR (Status)) {\r
946 goto ON_EXIT;\r
947 }\r
948\r
949ON_EXIT:\r
950\r
951 CloseFile (Private->FileContext->FHandle);\r
952 Private->FileContext->FileName = NULL;\r
953 Private->FileContext->FHandle = NULL;\r
954\r
955 if (Private->SignatureGUID != NULL) {\r
956 FreePool (Private->SignatureGUID);\r
957 Private->SignatureGUID = NULL;\r
958 }\r
959\r
960 if (Data != NULL) {\r
961 FreePool (Data);\r
962 }\r
963\r
964 if (X509Data != NULL) {\r
965 FreePool (X509Data);\r
966 }\r
967\r
968 return Status;\r
969}\r
970\r
971/**\r
972 Check whether signature is in specified database.\r
973\r
974 @param[in] VariableName Name of database variable that is searched in.\r
975 @param[in] Signature Pointer to signature that is searched for.\r
976 @param[in] SignatureSize Size of Signature.\r
977\r
978 @return TRUE Found the signature in the variable database.\r
979 @return FALSE Not found the signature in the variable database.\r
980\r
981**/\r
982BOOLEAN\r
983IsSignatureFoundInDatabase (\r
984 IN CHAR16 *VariableName,\r
985 IN UINT8 *Signature,\r
986 IN UINTN SignatureSize\r
987 )\r
988{\r
989 EFI_STATUS Status;\r
990 EFI_SIGNATURE_LIST *CertList;\r
991 EFI_SIGNATURE_DATA *Cert;\r
992 UINTN DataSize;\r
993 UINT8 *Data;\r
994 UINTN Index;\r
995 UINTN CertCount;\r
996 BOOLEAN IsFound;\r
997\r
998 //\r
999 // Read signature database variable.\r
1000 //\r
1001 IsFound = FALSE;\r
1002 Data = NULL;\r
1003 DataSize = 0;\r
1004 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
1005 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1006 return FALSE;\r
1007 }\r
1008\r
1009 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1010 if (Data == NULL) {\r
1011 return FALSE;\r
1012 }\r
1013\r
1014 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
1015 if (EFI_ERROR (Status)) {\r
1016 goto Done;\r
1017 }\r
1018\r
1019 //\r
1020 // Enumerate all signature data in SigDB to check if executable's signature exists.\r
1021 //\r
1022 CertList = (EFI_SIGNATURE_LIST *) Data;\r
1023 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
1024 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
1025 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
1026 if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) {\r
1027 for (Index = 0; Index < CertCount; Index++) {\r
1028 if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {\r
1029 //\r
1030 // Find the signature in database.\r
1031 //\r
1032 IsFound = TRUE;\r
1033 break;\r
1034 }\r
1035 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
1036 }\r
1037\r
1038 if (IsFound) {\r
1039 break;\r
1040 }\r
1041 }\r
1042\r
1043 DataSize -= CertList->SignatureListSize;\r
1044 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
1045 }\r
1046\r
1047Done:\r
1048 if (Data != NULL) {\r
1049 FreePool (Data);\r
1050 }\r
1051\r
1052 return IsFound;\r
1053}\r
1054\r
1055/**\r
1056 Calculate the hash of a certificate data with the specified hash algorithm.\r
1057\r
1058 @param[in] CertData The certificate data to be hashed.\r
1059 @param[in] CertSize The certificate size in bytes.\r
1060 @param[in] HashAlg The specified hash algorithm.\r
1061 @param[out] CertHash The output digest of the certificate\r
1062\r
1063 @retval TRUE Successfully got the hash of the CertData.\r
1064 @retval FALSE Failed to get the hash of CertData.\r
1065\r
1066**/\r
1067BOOLEAN\r
1068CalculateCertHash (\r
1069 IN UINT8 *CertData,\r
1070 IN UINTN CertSize,\r
1071 IN UINT32 HashAlg,\r
1072 OUT UINT8 *CertHash\r
1073 )\r
1074{\r
1075 BOOLEAN Status;\r
1076 VOID *HashCtx;\r
1077 UINTN CtxSize;\r
12d95665
LQ
1078 UINT8 *TBSCert;\r
1079 UINTN TBSCertSize;\r
20333c6d
QL
1080\r
1081 HashCtx = NULL;\r
1082 Status = FALSE;\r
1083\r
1084 if (HashAlg >= HASHALG_MAX) {\r
1085 return FALSE;\r
1086 }\r
1087\r
12d95665
LQ
1088 //\r
1089 // Retrieve the TBSCertificate for Hash Calculation.\r
1090 //\r
1091 if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {\r
1092 return FALSE;\r
1093 }\r
1094\r
20333c6d
QL
1095 //\r
1096 // 1. Initialize context of hash.\r
1097 //\r
1098 CtxSize = mHash[HashAlg].GetContextSize ();\r
1099 HashCtx = AllocatePool (CtxSize);\r
1100 ASSERT (HashCtx != NULL);\r
1101\r
1102 //\r
1103 // 2. Initialize a hash context.\r
1104 //\r
1105 Status = mHash[HashAlg].HashInit (HashCtx);\r
1106 if (!Status) {\r
1107 goto Done;\r
1108 }\r
1109\r
1110 //\r
1111 // 3. Calculate the hash.\r
1112 //\r
12d95665 1113 Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
20333c6d
QL
1114 if (!Status) {\r
1115 goto Done;\r
1116 }\r
1117\r
1118 //\r
1119 // 4. Get the hash result.\r
1120 //\r
1121 ZeroMem (CertHash, mHash[HashAlg].DigestLength);\r
1122 Status = mHash[HashAlg].HashFinal (HashCtx, CertHash);\r
1123\r
1124Done:\r
1125 if (HashCtx != NULL) {\r
1126 FreePool (HashCtx);\r
1127 }\r
1128\r
1129 return Status;\r
1130}\r
1131\r
1132/**\r
1133 Check whether the hash of an X.509 certificate is in forbidden database (DBX).\r
1134\r
1135 @param[in] Certificate Pointer to X.509 Certificate that is searched for.\r
1136 @param[in] CertSize Size of X.509 Certificate.\r
1137\r
1138 @return TRUE Found the certificate hash in the forbidden database.\r
1139 @return FALSE Certificate hash is Not found in the forbidden database.\r
1140\r
1141**/\r
1142BOOLEAN\r
1143IsCertHashFoundInDbx (\r
1144 IN UINT8 *Certificate,\r
1145 IN UINTN CertSize\r
1146 )\r
1147{\r
1148 BOOLEAN IsFound;\r
1149 EFI_STATUS Status;\r
1150 EFI_SIGNATURE_LIST *DbxList;\r
1151 EFI_SIGNATURE_DATA *CertHash;\r
1152 UINTN CertHashCount;\r
1153 UINTN Index;\r
1154 UINT32 HashAlg;\r
1155 UINT8 CertDigest[MAX_DIGEST_SIZE];\r
1156 UINT8 *DbxCertHash;\r
1157 UINTN SiglistHeaderSize;\r
1158 UINT8 *Data;\r
1159 UINTN DataSize;\r
1160\r
1161 IsFound = FALSE;\r
1162 HashAlg = HASHALG_MAX;\r
1163 Data = NULL;\r
1164\r
1165 //\r
1166 // Read signature database variable.\r
1167 //\r
1168 DataSize = 0;\r
1169 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
1170 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1171 return FALSE;\r
1172 }\r
1173\r
1174 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1175 if (Data == NULL) {\r
1176 return FALSE;\r
1177 }\r
1178\r
1179 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
1180 if (EFI_ERROR (Status)) {\r
1181 goto Done;\r
1182 }\r
1183\r
1184 //\r
1185 // Check whether the certificate hash exists in the forbidden database.\r
1186 //\r
1187 DbxList = (EFI_SIGNATURE_LIST *) Data;\r
1188 while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {\r
1189 //\r
1190 // Determine Hash Algorithm of Certificate in the forbidden database.\r
1191 //\r
1192 if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
1193 HashAlg = HASHALG_SHA256;\r
1194 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
1195 HashAlg = HASHALG_SHA384;\r
1196 } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
1197 HashAlg = HASHALG_SHA512;\r
1198 } else {\r
1199 DataSize -= DbxList->SignatureListSize;\r
1200 DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
1201 continue;\r
1202 }\r
1203\r
1204 //\r
1205 // Calculate the hash value of current db certificate for comparision.\r
1206 //\r
1207 if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {\r
1208 goto Done;\r
1209 }\r
1210\r
1211 SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;\r
1212 CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);\r
1213 CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;\r
1214 for (Index = 0; Index < CertHashCount; Index++) {\r
1215 //\r
1216 // Iterate each Signature Data Node within this CertList for verify.\r
1217 //\r
1218 DbxCertHash = CertHash->SignatureData;\r
1219 if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {\r
1220 //\r
1221 // Hash of Certificate is found in forbidden database.\r
1222 //\r
1223 IsFound = TRUE;\r
1224 goto Done;\r
1225 }\r
1226 CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);\r
1227 }\r
1228\r
1229 DataSize -= DbxList->SignatureListSize;\r
1230 DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
1231 }\r
1232\r
1233Done:\r
1234 if (Data != NULL) {\r
1235 FreePool (Data);\r
1236 }\r
1237\r
1238 return IsFound;\r
1239}\r
1240\r
1241/**\r
1242 Check whether the signature list exists in given variable data.\r
1243\r
1244 It searches the signature list for the ceritificate hash by CertType.\r
1245 If the signature list is found, get the offset of Database for the\r
1246 next hash of a certificate.\r
1247\r
1248 @param[in] Database Variable data to save signature list.\r
1249 @param[in] DatabaseSize Variable size.\r
1250 @param[in] SignatureType The type of the signature.\r
1251 @param[out] Offset The offset to save a new hash of certificate.\r
1252\r
1253 @return TRUE The signature list is found in the forbidden database.\r
1254 @return FALSE The signature list is not found in the forbidden database.\r
1255**/\r
1256BOOLEAN\r
1257GetSignaturelistOffset (\r
1258 IN EFI_SIGNATURE_LIST *Database,\r
1259 IN UINTN DatabaseSize,\r
1260 IN EFI_GUID *SignatureType,\r
1261 OUT UINTN *Offset\r
1262 )\r
1263{\r
1264 EFI_SIGNATURE_LIST *SigList;\r
1265 UINTN SiglistSize;\r
1266\r
1267 if ((Database == NULL) || (DatabaseSize == 0)) {\r
1268 *Offset = 0;\r
1269 return FALSE;\r
1270 }\r
1271\r
1272 SigList = Database;\r
1273 SiglistSize = DatabaseSize;\r
1274 while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {\r
1275 if (CompareGuid (&SigList->SignatureType, SignatureType)) {\r
1276 *Offset = DatabaseSize - SiglistSize;\r
1277 return TRUE;\r
1278 }\r
1279 SiglistSize -= SigList->SignatureListSize;\r
1280 SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);\r
1281 }\r
1282 *Offset = 0;\r
1283 return FALSE;\r
1284}\r
1285\r
1286/**\r
1287 Enroll a new X509 certificate hash into Signature Database (dbx) without\r
1288 KEK's authentication.\r
1289\r
1290 @param[in] PrivateData The module's private data.\r
1291 @param[in] HashAlg The hash algorithm to enroll the certificate.\r
1292 @param[in] RevocationDate The revocation date of the certificate.\r
1293 @param[in] RevocationTime The revocation time of the certificate.\r
1294 @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.\r
1295\r
1296 @retval EFI_SUCCESS New X509 is enrolled successfully.\r
1297 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1298 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
1299\r
1300**/\r
1301EFI_STATUS\r
1302EnrollX509HashtoSigDB (\r
1303 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1304 IN UINT32 HashAlg,\r
1305 IN EFI_HII_DATE *RevocationDate,\r
1306 IN EFI_HII_TIME *RevocationTime,\r
1307 IN BOOLEAN AlwaysRevocation\r
1308 )\r
1309{\r
1310 EFI_STATUS Status;\r
1311 UINTN X509DataSize;\r
1312 VOID *X509Data;\r
1313 EFI_SIGNATURE_LIST *SignatureList;\r
1314 UINTN SignatureListSize;\r
1315 UINT8 *Data;\r
1316 UINT8 *NewData;\r
1317 UINTN DataSize;\r
1318 UINTN DbSize;\r
1319 UINT32 Attr;\r
1320 EFI_SIGNATURE_DATA *SignatureData;\r
1321 UINTN SignatureSize;\r
1322 EFI_GUID SignatureType;\r
1323 UINTN Offset;\r
1324 UINT8 CertHash[MAX_DIGEST_SIZE];\r
1325 UINT16* FilePostFix;\r
1326 UINTN NameLength;\r
1327 EFI_TIME *Time;\r
1328\r
1329 X509DataSize = 0;\r
1330 DbSize = 0;\r
1331 X509Data = NULL;\r
1332 SignatureData = NULL;\r
1333 SignatureList = NULL;\r
1334 Data = NULL;\r
1335 NewData = NULL;\r
1336\r
1337 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
1338 return EFI_INVALID_PARAMETER;\r
1339 }\r
1340\r
1341 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
1342 if (EFI_ERROR (Status)) {\r
1343 return Status;\r
1344 }\r
1345\r
1346 //\r
1347 // Parse the file's postfix.\r
1348 //\r
1349 NameLength = StrLen (Private->FileContext->FileName);\r
1350 if (NameLength <= 4) {\r
1351 return EFI_INVALID_PARAMETER;\r
1352 }\r
1353 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
1354 if (!IsDerEncodeCertificate(FilePostFix)) {\r
1355 //\r
1356 // Only supports DER-encoded X509 certificate.\r
1357 //\r
1358 return EFI_INVALID_PARAMETER;\r
1359 }\r
1360\r
1361 //\r
1362 // Get the certificate from file and calculate its hash.\r
1363 //\r
1364 Status = ReadFileContent (\r
1365 Private->FileContext->FHandle,\r
1366 &X509Data,\r
1367 &X509DataSize,\r
1368 0\r
1369 );\r
1370 if (EFI_ERROR (Status)) {\r
1371 goto ON_EXIT;\r
1372 }\r
1373 ASSERT (X509Data != NULL);\r
1374\r
1375 if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {\r
1376 goto ON_EXIT;\r
1377 }\r
1378\r
1379 //\r
1380 // Get the variable for enrollment.\r
1381 //\r
1382 DataSize = 0;\r
1383 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
1384 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1385 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
1386 if (Data == NULL) {\r
1387 return EFI_OUT_OF_RESOURCES;\r
1388 }\r
1389\r
1390 Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
1391 if (EFI_ERROR (Status)) {\r
1392 goto ON_EXIT;\r
1393 }\r
1394 }\r
1395\r
1396 //\r
1397 // Allocate memory for Signature and fill the Signature\r
1398 //\r
1399 SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;\r
1400 SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize);\r
1401 if (SignatureData == NULL) {\r
1402 return EFI_OUT_OF_RESOURCES;\r
1403 }\r
1404 CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);\r
1405 CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);\r
1406\r
1407 //\r
1408 // Fill the time.\r
1409 //\r
1410 if (!AlwaysRevocation) {\r
1411 Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);\r
1412 Time->Year = RevocationDate->Year;\r
1413 Time->Month = RevocationDate->Month;\r
1414 Time->Day = RevocationDate->Day;\r
1415 Time->Hour = RevocationTime->Hour;\r
1416 Time->Minute = RevocationTime->Minute;\r
1417 Time->Second = RevocationTime->Second;\r
1418 }\r
1419\r
1420 //\r
1421 // Determine the GUID for certificate hash.\r
1422 //\r
1423 switch (HashAlg) {\r
1424 case HASHALG_SHA256:\r
1425 SignatureType = gEfiCertX509Sha256Guid;\r
1426 break;\r
1427 case HASHALG_SHA384:\r
1428 SignatureType = gEfiCertX509Sha384Guid;\r
1429 break;\r
1430 case HASHALG_SHA512:\r
1431 SignatureType = gEfiCertX509Sha512Guid;\r
1432 break;\r
1433 default:\r
1434 return FALSE;\r
1435 }\r
1436\r
1437 //\r
1438 // Add signature into the new variable data buffer\r
1439 //\r
1440 if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {\r
1441 //\r
1442 // Add the signature to the found signaturelist.\r
1443 //\r
1444 DbSize = DataSize + SignatureSize;\r
1445 NewData = AllocateZeroPool (DbSize);\r
1446 if (NewData == NULL) {\r
1447 Status = EFI_OUT_OF_RESOURCES;\r
1448 goto ON_EXIT;\r
1449 }\r
1450\r
1451 SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
1452 SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);\r
1453 CopyMem (NewData, Data, Offset + SignatureListSize);\r
1454\r
1455 SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);\r
1456 WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));\r
1457\r
1458 Offset += SignatureListSize;\r
1459 CopyMem (NewData + Offset, SignatureData, SignatureSize);\r
1460 CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);\r
1461\r
1462 FreePool (Data);\r
1463 Data = NewData;\r
1464 DataSize = DbSize;\r
1465 } else {\r
1466 //\r
1467 // Create a new signaturelist, and add the signature into the signaturelist.\r
1468 //\r
1469 DbSize = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize;\r
1470 NewData = AllocateZeroPool (DbSize);\r
1471 if (NewData == NULL) {\r
1472 Status = EFI_OUT_OF_RESOURCES;\r
1473 goto ON_EXIT;\r
1474 }\r
1475 //\r
1476 // Fill Certificate Database parameters.\r
1477 //\r
1478 SignatureList = (EFI_SIGNATURE_LIST*) (NewData + DataSize);\r
1479 SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize;\r
1480 WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize);\r
1481 WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize);\r
1482 CopyGuid (&SignatureList->SignatureType, &SignatureType);\r
1483 CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);\r
1484 if ((DataSize != 0) && (Data != NULL)) {\r
1485 CopyMem (NewData, Data, DataSize);\r
1486 FreePool (Data);\r
1487 }\r
1488 Data = NewData;\r
1489 DataSize = DbSize;\r
1490 }\r
1491\r
1492 Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data);\r
1493 if (EFI_ERROR (Status)) {\r
1494 goto ON_EXIT;\r
1495 }\r
1496\r
1497 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
1498 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
1499 Status = gRT->SetVariable(\r
1500 EFI_IMAGE_SECURITY_DATABASE1,\r
1501 &gEfiImageSecurityDatabaseGuid,\r
1502 Attr,\r
1503 DataSize,\r
1504 Data\r
1505 );\r
1506 if (EFI_ERROR (Status)) {\r
1507 goto ON_EXIT;\r
1508 }\r
1509\r
1510ON_EXIT:\r
ecc722ad 1511 CloseFile (Private->FileContext->FHandle);\r
1512 Private->FileContext->FileName = NULL;\r
1513 Private->FileContext->FHandle = NULL;\r
1514\r
1515 if (Private->SignatureGUID != NULL) {\r
1516 FreePool (Private->SignatureGUID);\r
1517 Private->SignatureGUID = NULL;\r
1518 }\r
1519\r
20333c6d
QL
1520 if (Data != NULL) {\r
1521 FreePool (Data);\r
ecc722ad 1522 }\r
1523\r
20333c6d
QL
1524 if (SignatureData != NULL) {\r
1525 FreePool (SignatureData);\r
ecc722ad 1526 }\r
1527\r
20333c6d
QL
1528 if (X509Data != NULL) {\r
1529 FreePool (X509Data);\r
f71ed839 1530 }\r
1531\r
20333c6d 1532 return Status;\r
ecc722ad 1533}\r
1534\r
1535/**\r
20333c6d 1536 Check whether a certificate from a file exists in dbx.\r
ecc722ad 1537\r
1538 @param[in] PrivateData The module's private data.\r
20333c6d
QL
1539 @param[in] VariableName Variable name of signature database, must be\r
1540 EFI_IMAGE_SECURITY_DATABASE1.\r
ecc722ad 1541\r
20333c6d
QL
1542 @retval TRUE The X509 certificate is found in dbx successfully.\r
1543 @retval FALSE The X509 certificate is not found in dbx.\r
ecc722ad 1544**/\r
20333c6d
QL
1545BOOLEAN\r
1546IsX509CertInDbx (\r
ecc722ad 1547 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
1548 IN CHAR16 *VariableName\r
20333c6d 1549 )\r
ecc722ad 1550{\r
20333c6d
QL
1551 EFI_STATUS Status;\r
1552 UINTN X509DataSize;\r
1553 VOID *X509Data;\r
1554 BOOLEAN IsFound;\r
ecc722ad 1555\r
20333c6d
QL
1556 //\r
1557 // Read the certificate from file\r
1558 //\r
ecc722ad 1559 X509DataSize = 0;\r
ecc722ad 1560 X509Data = NULL;\r
ecc722ad 1561 Status = ReadFileContent (\r
1562 Private->FileContext->FHandle,\r
1563 &X509Data,\r
1564 &X509DataSize,\r
1565 0\r
1566 );\r
1567 if (EFI_ERROR (Status)) {\r
20333c6d 1568 return FALSE;\r
ecc722ad 1569 }\r
1570\r
1571 //\r
20333c6d 1572 // Check the raw certificate.\r
ecc722ad 1573 //\r
20333c6d
QL
1574 IsFound = FALSE;\r
1575 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {\r
1576 IsFound = TRUE;\r
8c1babfd 1577 goto ON_EXIT;\r
1578 }\r
ecc722ad 1579\r
20333c6d
QL
1580 //\r
1581 // Check the hash of certificate.\r
1582 //\r
1583 if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {\r
1584 IsFound = TRUE;\r
ecc722ad 1585 goto ON_EXIT;\r
1586 }\r
1587\r
1588ON_EXIT:\r
ecc722ad 1589 if (X509Data != NULL) {\r
1590 FreePool (X509Data);\r
1591 }\r
1592\r
20333c6d 1593 return IsFound;\r
ecc722ad 1594}\r
1595\r
1596/**\r
1597 Load PE/COFF image information into internal buffer and check its validity.\r
1598\r
1599 @retval EFI_SUCCESS Successful\r
1600 @retval EFI_UNSUPPORTED Invalid PE/COFF file\r
1601 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.\r
1602\r
1603**/\r
1604EFI_STATUS\r
1605LoadPeImage (\r
20333c6d
QL
1606 VOID\r
1607 )\r
ecc722ad 1608{\r
1609 EFI_IMAGE_DOS_HEADER *DosHdr;\r
1610 EFI_IMAGE_NT_HEADERS32 *NtHeader32;\r
1611 EFI_IMAGE_NT_HEADERS64 *NtHeader64;\r
1612\r
1613 NtHeader32 = NULL;\r
1614 NtHeader64 = NULL;\r
1615 //\r
1616 // Read the Dos header\r
1617 //\r
1618 DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);\r
1619 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)\r
1620 {\r
1621 //\r
20333c6d 1622 // DOS image header is present,\r
ecc722ad 1623 // So read the PE header after the DOS image header\r
1624 //\r
1625 mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
1626 }\r
1627 else\r
1628 {\r
1629 mPeCoffHeaderOffset = 0;\r
1630 }\r
1631\r
1632 //\r
1633 // Read PE header and check the signature validity and machine compatibility\r
1634 //\r
1635 NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);\r
1636 if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)\r
1637 {\r
1638 return EFI_UNSUPPORTED;\r
1639 }\r
1640\r
1641 mNtHeader.Pe32 = NtHeader32;\r
1642\r
1643 //\r
1644 // Check the architecture field of PE header and get the Certificate Data Directory data\r
1645 // Note the size of FileHeader field is constant for both IA32 and X64 arch\r
1646 //\r
20333c6d 1647 if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)\r
a16170a1
AB
1648 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)\r
1649 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) {\r
ecc722ad 1650 //\r
a16170a1 1651 // 32-bits Architecture\r
ecc722ad 1652 //\r
1653 mImageType = ImageType_IA32;\r
1654 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
1655 }\r
1656 else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
a16170a1
AB
1657 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)\r
1658 || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) {\r
ecc722ad 1659 //\r
1660 // 64-bits Architecture\r
1661 //\r
1662 mImageType = ImageType_X64;\r
1663 NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);\r
1664 mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
1665 } else {\r
1666 return EFI_UNSUPPORTED;\r
1667 }\r
1668\r
1669 return EFI_SUCCESS;\r
1670}\r
1671\r
1672/**\r
1673 Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
1674 PE/COFF Specification 8.0 Appendix A\r
1675\r
1676 @param[in] HashAlg Hash algorithm type.\r
20333c6d 1677\r
ecc722ad 1678 @retval TRUE Successfully hash image.\r
1679 @retval FALSE Fail in hash image.\r
1680\r
1681**/\r
20333c6d 1682BOOLEAN\r
ecc722ad 1683HashPeImage (\r
1684 IN UINT32 HashAlg\r
1685 )\r
1686{\r
1687 BOOLEAN Status;\r
1688 UINT16 Magic;\r
1689 EFI_IMAGE_SECTION_HEADER *Section;\r
1690 VOID *HashCtx;\r
1691 UINTN CtxSize;\r
1692 UINT8 *HashBase;\r
1693 UINTN HashSize;\r
1694 UINTN SumOfBytesHashed;\r
1695 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1696 UINTN Index;\r
1697 UINTN Pos;\r
1698\r
1699 HashCtx = NULL;\r
1700 SectionHeader = NULL;\r
1701 Status = FALSE;\r
1702\r
1703 if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
1704 return FALSE;\r
1705 }\r
20333c6d 1706\r
ecc722ad 1707 //\r
1708 // Initialize context of hash.\r
1709 //\r
1710 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
1711\r
1712 if (HashAlg == HASHALG_SHA1) {\r
1713 mImageDigestSize = SHA1_DIGEST_SIZE;\r
20333c6d 1714 mCertType = gEfiCertSha1Guid;\r
ecc722ad 1715 } else if (HashAlg == HASHALG_SHA256) {\r
1716 mImageDigestSize = SHA256_DIGEST_SIZE;\r
1717 mCertType = gEfiCertSha256Guid;\r
1718 }\r
1719\r
1720 CtxSize = mHash[HashAlg].GetContextSize();\r
20333c6d 1721\r
ecc722ad 1722 HashCtx = AllocatePool (CtxSize);\r
1723 ASSERT (HashCtx != NULL);\r
1724\r
1725 // 1. Load the image header into memory.\r
1726\r
1727 // 2. Initialize a SHA hash context.\r
1728 Status = mHash[HashAlg].HashInit(HashCtx);\r
1729 if (!Status) {\r
1730 goto Done;\r
1731 }\r
1732 //\r
1733 // Measuring PE/COFF Image Header;\r
1734 // But CheckSum field and SECURITY data directory (certificate) are excluded\r
1735 //\r
de2447dd 1736 if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1737 //\r
20333c6d
QL
1738 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
1739 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
de2447dd 1740 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1741 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1742 //\r
1743 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
1744 } else {\r
1745 //\r
1746 // Get the magic value from the PE/COFF Optional Header\r
1747 //\r
1748 Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
1749 }\r
20333c6d 1750\r
ecc722ad 1751 //\r
1752 // 3. Calculate the distance from the base of the image header to the image checksum address.\r
1753 // 4. Hash the image header from its base to beginning of the image checksum.\r
1754 //\r
1755 HashBase = mImageBase;\r
1756 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1757 //\r
1758 // Use PE32 offset.\r
1759 //\r
1760 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
1761 } else {\r
1762 //\r
1763 // Use PE32+ offset.\r
1764 //\r
1765 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
1766 }\r
1767\r
1768 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1769 if (!Status) {\r
1770 goto Done;\r
1771 }\r
1772 //\r
1773 // 5. Skip over the image checksum (it occupies a single ULONG).\r
1774 // 6. Get the address of the beginning of the Cert Directory.\r
1775 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
1776 //\r
1777 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1778 //\r
1779 // Use PE32 offset.\r
1780 //\r
1781 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
1782 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1783 } else {\r
1784 //\r
1785 // Use PE32+ offset.\r
20333c6d 1786 //\r
ecc722ad 1787 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
1788 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
1789 }\r
1790\r
1791 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1792 if (!Status) {\r
1793 goto Done;\r
1794 }\r
1795 //\r
1796 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
1797 // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
1798 //\r
1799 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1800 //\r
1801 // Use PE32 offset\r
1802 //\r
1803 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1804 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1805 } else {\r
1806 //\r
1807 // Use PE32+ offset.\r
1808 //\r
1809 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
1810 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
1811 }\r
1812\r
1813 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1814 if (!Status) {\r
1815 goto Done;\r
1816 }\r
1817 //\r
1818 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
1819 //\r
1820 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1821 //\r
1822 // Use PE32 offset.\r
1823 //\r
1824 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
1825 } else {\r
1826 //\r
1827 // Use PE32+ offset\r
1828 //\r
1829 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
1830 }\r
1831\r
1832 //\r
1833 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
1834 // structures in the image. The 'NumberOfSections' field of the image\r
1835 // header indicates how big the table should be. Do not include any\r
1836 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
1837 //\r
1838 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
1839 ASSERT (SectionHeader != NULL);\r
1840 //\r
1841 // 12. Using the 'PointerToRawData' in the referenced section headers as\r
1842 // a key, arrange the elements in the table in ascending order. In other\r
1843 // words, sort the section headers according to the disk-file offset of\r
1844 // the section.\r
1845 //\r
1846 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1847 mImageBase +\r
1848 mPeCoffHeaderOffset +\r
1849 sizeof (UINT32) +\r
1850 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1851 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
1852 );\r
1853 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1854 Pos = Index;\r
1855 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
1856 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
1857 Pos--;\r
1858 }\r
1859 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
1860 Section += 1;\r
1861 }\r
1862\r
1863 //\r
1864 // 13. Walk through the sorted table, bring the corresponding section\r
1865 // into memory, and hash the entire section (using the 'SizeOfRawData'\r
1866 // field in the section header to determine the amount of data to hash).\r
1867 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
1868 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.\r
1869 //\r
1870 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
1871 Section = &SectionHeader[Index];\r
1872 if (Section->SizeOfRawData == 0) {\r
1873 continue;\r
1874 }\r
1875 HashBase = mImageBase + Section->PointerToRawData;\r
1876 HashSize = (UINTN) Section->SizeOfRawData;\r
1877\r
1878 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1879 if (!Status) {\r
1880 goto Done;\r
1881 }\r
1882\r
1883 SumOfBytesHashed += HashSize;\r
1884 }\r
1885\r
1886 //\r
1887 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
1888 // data in the file that needs to be added to the hash. This data begins\r
1889 // at file offset SUM_OF_BYTES_HASHED and its length is:\r
1890 // FileSize - (CertDirectory->Size)\r
1891 //\r
1892 if (mImageSize > SumOfBytesHashed) {\r
1893 HashBase = mImageBase + SumOfBytesHashed;\r
1894 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1895 //\r
1896 // Use PE32 offset.\r
1897 //\r
1898 HashSize = (UINTN)(\r
1899 mImageSize -\r
1900 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
1901 SumOfBytesHashed);\r
1902 } else {\r
1903 //\r
1904 // Use PE32+ offset.\r
1905 //\r
1906 HashSize = (UINTN)(\r
1907 mImageSize -\r
1908 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
20333c6d 1909 SumOfBytesHashed);\r
ecc722ad 1910 }\r
1911\r
1912 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
1913 if (!Status) {\r
1914 goto Done;\r
1915 }\r
1916 }\r
1917\r
1918 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
1919\r
1920Done:\r
1921 if (HashCtx != NULL) {\r
1922 FreePool (HashCtx);\r
1923 }\r
1924 if (SectionHeader != NULL) {\r
1925 FreePool (SectionHeader);\r
1926 }\r
1927 return Status;\r
1928}\r
1929\r
1930/**\r
69f8bb52 1931 Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of\r
20333c6d 1932 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification\r
ecc722ad 1933 8.0 Appendix A\r
1934\r
1935 @retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
1936 @retval EFI_SUCCESS Hash successfully.\r
1937\r
1938**/\r
20333c6d 1939EFI_STATUS\r
ecc722ad 1940HashPeImageByType (\r
1941 VOID\r
1942 )\r
1943{\r
1944 UINT8 Index;\r
1945 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
1946\r
1947 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
1948\r
20333c6d 1949 for (Index = 0; Index < HASHALG_MAX; Index++) {\r
ecc722ad 1950 //\r
1951 // Check the Hash algorithm in PE/COFF Authenticode.\r
20333c6d 1952 // According to PKCS#7 Definition:\r
ecc722ad 1953 // SignedData ::= SEQUENCE {\r
1954 // version Version,\r
1955 // digestAlgorithms DigestAlgorithmIdentifiers,\r
1956 // contentInfo ContentInfo,\r
1957 // .... }\r
1958 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
1959 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
1960 // Fixed offset (+32) is calculated based on two bytes of length encoding.\r
1961 //\r
1962 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
1963 //\r
1964 // Only support two bytes of Long Form of Length Encoding.\r
1965 //\r
1966 continue;\r
1967 }\r
1968\r
20333c6d 1969 //\r
ecc722ad 1970 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
1971 break;\r
1972 }\r
1973 }\r
1974\r
1975 if (Index == HASHALG_MAX) {\r
1976 return EFI_UNSUPPORTED;\r
1977 }\r
1978\r
1979 //\r
1980 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
1981 //\r
1982 if (!HashPeImage(Index)) {\r
1983 return EFI_UNSUPPORTED;\r
1984 }\r
1985\r
1986 return EFI_SUCCESS;\r
1987}\r
1988\r
1989/**\r
20333c6d 1990 Enroll a new executable's signature into Signature Database.\r
ecc722ad 1991\r
1992 @param[in] PrivateData The module's private data.\r
20333c6d
QL
1993 @param[in] VariableName Variable name of signature database, must be\r
1994 EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1\r
1995 or EFI_IMAGE_SECURITY_DATABASE2.\r
ecc722ad 1996\r
1997 @retval EFI_SUCCESS New signature is enrolled successfully.\r
1998 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1999 @retval EFI_UNSUPPORTED Unsupported command.\r
2000 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
2001\r
2002**/\r
2003EFI_STATUS\r
2004EnrollImageSignatureToSigDB (\r
2005 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2006 IN CHAR16 *VariableName\r
2007 )\r
2008{\r
2009 EFI_STATUS Status;\r
2010 EFI_SIGNATURE_LIST *SigDBCert;\r
2011 EFI_SIGNATURE_DATA *SigDBCertData;\r
2012 VOID *Data;\r
2013 UINTN DataSize;\r
2014 UINTN SigDBSize;\r
2015 UINT32 Attr;\r
2016 WIN_CERTIFICATE_UEFI_GUID *GuidCertData;\r
2017\r
2018 Data = NULL;\r
2019 GuidCertData = NULL;\r
ecc722ad 2020\r
20333c6d
QL
2021 if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {\r
2022 return EFI_UNSUPPORTED;\r
2023 }\r
2024\r
ecc722ad 2025 //\r
2026 // Form the SigDB certificate list.\r
2027 // Format the data item into EFI_SIGNATURE_LIST type.\r
2028 //\r
2029 // We need to parse executable's signature data from specified signed executable file.\r
2030 // In current implementation, we simply trust the pass-in signed executable file.\r
2031 // In reality, it's OS's responsibility to verify the signed executable file.\r
2032 //\r
2033\r
2034 //\r
2035 // Read the whole file content\r
2036 //\r
2037 Status = ReadFileContent(\r
2038 Private->FileContext->FHandle,\r
20333c6d
QL
2039 (VOID **) &mImageBase,\r
2040 &mImageSize,\r
ecc722ad 2041 0\r
2042 );\r
2043 if (EFI_ERROR (Status)) {\r
2044 goto ON_EXIT;\r
20333c6d 2045 }\r
ba57d4fd 2046 ASSERT (mImageBase != NULL);\r
ecc722ad 2047\r
2048 Status = LoadPeImage ();\r
2049 if (EFI_ERROR (Status)) {\r
2050 goto ON_EXIT;\r
2051 }\r
2052\r
2053 if (mSecDataDir->SizeOfCert == 0) {\r
2054 if (!HashPeImage (HASHALG_SHA256)) {\r
2055 Status = EFI_SECURITY_VIOLATION;\r
2056 goto ON_EXIT;\r
2057 }\r
2058 } else {\r
20333c6d 2059\r
ecc722ad 2060 //\r
2061 // Read the certificate data\r
2062 //\r
2063 mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
2064\r
2065 if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
2066 GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
2067 if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
2068 Status = EFI_ABORTED;\r
2069 goto ON_EXIT;\r
2070 }\r
2071\r
2072 if (!HashPeImage (HASHALG_SHA256)) {\r
2073 Status = EFI_ABORTED;\r
2074 goto ON_EXIT;;\r
2075 }\r
20333c6d 2076\r
ecc722ad 2077 } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
2078\r
2079 Status = HashPeImageByType ();\r
2080 if (EFI_ERROR (Status)) {\r
2081 goto ON_EXIT;;\r
2082 }\r
2083 } else {\r
2084 Status = EFI_ABORTED;\r
2085 goto ON_EXIT;\r
2086 }\r
2087 }\r
2088\r
2089 //\r
2090 // Create a new SigDB entry.\r
2091 //\r
20333c6d 2092 SigDBSize = sizeof(EFI_SIGNATURE_LIST)\r
ecc722ad 2093 + sizeof(EFI_SIGNATURE_DATA) - 1\r
2094 + (UINT32) mImageDigestSize;\r
2095\r
2096 Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
2097 if (Data == NULL) {\r
2098 Status = EFI_OUT_OF_RESOURCES;\r
2099 goto ON_EXIT;\r
2100 }\r
20333c6d 2101\r
ecc722ad 2102 //\r
2103 // Adjust the Certificate Database parameters.\r
20333c6d 2104 //\r
ecc722ad 2105 SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
2106 SigDBCert->SignatureListSize = (UINT32) SigDBSize;\r
2107 SigDBCert->SignatureHeaderSize = 0;\r
2108 SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
2109 CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
2110\r
2111 SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
2112 CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
2113 CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
2114\r
20333c6d 2115 Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
8c1babfd 2116 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
2117 Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
2118 if (EFI_ERROR (Status)) {\r
2119 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2120 goto ON_EXIT;\r
2121 }\r
20333c6d 2122\r
ecc722ad 2123 //\r
20333c6d
QL
2124 // Check if SigDB variable has been already existed.\r
2125 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
ecc722ad 2126 // new signature data to original variable\r
20333c6d 2127 //\r
ecc722ad 2128 DataSize = 0;\r
2129 Status = gRT->GetVariable(\r
20333c6d
QL
2130 VariableName,\r
2131 &gEfiImageSecurityDatabaseGuid,\r
2132 NULL,\r
2133 &DataSize,\r
ecc722ad 2134 NULL\r
2135 );\r
2136 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2137 Attr |= EFI_VARIABLE_APPEND_WRITE;\r
2138 } else if (Status != EFI_NOT_FOUND) {\r
2139 goto ON_EXIT;\r
20333c6d 2140 }\r
ecc722ad 2141\r
2142 //\r
2143 // Enroll the variable.\r
2144 //\r
2145 Status = gRT->SetVariable(\r
20333c6d
QL
2146 VariableName,\r
2147 &gEfiImageSecurityDatabaseGuid,\r
2148 Attr,\r
2149 SigDBSize,\r
ecc722ad 2150 Data\r
2151 );\r
2152 if (EFI_ERROR (Status)) {\r
2153 goto ON_EXIT;\r
2154 }\r
2155\r
2156ON_EXIT:\r
2157\r
2158 CloseFile (Private->FileContext->FHandle);\r
2159 Private->FileContext->FHandle = NULL;\r
2160 Private->FileContext->FileName = NULL;\r
2161\r
2162 if (Private->SignatureGUID != NULL) {\r
2163 FreePool (Private->SignatureGUID);\r
2164 Private->SignatureGUID = NULL;\r
2165 }\r
2166\r
2167 if (Data != NULL) {\r
2168 FreePool (Data);\r
2169 }\r
2170\r
2171 if (mImageBase != NULL) {\r
2172 FreePool (mImageBase);\r
2173 mImageBase = NULL;\r
2174 }\r
2175\r
2176 return Status;\r
2177}\r
2178\r
2179/**\r
20333c6d 2180 Enroll signature into DB/DBX/DBT without KEK's authentication.\r
ecc722ad 2181 The SignatureOwner GUID will be Private->SignatureGUID.\r
20333c6d 2182\r
ecc722ad 2183 @param[in] PrivateData The module's private data.\r
20333c6d 2184 @param[in] VariableName Variable name of signature database, must be\r
ecc722ad 2185 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
20333c6d 2186\r
ecc722ad 2187 @retval EFI_SUCCESS New signature enrolled successfully.\r
2188 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2189 @retval others Fail to enroll signature data.\r
20333c6d 2190\r
ecc722ad 2191**/\r
2192EFI_STATUS\r
2193EnrollSignatureDatabase (\r
2194 IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
2195 IN CHAR16 *VariableName\r
20333c6d 2196 )\r
ecc722ad 2197{\r
2198 UINT16* FilePostFix;\r
f71ed839 2199 EFI_STATUS Status;\r
fd64f84f 2200 UINTN NameLength;\r
ecc722ad 2201\r
2202 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
2203 return EFI_INVALID_PARAMETER;\r
2204 }\r
2205\r
20333c6d 2206 Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
f71ed839 2207 if (EFI_ERROR (Status)) {\r
2208 return Status;\r
2209 }\r
20333c6d 2210\r
ecc722ad 2211 //\r
20333c6d 2212 // Parse the file's postfix.\r
ecc722ad 2213 //\r
fd64f84f
GCPL
2214 NameLength = StrLen (Private->FileContext->FileName);\r
2215 if (NameLength <= 4) {\r
2216 return EFI_INVALID_PARAMETER;\r
2217 }\r
2218 FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
20333c6d 2219 if (IsDerEncodeCertificate (FilePostFix)) {\r
ecc722ad 2220 //\r
e4d7370d 2221 // Supports DER-encoded X509 certificate.\r
ecc722ad 2222 //\r
2223 return EnrollX509toSigDB (Private, VariableName);\r
2224 }\r
2225\r
2226 return EnrollImageSignatureToSigDB (Private, VariableName);\r
2227}\r
2228\r
2229/**\r
20333c6d 2230 List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)\r
ecc722ad 2231 by GUID in the page for user to select and delete as needed.\r
2232\r
2233 @param[in] PrivateData Module's private data.\r
2234 @param[in] VariableName The variable name of the vendor's signature database.\r
2235 @param[in] VendorGuid A unique identifier for the vendor.\r
2236 @param[in] LabelNumber Label number to insert opcodes.\r
2237 @param[in] FormId Form ID of current page.\r
2238 @param[in] QuestionIdBase Base question id of the signature list.\r
2239\r
2240 @retval EFI_SUCCESS Success to update the signature list page\r
2241 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
20333c6d 2242\r
ecc722ad 2243**/\r
2244EFI_STATUS\r
2245UpdateDeletePage (\r
2246 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2247 IN CHAR16 *VariableName,\r
2248 IN EFI_GUID *VendorGuid,\r
2249 IN UINT16 LabelNumber,\r
2250 IN EFI_FORM_ID FormId,\r
2251 IN EFI_QUESTION_ID QuestionIdBase\r
2252 )\r
2253{\r
2254 EFI_STATUS Status;\r
2255 UINT32 Index;\r
2256 UINTN CertCount;\r
2257 UINTN GuidIndex;\r
2258 VOID *StartOpCodeHandle;\r
2259 VOID *EndOpCodeHandle;\r
2260 EFI_IFR_GUID_LABEL *StartLabel;\r
20333c6d 2261 EFI_IFR_GUID_LABEL *EndLabel;\r
ecc722ad 2262 UINTN DataSize;\r
2263 UINT8 *Data;\r
2264 EFI_SIGNATURE_LIST *CertList;\r
2265 EFI_SIGNATURE_DATA *Cert;\r
2266 UINT32 ItemDataSize;\r
2267 CHAR16 *GuidStr;\r
2268 EFI_STRING_ID GuidID;\r
2269 EFI_STRING_ID Help;\r
2270\r
2271 Data = NULL;\r
2272 CertList = NULL;\r
2273 Cert = NULL;\r
2274 GuidStr = NULL;\r
2275 StartOpCodeHandle = NULL;\r
2276 EndOpCodeHandle = NULL;\r
20333c6d 2277\r
ecc722ad 2278 //\r
2279 // Initialize the container for dynamic opcodes.\r
2280 //\r
2281 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2282 if (StartOpCodeHandle == NULL) {\r
2283 Status = EFI_OUT_OF_RESOURCES;\r
20333c6d 2284 goto ON_EXIT;\r
ecc722ad 2285 }\r
2286\r
2287 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2288 if (EndOpCodeHandle == NULL) {\r
2289 Status = EFI_OUT_OF_RESOURCES;\r
20333c6d 2290 goto ON_EXIT;\r
ecc722ad 2291 }\r
2292\r
2293 //\r
2294 // Create Hii Extend Label OpCode.\r
2295 //\r
2296 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2297 StartOpCodeHandle,\r
2298 &gEfiIfrTianoGuid,\r
2299 NULL,\r
2300 sizeof (EFI_IFR_GUID_LABEL)\r
2301 );\r
2302 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2303 StartLabel->Number = LabelNumber;\r
2304\r
2305 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2306 EndOpCodeHandle,\r
2307 &gEfiIfrTianoGuid,\r
2308 NULL,\r
2309 sizeof (EFI_IFR_GUID_LABEL)\r
2310 );\r
2311 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2312 EndLabel->Number = LABEL_END;\r
2313\r
2314 //\r
2315 // Read Variable.\r
2316 //\r
2317 DataSize = 0;\r
20333c6d 2318 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
ecc722ad 2319 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2320 goto ON_EXIT;\r
2321 }\r
2322\r
2323 Data = (UINT8 *) AllocateZeroPool (DataSize);\r
2324 if (Data == NULL) {\r
2325 Status = EFI_OUT_OF_RESOURCES;\r
2326 goto ON_EXIT;\r
2327 }\r
2328\r
2329 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
2330 if (EFI_ERROR (Status)) {\r
2331 goto ON_EXIT;\r
2332 }\r
2333\r
2334 GuidStr = AllocateZeroPool (100);\r
2335 if (GuidStr == NULL) {\r
2336 Status = EFI_OUT_OF_RESOURCES;\r
2337 goto ON_EXIT;\r
2338 }\r
2339\r
2340 //\r
2341 // Enumerate all KEK pub data.\r
2342 //\r
2343 ItemDataSize = (UINT32) DataSize;\r
2344 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2345 GuidIndex = 0;\r
2346\r
2347 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2348\r
2349 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
2350 Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
2351 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
2352 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
2353 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
2354 Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
2355 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
2356 Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
20333c6d
QL
2357 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
2358 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);\r
2359 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
2360 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);\r
2361 } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
2362 Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);\r
ecc722ad 2363 } else {\r
2364 //\r
2365 // The signature type is not supported in current implementation.\r
2366 //\r
b7d269ea 2367 ItemDataSize -= CertList->SignatureListSize;\r
2368 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
ecc722ad 2369 continue;\r
2370 }\r
2371\r
2372 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2373 for (Index = 0; Index < CertCount; Index++) {\r
20333c6d
QL
2374 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList\r
2375 + sizeof (EFI_SIGNATURE_LIST)\r
2376 + CertList->SignatureHeaderSize\r
ecc722ad 2377 + Index * CertList->SignatureSize);\r
2378 //\r
20333c6d 2379 // Display GUID and help\r
ecc722ad 2380 //\r
2381 GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
2382 GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
2383 HiiCreateCheckBoxOpCode (\r
2384 StartOpCodeHandle,\r
2385 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
20333c6d
QL
2386 0,\r
2387 0,\r
2388 GuidID,\r
ecc722ad 2389 Help,\r
2390 EFI_IFR_FLAG_CALLBACK,\r
2391 0,\r
2392 NULL\r
20333c6d 2393 );\r
ecc722ad 2394 }\r
2395\r
2396 ItemDataSize -= CertList->SignatureListSize;\r
2397 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2398 }\r
2399\r
2400ON_EXIT:\r
2401 HiiUpdateForm (\r
2402 PrivateData->HiiHandle,\r
2403 &gSecureBootConfigFormSetGuid,\r
2404 FormId,\r
2405 StartOpCodeHandle,\r
2406 EndOpCodeHandle\r
2407 );\r
2408\r
2409 if (StartOpCodeHandle != NULL) {\r
2410 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2411 }\r
2412\r
2413 if (EndOpCodeHandle != NULL) {\r
2414 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2415 }\r
20333c6d 2416\r
ecc722ad 2417 if (Data != NULL) {\r
2418 FreePool (Data);\r
2419 }\r
2420\r
2421 if (GuidStr != NULL) {\r
2422 FreePool (GuidStr);\r
2423 }\r
2424\r
2425 return EFI_SUCCESS;\r
2426}\r
2427\r
beda2356 2428/**\r
20333c6d 2429 Delete a KEK entry from KEK database.\r
beda2356 2430\r
ecc722ad 2431 @param[in] PrivateData Module's private data.\r
2432 @param[in] QuestionId Question id of the KEK item to delete.\r
beda2356 2433\r
ecc722ad 2434 @retval EFI_SUCCESS Delete kek item successfully.\r
2435 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
20333c6d 2436\r
ecc722ad 2437**/\r
2438EFI_STATUS\r
2439DeleteKeyExchangeKey (\r
2440 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2441 IN EFI_QUESTION_ID QuestionId\r
2442 )\r
2443{\r
2444 EFI_STATUS Status;\r
2445 UINTN DataSize;\r
2446 UINT8 *Data;\r
2447 UINT8 *OldData;\r
2448 UINT32 Attr;\r
2449 UINT32 Index;\r
2450 EFI_SIGNATURE_LIST *CertList;\r
2451 EFI_SIGNATURE_LIST *NewCertList;\r
2452 EFI_SIGNATURE_DATA *Cert;\r
2453 UINTN CertCount;\r
2454 UINT32 Offset;\r
2455 BOOLEAN IsKEKItemFound;\r
2456 UINT32 KekDataSize;\r
2457 UINTN DeleteKekIndex;\r
2458 UINTN GuidIndex;\r
2459\r
2460 Data = NULL;\r
2461 OldData = NULL;\r
2462 CertList = NULL;\r
2463 Cert = NULL;\r
20333c6d 2464 Attr = 0;\r
ecc722ad 2465 DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
f71ed839 2466\r
2467 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2468 if (EFI_ERROR (Status)) {\r
2469 return Status;\r
2470 }\r
20333c6d 2471\r
ecc722ad 2472 //\r
2473 // Get original KEK variable.\r
20333c6d
QL
2474 //\r
2475 DataSize = 0;\r
ecc722ad 2476 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
2477 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2478 goto ON_EXIT;\r
2479 }\r
2480\r
2481 OldData = (UINT8*)AllocateZeroPool(DataSize);\r
2482 if (OldData == NULL) {\r
20333c6d 2483 Status = EFI_OUT_OF_RESOURCES;\r
ecc722ad 2484 goto ON_EXIT;\r
2485 }\r
2486\r
2487 Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
2488 if (EFI_ERROR(Status)) {\r
2489 goto ON_EXIT;\r
2490 }\r
2491\r
2492 //\r
20333c6d 2493 // Allocate space for new variable.\r
ecc722ad 2494 //\r
2495 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2496 if (Data == NULL) {\r
2497 Status = EFI_OUT_OF_RESOURCES;\r
2498 goto ON_EXIT;\r
2499 }\r
2500\r
2501 //\r
2502 // Enumerate all KEK pub data and erasing the target item.\r
2503 //\r
2504 IsKEKItemFound = FALSE;\r
2505 KekDataSize = (UINT32) DataSize;\r
2506 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2507 Offset = 0;\r
2508 GuidIndex = 0;\r
2509 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
2510 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2511 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
2512 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2513 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
2514 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2515 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2516 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2517 for (Index = 0; Index < CertCount; Index++) {\r
2518 if (GuidIndex == DeleteKekIndex ) {\r
2519 //\r
2520 // Find it! Skip it!\r
2521 //\r
2522 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
20333c6d 2523 IsKEKItemFound = TRUE;\r
ecc722ad 2524 } else {\r
2525 //\r
2526 // This item doesn't match. Copy it to the Data buffer.\r
2527 //\r
2528 CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
2529 Offset += CertList->SignatureSize;\r
2530 }\r
2531 GuidIndex++;\r
2532 Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
2533 }\r
2534 } else {\r
2535 //\r
2536 // This List doesn't match. Copy it to the Data buffer.\r
2537 //\r
2538 CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
2539 Offset += CertList->SignatureListSize;\r
2540 }\r
20333c6d 2541\r
ecc722ad 2542 KekDataSize -= CertList->SignatureListSize;\r
2543 CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
2544 }\r
2545\r
2546 if (!IsKEKItemFound) {\r
2547 //\r
2548 // Doesn't find the Kek Item!\r
2549 //\r
2550 Status = EFI_NOT_FOUND;\r
2551 goto ON_EXIT;\r
2552 }\r
2553\r
2554 //\r
2555 // Delete the Signature header if there is no signature in the list.\r
2556 //\r
2557 KekDataSize = Offset;\r
2558 CertList = (EFI_SIGNATURE_LIST*) Data;\r
2559 Offset = 0;\r
2560 ZeroMem (OldData, KekDataSize);\r
2561 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
2562 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
33985e3b 2563 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));\r
ecc722ad 2564 if (CertCount != 0) {\r
2565 CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
2566 Offset += CertList->SignatureListSize;\r
20333c6d 2567 }\r
ecc722ad 2568 KekDataSize -= CertList->SignatureListSize;\r
2569 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2570 }\r
2571\r
ecc722ad 2572 DataSize = Offset;\r
8c1babfd 2573 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2574 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2575 if (EFI_ERROR (Status)) {\r
2576 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2577 goto ON_EXIT;\r
2578 }\r
2579 }\r
ecc722ad 2580\r
2581 Status = gRT->SetVariable(\r
20333c6d
QL
2582 EFI_KEY_EXCHANGE_KEY_NAME,\r
2583 &gEfiGlobalVariableGuid,\r
2584 Attr,\r
2585 DataSize,\r
ecc722ad 2586 OldData\r
2587 );\r
2588 if (EFI_ERROR (Status)) {\r
2589 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2590 goto ON_EXIT;\r
2591 }\r
20333c6d 2592\r
ecc722ad 2593ON_EXIT:\r
2594 if (Data != NULL) {\r
2595 FreePool(Data);\r
2596 }\r
2597\r
2598 if (OldData != NULL) {\r
2599 FreePool(OldData);\r
2600 }\r
2601\r
2602 return UpdateDeletePage (\r
20333c6d 2603 PrivateData,\r
ecc722ad 2604 EFI_KEY_EXCHANGE_KEY_NAME,\r
2605 &gEfiGlobalVariableGuid,\r
2606 LABEL_KEK_DELETE,\r
2607 FORMID_DELETE_KEK_FORM,\r
2608 OPTION_DEL_KEK_QUESTION_ID\r
2609 );\r
2610}\r
2611\r
2612/**\r
2613 Delete a signature entry from siganture database.\r
beda2356 2614\r
ecc722ad 2615 @param[in] PrivateData Module's private data.\r
2616 @param[in] VariableName The variable name of the vendor's signature database.\r
2617 @param[in] VendorGuid A unique identifier for the vendor.\r
2618 @param[in] LabelNumber Label number to insert opcodes.\r
2619 @param[in] FormId Form ID of current page.\r
2620 @param[in] QuestionIdBase Base question id of the signature list.\r
2621 @param[in] DeleteIndex Signature index to delete.\r
20333c6d 2622\r
ecc722ad 2623 @retval EFI_SUCCESS Delete siganture successfully.\r
2624 @retval EFI_NOT_FOUND Can't find the signature item,\r
2625 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
beda2356 2626**/\r
2627EFI_STATUS\r
ecc722ad 2628DeleteSignature (\r
2629 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
2630 IN CHAR16 *VariableName,\r
2631 IN EFI_GUID *VendorGuid,\r
2632 IN UINT16 LabelNumber,\r
2633 IN EFI_FORM_ID FormId,\r
2634 IN EFI_QUESTION_ID QuestionIdBase,\r
2635 IN UINTN DeleteIndex\r
beda2356 2636 )\r
2637{\r
ecc722ad 2638 EFI_STATUS Status;\r
2639 UINTN DataSize;\r
2640 UINT8 *Data;\r
2641 UINT8 *OldData;\r
2642 UINT32 Attr;\r
2643 UINT32 Index;\r
2644 EFI_SIGNATURE_LIST *CertList;\r
2645 EFI_SIGNATURE_LIST *NewCertList;\r
2646 EFI_SIGNATURE_DATA *Cert;\r
2647 UINTN CertCount;\r
2648 UINT32 Offset;\r
2649 BOOLEAN IsItemFound;\r
2650 UINT32 ItemDataSize;\r
2651 UINTN GuidIndex;\r
bc0c99b3 2652\r
ecc722ad 2653 Data = NULL;\r
2654 OldData = NULL;\r
2655 CertList = NULL;\r
2656 Cert = NULL;\r
20333c6d 2657 Attr = 0;\r
ecc722ad 2658\r
f71ed839 2659 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2660 if (EFI_ERROR (Status)) {\r
2661 return Status;\r
2662 }\r
2663\r
ecc722ad 2664 //\r
2665 // Get original signature list data.\r
20333c6d 2666 //\r
ecc722ad 2667 DataSize = 0;\r
2668 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
2669 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
2670 goto ON_EXIT;\r
2671 }\r
2672\r
2673 OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
2674 if (OldData == NULL) {\r
20333c6d 2675 Status = EFI_OUT_OF_RESOURCES;\r
ecc722ad 2676 goto ON_EXIT;\r
2677 }\r
2678\r
2679 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
2680 if (EFI_ERROR(Status)) {\r
2681 goto ON_EXIT;\r
20333c6d 2682 }\r
ecc722ad 2683\r
2684 //\r
20333c6d 2685 // Allocate space for new variable.\r
ecc722ad 2686 //\r
2687 Data = (UINT8*) AllocateZeroPool (DataSize);\r
2688 if (Data == NULL) {\r
2689 Status = EFI_OUT_OF_RESOURCES;\r
2690 goto ON_EXIT;\r
2691 }\r
2692\r
2693 //\r
2694 // Enumerate all signature data and erasing the target item.\r
2695 //\r
2696 IsItemFound = FALSE;\r
2697 ItemDataSize = (UINT32) DataSize;\r
2698 CertList = (EFI_SIGNATURE_LIST *) OldData;\r
2699 Offset = 0;\r
2700 GuidIndex = 0;\r
2701 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2702 if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
2703 CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
2704 CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
20333c6d
QL
2705 CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||\r
2706 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||\r
2707 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||\r
2708 CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)\r
ecc722ad 2709 ) {\r
2710 //\r
2711 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
2712 //\r
2713 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
2714 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
2715 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2716 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
2717 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
2718 for (Index = 0; Index < CertCount; Index++) {\r
2719 if (GuidIndex == DeleteIndex) {\r
2720 //\r
2721 // Find it! Skip it!\r
2722 //\r
2723 NewCertList->SignatureListSize -= CertList->SignatureSize;\r
20333c6d 2724 IsItemFound = TRUE;\r
ecc722ad 2725 } else {\r
2726 //\r
2727 // This item doesn't match. Copy it to the Data buffer.\r
2728 //\r
2729 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
2730 Offset += CertList->SignatureSize;\r
2731 }\r
2732 GuidIndex++;\r
2733 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
2734 }\r
2735 } else {\r
2736 //\r
2737 // This List doesn't match. Just copy it to the Data buffer.\r
2738 //\r
2739 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2740 Offset += CertList->SignatureListSize;\r
2741 }\r
20333c6d 2742\r
ecc722ad 2743 ItemDataSize -= CertList->SignatureListSize;\r
2744 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2745 }\r
2746\r
2747 if (!IsItemFound) {\r
2748 //\r
2749 // Doesn't find the signature Item!\r
2750 //\r
2751 Status = EFI_NOT_FOUND;\r
2752 goto ON_EXIT;\r
2753 }\r
2754\r
2755 //\r
2756 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
2757 //\r
2758 ItemDataSize = Offset;\r
2759 CertList = (EFI_SIGNATURE_LIST *) Data;\r
2760 Offset = 0;\r
2761 ZeroMem (OldData, ItemDataSize);\r
2762 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
2763 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
33985e3b 2764 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));\r
ecc722ad 2765 if (CertCount != 0) {\r
2766 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
2767 Offset += CertList->SignatureListSize;\r
20333c6d 2768 }\r
ecc722ad 2769 ItemDataSize -= CertList->SignatureListSize;\r
2770 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
2771 }\r
2772\r
ecc722ad 2773 DataSize = Offset;\r
8c1babfd 2774 if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
2775 Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
2776 if (EFI_ERROR (Status)) {\r
2777 DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
2778 goto ON_EXIT;\r
2779 }\r
2780 }\r
ecc722ad 2781\r
2782 Status = gRT->SetVariable(\r
20333c6d
QL
2783 VariableName,\r
2784 VendorGuid,\r
2785 Attr,\r
2786 DataSize,\r
ecc722ad 2787 OldData\r
2788 );\r
beda2356 2789 if (EFI_ERROR (Status)) {\r
ecc722ad 2790 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
2791 goto ON_EXIT;\r
beda2356 2792 }\r
20333c6d 2793\r
ecc722ad 2794ON_EXIT:\r
2795 if (Data != NULL) {\r
2796 FreePool(Data);\r
2797 }\r
2798\r
2799 if (OldData != NULL) {\r
2800 FreePool(OldData);\r
2801 }\r
2802\r
2803 return UpdateDeletePage (\r
20333c6d 2804 PrivateData,\r
ecc722ad 2805 VariableName,\r
2806 VendorGuid,\r
2807 LabelNumber,\r
2808 FormId,\r
2809 QuestionIdBase\r
2810 );\r
2811}\r
2812\r
96832eef
CZ
2813/**\r
2814 Perform secure boot mode transition from User Mode by setting AuditMode \r
2815 or DeployedMode variable.\r
2816\r
2817 @param[in] NewMode New secure boot mode.\r
2818\r
2819 @retval EFI_SUCCESS Secure Boot mode transition is successful.\r
2820**/\r
2821EFI_STATUS\r
2822TransitionFromUserMode(\r
2823 IN UINT8 NewMode\r
2824 )\r
2825{\r
2826 UINT8 Data;\r
2827 EFI_STATUS Status;\r
2828\r
2829 if (NewMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
2830 Data = 1;\r
2831 Status = gRT->SetVariable(\r
2832 EFI_AUDIT_MODE_NAME,\r
2833 &gEfiGlobalVariableGuid,\r
2834 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
2835 sizeof(UINT8),\r
2836 &Data\r
2837 );\r
2838 return Status;\r
2839 } else if (NewMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
2840 Data = 1;\r
2841 Status = gRT->SetVariable(\r
2842 EFI_DEPLOYED_MODE_NAME,\r
2843 &gEfiGlobalVariableGuid,\r
2844 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
2845 sizeof(UINT8),\r
2846 &Data\r
2847 );\r
2848 return Status;\r
2849 }\r
2850\r
2851 //\r
2852 // Other case do nothing here. May Goto enroll PK page.\r
2853 //\r
2854 return EFI_SUCCESS;\r
2855}\r
2856\r
2857/**\r
2858 Perform secure boot mode transition from Setup Mode by setting AuditMode \r
2859 variable.\r
2860\r
2861 @param[in] NewMode New secure boot mode.\r
2862\r
2863 @retval EFI_SUCCESS Secure Boot mode transition is successful.\r
2864**/\r
2865EFI_STATUS\r
2866TransitionFromSetupMode(\r
2867 IN UINT8 NewMode\r
2868 )\r
2869{\r
2870 UINT8 Data;\r
2871 EFI_STATUS Status;\r
2872\r
2873 Status = EFI_INVALID_PARAMETER;\r
2874\r
2875 if (NewMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
2876 Data = 1;\r
2877 Status = gRT->SetVariable(\r
2878 EFI_AUDIT_MODE_NAME,\r
2879 &gEfiGlobalVariableGuid,\r
2880 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
2881 sizeof(UINT8),\r
2882 &Data\r
2883 );\r
2884 return Status;\r
2885 }\r
2886\r
2887 //\r
2888 // Other case do nothing here. May Goto enroll PK page.\r
2889 //\r
2890 return EFI_SUCCESS;\r
2891}\r
2892\r
2893/**\r
2894 Perform secure boot mode transition from Audit Mode. Nothing is done here,\r
2895 should goto enroll PK page.\r
2896\r
2897 @param[in] NewMode New secure boot mode.\r
2898\r
2899 @retval EFI_SUCCESS Secure Boot mode transition is successful.\r
2900**/\r
2901EFI_STATUS\r
2902TransitionFromAuditMode(\r
2903 IN UINT8 NewMode\r
2904 )\r
2905{\r
2906 //\r
2907 // Other case do nothing here. Should Goto enroll PK page.\r
2908 //\r
2909 return EFI_SUCCESS;\r
2910}\r
2911\r
2912/**\r
2913 Perform secure boot mode transition from Deployed Mode by setting Deployed Mode\r
2914 variable to 0.\r
2915\r
2916 @param[in] NewMode New secure boot mode.\r
2917\r
2918 @retval EFI_SUCCESS Secure Boot mode transition is successful.\r
2919**/\r
2920EFI_STATUS\r
2921TransitionFromDeployedMode(\r
2922 IN UINT8 NewMode\r
2923 )\r
2924{\r
2925 UINT8 Data;\r
2926 EFI_STATUS Status;\r
2927\r
2928 //\r
2929 // Platform specific logic. when physical presence, Allow to set DeployedMode =:0\r
2930 // to switch back to UserMode\r
2931 //\r
2932 if (NewMode == SECURE_BOOT_MODE_USER_MODE) {\r
2933 Data = 0;\r
2934 Status = gRT->SetVariable(\r
2935 EFI_DEPLOYED_MODE_NAME,\r
2936 &gEfiGlobalVariableGuid,\r
2937 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
2938 sizeof(UINT8),\r
2939 &Data\r
2940 );\r
2941 DEBUG((EFI_D_INFO, "DeployedMode Status %x\n", Status));\r
2942 return Status;\r
2943 }\r
2944 return EFI_SUCCESS;\r
2945}\r
2946\r
2947/**\r
2948 Perform main secure boot mode transition.\r
2949\r
2950 @param[in] CurMode New secure boot mode.\r
2951 @param[in] NewMode New secure boot mode.\r
2952\r
2953 @retval EFI_SUCCESS Secure Boot mode transition is successful.\r
2954**/\r
2955EFI_STATUS\r
2956SecureBootModeTransition(\r
2957 IN UINT8 CurMode,\r
2958 IN UINT8 NewMode\r
2959 )\r
2960{\r
2961 EFI_STATUS Status;\r
2962\r
2963 //\r
2964 // Set platform to be customized mode to ensure platform specific mode switch sucess\r
2965 //\r
2966 Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
2967 if (EFI_ERROR (Status)) {\r
2968 return Status;\r
2969 }\r
2970\r
2971 //\r
2972 // SecureBootMode transition\r
2973 //\r
2974 switch (CurMode) {\r
2975 case SECURE_BOOT_MODE_USER_MODE:\r
2976 Status = TransitionFromUserMode(NewMode);\r
2977 break;\r
2978\r
2979 case SECURE_BOOT_MODE_SETUP_MODE:\r
2980 Status = TransitionFromSetupMode(NewMode);\r
2981 break;\r
2982\r
2983 case SECURE_BOOT_MODE_AUDIT_MODE:\r
2984 Status = TransitionFromAuditMode(NewMode);\r
2985 break;\r
2986\r
2987 case SECURE_BOOT_MODE_DEPLOYED_MODE:\r
2988 Status = TransitionFromDeployedMode(NewMode);\r
2989 break;\r
2990\r
2991 default:\r
2992 Status = EFI_INVALID_PARAMETER;\r
2993 ASSERT(FALSE);\r
2994 }\r
2995\r
2996 return Status;\r
2997}\r
2998\r
2999/**\r
3000 Get current secure boot mode by retrieve data from SetupMode/AuditMode/DeployedMode.\r
3001\r
3002 @param[out] SecureBootMode Current secure boot mode.\r
3003\r
3004**/\r
3005VOID\r
3006ExtractSecureBootModeFromVariable(\r
3007 OUT UINT8 *SecureBootMode\r
3008 )\r
3009{\r
3010 UINT8 *SetupMode;\r
3011 UINT8 *AuditMode;\r
3012 UINT8 *DeployedMode;\r
3013\r
3014 SetupMode = NULL;\r
3015 AuditMode = NULL;\r
3016 DeployedMode = NULL;\r
3017\r
3018 //\r
3019 // Get AuditMode/DeployedMode from variable\r
3020 //\r
3021 GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
3022 GetVariable2 (EFI_AUDIT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&AuditMode, NULL);\r
3023 GetVariable2 (EFI_DEPLOYED_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&DeployedMode, NULL);\r
3024 if (SetupMode != NULL && AuditMode != NULL && DeployedMode != NULL) {\r
3025 if (*SetupMode == 0 && *AuditMode == 0 && *DeployedMode == 0) {\r
3026 //\r
3027 // User Mode\r
3028 //\r
3029 *SecureBootMode = SECURE_BOOT_MODE_USER_MODE;\r
3030 } else if (*SetupMode == 1 && *AuditMode == 0 && *DeployedMode == 0) {\r
3031 //\r
3032 // Setup Mode\r
3033 //\r
3034 *SecureBootMode = SECURE_BOOT_MODE_SETUP_MODE;\r
3035 } else if (*SetupMode == 1 && *AuditMode == 1 && *DeployedMode == 0) {\r
3036 //\r
3037 // Audit Mode\r
3038 //\r
3039 *SecureBootMode = SECURE_BOOT_MODE_AUDIT_MODE;\r
3040 } else if (*SetupMode == 0 && *AuditMode == 0 && *DeployedMode == 1) {\r
3041 //\r
3042 // Deployed Mode\r
3043 //\r
3044 *SecureBootMode = SECURE_BOOT_MODE_DEPLOYED_MODE;\r
3045 } else {\r
3046 ASSERT(FALSE);\r
3047 }\r
3048 }else {\r
3049 ASSERT(FALSE);\r
3050 }\r
3051\r
3052 if (SetupMode != NULL) {\r
3053 FreePool (SetupMode);\r
3054 }\r
3055 if (DeployedMode != NULL) {\r
3056 FreePool (DeployedMode);\r
3057 }\r
3058 if (AuditMode != NULL) {\r
3059 FreePool (AuditMode);\r
3060 }\r
3061}\r
3062\r
ecc722ad 3063/**\r
3064 This function extracts configuration from variable.\r
20333c6d 3065\r
ecc722ad 3066 @param[in, out] ConfigData Point to SecureBoot configuration private data.\r
3067\r
3068**/\r
3069VOID\r
3070SecureBootExtractConfigFromVariable (\r
3071 IN OUT SECUREBOOT_CONFIGURATION *ConfigData\r
20333c6d 3072 )\r
ecc722ad 3073{\r
20333c6d 3074 UINT8 *SecureBootEnable;\r
20333c6d
QL
3075 UINT8 *SecureBootMode;\r
3076 EFI_TIME CurrTime;\r
ecc722ad 3077\r
3078 SecureBootEnable = NULL;\r
ecc722ad 3079 SecureBootMode = NULL;\r
20333c6d
QL
3080\r
3081 //\r
3082 // Initilize the Date and Time using system time.\r
3083 //\r
3084 ConfigData->CertificateFormat = HASHALG_RAW;\r
3085 ConfigData->AlwaysRevocation = TRUE;\r
3086 gRT->GetTime (&CurrTime, NULL);\r
3087 ConfigData->RevocationDate.Year = CurrTime.Year;\r
3088 ConfigData->RevocationDate.Month = CurrTime.Month;\r
3089 ConfigData->RevocationDate.Day = CurrTime.Day;\r
3090 ConfigData->RevocationTime.Hour = CurrTime.Hour;\r
3091 ConfigData->RevocationTime.Minute = CurrTime.Minute;\r
3092 ConfigData->RevocationTime.Second = 0;\r
3093\r
ecc722ad 3094 //\r
3095 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
3096 // Checkbox.\r
3097 //\r
f71ed839 3098 ConfigData->AttemptSecureBoot = FALSE;\r
8f8ca22e 3099 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
ecc722ad 3100 if (SecureBootEnable == NULL) {\r
3101 ConfigData->HideSecureBoot = TRUE;\r
3102 } else {\r
3103 ConfigData->HideSecureBoot = FALSE;\r
f71ed839 3104 if ((*SecureBootEnable) == SECURE_BOOT_ENABLE) {\r
3105 ConfigData->AttemptSecureBoot = TRUE;\r
3106 }\r
ecc722ad 3107 }\r
20333c6d 3108\r
ecc722ad 3109 //\r
3110 // If it is Physical Presence User, set the PhysicalPresent to true.\r
3111 //\r
3112 if (UserPhysicalPresent()) {\r
3113 ConfigData->PhysicalPresent = TRUE;\r
3114 } else {\r
3115 ConfigData->PhysicalPresent = FALSE;\r
3116 }\r
20333c6d 3117\r
ecc722ad 3118 //\r
3119 // Get the SecureBootMode from CustomMode variable.\r
3120 //\r
f01b91ae 3121 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
ecc722ad 3122 if (SecureBootMode == NULL) {\r
3123 ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
3124 } else {\r
3125 ConfigData->SecureBootMode = *(SecureBootMode);\r
3126 }\r
f71ed839 3127\r
96832eef
CZ
3128 //\r
3129 // Extact current Secure Boot Mode\r
3130 //\r
3131 ExtractSecureBootModeFromVariable(&ConfigData->CurSecureBootMode);\r
3132\r
3133 //\r
3134 // If there is no PK then the Delete Pk button will be gray.\r
3135 //\r
3136 if (ConfigData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE || ConfigData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
3137 ConfigData->HasPk = FALSE;\r
3138 } else {\r
3139 ConfigData->HasPk = TRUE;\r
3140 }\r
3141\r
f71ed839 3142 if (SecureBootEnable != NULL) {\r
3143 FreePool (SecureBootEnable);\r
3144 }\r
96832eef 3145\r
f71ed839 3146 if (SecureBootMode != NULL) {\r
3147 FreePool (SecureBootMode);\r
3148 }\r
beda2356 3149}\r
3150\r
3151/**\r
3152 This function allows a caller to extract the current configuration for one\r
3153 or more named elements from the target driver.\r
3154\r
3155 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3156 @param[in] Request A null-terminated Unicode string in\r
3157 <ConfigRequest> format.\r
3158 @param[out] Progress On return, points to a character in the Request\r
3159 string. Points to the string's null terminator if\r
3160 request was successful. Points to the most recent\r
3161 '&' before the first failing name/value pair (or\r
3162 the beginning of the string if the failure is in\r
3163 the first name/value pair) if the request was not\r
3164 successful.\r
3165 @param[out] Results A null-terminated Unicode string in\r
3166 <ConfigAltResp> format which has all values filled\r
3167 in for the names in the Request string. String to\r
3168 be allocated by the called function.\r
3169\r
3170 @retval EFI_SUCCESS The Results is filled with the requested values.\r
3171 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
3172 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
3173 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
3174 driver.\r
3175\r
3176**/\r
3177EFI_STATUS\r
3178EFIAPI\r
3179SecureBootExtractConfig (\r
3180 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3181 IN CONST EFI_STRING Request,\r
3182 OUT EFI_STRING *Progress,\r
3183 OUT EFI_STRING *Results\r
3184 )\r
3185{\r
3186 EFI_STATUS Status;\r
3187 UINTN BufferSize;\r
bc0c99b3 3188 UINTN Size;\r
beda2356 3189 SECUREBOOT_CONFIGURATION Configuration;\r
beda2356 3190 EFI_STRING ConfigRequest;\r
bc0c99b3 3191 EFI_STRING ConfigRequestHdr;\r
bc0c99b3 3192 SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;\r
3193 BOOLEAN AllocatedRequest;\r
f71ed839 3194 UINT8 *SecureBoot;\r
bc0c99b3 3195\r
beda2356 3196 if (Progress == NULL || Results == NULL) {\r
3197 return EFI_INVALID_PARAMETER;\r
3198 }\r
20333c6d 3199\r
bc0c99b3 3200 AllocatedRequest = FALSE;\r
3201 ConfigRequestHdr = NULL;\r
3202 ConfigRequest = NULL;\r
3203 Size = 0;\r
f71ed839 3204 SecureBoot = NULL;\r
20333c6d 3205\r
ea71453f 3206 ZeroMem (&Configuration, sizeof (Configuration));\r
bc0c99b3 3207 PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
3208 *Progress = Request;\r
20333c6d 3209\r
beda2356 3210 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
3211 return EFI_NOT_FOUND;\r
3212 }\r
3213\r
beda2356 3214 //\r
ecc722ad 3215 // Get Configuration from Variable.\r
beda2356 3216 //\r
ecc722ad 3217 SecureBootExtractConfigFromVariable (&Configuration);\r
f71ed839 3218\r
3219 //\r
96832eef 3220 // Get current secure boot state.\r
f71ed839 3221 //\r
3222 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
96832eef 3223\r
f71ed839 3224 if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
3225 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
3226 } else {\r
3227 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
3228 }\r
96832eef
CZ
3229\r
3230 //\r
3231 // Get current secure boot mode\r
3232 //\r
3233 DEBUG((EFI_D_INFO, "Configuration.CurSecureBootMode %d\n", Configuration.CurSecureBootMode));\r
3234 if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE) {\r
3235 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"UserMode", NULL);\r
3236 } else if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE) {\r
3237 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"SetupMode", NULL);\r
3238 } else if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
3239 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"AuditMode", NULL);\r
3240 } else if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
3241 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"DeployedMode", NULL);\r
f71ed839 3242 }\r
20333c6d 3243\r
bc0c99b3 3244 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
beda2356 3245 ConfigRequest = Request;\r
bc0c99b3 3246 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
3247 //\r
3248 // Request is set to NULL or OFFSET is NULL, construct full request string.\r
bc0c99b3 3249 //\r
3250 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
3251 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
3252 //\r
3253 ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
3254 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
3255 ConfigRequest = AllocateZeroPool (Size);\r
3256 ASSERT (ConfigRequest != NULL);\r
3257 AllocatedRequest = TRUE;\r
3258 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
3259 FreePool (ConfigRequestHdr);\r
3260 ConfigRequestHdr = NULL;\r
3261 }\r
beda2356 3262\r
3263 Status = gHiiConfigRouting->BlockToConfig (\r
3264 gHiiConfigRouting,\r
3265 ConfigRequest,\r
3266 (UINT8 *) &Configuration,\r
3267 BufferSize,\r
3268 Results,\r
3269 Progress\r
3270 );\r
bc0c99b3 3271\r
3272 //\r
3273 // Free the allocated config request string.\r
3274 //\r
3275 if (AllocatedRequest) {\r
3276 FreePool (ConfigRequest);\r
3277 }\r
3278\r
beda2356 3279 //\r
3280 // Set Progress string to the original request string.\r
3281 //\r
3282 if (Request == NULL) {\r
3283 *Progress = NULL;\r
3284 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
3285 *Progress = Request + StrLen (Request);\r
3286 }\r
3287\r
96832eef
CZ
3288 if (SecureBoot != NULL) {\r
3289 FreePool (SecureBoot);\r
3290 }\r
3291\r
beda2356 3292 return Status;\r
3293}\r
3294\r
3295/**\r
3296 This function processes the results of changes in configuration.\r
3297\r
3298 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3299 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>\r
3300 format.\r
3301 @param[out] Progress A pointer to a string filled in with the offset of\r
3302 the most recent '&' before the first failing\r
3303 name/value pair (or the beginning of the string if\r
3304 the failure is in the first name/value pair) or\r
3305 the terminating NULL if all was successful.\r
3306\r
3307 @retval EFI_SUCCESS The Results is processed successfully.\r
3308 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
3309 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
3310 driver.\r
3311\r
3312**/\r
3313EFI_STATUS\r
3314EFIAPI\r
3315SecureBootRouteConfig (\r
3316 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3317 IN CONST EFI_STRING Configuration,\r
3318 OUT EFI_STRING *Progress\r
3319 )\r
3320{\r
a2f2c258 3321 UINT8 *SecureBootEnable;\r
3322 SECUREBOOT_CONFIGURATION IfrNvData;\r
3323 UINTN BufferSize;\r
3324 EFI_STATUS Status;\r
20333c6d 3325\r
beda2356 3326 if (Configuration == NULL || Progress == NULL) {\r
3327 return EFI_INVALID_PARAMETER;\r
3328 }\r
3329\r
3330 *Progress = Configuration;\r
3331 if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
3332 return EFI_NOT_FOUND;\r
3333 }\r
3334\r
a365eed4
FS
3335 //\r
3336 // Get Configuration from Variable.\r
3337 //\r
3338 SecureBootExtractConfigFromVariable (&IfrNvData);\r
3339\r
3340 //\r
3341 // Map the Configuration to the configuration block.\r
3342 //\r
a2f2c258 3343 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
3344 Status = gHiiConfigRouting->ConfigToBlock (\r
3345 gHiiConfigRouting,\r
3346 Configuration,\r
3347 (UINT8 *)&IfrNvData,\r
3348 &BufferSize,\r
3349 Progress\r
3350 );\r
3351 if (EFI_ERROR (Status)) {\r
3352 return Status;\r
3353 }\r
3354\r
3355 //\r
3356 // Store Buffer Storage back to EFI variable if needed\r
3357 //\r
3358 SecureBootEnable = NULL;\r
3359 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
3360 if (NULL != SecureBootEnable) {\r
3361 FreePool (SecureBootEnable);\r
3362 Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);\r
3363 if (EFI_ERROR (Status)) {\r
3364 return Status;\r
3365 }\r
3366 }\r
3367\r
ecc722ad 3368 *Progress = Configuration + StrLen (Configuration);\r
beda2356 3369 return EFI_SUCCESS;\r
3370}\r
3371\r
3372/**\r
ecc722ad 3373 This function is called to provide results data to the driver.\r
beda2356 3374\r
3375 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3376 @param[in] Action Specifies the type of action taken by the browser.\r
3377 @param[in] QuestionId A unique value which is sent to the original\r
3378 exporting driver so that it can identify the type\r
3379 of data to expect.\r
3380 @param[in] Type The type of value for the question.\r
3381 @param[in] Value A pointer to the data being sent to the original\r
3382 exporting driver.\r
3383 @param[out] ActionRequest On return, points to the action requested by the\r
3384 callback function.\r
3385\r
3386 @retval EFI_SUCCESS The callback successfully handled the action.\r
3387 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
3388 variable and its data.\r
3389 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
3390 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
3391 callback.\r
3392\r
3393**/\r
3394EFI_STATUS\r
3395EFIAPI\r
3396SecureBootCallback (\r
3397 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3398 IN EFI_BROWSER_ACTION Action,\r
3399 IN EFI_QUESTION_ID QuestionId,\r
3400 IN UINT8 Type,\r
3401 IN EFI_IFR_TYPE_VALUE *Value,\r
3402 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
3403 )\r
3404{\r
ecc722ad 3405 EFI_INPUT_KEY Key;\r
20333c6d 3406 EFI_STATUS Status;\r
ecc722ad 3407 SECUREBOOT_CONFIG_PRIVATE_DATA *Private;\r
3408 UINTN BufferSize;\r
3409 SECUREBOOT_CONFIGURATION *IfrNvData;\r
3410 UINT16 LabelId;\r
bf4a3dbd 3411 UINT8 *SecureBootEnable;\r
f71ed839 3412 UINT8 *SecureBootMode;\r
e4d7370d 3413 CHAR16 PromptString[100];\r
96832eef 3414 UINT8 CurSecureBootMode;\r
bf4a3dbd 3415\r
96832eef 3416 Status = EFI_SUCCESS;\r
bf4a3dbd 3417 SecureBootEnable = NULL;\r
f71ed839 3418 SecureBootMode = NULL;\r
bc0c99b3 3419\r
beda2356 3420 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
3421 return EFI_INVALID_PARAMETER;\r
3422 }\r
96832eef
CZ
3423 Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
3424\r
3425 //\r
3426 // Retrieve uncommitted data from Browser\r
3427 //\r
3428 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
3429 IfrNvData = AllocateZeroPool (BufferSize);\r
3430 if (IfrNvData == NULL) {\r
3431 return EFI_OUT_OF_RESOURCES;\r
3432 }\r
3433\r
3434 HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
beda2356 3435\r
a365eed4
FS
3436 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
3437 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
3438 mIsEnterSecureBootForm = TRUE;\r
96832eef
CZ
3439 } else if (QuestionId == KEY_TRANS_SECURE_BOOT_MODE){\r
3440 //\r
3441 // Secure Boot Policy variable changes after tranistion. Re-sync CurSecureBootMode\r
3442 //\r
3443 ExtractSecureBootModeFromVariable(&IfrNvData->CurSecureBootMode);\r
3444 mIsSelectedSecureBootModeForm = TRUE;\r
3445 mIsSecureBootModeChanged = FALSE;\r
a365eed4 3446 }\r
96832eef 3447 goto EXIT;\r
a365eed4 3448 }\r
20333c6d 3449\r
a365eed4
FS
3450 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
3451 Status = EFI_UNSUPPORTED;\r
3452 if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
3453 if (mIsEnterSecureBootForm) {\r
3454 Value->u8 = SECURE_BOOT_MODE_STANDARD;\r
3455 Status = EFI_SUCCESS;\r
3456 }\r
96832eef
CZ
3457 } else if (QuestionId == KEY_TRANS_SECURE_BOOT_MODE) {\r
3458 if (mIsSelectedSecureBootModeForm) {\r
3459 Value->u8 = IfrNvData->CurSecureBootMode;\r
3460 Status = EFI_SUCCESS;\r
3461 }\r
a365eed4 3462 }\r
96832eef 3463 goto EXIT;\r
a365eed4 3464 }\r
20333c6d 3465\r
f71ed839 3466 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
3467 (Action != EFI_BROWSER_ACTION_CHANGING) &&\r
a2f2c258 3468 (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&\r
3469 (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {\r
96832eef
CZ
3470 Status = EFI_UNSUPPORTED;\r
3471 goto EXIT;\r
beda2356 3472 }\r
bc0c99b3 3473\r
ecc722ad 3474 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
3475\r
3476 switch (QuestionId) {\r
3477 case KEY_SECURE_BOOT_ENABLE:\r
f01b91ae 3478 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
bf4a3dbd 3479 if (NULL != SecureBootEnable) {\r
f71ed839 3480 FreePool (SecureBootEnable);\r
ecc722ad 3481 if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {\r
3482 CreatePopUp (\r
3483 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3484 &Key,\r
3485 L"Only Physical Presence User could disable secure boot!",\r
3486 NULL\r
3487 );\r
3488 Status = EFI_UNSUPPORTED;\r
0357efe3 3489 } else {\r
3490 CreatePopUp (\r
3491 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3492 &Key,\r
f71ed839 3493 L"Configuration changed, please reset the platform to take effect!",\r
0357efe3 3494 NULL\r
3495 );\r
ecc722ad 3496 }\r
ecc722ad 3497 }\r
3498 break;\r
3499\r
3500 case KEY_SECURE_BOOT_OPTION:\r
3501 FreeMenu (&DirectoryMenu);\r
3502 FreeMenu (&FsOptionMenu);\r
3503 break;\r
3504\r
3505 case KEY_SECURE_BOOT_KEK_OPTION:\r
3506 case KEY_SECURE_BOOT_DB_OPTION:\r
3507 case KEY_SECURE_BOOT_DBX_OPTION:\r
20333c6d 3508 case KEY_SECURE_BOOT_DBT_OPTION:\r
ecc722ad 3509 //\r
3510 // Clear Signature GUID.\r
3511 //\r
3512 ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));\r
3513 if (Private->SignatureGUID == NULL) {\r
3514 Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
3515 if (Private->SignatureGUID == NULL) {\r
3516 return EFI_OUT_OF_RESOURCES;\r
3517 }\r
3518 }\r
beda2356 3519\r
ecc722ad 3520 if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {\r
3521 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
3522 } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {\r
3523 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
20333c6d
QL
3524 } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {\r
3525 LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;\r
ecc722ad 3526 } else {\r
3527 LabelId = FORMID_ENROLL_KEK_FORM;\r
3528 }\r
3529\r
3530 //\r
3531 // Refresh selected file.\r
3532 //\r
20333c6d 3533 CleanUpPage (LabelId, Private);\r
ecc722ad 3534 break;\r
20333c6d 3535\r
ecc722ad 3536 case SECUREBOOT_ADD_PK_FILE_FORM_ID:\r
3537 case FORMID_ENROLL_KEK_FORM:\r
3538 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
3539 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
20333c6d 3540 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:\r
ecc722ad 3541 if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {\r
3542 Private->FeCurrentState = FileExplorerStateEnrollPkFile;\r
3543 } else if (QuestionId == FORMID_ENROLL_KEK_FORM) {\r
3544 Private->FeCurrentState = FileExplorerStateEnrollKekFile;\r
3545 } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {\r
3546 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;\r
20333c6d 3547 } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DBX) {\r
ecc722ad 3548 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;\r
20333c6d
QL
3549 IfrNvData->CertificateFormat = HASHALG_SHA256;\r
3550 } else {\r
3551 Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbt;\r
ecc722ad 3552 }\r
3553\r
3554 Private->FeDisplayContext = FileExplorerDisplayUnknown;\r
3555 CleanUpPage (FORM_FILE_EXPLORER_ID, Private);\r
3556 UpdateFileExplorer (Private, 0);\r
3557 break;\r
3558\r
20333c6d 3559 case KEY_SECURE_BOOT_DELETE_PK:\r
f71ed839 3560 if (Value->u8) {\r
3561 CreatePopUp (\r
3562 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3563 &Key,\r
3564 L"Are you sure you want to delete PK? Secure boot will be disabled!",\r
3565 L"Press 'Y' to delete PK and exit, 'N' to discard change and return",\r
3566 NULL\r
3567 );\r
3568 if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {\r
ecc722ad 3569 Status = DeletePlatformKey ();\r
f71ed839 3570 if (EFI_ERROR (Status)) {\r
3571 CreatePopUp (\r
3572 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3573 &Key,\r
3574 L"Only Physical Presence User could delete PK in custom mode!",\r
3575 NULL\r
3576 );\r
3577 }\r
ecc722ad 3578 }\r
f71ed839 3579 }\r
ecc722ad 3580 break;\r
3581\r
3582 case KEY_DELETE_KEK:\r
3583 UpdateDeletePage (\r
20333c6d 3584 Private,\r
ecc722ad 3585 EFI_KEY_EXCHANGE_KEY_NAME,\r
3586 &gEfiGlobalVariableGuid,\r
3587 LABEL_KEK_DELETE,\r
3588 FORMID_DELETE_KEK_FORM,\r
20333c6d 3589 OPTION_DEL_KEK_QUESTION_ID\r
ecc722ad 3590 );\r
3591 break;\r
3592\r
20333c6d 3593 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:\r
ecc722ad 3594 UpdateDeletePage (\r
3595 Private,\r
3596 EFI_IMAGE_SECURITY_DATABASE,\r
3597 &gEfiImageSecurityDatabaseGuid,\r
3598 LABEL_DB_DELETE,\r
3599 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
3600 OPTION_DEL_DB_QUESTION_ID\r
3601 );\r
3602 break;\r
3603\r
3604 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:\r
3605 UpdateDeletePage (\r
3606 Private,\r
3607 EFI_IMAGE_SECURITY_DATABASE1,\r
3608 &gEfiImageSecurityDatabaseGuid,\r
3609 LABEL_DBX_DELETE,\r
3610 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
3611 OPTION_DEL_DBX_QUESTION_ID\r
3612 );\r
3613\r
3614 break;\r
3615\r
20333c6d
QL
3616 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:\r
3617 UpdateDeletePage (\r
3618 Private,\r
3619 EFI_IMAGE_SECURITY_DATABASE2,\r
3620 &gEfiImageSecurityDatabaseGuid,\r
3621 LABEL_DBT_DELETE,\r
3622 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
3623 OPTION_DEL_DBT_QUESTION_ID\r
3624 );\r
3625\r
3626 break;\r
3627\r
ecc722ad 3628 case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
3629 Status = EnrollKeyExchangeKey (Private);\r
ee79ac8d 3630 if (EFI_ERROR (Status)) {\r
3631 CreatePopUp (\r
3632 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3633 &Key,\r
3634 L"ERROR: Unsupported file type!",\r
3635 L"Only supports DER-encoded X509 certificate",\r
3636 NULL\r
3637 );\r
3638 }\r
ecc722ad 3639 break;\r
3640\r
3641 case KEY_VALUE_SAVE_AND_EXIT_DB:\r
3642 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
ee79ac8d 3643 if (EFI_ERROR (Status)) {\r
3644 CreatePopUp (\r
3645 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3646 &Key,\r
3647 L"ERROR: Unsupported file type!",\r
3648 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
3649 NULL\r
3650 );\r
3651 }\r
ecc722ad 3652 break;\r
3653\r
3654 case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
20333c6d
QL
3655 if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {\r
3656 CreatePopUp (\r
3657 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3658 &Key,\r
3659 L"Enrollment failed! Same certificate had already been in the dbx!",\r
3660 NULL\r
3661 );\r
3662 break;\r
3663 }\r
3664\r
3665 if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {\r
3666 Status = EnrollX509HashtoSigDB (\r
3667 Private,\r
3668 IfrNvData->CertificateFormat,\r
3669 &IfrNvData->RevocationDate,\r
3670 &IfrNvData->RevocationTime,\r
3671 IfrNvData->AlwaysRevocation\r
3672 );\r
3673 } else {\r
3674 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
3675 }\r
ee79ac8d 3676 if (EFI_ERROR (Status)) {\r
3677 CreatePopUp (\r
3678 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3679 &Key,\r
3680 L"ERROR: Unsupported file type!",\r
3681 L"Only supports DER-encoded X509 certificate and executable EFI image",\r
3682 NULL\r
3683 );\r
3684 }\r
ecc722ad 3685 break;\r
3686\r
20333c6d
QL
3687 case KEY_VALUE_SAVE_AND_EXIT_DBT:\r
3688 Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);\r
3689 if (EFI_ERROR (Status)) {\r
3690 CreatePopUp (\r
3691 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3692 &Key,\r
3693 L"ERROR: Unsupported file type!",\r
3694 L"Only supports DER-encoded X509 certificate.",\r
3695 NULL\r
3696 );\r
3697 }\r
3698 break;\r
96832eef
CZ
3699 case KEY_TRANS_SECURE_BOOT_MODE:\r
3700 //\r
3701 // Pop up to alert user want to change secure boot mode \r
3702 //\r
3703 if ((IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE && \r
3704 (Value->u8 == SECURE_BOOT_MODE_AUDIT_MODE || Value->u8 == SECURE_BOOT_MODE_DEPLOYED_MODE))\r
3705 ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE && \r
3706 Value->u8 == SECURE_BOOT_MODE_AUDIT_MODE)\r
3707 ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE && \r
3708 Value->u8 == SECURE_BOOT_MODE_USER_MODE && IfrNvData->PhysicalPresent == 1)){\r
3709 CreatePopUp (\r
3710 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3711 &Key,\r
3712 L"Are you sure you want to switch secure boot mode?",\r
3713 L"Press 'Y' to switch secure boot mode, 'N' to discard change and return",\r
3714 NULL\r
3715 );\r
3716 if (Key.UnicodeChar != 'y' && Key.UnicodeChar != 'Y') {\r
3717 //\r
3718 // If not 'Y'/''y' restore to defualt secure boot mode\r
3719 //\r
3720 Value->u8 = IfrNvData->CurSecureBootMode;\r
3721 goto EXIT;\r
3722 }\r
3723 } else if ((IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE && Value->u8 == SECURE_BOOT_MODE_USER_MODE)\r
3724 ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE && Value->u8 == SECURE_BOOT_MODE_SETUP_MODE)\r
3725 ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE && Value->u8 == SECURE_BOOT_MODE_DEPLOYED_MODE)\r
3726 ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE && Value->u8 == SECURE_BOOT_MODE_SETUP_MODE)) {\r
3727 CreatePopUp (\r
3728 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3729 &Key,\r
3730 L"Secure boot mode tranistion requires PK change",\r
3731 L"Please go to link below to update PK",\r
3732 NULL\r
3733 );\r
3734 } else {\r
3735 Status = EFI_INVALID_PARAMETER;\r
3736 goto EXIT;\r
3737 }\r
3738\r
3739 Status = SecureBootModeTransition(IfrNvData->CurSecureBootMode, Value->u8);\r
3740 //\r
3741 // Secure Boot Policy variable may change after tranistion. Re-sync CurSecureBootMode\r
3742 //\r
3743 ExtractSecureBootModeFromVariable(&CurSecureBootMode);\r
3744 if (IfrNvData->CurSecureBootMode != CurSecureBootMode) {\r
3745 IfrNvData->CurSecureBootMode = CurSecureBootMode;\r
3746 mIsSecureBootModeChanged = TRUE;\r
3747\r
3748 if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE) {\r
3749 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"UserMode", NULL);\r
3750 } else if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE) {\r
3751 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"SetupMode", NULL);\r
3752 } else if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
3753 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"AuditMode", NULL);\r
3754 } else if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
3755 HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"DeployedMode", NULL);\r
3756 }\r
3757 }\r
3758 break;\r
20333c6d 3759\r
ecc722ad 3760 default:\r
c93bcb7e 3761 if (QuestionId >= FILE_OPTION_GOTO_OFFSET) {\r
ecc722ad 3762 UpdateFileExplorer (Private, QuestionId);\r
3763 } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
3764 (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3765 DeleteKeyExchangeKey (Private, QuestionId);\r
3766 } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&\r
3767 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3768 DeleteSignature (\r
3769 Private,\r
3770 EFI_IMAGE_SECURITY_DATABASE,\r
3771 &gEfiImageSecurityDatabaseGuid,\r
20333c6d 3772 LABEL_DB_DELETE,\r
ecc722ad 3773 SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
3774 OPTION_DEL_DB_QUESTION_ID,\r
3775 QuestionId - OPTION_DEL_DB_QUESTION_ID\r
3776 );\r
3777 } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&\r
3778 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3779 DeleteSignature (\r
3780 Private,\r
3781 EFI_IMAGE_SECURITY_DATABASE1,\r
3782 &gEfiImageSecurityDatabaseGuid,\r
20333c6d 3783 LABEL_DBX_DELETE,\r
ecc722ad 3784 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
3785 OPTION_DEL_DBX_QUESTION_ID,\r
3786 QuestionId - OPTION_DEL_DBX_QUESTION_ID\r
3787 );\r
20333c6d
QL
3788 } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&\r
3789 (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
3790 DeleteSignature (\r
3791 Private,\r
3792 EFI_IMAGE_SECURITY_DATABASE2,\r
3793 &gEfiImageSecurityDatabaseGuid,\r
3794 LABEL_DBT_DELETE,\r
3795 SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
3796 OPTION_DEL_DBT_QUESTION_ID,\r
3797 QuestionId - OPTION_DEL_DBT_QUESTION_ID\r
3798 );\r
ecc722ad 3799 }\r
3800 break;\r
3801 }\r
3802 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
3803 switch (QuestionId) {\r
3804 case KEY_SECURE_BOOT_ENABLE:\r
f71ed839 3805 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
20333c6d 3806 break;\r
ecc722ad 3807 case KEY_VALUE_SAVE_AND_EXIT_PK:\r
3808 Status = EnrollPlatformKey (Private);\r
3809 if (EFI_ERROR (Status)) {\r
ee79ac8d 3810 UnicodeSPrint (\r
3811 PromptString,\r
3812 sizeof (PromptString),\r
3813 L"Only DER encoded certificate file (%s) is supported.",\r
3814 mSupportX509Suffix\r
3815 );\r
ecc722ad 3816 CreatePopUp (\r
3817 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3818 &Key,\r
e4d7370d 3819 L"ERROR: Unsupported file type!",\r
3820 PromptString,\r
ecc722ad 3821 NULL\r
3822 );\r
3823 } else {\r
20333c6d
QL
3824 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
3825 }\r
ecc722ad 3826 break;\r
3827\r
3828 case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
3829 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
3830 case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
3831 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
20333c6d 3832 case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:\r
ecc722ad 3833 if (Private->FileContext->FHandle != NULL) {\r
3834 CloseFile (Private->FileContext->FHandle);\r
3835 Private->FileContext->FHandle = NULL;\r
3836 Private->FileContext->FileName = NULL;\r
3837 }\r
20333c6d 3838\r
ecc722ad 3839 if (Private->SignatureGUID != NULL) {\r
3840 FreePool (Private->SignatureGUID);\r
3841 Private->SignatureGUID = NULL;\r
3842 }\r
3843 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
3844 break;\r
20333c6d 3845\r
ecc722ad 3846 case KEY_SECURE_BOOT_MODE:\r
a365eed4 3847 mIsEnterSecureBootForm = FALSE;\r
ecc722ad 3848 break;\r
96832eef
CZ
3849 case KEY_TRANS_SECURE_BOOT_MODE:\r
3850 mIsSelectedSecureBootModeForm = FALSE;\r
3851 if (mIsSecureBootModeChanged) {\r
3852 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
3853 }\r
3854 mIsSecureBootModeChanged = FALSE;\r
3855 break;\r
ecc722ad 3856 case KEY_SECURE_BOOT_KEK_GUID:\r
3857 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
3858 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
20333c6d 3859 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:\r
ecc722ad 3860 ASSERT (Private->SignatureGUID != NULL);\r
3861 Status = StringToGuid (\r
3862 IfrNvData->SignatureGuid,\r
3863 StrLen (IfrNvData->SignatureGuid),\r
3864 Private->SignatureGUID\r
3865 );\r
3866 if (EFI_ERROR (Status)) {\r
3867 break;\r
3868 }\r
3869\r
3870 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
3871 break;\r
3872\r
3873 case KEY_SECURE_BOOT_DELETE_PK:\r
96832eef 3874 if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE || IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
f71ed839 3875 IfrNvData->DeletePk = TRUE;\r
3876 IfrNvData->HasPk = FALSE;\r
ecc722ad 3877 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
f71ed839 3878 } else {\r
3879 IfrNvData->DeletePk = FALSE;\r
3880 IfrNvData->HasPk = TRUE;\r
3881 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
3882 }\r
c93bcb7e
ED
3883 break;\r
3884 default:\r
3885 if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) {\r
3886 if (UpdateFileExplorer (Private, QuestionId)) {\r
3887 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
3888 }\r
3889 }\r
3890 break;\r
ecc722ad 3891 }\r
a2f2c258 3892 } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {\r
3893 if (QuestionId == KEY_HIDE_SECURE_BOOT) {\r
3894 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
3895 if (SecureBootEnable == NULL) {\r
3896 IfrNvData->HideSecureBoot = TRUE;\r
3897 } else {\r
3898 FreePool (SecureBootEnable);\r
3899 IfrNvData->HideSecureBoot = FALSE;\r
3900 }\r
3901 Value->b = IfrNvData->HideSecureBoot;\r
3902 }\r
f71ed839 3903 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
3904 //\r
3905 // Force the platform back to Standard Mode once user leave the setup screen.\r
3906 //\r
3907 GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
3908 if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {\r
3909 IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
3910 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);\r
3911 }\r
3912 if (SecureBootMode != NULL) {\r
3913 FreePool (SecureBootMode);\r
3914 }\r
ecc722ad 3915 }\r
20333c6d 3916\r
96832eef
CZ
3917EXIT:\r
3918\r
ecc722ad 3919 if (!EFI_ERROR (Status)) {\r
3920 BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
742d9b3a 3921 HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
ecc722ad 3922 }\r
96832eef 3923\r
ecc722ad 3924 FreePool (IfrNvData);\r
20333c6d 3925\r
ecc722ad 3926 return EFI_SUCCESS;\r
beda2356 3927}\r
3928\r
3929/**\r
3930 This function publish the SecureBoot configuration Form.\r
3931\r
3932 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
3933\r
ecc722ad 3934 @retval EFI_SUCCESS HII Form is installed successfully.\r
beda2356 3935 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.\r
3936 @retval Others Other errors as indicated.\r
3937\r
3938**/\r
3939EFI_STATUS\r
3940InstallSecureBootConfigForm (\r
3941 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
3942 )\r
3943{\r
3944 EFI_STATUS Status;\r
3945 EFI_HII_HANDLE HiiHandle;\r
3946 EFI_HANDLE DriverHandle;\r
beda2356 3947 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3948\r
3949 DriverHandle = NULL;\r
3950 ConfigAccess = &PrivateData->ConfigAccess;\r
3951 Status = gBS->InstallMultipleProtocolInterfaces (\r
3952 &DriverHandle,\r
3953 &gEfiDevicePathProtocolGuid,\r
3954 &mSecureBootHiiVendorDevicePath,\r
3955 &gEfiHiiConfigAccessProtocolGuid,\r
3956 ConfigAccess,\r
3957 NULL\r
3958 );\r
3959 if (EFI_ERROR (Status)) {\r
3960 return Status;\r
3961 }\r
3962\r
3963 PrivateData->DriverHandle = DriverHandle;\r
3964\r
3965 //\r
3966 // Publish the HII package list\r
3967 //\r
3968 HiiHandle = HiiAddPackages (\r
3969 &gSecureBootConfigFormSetGuid,\r
3970 DriverHandle,\r
3971 SecureBootConfigDxeStrings,\r
3972 SecureBootConfigBin,\r
3973 NULL\r
3974 );\r
3975 if (HiiHandle == NULL) {\r
3976 gBS->UninstallMultipleProtocolInterfaces (\r
3977 DriverHandle,\r
3978 &gEfiDevicePathProtocolGuid,\r
3979 &mSecureBootHiiVendorDevicePath,\r
3980 &gEfiHiiConfigAccessProtocolGuid,\r
3981 ConfigAccess,\r
3982 NULL\r
bc0c99b3 3983 );\r
beda2356 3984 return EFI_OUT_OF_RESOURCES;\r
3985 }\r
bc0c99b3 3986\r
beda2356 3987 PrivateData->HiiHandle = HiiHandle;\r
ecc722ad 3988\r
3989 PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
3990 PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));\r
20333c6d 3991\r
ecc722ad 3992 if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) {\r
3993 UninstallSecureBootConfigForm (PrivateData);\r
3994 return EFI_OUT_OF_RESOURCES;\r
3995 }\r
20333c6d 3996\r
ecc722ad 3997 PrivateData->FeCurrentState = FileExplorerStateInActive;\r
3998 PrivateData->FeDisplayContext = FileExplorerDisplayUnknown;\r
20333c6d 3999\r
ecc722ad 4000 InitializeListHead (&FsOptionMenu.Head);\r
4001 InitializeListHead (&DirectoryMenu.Head);\r
4002\r
4003 //\r
4004 // Init OpCode Handle and Allocate space for creation of Buffer\r
4005 //\r
4006 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
4007 if (mStartOpCodeHandle == NULL) {\r
4008 UninstallSecureBootConfigForm (PrivateData);\r
4009 return EFI_OUT_OF_RESOURCES;\r
4010 }\r
4011\r
4012 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
4013 if (mEndOpCodeHandle == NULL) {\r
4014 UninstallSecureBootConfigForm (PrivateData);\r
4015 return EFI_OUT_OF_RESOURCES;\r
4016 }\r
4017\r
4018 //\r
4019 // Create Hii Extend Label OpCode as the start opcode\r
4020 //\r
4021 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
4022 mStartOpCodeHandle,\r
4023 &gEfiIfrTianoGuid,\r
4024 NULL,\r
4025 sizeof (EFI_IFR_GUID_LABEL)\r
4026 );\r
4027 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
4028\r
4029 //\r
4030 // Create Hii Extend Label OpCode as the end opcode\r
4031 //\r
4032 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
4033 mEndOpCodeHandle,\r
4034 &gEfiIfrTianoGuid,\r
4035 NULL,\r
4036 sizeof (EFI_IFR_GUID_LABEL)\r
4037 );\r
4038 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
4039 mEndLabel->Number = LABEL_END;\r
20333c6d 4040\r
bc0c99b3 4041 return EFI_SUCCESS;\r
beda2356 4042}\r
4043\r
4044/**\r
4045 This function removes SecureBoot configuration Form.\r
4046\r
4047 @param[in, out] PrivateData Points to SecureBoot configuration private data.\r
4048\r
4049**/\r
4050VOID\r
4051UninstallSecureBootConfigForm (\r
4052 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
4053 )\r
4054{\r
4055 //\r
4056 // Uninstall HII package list\r
4057 //\r
4058 if (PrivateData->HiiHandle != NULL) {\r
4059 HiiRemovePackages (PrivateData->HiiHandle);\r
4060 PrivateData->HiiHandle = NULL;\r
4061 }\r
4062\r
4063 //\r
4064 // Uninstall HII Config Access Protocol\r
4065 //\r
4066 if (PrivateData->DriverHandle != NULL) {\r
4067 gBS->UninstallMultipleProtocolInterfaces (\r
4068 PrivateData->DriverHandle,\r
4069 &gEfiDevicePathProtocolGuid,\r
4070 &mSecureBootHiiVendorDevicePath,\r
4071 &gEfiHiiConfigAccessProtocolGuid,\r
4072 &PrivateData->ConfigAccess,\r
4073 NULL\r
4074 );\r
4075 PrivateData->DriverHandle = NULL;\r
4076 }\r
bc0c99b3 4077\r
ecc722ad 4078 if (PrivateData->SignatureGUID != NULL) {\r
4079 FreePool (PrivateData->SignatureGUID);\r
4080 }\r
4081\r
4082 if (PrivateData->MenuEntry != NULL) {\r
4083 FreePool (PrivateData->MenuEntry);\r
4084 }\r
4085\r
4086 if (PrivateData->FileContext != NULL) {\r
4087 FreePool (PrivateData->FileContext);\r
4088 }\r
4089\r
beda2356 4090 FreePool (PrivateData);\r
ecc722ad 4091\r
4092 FreeMenu (&DirectoryMenu);\r
4093 FreeMenu (&FsOptionMenu);\r
4094\r
4095 if (mStartOpCodeHandle != NULL) {\r
4096 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
4097 }\r
4098\r
4099 if (mEndOpCodeHandle != NULL) {\r
4100 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
4101 }\r
beda2356 4102}\r