They will do basic validation for authentication data structure, then call crypto library\r
to verify the signature.\r
\r
-Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
//\r
CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };\r
\r
+CONST UINT8 mSha256OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 };\r
+\r
//\r
// Requirement for different signature type which have been defined in UEFI spec.\r
// These data are used to perform SignatureList format check while setting PK/KEK variable.\r
{EFI_CERT_X509_SHA512_GUID, 0, 80 }\r
};\r
\r
-//\r
-// Secure Boot Mode state machine\r
-//\r
-SECURE_BOOT_MODE mSecureBootState[SecureBootModeTypeMax] = {\r
- // USER MODE\r
- {\r
- AUDIT_MODE_DISABLE, // AuditMode\r
- FALSE, // IsAuditModeRO, AuditMode is RW\r
- DEPLOYED_MODE_DISABLE, // DeployedMode\r
- FALSE, // IsDeployedModeRO, DeployedMode is RW\r
- SETUP_MODE_DISABLE, // SetupMode\r
- // SetupMode is always RO\r
- SECURE_BOOT_MODE_ENABLE // SecureBoot\r
- },\r
- // SETUP MODE\r
- {\r
- AUDIT_MODE_DISABLE, // AuditMode\r
- FALSE, // IsAuditModeRO, AuditMode is RW\r
- DEPLOYED_MODE_DISABLE, // DeployedMode\r
- TRUE, // IsDeployedModeRO, DeployedMode is RO\r
- SETUP_MODE_ENABLE, // SetupMode\r
- // SetupMode is always RO\r
- SECURE_BOOT_MODE_DISABLE // SecureBoot\r
- },\r
- // AUDIT MODE\r
- {\r
- AUDIT_MODE_ENABLE, // AuditMode\r
- TRUE, // AuditModeValAttr RO, AuditMode is RO\r
- DEPLOYED_MODE_DISABLE, // DeployedMode\r
- TRUE, // DeployedModeValAttr RO, DeployedMode is RO\r
- SETUP_MODE_ENABLE, // SetupMode\r
- // SetupMode is always RO\r
- SECURE_BOOT_MODE_DISABLE // SecureBoot\r
- },\r
- // DEPLOYED MODE\r
- {\r
- AUDIT_MODE_DISABLE, // AuditMode, AuditMode is RO\r
- TRUE, // AuditModeValAttr RO\r
- DEPLOYED_MODE_ENABLE, // DeployedMode\r
- TRUE, // DeployedModeValAttr RO, DeployedMode is RO\r
- SETUP_MODE_DISABLE, // SetupMode\r
- // SetupMode is always RO\r
- SECURE_BOOT_MODE_ENABLE // SecureBoot\r
- }\r
-};\r
-\r
-SECURE_BOOT_MODE_TYPE mSecureBootMode;\r
-\r
/**\r
Finds variable in storage blocks of volatile and non-volatile storage areas.\r
\r
);\r
}\r
\r
-/**\r
- Update the variable region with Variable information.\r
-\r
- @param[in] VariableName Name of variable.\r
- @param[in] VendorGuid Guid of variable.\r
- @param[in] Data Data pointer.\r
- @param[in] DataSize Size of Data.\r
- @param[in] Attributes Attribute value of the variable.\r
- @param[in] KeyIndex Index of associated public key.\r
- @param[in] MonotonicCount Value of associated monotonic count.\r
-\r
- @retval EFI_SUCCESS The update operation is success.\r
- @retval EFI_INVALID_PARAMETER Invalid parameter.\r
- @retval EFI_WRITE_PROTECTED Variable is write-protected.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
-\r
-**/\r
-EFI_STATUS\r
-AuthServiceInternalUpdateVariableWithMonotonicCount (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid,\r
- IN VOID *Data,\r
- IN UINTN DataSize,\r
- IN UINT32 Attributes,\r
- IN UINT32 KeyIndex,\r
- IN UINT64 MonotonicCount\r
- )\r
-{\r
- AUTH_VARIABLE_INFO AuthVariableInfo;\r
-\r
- ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));\r
- AuthVariableInfo.VariableName = VariableName;\r
- AuthVariableInfo.VendorGuid = VendorGuid;\r
- AuthVariableInfo.Data = Data;\r
- AuthVariableInfo.DataSize = DataSize;\r
- AuthVariableInfo.Attributes = Attributes;\r
- AuthVariableInfo.PubKeyIndex = KeyIndex;\r
- AuthVariableInfo.MonotonicCount = MonotonicCount;\r
-\r
- return mAuthVarLibContextIn->UpdateVariable (\r
- &AuthVariableInfo\r
- );\r
-}\r
-\r
/**\r
Update the variable region with Variable information.\r
\r
}\r
\r
/**\r
- Initialize Secure Boot variables.\r
+ Determine whether this operation needs a physical present user.\r
\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
+ @param[in] VariableName Name of the Variable.\r
+ @param[in] VendorGuid GUID of the Variable.\r
+\r
+ @retval TRUE This variable is protected, only a physical present user could set this variable.\r
+ @retval FALSE This variable is not protected.\r
\r
**/\r
-EFI_STATUS\r
-InitSecureBootVariables (\r
- VOID\r
+BOOLEAN\r
+NeedPhysicallyPresent(\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 *Data;\r
- UINTN DataSize;\r
- UINT32 SecureBoot;\r
- UINT8 SecureBootEnable;\r
- SECURE_BOOT_MODE_TYPE SecureBootMode;\r
- BOOLEAN IsPkPresent;\r
-\r
- //\r
- // Find "PK" variable\r
- //\r
- Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);\r
- if (EFI_ERROR (Status)) {\r
- IsPkPresent = FALSE;\r
- DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));\r
- } else {\r
- IsPkPresent = TRUE;\r
- DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME));\r
- }\r
-\r
- //\r
- // Init "SecureBootMode" variable.\r
- // Initial case\r
- // SecureBootMode doesn't exist. Init it with PK state\r
- // 3 inconsistency cases need to sync\r
- // 1.1 Add PK -> system break -> update SecureBootMode Var\r
- // 1.2 Delete PK -> system break -> update SecureBootMode Var\r
- // 1.3 Set AuditMode ->Delete PK -> system break -> Update SecureBootMode Var\r
- //\r
- Status = AuthServiceInternalFindVariable (EDKII_SECURE_BOOT_MODE_NAME, &gEdkiiSecureBootModeGuid, (VOID **)&Data, &DataSize);\r
- if (EFI_ERROR(Status)) {\r
- //\r
- // Variable driver Initial Case\r
- //\r
- if (IsPkPresent) {\r
- SecureBootMode = SecureBootModeTypeUserMode;\r
- } else {\r
- SecureBootMode = SecureBootModeTypeSetupMode;\r
- }\r
- } else {\r
- //\r
- // 3 inconsistency cases need to sync\r
- //\r
- SecureBootMode = (SECURE_BOOT_MODE_TYPE)*Data;\r
- ASSERT(SecureBootMode < SecureBootModeTypeMax);\r
-\r
- if (IsPkPresent) {\r
- //\r
- // 3.1 Add PK -> system break -> update SecureBootMode Var\r
- //\r
- if (SecureBootMode == SecureBootModeTypeSetupMode) {\r
- SecureBootMode = SecureBootModeTypeUserMode;\r
- } else if (SecureBootMode == SecureBootModeTypeAuditMode) {\r
- SecureBootMode = SecureBootModeTypeDeployedMode;\r
- }\r
- } else {\r
- //\r
- // 3.2 Delete PK -> system break -> update SecureBootMode Var\r
- // 3.3 Set AuditMode ->Delete PK -> system break -> Update SecureBootMode Var. Reinit to be SetupMode\r
- //\r
- if ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode)) {\r
- SecureBootMode = SecureBootModeTypeSetupMode;\r
- }\r
- }\r
- }\r
-\r
- if (EFI_ERROR(Status) || (SecureBootMode != (SECURE_BOOT_MODE_TYPE)*Data)) {\r
- //\r
- // Update SecureBootMode Var\r
- //\r
- Status = AuthServiceInternalUpdateVariable (\r
- EDKII_SECURE_BOOT_MODE_NAME,\r
- &gEdkiiSecureBootModeGuid,\r
- &SecureBootMode,\r
- sizeof (UINT8),\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
- );\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // Init "AuditMode"\r
- //\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_AUDIT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &mSecureBootState[SecureBootMode].AuditMode,\r
- sizeof(UINT8),\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
- );\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Init "DeployedMode"\r
- //\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_DEPLOYED_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &mSecureBootState[SecureBootMode].DeployedMode,\r
- sizeof(UINT8),\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
- );\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Init "SetupMode"\r
- //\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_SETUP_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &mSecureBootState[SecureBootMode].SetupMode,\r
- sizeof(UINT8),\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
- );\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.\r
- // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in User Mode or Deployed Mode, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.\r
- // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.\r
- //\r
- SecureBootEnable = SECURE_BOOT_DISABLE;\r
- Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **)&Data, &DataSize);\r
- if (!EFI_ERROR(Status)) {\r
- if (!IsPkPresent) {\r
- //\r
- // PK is cleared in runtime. "SecureBootMode" is not updated before reboot\r
- // Delete "SecureBootMode"\r
- //\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_ENABLE_NAME,\r
- &gEfiSecureBootEnableDisableGuid,\r
- &SecureBootEnable,\r
- 0,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
- } else {\r
- SecureBootEnable = *Data;\r
- }\r
- } else if ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode)) {\r
- //\r
- // "SecureBootEnable" not exist, initialize it in User Mode or Deployed Mode.\r
- //\r
- SecureBootEnable = SECURE_BOOT_ENABLE;\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_ENABLE_NAME,\r
- &gEfiSecureBootEnableDisableGuid,\r
- &SecureBootEnable,\r
- sizeof (UINT8),\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // Create "SecureBoot" variable with BS+RT attribute set.\r
- //\r
- if ((SecureBootEnable == SECURE_BOOT_ENABLE) \r
- && ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode))) {\r
- SecureBoot = SECURE_BOOT_MODE_ENABLE;\r
- } else {\r
- SecureBoot = SECURE_BOOT_MODE_DISABLE;\r
+ if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))\r
+ || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {\r
+ return TRUE;\r
}\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SecureBoot,\r
- sizeof (UINT8),\r
- EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
-\r
- DEBUG ((EFI_D_INFO, "SecureBootMode is %x\n", SecureBootMode));\r
- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBoot));\r
- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));\r
\r
- //\r
- // Save SecureBootMode in global space\r
- //\r
- mSecureBootMode = SecureBootMode;\r
-\r
- return Status;\r
+ return FALSE;\r
}\r
\r
/**\r
- Update SecureBootMode variable.\r
-\r
- @param[in] NewMode New Secure Boot Mode.\r
+ Determine whether the platform is operating in Custom Secure Boot mode.\r
\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
+ @retval TRUE The platform is operating in Custom mode.\r
+ @retval FALSE The platform is operating in Standard mode.\r
\r
**/\r
-EFI_STATUS\r
-UpdateSecureBootMode(\r
- IN SECURE_BOOT_MODE_TYPE NewMode\r
+BOOLEAN\r
+InCustomMode (\r
+ VOID\r
)\r
{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Update "SecureBootMode" variable to new Secure Boot Mode\r
- //\r
- Status = AuthServiceInternalUpdateVariable (\r
- EDKII_SECURE_BOOT_MODE_NAME,\r
- &gEdkiiSecureBootModeGuid,\r
- &NewMode,\r
- sizeof (UINT8),\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
- );\r
+ EFI_STATUS Status;\r
+ VOID *Data;\r
+ UINTN DataSize;\r
\r
- if (!EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_INFO, "SecureBootMode Update to %x\n", NewMode));\r
- mSecureBootMode = NewMode;\r
- } else {\r
- DEBUG((EFI_D_ERROR, "SecureBootMode Update failure %x\n", Status));\r
+ Status = AuthServiceInternalFindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Data, &DataSize);\r
+ if (!EFI_ERROR (Status) && (*(UINT8 *) Data == CUSTOM_SECURE_BOOT_MODE)) {\r
+ return TRUE;\r
}\r
\r
- return Status;\r
+ return FALSE;\r
}\r
\r
/**\r
- Current secure boot mode is AuditMode. This function performs secure boot mode transition\r
- to a new mode.\r
+ Update platform mode.\r
\r
- @param[in] NewMode New Secure Boot Mode.\r
+ @param[in] Mode SETUP_MODE or USER_MODE.\r
\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
+ @return EFI_INVALID_PARAMETER Invalid parameter.\r
+ @return EFI_SUCCESS Update platform mode successfully.\r
\r
**/\r
EFI_STATUS\r
-TransitionFromAuditMode(\r
- IN SECURE_BOOT_MODE_TYPE NewMode\r
+UpdatePlatformMode (\r
+ IN UINT32 Mode\r
)\r
{\r
- EFI_STATUS Status;\r
- VOID *AuditVarData;\r
- VOID *DeployedVarData;\r
- VOID *SetupVarData;\r
- VOID *SecureBootVarData;\r
- UINT8 SecureBootEnable;\r
- UINTN DataSize;\r
+ EFI_STATUS Status;\r
+ VOID *Data;\r
+ UINTN DataSize;\r
+ UINT8 SecureBootMode;\r
+ UINT8 SecureBootEnable;\r
+ UINTN VariableDataSize;\r
\r
- //\r
- // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
- // they can be RW. but can't be deleted. so they can always be found.\r
- //\r
Status = AuthServiceInternalFindVariable (\r
- EFI_AUDIT_MODE_NAME,\r
+ EFI_SETUP_MODE_NAME,\r
&gEfiGlobalVariableGuid,\r
- &AuditVarData,\r
+ &Data,\r
&DataSize\r
);\r
if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
+ return Status;\r
}\r
\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_DEPLOYED_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &DeployedVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
+ //\r
+ // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
+ // variable storage reclaim at runtime.\r
+ //\r
+ mPlatformMode = (UINT8) Mode;\r
+ CopyMem (Data, &mPlatformMode, sizeof(UINT8));\r
+\r
+ if (mAuthVarLibContextIn->AtRuntime ()) {\r
+ //\r
+ // SecureBoot Variable indicates whether the platform firmware is operating\r
+ // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
+ // Variable in runtime.\r
+ //\r
+ return Status;\r
}\r
\r
+ //\r
+ // Check "SecureBoot" variable's existence.\r
+ // If it doesn't exist, firmware has no capability to perform driver signing verification,\r
+ // then set "SecureBoot" to 0.\r
+ //\r
Status = AuthServiceInternalFindVariable (\r
- EFI_SETUP_MODE_NAME,\r
+ EFI_SECURE_BOOT_MODE_NAME,\r
&gEfiGlobalVariableGuid,\r
- &SetupVarData,\r
+ &Data,\r
&DataSize\r
);\r
+ //\r
+ // If "SecureBoot" variable exists, then check "SetupMode" variable update.\r
+ // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.\r
+ // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.\r
+ //\r
if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
+ SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
+ } else {\r
+ if (mPlatformMode == USER_MODE) {\r
+ SecureBootMode = SECURE_BOOT_MODE_ENABLE;\r
+ } else if (mPlatformMode == SETUP_MODE) {\r
+ SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
+ } else {\r
+ return EFI_NOT_FOUND;\r
+ }\r
}\r
\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SECURE_BOOT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SecureBootVarData,\r
- &DataSize\r
- );\r
+ Status = AuthServiceInternalUpdateVariable (\r
+ EFI_SECURE_BOOT_MODE_NAME,\r
+ &gEfiGlobalVariableGuid,\r
+ &SecureBootMode,\r
+ sizeof(UINT8),\r
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+ );\r
if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
+ return Status;\r
}\r
\r
//\r
- // Make Secure Boot Mode transition ATOMIC\r
- // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow.\r
- // other tranisition logic are all memory operations.\r
+ // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.\r
//\r
- Status = UpdateSecureBootMode(NewMode);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
- }\r
-\r
- if (NewMode == SecureBootModeTypeDeployedMode) {\r
- //\r
- // Since PK is enrolled, can't rollback, always update SecureBootMode in memory\r
- //\r
- mSecureBootMode = NewMode;\r
- Status = EFI_SUCCESS;\r
+ Status = AuthServiceInternalFindVariable (\r
+ EFI_SECURE_BOOT_ENABLE_NAME,\r
+ &gEfiSecureBootEnableDisableGuid,\r
+ &Data,\r
+ &DataSize\r
+ );\r
\r
+ if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {\r
//\r
- // AuditMode ----> DeployedMode\r
- // Side Effects\r
- // AuditMode =: 0 / DeployedMode := 1 / SetupMode := 0\r
- //\r
- // Update the value of AuditMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8));\r
+ // Create the "SecureBootEnable" variable as secure boot is enabled.\r
//\r
- // Update the value of DeployedMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
+ SecureBootEnable = SECURE_BOOT_ENABLE;\r
+ VariableDataSize = sizeof (SecureBootEnable);\r
+ } else {\r
//\r
- // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
+ // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"\r
+ // variable is not in secure boot state.\r
//\r
- CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
-\r
- if (mAuthVarLibContextIn->AtRuntime ()) {\r
- //\r
- // SecureBoot Variable indicates whether the platform firmware is operating\r
- // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
- // Variable in runtime.\r
- //\r
- return Status;\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_SUCCESS;\r
}\r
-\r
- //\r
- // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
-\r
- //\r
- // Create "SecureBootEnable" variable as secure boot is enabled.\r
- //\r
- SecureBootEnable = SECURE_BOOT_ENABLE;\r
- AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_ENABLE_NAME,\r
- &gEfiSecureBootEnableDisableGuid,\r
- &SecureBootEnable,\r
- sizeof (SecureBootEnable),\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
- } else {\r
- DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeAuditMode, NewMode));\r
- ASSERT(FALSE);\r
+ SecureBootEnable = SECURE_BOOT_DISABLE;\r
+ VariableDataSize = 0;\r
}\r
\r
- return Status;\r
-}\r
-\r
-/**\r
- Current secure boot mode is DeployedMode. This function performs secure boot mode transition\r
- to a new mode.\r
-\r
- @param[in] NewMode New Secure Boot Mode.\r
-\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
-\r
-**/\r
-EFI_STATUS\r
-TransitionFromDeployedMode(\r
- IN SECURE_BOOT_MODE_TYPE NewMode\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *DeployedVarData;\r
- VOID *SetupVarData;\r
- VOID *SecureBootVarData;\r
- UINT8 SecureBootEnable;\r
- UINTN DataSize;\r
-\r
- //\r
- // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
- // they can be RW. but can't be deleted. so they can always be found.\r
- //\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_DEPLOYED_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &DeployedVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SETUP_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SetupVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SECURE_BOOT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SecureBootVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- //\r
- // Make Secure Boot Mode transition ATOMIC\r
- // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow.\r
- // other tranisition logic are all memory operations.\r
- //\r
- Status = UpdateSecureBootMode(NewMode);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
- }\r
-\r
- switch(NewMode) {\r
- case SecureBootModeTypeUserMode:\r
- //\r
- // DeployedMode ----> UserMode\r
- // Side Effects\r
- // DeployedMode := 0\r
- //\r
- // Platform Specific DeployedMode clear. UpdateSecureBootMode fails and no other variables are updated before. rollback this transition\r
- //\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
- CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
-\r
- break;\r
-\r
- case SecureBootModeTypeSetupMode:\r
- //\r
- // Since PK is processed before, can't rollback, still update SecureBootMode in memory\r
- //\r
- mSecureBootMode = NewMode;\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // DeployedMode ----> SetupMode\r
- //\r
- // Platform Specific PKpub clear or Delete Pkpub\r
- // Side Effects\r
- // DeployedMode := 0 / SetupMode := 1 / SecureBoot := 0\r
- //\r
- // Update the value of DeployedMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
- //\r
- // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
-\r
- if (mAuthVarLibContextIn->AtRuntime ()) {\r
- //\r
- // SecureBoot Variable indicates whether the platform firmware is operating\r
- // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
- // Variable in runtime.\r
- //\r
- return Status;\r
- }\r
-\r
- //\r
- // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
-\r
- //\r
- // Delete the "SecureBootEnable" variable as secure boot is Disabled.\r
- //\r
- SecureBootEnable = SECURE_BOOT_DISABLE;\r
- AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_ENABLE_NAME,\r
- &gEfiSecureBootEnableDisableGuid,\r
- &SecureBootEnable,\r
- 0,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
- break;\r
-\r
- default:\r
- DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeDeployedMode, NewMode));\r
- ASSERT(FALSE);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Current secure boot mode is UserMode. This function performs secure boot mode transition\r
- to a new mode.\r
-\r
- @param[in] NewMode New Secure Boot Mode.\r
-\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
-\r
-**/\r
-EFI_STATUS\r
-TransitionFromUserMode(\r
- IN SECURE_BOOT_MODE_TYPE NewMode\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *AuditVarData;\r
- VOID *DeployedVarData;\r
- VOID *SetupVarData;\r
- VOID *PkVarData;\r
- VOID *SecureBootVarData;\r
- UINT8 SecureBootEnable;\r
- UINTN DataSize;\r
- VARIABLE_ENTRY_CONSISTENCY VariableEntry;\r
-\r
- //\r
- // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
- // they can be RW. but can't be deleted. so they can always be found.\r
- //\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_AUDIT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &AuditVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_DEPLOYED_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &DeployedVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SETUP_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SetupVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SECURE_BOOT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SecureBootVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- //\r
- // Make Secure Boot Mode transition ATOMIC\r
- // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow. \r
- // Other tranisition logic are all memory operations and PK delete is assumed to be always successful.\r
- //\r
- if (NewMode != SecureBootModeTypeAuditMode) {\r
- Status = UpdateSecureBootMode(NewMode);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
- }\r
- } else {\r
- //\r
- // UserMode -----> AuditMode. Check RemainingSpace for SecureBootMode var first.\r
- // Will update SecureBootMode after DeletePK logic\r
- //\r
- VariableEntry.VariableSize = sizeof(UINT8);\r
- VariableEntry.Guid = &gEdkiiSecureBootModeGuid;\r
- VariableEntry.Name = EDKII_SECURE_BOOT_MODE_NAME;\r
- if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry, NULL)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
-\r
- switch(NewMode) {\r
- case SecureBootModeTypeDeployedMode:\r
- //\r
- // UpdateSecureBootMode fails and no other variables are updated before. rollback this transition\r
- //\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // UserMode ----> DeployedMode\r
- // Side Effects\r
- // DeployedMode := 1\r
- //\r
- CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
- break;\r
-\r
- case SecureBootModeTypeAuditMode:\r
- //\r
- // UserMode ----> AuditMode\r
- // Side Effects\r
- // Delete PKpub / SetupMode := 1 / SecureBoot := 0\r
- //\r
- // Delete PKpub without verification. Should always succeed.\r
- //\r
- PkVarData = NULL;\r
- Status = AuthServiceInternalUpdateVariable (\r
- EFI_PLATFORM_KEY_NAME,\r
- &gEfiGlobalVariableGuid,\r
- PkVarData,\r
- 0,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\r
- );\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "UserMode -> AuditMode. Delete PK fail %x\n", Status));\r
- ASSERT(FALSE);\r
- }\r
-\r
- //\r
- // Update Private NV SecureBootMode Variable\r
- //\r
- Status = UpdateSecureBootMode(NewMode);\r
- if (EFI_ERROR(Status)) {\r
- //\r
- // Since PK is deleted successfully, Doesn't break, continue to update other variable.\r
- //\r
- DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
- }\r
- CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8));\r
-\r
- //\r
- // Fall into SetupMode logic\r
- //\r
- case SecureBootModeTypeSetupMode:\r
- //\r
- // Since PK is deleted before , can't rollback, still update SecureBootMode in memory\r
- //\r
- mSecureBootMode = NewMode;\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // UserMode ----> SetupMode\r
- // Side Effects\r
- // DeployedMode :=0 / SetupMode :=1 / SecureBoot :=0\r
- //\r
- // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
-\r
- if (mAuthVarLibContextIn->AtRuntime ()) {\r
- //\r
- // SecureBoot Variable indicates whether the platform firmware is operating\r
- // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
- // Variable in runtime.\r
- //\r
- return Status;\r
- }\r
-\r
- //\r
- // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
-\r
- //\r
- // Delete the "SecureBootEnable" variable as secure boot is Disabled.\r
- //\r
- SecureBootEnable = SECURE_BOOT_DISABLE;\r
- AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_ENABLE_NAME,\r
- &gEfiSecureBootEnableDisableGuid,\r
- &SecureBootEnable,\r
- 0,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
-\r
- break;\r
-\r
- default:\r
- DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeUserMode, NewMode));\r
- ASSERT(FALSE);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Current secure boot mode is SetupMode. This function performs secure boot mode transition\r
- to a new mode.\r
-\r
- @param[in] NewMode New Secure Boot Mode.\r
-\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
-\r
-**/\r
-EFI_STATUS\r
-TransitionFromSetupMode(\r
- IN SECURE_BOOT_MODE_TYPE NewMode\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *AuditVarData;\r
- VOID *SetupVarData;\r
- VOID *SecureBootVarData;\r
- UINT8 SecureBootEnable;\r
- UINTN DataSize;\r
-\r
- //\r
- // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
- // they can be RW. but can't be deleted. so they can always be found.\r
- //\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_AUDIT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &AuditVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SETUP_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SetupVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- EFI_SECURE_BOOT_MODE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- &SecureBootVarData,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- //\r
- // Make Secure Boot Mode transition ATOMIC\r
- // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow.\r
- // Other tranisition logic are all memory operations and PK delete is assumed to be always successful.\r
- //\r
- Status = UpdateSecureBootMode(NewMode);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
- }\r
-\r
- switch(NewMode) {\r
- case SecureBootModeTypeAuditMode:\r
- //\r
- // UpdateSecureBootMode fails and no other variables are updated before. rollback this transition\r
- //\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // SetupMode ----> AuditMode\r
- // Side Effects\r
- // AuditMode := 1\r
- //\r
- // Update the value of AuditMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8));\r
- break;\r
-\r
- case SecureBootModeTypeUserMode:\r
- //\r
- // Since PK is enrolled before, can't rollback, still update SecureBootMode in memory\r
- //\r
- mSecureBootMode = NewMode;\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // SetupMode ----> UserMode\r
- // Side Effects\r
- // SetupMode := 0 / SecureBoot := 1\r
- //\r
- // Update the value of AuditMode variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
-\r
- if (mAuthVarLibContextIn->AtRuntime ()) {\r
- //\r
- // SecureBoot Variable indicates whether the platform firmware is operating\r
- // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
- // Variable in runtime.\r
- //\r
- return Status;\r
- }\r
-\r
- //\r
- // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
- // variable storage reclaim at runtime.\r
- //\r
- CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
-\r
- //\r
- // Create the "SecureBootEnable" variable as secure boot is enabled.\r
- //\r
- SecureBootEnable = SECURE_BOOT_ENABLE;\r
- AuthServiceInternalUpdateVariable (\r
- EFI_SECURE_BOOT_ENABLE_NAME,\r
- &gEfiSecureBootEnableDisableGuid,\r
- &SecureBootEnable,\r
- sizeof (SecureBootEnable),\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
- );\r
- break;\r
-\r
- default:\r
- DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeSetupMode, NewMode));\r
- ASSERT(FALSE);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- This function performs main secure boot mode transition logic.\r
-\r
- @param[in] CurMode Current Secure Boot Mode.\r
- @param[in] NewMode New Secure Boot Mode.\r
-\r
- @retval EFI_SUCCESS The initialization operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
- @retval EFI_INVALID_PARAMETER The Current Secure Boot Mode is wrong.\r
-\r
-**/\r
-EFI_STATUS\r
-SecureBootModeTransition(\r
- IN SECURE_BOOT_MODE_TYPE CurMode,\r
- IN SECURE_BOOT_MODE_TYPE NewMode\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // SecureBootMode transition\r
- //\r
- switch (CurMode) {\r
- case SecureBootModeTypeUserMode:\r
- Status = TransitionFromUserMode(NewMode);\r
- break;\r
-\r
- case SecureBootModeTypeSetupMode:\r
- Status = TransitionFromSetupMode(NewMode);\r
- break;\r
-\r
- case SecureBootModeTypeAuditMode:\r
- Status = TransitionFromAuditMode(NewMode);\r
- break;\r
-\r
- case SecureBootModeTypeDeployedMode:\r
- Status = TransitionFromDeployedMode(NewMode);\r
- break;\r
-\r
- default:\r
- Status = EFI_INVALID_PARAMETER;\r
- ASSERT(FALSE);\r
- }\r
-\r
- return Status;\r
-\r
-}\r
-\r
-/**\r
- Determine whether this operation needs a physical present user.\r
-\r
- @param[in] VariableName Name of the Variable.\r
- @param[in] VendorGuid GUID of the Variable.\r
-\r
- @retval TRUE This variable is protected, only a physical present user could set this variable.\r
- @retval FALSE This variable is not protected.\r
-\r
-**/\r
-BOOLEAN\r
-NeedPhysicallyPresent(\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid\r
- )\r
-{\r
- if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))\r
- || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Determine whether the platform is operating in Custom Secure Boot mode.\r
-\r
- @retval TRUE The platform is operating in Custom mode.\r
- @retval FALSE The platform is operating in Standard mode.\r
-\r
-**/\r
-BOOLEAN\r
-InCustomMode (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *Data;\r
- UINTN DataSize;\r
-\r
- Status = AuthServiceInternalFindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Data, &DataSize);\r
- if (!EFI_ERROR (Status) && (*(UINT8 *) Data == CUSTOM_SECURE_BOOT_MODE)) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Get available public key index.\r
-\r
- @param[in] PubKey Pointer to Public Key data.\r
-\r
- @return Public key index, 0 if no any public key index available.\r
-\r
-**/\r
-UINT32\r
-GetAvailableKeyIndex (\r
- IN UINT8 *PubKey\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 *Data;\r
- UINTN DataSize;\r
- UINT8 *Ptr;\r
- UINT32 Index;\r
- BOOLEAN IsFound;\r
- EFI_GUID VendorGuid;\r
- CHAR16 Name[1];\r
- AUTH_VARIABLE_INFO AuthVariableInfo;\r
- UINT32 KeyIndex;\r
-\r
- Status = AuthServiceInternalFindVariable (\r
- AUTHVAR_KEYDB_NAME,\r
- &gEfiAuthenticatedVariableGuid,\r
- (VOID **) &Data,\r
- &DataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));\r
- return 0;\r
- }\r
-\r
- if (mPubKeyNumber == mMaxKeyNumber) {\r
- Name[0] = 0;\r
- AuthVariableInfo.VariableName = Name;\r
- ZeroMem (&VendorGuid, sizeof (VendorGuid));\r
- AuthVariableInfo.VendorGuid = &VendorGuid;\r
- mPubKeyNumber = 0;\r
- //\r
- // Collect valid key data.\r
- //\r
- do {\r
- Status = mAuthVarLibContextIn->FindNextVariable (AuthVariableInfo.VariableName, AuthVariableInfo.VendorGuid, &AuthVariableInfo);\r
- if (!EFI_ERROR (Status)) {\r
- if (AuthVariableInfo.PubKeyIndex != 0) {\r
- for (Ptr = Data; Ptr < (Data + DataSize); Ptr += sizeof (AUTHVAR_KEY_DB_DATA)) {\r
- if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) Ptr)->KeyIndex)) == AuthVariableInfo.PubKeyIndex) {\r
- //\r
- // Check if the key data has been collected.\r
- //\r
- for (Index = 0; Index < mPubKeyNumber; Index++) {\r
- if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyIndex)) == AuthVariableInfo.PubKeyIndex) {\r
- break;\r
- }\r
- }\r
- if (Index == mPubKeyNumber) {\r
- //\r
- // New key data.\r
- //\r
- CopyMem ((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber, Ptr, sizeof (AUTHVAR_KEY_DB_DATA));\r
- mPubKeyNumber++;\r
- }\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- } while (Status != EFI_NOT_FOUND);\r
-\r
- //\r
- // No available space to add new public key.\r
- //\r
- if (mPubKeyNumber == mMaxKeyNumber) {\r
- return 0;\r
- }\r
- }\r
-\r
- //\r
- // Find available public key index.\r
- //\r
- for (KeyIndex = 1; KeyIndex <= mMaxKeyNumber; KeyIndex++) {\r
- IsFound = FALSE;\r
- for (Ptr = mPubKeyStore; Ptr < (mPubKeyStore + mPubKeyNumber * sizeof (AUTHVAR_KEY_DB_DATA)); Ptr += sizeof (AUTHVAR_KEY_DB_DATA)) {\r
- if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) Ptr)->KeyIndex)) == KeyIndex) {\r
- IsFound = TRUE;\r
- break;\r
- }\r
- }\r
- if (!IsFound) {\r
- break;\r
- }\r
- }\r
-\r
- return KeyIndex;\r
-}\r
-\r
-/**\r
- Add public key in store and return its index.\r
-\r
- @param[in] PubKey Input pointer to Public Key data.\r
- @param[in] VariableDataEntry The variable data entry.\r
-\r
- @return Index of new added public key.\r
-\r
-**/\r
-UINT32\r
-AddPubKeyInStore (\r
- IN UINT8 *PubKey,\r
- IN VARIABLE_ENTRY_CONSISTENCY *VariableDataEntry\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 Index;\r
- VARIABLE_ENTRY_CONSISTENCY PublicKeyEntry;\r
- UINT32 Attributes;\r
- UINT32 KeyIndex;\r
-\r
- if (PubKey == NULL) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Check whether the public key entry does exist.\r
- //\r
- for (Index = 0; Index < mPubKeyNumber; Index++) {\r
- if (CompareMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
- return ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyIndex));\r
- }\r
- }\r
-\r
- KeyIndex = GetAvailableKeyIndex (PubKey);\r
- if (KeyIndex == 0) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Check the variable space for both public key and variable data.\r
- //\r
- PublicKeyEntry.VariableSize = (mPubKeyNumber + 1) * sizeof (AUTHVAR_KEY_DB_DATA);\r
- PublicKeyEntry.Guid = &gEfiAuthenticatedVariableGuid;\r
- PublicKeyEntry.Name = AUTHVAR_KEYDB_NAME;\r
- Attributes = VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;\r
-\r
- if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (Attributes, &PublicKeyEntry, VariableDataEntry, NULL)) {\r
- //\r
- // No enough variable space.\r
- //\r
- return 0;\r
- }\r
-\r
- WriteUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber)->KeyIndex), KeyIndex);\r
- CopyMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
- mPubKeyNumber++;\r
-\r
- //\r
- // Update public key database variable.\r
- //\r
Status = AuthServiceInternalUpdateVariable (\r
- AUTHVAR_KEYDB_NAME,\r
- &gEfiAuthenticatedVariableGuid,\r
- mPubKeyStore,\r
- mPubKeyNumber * sizeof (AUTHVAR_KEY_DB_DATA),\r
- Attributes\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Update public key database variable failure, Status = %r\n", Status));\r
- return 0;\r
- }\r
-\r
- return KeyIndex;\r
-}\r
-\r
-/**\r
- Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.\r
- Follow the steps in UEFI2.2.\r
-\r
- Caution: This function may receive untrusted input.\r
- This function may be invoked in SMM mode, and datasize and data are external input.\r
- This function will do basic validation, before parse the data.\r
- This function will parse the authentication carefully to avoid security issues, like\r
- buffer overflow, integer overflow.\r
-\r
- @param[in] Data Pointer to data with AuthInfo.\r
- @param[in] DataSize Size of Data.\r
- @param[in] PubKey Public key used for verification.\r
-\r
- @retval EFI_INVALID_PARAMETER Invalid parameter.\r
- @retval EFI_SECURITY_VIOLATION If authentication failed.\r
- @retval EFI_SUCCESS Authentication successful.\r
-\r
-**/\r
-EFI_STATUS\r
-VerifyCounterBasedPayload (\r
- IN UINT8 *Data,\r
- IN UINTN DataSize,\r
- IN UINT8 *PubKey\r
- )\r
-{\r
- BOOLEAN Status;\r
- EFI_VARIABLE_AUTHENTICATION *CertData;\r
- EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;\r
- UINT8 Digest[SHA256_DIGEST_SIZE];\r
- VOID *Rsa;\r
- UINTN PayloadSize;\r
-\r
- PayloadSize = DataSize - AUTHINFO_SIZE;\r
- Rsa = NULL;\r
- CertData = NULL;\r
- CertBlock = NULL;\r
-\r
- if (Data == NULL || PubKey == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;\r
- CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);\r
-\r
- //\r
- // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.\r
- // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256_GUID.\r
- //\r
- if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||\r
- !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
- //\r
- // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.\r
- //\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
- //\r
- // Hash data payload with SHA256.\r
- //\r
- ZeroMem (Digest, SHA256_DIGEST_SIZE);\r
- Status = Sha256Init (mHashCtx);\r
- if (!Status) {\r
- goto Done;\r
- }\r
- Status = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, PayloadSize);\r
- if (!Status) {\r
- goto Done;\r
- }\r
- //\r
- // Hash Size.\r
- //\r
- Status = Sha256Update (mHashCtx, &PayloadSize, sizeof (UINTN));\r
- if (!Status) {\r
- goto Done;\r
- }\r
- //\r
- // Hash Monotonic Count.\r
- //\r
- Status = Sha256Update (mHashCtx, &CertData->MonotonicCount, sizeof (UINT64));\r
- if (!Status) {\r
- goto Done;\r
- }\r
- Status = Sha256Final (mHashCtx, Digest);\r
- if (!Status) {\r
- goto Done;\r
- }\r
- //\r
- // Generate & Initialize RSA Context.\r
- //\r
- Rsa = RsaNew ();\r
- ASSERT (Rsa != NULL);\r
- //\r
- // Set RSA Key Components.\r
- // NOTE: Only N and E are needed to be set as RSA public key for signature verification.\r
- //\r
- Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
- if (!Status) {\r
- goto Done;\r
- }\r
- Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));\r
- if (!Status) {\r
- goto Done;\r
- }\r
- //\r
- // Verify the signature.\r
- //\r
- Status = RsaPkcs1Verify (\r
- Rsa,\r
- Digest,\r
- SHA256_DIGEST_SIZE,\r
- CertBlock->Signature,\r
- EFI_CERT_TYPE_RSA2048_SHA256_SIZE\r
- );\r
-\r
-Done:\r
- if (Rsa != NULL) {\r
- RsaFree (Rsa);\r
- }\r
- if (Status) {\r
- return EFI_SUCCESS;\r
- } else {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
+ EFI_SECURE_BOOT_ENABLE_NAME,\r
+ &gEfiSecureBootEnableDisableGuid,\r
+ &SecureBootEnable,\r
+ VariableDataSize,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+ );\r
+ return Status;\r
}\r
\r
-\r
/**\r
Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx/dbt variable.\r
\r
RsaContext = NULL;\r
\r
//\r
- // Walk throuth the input signature list and check the data format.\r
+ // Walk through the input signature list and check the data format.\r
// If any signature is incorrectly formed, the whole check will fail.\r
//\r
while ((SigDataSize > 0) && (SigDataSize >= SigList->SignatureListSize)) {\r
);\r
}\r
\r
-/**\r
- Process Secure Boot Mode variable.\r
-\r
- Caution: This function may receive untrusted input.\r
- This function may be invoked in SMM mode, and datasize and data are external input.\r
- This function will do basic validation, before parse the data.\r
- This function will parse the authentication carefully to avoid security issues, like\r
- buffer overflow, integer overflow.\r
- This function will check attribute carefully to avoid authentication bypass.\r
-\r
- @param[in] VariableName Name of Variable to be found.\r
- @param[in] VendorGuid Variable vendor GUID.\r
- @param[in] Data Data pointer.\r
- @param[in] DataSize Size of Data found. If size is less than the\r
- data, this value contains the required size.\r
- @param[in] Attributes Attribute value of the variable\r
-\r
- @return EFI_INVALID_PARAMETER Invalid parameter\r
- @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation\r
- check carried out by the firmware.\r
- @return EFI_WRITE_PROTECTED Variable is Read-Only.\r
- @return EFI_SUCCESS Variable passed validation successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-ProcessSecureBootModeVar (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid,\r
- IN VOID *Data,\r
- IN UINTN DataSize,\r
- IN UINT32 Attributes OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *VarData;\r
- UINTN VarDataSize;\r
-\r
- //\r
- // Check "AuditMode", "DeployedMode" Variable ReadWrite Attributes\r
- // if in Runtime, Always RO\r
- // if in Boottime, Depends on current Secure Boot Mode\r
- //\r
- if (mAuthVarLibContextIn->AtRuntime()) {\r
- return EFI_WRITE_PROTECTED;\r
- }\r
-\r
- //\r
- // Delete not OK\r
- //\r
- if ((DataSize != sizeof(UINT8)) || (Attributes == 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0) {\r
- if(mSecureBootState[mSecureBootMode].IsAuditModeRO) {\r
- return EFI_WRITE_PROTECTED;\r
- }\r
- } else {\r
- //\r
- // Platform specific deployedMode clear. Set DeployedMode = RW\r
- //\r
- if (!InCustomMode() || !UserPhysicalPresent() || mSecureBootMode != SecureBootModeTypeDeployedMode) {\r
- if(mSecureBootState[mSecureBootMode].IsDeployedModeRO) {\r
- return EFI_WRITE_PROTECTED;\r
- }\r
- }\r
- }\r
-\r
- if (*(UINT8 *)Data != 0 && *(UINT8 *)Data != 1) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
- // they can be RW. but can't be deleted. so they can always be found.\r
- //\r
- Status = AuthServiceInternalFindVariable (\r
- VariableName,\r
- VendorGuid,\r
- &VarData,\r
- &VarDataSize\r
- );\r
- if (EFI_ERROR(Status)) {\r
- ASSERT(FALSE);\r
- }\r
-\r
- //\r
- // If AuditMode/DeployedMode is assigned same value. Simply return EFI_SUCCESS\r
- //\r
- if (*(UINT8 *)VarData == *(UINT8 *)Data) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Perform SecureBootMode transition\r
- //\r
- if (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0) {\r
- DEBUG((EFI_D_INFO, "Current SecureBootMode %x Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeAuditMode));\r
- return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeAuditMode);\r
- } else if (StrCmp (VariableName, EFI_DEPLOYED_MODE_NAME) == 0) {\r
- if (mSecureBootMode == SecureBootModeTypeDeployedMode) {\r
- //\r
- // Platform specific DeployedMode clear. InCustomMode() && UserPhysicalPresent() is checked before\r
- //\r
- DEBUG((EFI_D_INFO, "Current SecureBootMode %x. Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeUserMode));\r
- return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeUserMode);\r
- } else {\r
- DEBUG((EFI_D_INFO, "Current SecureBootMode %x. Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeDeployedMode));\r
- return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeDeployedMode);\r
- }\r
- }\r
-\r
- return EFI_INVALID_PARAMETER;\r
-}\r
-\r
/**\r
Process variable with platform key for verification.\r
\r
BOOLEAN Del;\r
UINT8 *Payload;\r
UINTN PayloadSize;\r
- VARIABLE_ENTRY_CONSISTENCY VariableEntry[2];\r
\r
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||\r
(Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
// Init state of Del. State may change due to secure check\r
//\r
Del = FALSE;\r
- Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);\r
- PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
- if (PayloadSize == 0) {\r
- Del = TRUE;\r
- }\r
-\r
- //\r
- // Check the variable space for both PKpub and SecureBootMode variable.\r
- //\r
- VariableEntry[0].VariableSize = PayloadSize;\r
- VariableEntry[0].Guid = &gEfiGlobalVariableGuid;\r
- VariableEntry[0].Name = EFI_PLATFORM_KEY_NAME;\r
-\r
- VariableEntry[1].VariableSize = sizeof(UINT8);\r
- VariableEntry[1].Guid = &gEdkiiSecureBootModeGuid;\r
- VariableEntry[1].Name = EDKII_SECURE_BOOT_MODE_NAME;\r
-\r
- if ((InCustomMode() && UserPhysicalPresent()) || \r
- (((mSecureBootMode == SecureBootModeTypeSetupMode) || (mSecureBootMode == SecureBootModeTypeAuditMode)) && !IsPk)) {\r
+ if ((InCustomMode() && UserPhysicalPresent()) || (mPlatformMode == SETUP_MODE && !IsPk)) {\r
+ Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);\r
+ PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
+ if (PayloadSize == 0) {\r
+ Del = TRUE;\r
+ }\r
\r
Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- //\r
- // If delete PKpub, only check for "SecureBootMode" only\r
- // if update / add PKpub, check both NewPKpub & "SecureBootMode"\r
- //\r
- if (IsPk) {\r
- //\r
- // Delete PKpub\r
- //\r
- if (Del && ((mSecureBootMode == SecureBootModeTypeUserMode) || (mSecureBootMode == SecureBootModeTypeDeployedMode)) \r
- && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[1], NULL)){\r
- return EFI_OUT_OF_RESOURCES;\r
- //\r
- // Add PKpub\r
- //\r
- } else if (!Del && ((mSecureBootMode == SecureBootModeTypeSetupMode) || (mSecureBootMode == SecureBootModeTypeAuditMode))\r
- && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
-\r
Status = AuthServiceInternalUpdateVariableWithTimeStamp (\r
VariableName,\r
VendorGuid,\r
return Status;\r
}\r
\r
- if (((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) || IsPk) {\r
+ if ((mPlatformMode != SETUP_MODE) || IsPk) {\r
Status = VendorKeyIsModified ();\r
}\r
- } else if (mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode) {\r
- //\r
- // If delete PKpub, check "SecureBootMode" only\r
- //\r
- if (IsPk && Del && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[1], NULL)){\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
+ } else if (mPlatformMode == USER_MODE) {\r
//\r
// Verify against X509 Cert in PK database.\r
//\r
);\r
} else {\r
//\r
- // SetupMode or AuditMode to add PK\r
// Verify against the certificate in data payload.\r
//\r
- //\r
- // Check PKpub & SecureBootMode variable space consistency\r
- //\r
- if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {\r
- //\r
- // No enough variable space to set PK successfully.\r
- //\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
Status = VerifyTimeBasedPayloadAndUpdate (\r
VariableName,\r
VendorGuid,\r
}\r
\r
if (!EFI_ERROR(Status) && IsPk) {\r
- //\r
- // Delete or Enroll PK causes SecureBootMode change\r
- //\r
- if (!Del) {\r
- if (mSecureBootMode == SecureBootModeTypeSetupMode) {\r
- //\r
- // If enroll PK in setup mode, change to user mode.\r
- //\r
- Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeUserMode);\r
- } else if (mSecureBootMode == SecureBootModeTypeAuditMode) {\r
- //\r
- // If enroll PK in Audit mode, change to Deployed mode.\r
- //\r
- Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeDeployedMode);\r
- } else {\r
- DEBUG((EFI_D_INFO, "PK is updated in %x mode. No SecureBootMode change.\n", mSecureBootMode));\r
- }\r
- } else {\r
- if ((mSecureBootMode == SecureBootModeTypeUserMode) || (mSecureBootMode == SecureBootModeTypeDeployedMode)) {\r
- //\r
- // If delete PK in User Mode or DeployedMode, change to Setup Mode.\r
- //\r
- Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeSetupMode);\r
- }\r
+ if (mPlatformMode == SETUP_MODE && !Del) {\r
+ //\r
+ // If enroll PK in setup mode, need change to user mode.\r
+ //\r
+ Status = UpdatePlatformMode (USER_MODE);\r
+ } else if (mPlatformMode == USER_MODE && Del){\r
+ //\r
+ // If delete PK in user mode, need change to setup mode.\r
+ //\r
+ Status = UpdatePlatformMode (SETUP_MODE);\r
}\r
}\r
\r
}\r
\r
Status = EFI_SUCCESS;\r
- if ((mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode)\r
- && !(InCustomMode() && UserPhysicalPresent())) {\r
+ if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {\r
//\r
// Time-based, verify against X509 Cert KEK.\r
//\r
return Status;\r
}\r
\r
- if ((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) {\r
+ if (mPlatformMode != SETUP_MODE) {\r
Status = VendorKeyIsModified ();\r
}\r
}\r
}\r
\r
/**\r
- Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set\r
+ Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set\r
\r
Caution: This function may receive untrusted input.\r
This function may be invoked in SMM mode, and datasize and data are external input.\r
\r
@return EFI_INVALID_PARAMETER Invalid parameter.\r
@return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with\r
- EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.\r
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.\r
@return EFI_OUT_OF_RESOURCES The Database to save the public key is full.\r
- @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\r
+ @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\r
set, but the AuthInfo does NOT pass the validation\r
check carried out by the firmware.\r
@return EFI_SUCCESS Variable is not write-protected or pass validation successfully.\r
)\r
{\r
EFI_STATUS Status;\r
- BOOLEAN IsDeletion;\r
- BOOLEAN IsFirstTime;\r
- UINT8 *PubKey;\r
- EFI_VARIABLE_AUTHENTICATION *CertData;\r
- EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;\r
- UINT32 KeyIndex;\r
- UINT64 MonotonicCount;\r
- VARIABLE_ENTRY_CONSISTENCY VariableDataEntry;\r
- UINT32 Index;\r
AUTH_VARIABLE_INFO OrgVariableInfo;\r
\r
- KeyIndex = 0;\r
- CertData = NULL;\r
- CertBlock = NULL;\r
- PubKey = NULL;\r
- IsDeletion = FALSE;\r
Status = EFI_SUCCESS;\r
\r
ZeroMem (&OrgVariableInfo, sizeof (OrgVariableInfo));\r
\r
if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable (OrgVariableInfo.Attributes, Data, DataSize, Attributes) && UserPhysicalPresent()) {\r
//\r
- // Allow the delete operation of common authenticated variable at user physical presence.\r
+ // Allow the delete operation of common authenticated variable(AT or AW) at user physical presence.\r
//\r
Status = AuthServiceInternalUpdateVariable (\r
VariableName,\r
}\r
\r
//\r
- // A time-based authenticated variable and a count-based authenticated variable\r
- // can't be updated by each other.\r
- //\r
- if (OrgVariableInfo.Data != NULL) {\r
- if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) &&\r
- ((OrgVariableInfo.Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)) {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-\r
- if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&\r
- ((OrgVariableInfo.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0)) {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
- }\r
-\r
- //\r
- // Process Time-based Authenticated variable.\r
- //\r
- if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+ if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+ //\r
+ // Reject Counter Based Auth Variable processing request.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ } else if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+ //\r
+ // Process Time-based Authenticated variable.\r
+ //\r
return VerifyTimeBasedPayloadAndUpdate (\r
VariableName,\r
VendorGuid,\r
);\r
}\r
\r
- //\r
- // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.\r
- //\r
- if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
- //\r
- // Determine current operation type.\r
- //\r
- if (DataSize == AUTHINFO_SIZE) {\r
- IsDeletion = TRUE;\r
- }\r
- //\r
- // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.\r
- //\r
- if (OrgVariableInfo.Data == NULL) {\r
- IsFirstTime = TRUE;\r
- } else if ((OrgVariableInfo.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
- IsFirstTime = TRUE;\r
- } else {\r
- KeyIndex = OrgVariableInfo.PubKeyIndex;\r
- IsFirstTime = FALSE;\r
- }\r
- } else if ((OrgVariableInfo.Data != NULL) &&\r
- ((OrgVariableInfo.Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)\r
- ) {\r
+ if ((OrgVariableInfo.Data != NULL) &&\r
+ ((OrgVariableInfo.Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)) {\r
//\r
// If the variable is already write-protected, it always needs authentication before update.\r
//\r
return EFI_WRITE_PROTECTED;\r
- } else {\r
- //\r
- // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.\r
- // That means it is not authenticated variable, just update variable as usual.\r
- //\r
- Status = AuthServiceInternalUpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes);\r
- return Status;\r
- }\r
-\r
- //\r
- // Get PubKey and check Monotonic Count value corresponding to the variable.\r
- //\r
- CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;\r
- CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);\r
- PubKey = CertBlock->PublicKey;\r
-\r
- //\r
- // Update Monotonic Count value.\r
- //\r
- MonotonicCount = CertData->MonotonicCount;\r
-\r
- if (!IsFirstTime) {\r
- //\r
- // 2 cases need to check here\r
- // 1. Internal PubKey variable. PubKeyIndex is always 0\r
- // 2. Other counter-based AuthVariable. Check input PubKey.\r
- //\r
- if (KeyIndex == 0) {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
- for (Index = 0; Index < mPubKeyNumber; Index++) {\r
- if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyIndex)) == KeyIndex) {\r
- if (CompareMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
- break;\r
- } else {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
- }\r
- }\r
- if (Index == mPubKeyNumber) {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-\r
- //\r
- // Compare the current monotonic count and ensure that it is greater than the last SetVariable\r
- // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.\r
- //\r
- if (MonotonicCount <= OrgVariableInfo.MonotonicCount) {\r
- //\r
- // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.\r
- //\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
- }\r
- //\r
- // Verify the certificate in Data payload.\r
- //\r
- Status = VerifyCounterBasedPayload (Data, DataSize, PubKey);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
}\r
\r
//\r
- // Now, the signature has been verified!\r
+ // Not authenticated variable, just update variable as usual.\r
//\r
- if (IsFirstTime && !IsDeletion) {\r
- VariableDataEntry.VariableSize = DataSize - AUTHINFO_SIZE;\r
- VariableDataEntry.Guid = VendorGuid;\r
- VariableDataEntry.Name = VariableName;\r
-\r
- //\r
- // Update public key database variable if need.\r
- //\r
- KeyIndex = AddPubKeyInStore (PubKey, &VariableDataEntry);\r
- if (KeyIndex == 0) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
+ Status = AuthServiceInternalUpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes);\r
+ return Status;\r
\r
- //\r
- // Verification pass.\r
- //\r
- return AuthServiceInternalUpdateVariableWithMonotonicCount (VariableName, VendorGuid, (UINT8*)Data + AUTHINFO_SIZE, DataSize - AUTHINFO_SIZE, Attributes, KeyIndex, MonotonicCount);\r
}\r
\r
/**\r
return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);\r
}\r
\r
+/**\r
+ Calculate SHA256 digest of SignerCert CommonName + ToplevelCert tbsCertificate\r
+ SignerCert and ToplevelCert are inside the signer certificate chain.\r
+\r
+ @param[in] SignerCert A pointer to SignerCert data.\r
+ @param[in] SignerCertSize Length of SignerCert data.\r
+ @param[in] TopLevelCert A pointer to TopLevelCert data.\r
+ @param[in] TopLevelCertSize Length of TopLevelCert data.\r
+ @param[out] Sha256Digest Sha256 digest calculated.\r
+\r
+ @return EFI_ABORTED Digest process failed.\r
+ @return EFI_SUCCESS SHA256 Digest is successfully calculated.\r
+\r
+**/\r
+EFI_STATUS\r
+CalculatePrivAuthVarSignChainSHA256Digest(\r
+ IN UINT8 *SignerCert,\r
+ IN UINTN SignerCertSize,\r
+ IN UINT8 *TopLevelCert,\r
+ IN UINTN TopLevelCertSize,\r
+ OUT UINT8 *Sha256Digest\r
+ )\r
+{\r
+ UINT8 *TbsCert;\r
+ UINTN TbsCertSize;\r
+ CHAR8 CertCommonName[128];\r
+ UINTN CertCommonNameSize;\r
+ BOOLEAN CryptoStatus;\r
+ EFI_STATUS Status;\r
+\r
+ CertCommonNameSize = sizeof(CertCommonName);\r
+\r
+ //\r
+ // Get SignerCert CommonName\r
+ //\r
+ Status = X509GetCommonName(SignerCert, SignerCertSize, CertCommonName, &CertCommonNameSize);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_INFO, "%a Get SignerCert CommonName failed with status %x\n", __FUNCTION__, Status));\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get TopLevelCert tbsCertificate\r
+ //\r
+ if (!X509GetTBSCert(TopLevelCert, TopLevelCertSize, &TbsCert, &TbsCertSize)) {\r
+ DEBUG((DEBUG_INFO, "%a Get Top-level Cert tbsCertificate failed!\n", __FUNCTION__));\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Digest SignerCert CN + TopLevelCert tbsCertificate\r
+ //\r
+ ZeroMem (Sha256Digest, SHA256_DIGEST_SIZE);\r
+ CryptoStatus = Sha256Init (mHashCtx);\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // '\0' is forced in CertCommonName. No overflow issue\r
+ //\r
+ CryptoStatus = Sha256Update (\r
+ mHashCtx,\r
+ CertCommonName,\r
+ AsciiStrLen (CertCommonName)\r
+ );\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ CryptoStatus = Sha256Update (mHashCtx, TbsCert, TbsCertSize);\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ CryptoStatus = Sha256Final (mHashCtx, Sha256Digest);\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Find matching signer's certificates for common authenticated variable\r
by corresponding VariableName and VendorGuid from "certdb" or "certdbv".\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- \r
+\r
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
//\r
// Get variable "certdb".\r
\r
/**\r
Delete matching signer's certificates when deleting common authenticated\r
- variable by corresponding VariableName and VendorGuid from "certdb" or \r
+ variable by corresponding VariableName and VendorGuid from "certdb" or\r
"certdbv" according to authenticated variable attributes.\r
\r
@param[in] VariableName Name of authenticated Variable.\r
/**\r
Insert signer's certificates for common authenticated variable with VariableName\r
and VendorGuid in AUTH_CERT_DB_DATA to "certdb" or "certdbv" according to\r
- time based authenticated variable attributes.\r
+ time based authenticated variable attributes. CertData is the SHA256 digest of\r
+ SignerCert CommonName + TopLevelCert tbsCertificate.\r
\r
- @param[in] VariableName Name of authenticated Variable.\r
- @param[in] VendorGuid Vendor GUID of authenticated Variable.\r
- @param[in] Attributes Attributes of authenticated variable.\r
- @param[in] CertData Pointer to signer's certificates.\r
- @param[in] CertDataSize Length of CertData in bytes.\r
+ @param[in] VariableName Name of authenticated Variable.\r
+ @param[in] VendorGuid Vendor GUID of authenticated Variable.\r
+ @param[in] Attributes Attributes of authenticated variable.\r
+ @param[in] SignerCert Signer certificate data.\r
+ @param[in] SignerCertSize Length of signer certificate.\r
+ @param[in] TopLevelCert Top-level certificate data.\r
+ @param[in] TopLevelCertSize Length of top-level certificate.\r
\r
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
@retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName\r
IN CHAR16 *VariableName,\r
IN EFI_GUID *VendorGuid,\r
IN UINT32 Attributes,\r
- IN UINT8 *CertData,\r
- IN UINTN CertDataSize\r
+ IN UINT8 *SignerCert,\r
+ IN UINTN SignerCertSize,\r
+ IN UINT8 *TopLevelCert,\r
+ IN UINTN TopLevelCertSize\r
)\r
{\r
EFI_STATUS Status;\r
UINT32 NewCertDbSize;\r
UINT32 CertNodeSize;\r
UINT32 NameSize;\r
+ UINT32 CertDataSize;\r
AUTH_CERT_DB_DATA *Ptr;\r
CHAR16 *DbName;\r
+ UINT8 Sha256Digest[SHA256_DIGEST_SIZE];\r
\r
- if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) {\r
+ if ((VariableName == NULL) || (VendorGuid == NULL) || (SignerCert == NULL) ||(TopLevelCert == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
// Construct new data content of variable "certdb" or "certdbv".\r
//\r
NameSize = (UINT32) StrLen (VariableName);\r
+ CertDataSize = sizeof(Sha256Digest);\r
CertNodeSize = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16);\r
NewCertDbSize = (UINT32) DataSize + CertNodeSize;\r
if (NewCertDbSize > mMaxCertDbSize) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+\r
+ Status = CalculatePrivAuthVarSignChainSHA256Digest(\r
+ SignerCert,\r
+ SignerCertSize,\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
+ Sha256Digest\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
NewCertDb = (UINT8*) mCertDbStore;\r
\r
//\r
\r
CopyMem (\r
(UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),\r
- CertData,\r
+ Sha256Digest,\r
CertDataSize\r
);\r
\r
&AuthVariableInfo\r
);\r
\r
- if (EFI_ERROR(Status)) {\r
+ if (EFI_ERROR(Status) || (AuthVariableInfo.Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
+ //\r
+ // While cleaning certdb, always delete the variable in certdb regardless of it attributes.\r
+ //\r
Status = DeleteCertsFromDb(\r
VariableName,\r
&AuthVarGuid,\r
- AuthVariableInfo.Attributes\r
+ AuthVariableInfo.Attributes | EFI_VARIABLE_NON_VOLATILE\r
);\r
CertCleaned = TRUE;\r
DEBUG((EFI_D_INFO, "Recovery!! Cert for Auth Variable %s Guid %g is removed for consistency\n", VariableName, &AuthVarGuid));\r
UINTN NewDataSize;\r
UINT8 *Buffer;\r
UINTN Length;\r
- UINT8 *RootCert;\r
- UINTN RootCertSize;\r
+ UINT8 *TopLevelCert;\r
+ UINTN TopLevelCertSize;\r
+ UINT8 *TrustedCert;\r
+ UINTN TrustedCertSize;\r
UINT8 *SignerCerts;\r
UINTN CertStackSize;\r
UINT8 *CertsInCertDb;\r
UINT32 CertsSizeinDb;\r
+ UINT8 Sha256Digest[SHA256_DIGEST_SIZE];\r
+ EFI_CERT_DATA *CertDataPtr;\r
\r
+ //\r
+ // 1. TopLevelCert is the top-level issuer certificate in signature Signer Cert Chain\r
+ // 2. TrustedCert is the certificate which firmware trusts. It could be saved in protected\r
+ // storage or PK payload on PK init\r
+ //\r
VerifyStatus = FALSE;\r
CertData = NULL;\r
NewData = NULL;\r
Attr = Attributes;\r
SignerCerts = NULL;\r
- RootCert = NULL;\r
+ TopLevelCert = NULL;\r
CertsInCertDb = NULL;\r
+ CertDataPtr = NULL;\r
\r
//\r
// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is\r
SigData = CertData->AuthInfo.CertData;\r
SigDataSize = CertData->AuthInfo.Hdr.dwLength - (UINT32) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));\r
\r
+ //\r
+ // SignedData.digestAlgorithms shall contain the digest algorithm used when preparing the\r
+ // signature. Only a digest algorithm of SHA-256 is accepted.\r
+ //\r
+ // According to PKCS#7 Definition:\r
+ // SignedData ::= SEQUENCE {\r
+ // version Version,\r
+ // digestAlgorithms DigestAlgorithmIdentifiers,\r
+ // contentInfo ContentInfo,\r
+ // .... }\r
+ // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm\r
+ // in VARIABLE_AUTHENTICATION_2 descriptor.\r
+ // This field has the fixed offset (+13) and be calculated based on two bytes of length encoding.\r
+ //\r
+ if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+ if (SigDataSize >= (13 + sizeof (mSha256OidValue))) {\r
+ if (((*(SigData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) ||\r
+ (CompareMem (SigData + 13, &mSha256OidValue, sizeof (mSha256OidValue)) != 0)) {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+ }\r
+ }\r
+\r
//\r
// Find out the new data payload which follows Pkcs7 SignedData directly.\r
//\r
SigDataSize,\r
&SignerCerts,\r
&CertStackSize,\r
- &RootCert,\r
- &RootCertSize\r
+ &TopLevelCert,\r
+ &TopLevelCertSize\r
);\r
if (!VerifyStatus) {\r
goto Exit;\r
}\r
CertList = (EFI_SIGNATURE_LIST *) Data;\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- if ((RootCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
- (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {\r
+ if ((TopLevelCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
+ (CompareMem (Cert->SignatureData, TopLevelCert, TopLevelCertSize) != 0)) {\r
VerifyStatus = FALSE;\r
goto Exit;\r
}\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
NewData,\r
NewDataSize\r
);\r
//\r
// Iterate each Signature Data Node within this CertList for a verify\r
//\r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
+ TrustedCert = Cert->SignatureData;\r
+ TrustedCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
\r
//\r
// Verify Pkcs7 SignedData via Pkcs7Verify library.\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TrustedCert,\r
+ TrustedCertSize,\r
NewData,\r
NewDataSize\r
);\r
SigDataSize,\r
&SignerCerts,\r
&CertStackSize,\r
- &RootCert,\r
- &RootCertSize\r
+ &TopLevelCert,\r
+ &TopLevelCertSize\r
);\r
if (!VerifyStatus) {\r
goto Exit;\r
goto Exit;\r
}\r
\r
- if ((CertStackSize != CertsSizeinDb) ||\r
- (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
- goto Exit;\r
+ if (CertsSizeinDb == SHA256_DIGEST_SIZE) {\r
+ //\r
+ // Check hash of signer cert CommonName + Top-level issuer tbsCertificate against data in CertDb\r
+ //\r
+ CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1);\r
+ Status = CalculatePrivAuthVarSignChainSHA256Digest(\r
+ CertDataPtr->CertDataBuffer,\r
+ ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)),\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
+ Sha256Digest\r
+ );\r
+ if (EFI_ERROR(Status) || CompareMem (Sha256Digest, CertsInCertDb, CertsSizeinDb) != 0){\r
+ goto Exit;\r
+ }\r
+ } else {\r
+ //\r
+ // Keep backward compatible with previous solution which saves whole signer certs stack in CertDb\r
+ //\r
+ if ((CertStackSize != CertsSizeinDb) ||\r
+ (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
+ goto Exit;\r
+ }\r
}\r
}\r
\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
NewData,\r
NewDataSize\r
);\r
\r
if ((OrgTimeStamp == NULL) && (PayloadSize != 0)) {\r
//\r
- // Insert signer's certificates when adding a new common authenticated variable.\r
+ // When adding a new common authenticated variable, always save Hash of cn of signer cert + tbsCertificate of Top-level issuer\r
//\r
- Status = InsertCertsToDb (VariableName, VendorGuid, Attributes, SignerCerts, CertStackSize);\r
+ CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1);\r
+ Status = InsertCertsToDb (\r
+ VariableName,\r
+ VendorGuid,\r
+ Attributes,\r
+ CertDataPtr->CertDataBuffer,\r
+ ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)),\r
+ TopLevelCert,\r
+ TopLevelCertSize\r
+ );\r
if (EFI_ERROR (Status)) {\r
VerifyStatus = FALSE;\r
goto Exit;\r
} else if (AuthVarType == AuthVarTypePayload) {\r
CertList = (EFI_SIGNATURE_LIST *) PayloadPtr;\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
+ TrustedCert = Cert->SignatureData;\r
+ TrustedCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
//\r
// Verify Pkcs7 SignedData via Pkcs7Verify library.\r
//\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TrustedCert,\r
+ TrustedCertSize,\r
NewData,\r
NewDataSize\r
);\r
Exit:\r
\r
if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {\r
- Pkcs7FreeSigners (RootCert);\r
+ Pkcs7FreeSigners (TopLevelCert);\r
Pkcs7FreeSigners (SignerCerts);\r
}\r
\r