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