From: Zhang, Chao B Date: Thu, 28 Apr 2016 05:28:39 +0000 (+0800) Subject: SecurityPkg: AuthVariableLib: Remove Customized SecureBoot Mode transition. X-Git-Tag: edk2-stable201903~7159 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=560ac77ea155857da879648e559a60b528b19730 SecurityPkg: AuthVariableLib: Remove Customized SecureBoot Mode transition. Remove Customized SecureBoot Mode transition logic for Mantis 1263, including AuditMode/DeployedMode/PK update management. Also remove image verification logic in AuditMode. The feature has been moved to https://github.com/tianocore/edk2-staging/tree/Customized-Secure-Boot Previous check-in hash is SHA-1: 4fc08e8d683522f255727626197d919a40d4836c Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chao Zhang Reviewed-by: El-Haj-Mahmoud Samer Reviewed-by: Fu Siyuan --- diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c index 4649e50e5e..6e1e284801 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthService.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c @@ -56,54 +56,6 @@ EFI_SIGNATURE_ITEM mSupportSigItem[] = { {EFI_CERT_X509_SHA512_GUID, 0, 80 } }; -// -// Secure Boot Mode state machine -// -SECURE_BOOT_MODE mSecureBootState[SecureBootModeTypeMax] = { - // USER MODE - { - AUDIT_MODE_DISABLE, // AuditMode - FALSE, // IsAuditModeRO, AuditMode is RW - DEPLOYED_MODE_DISABLE, // DeployedMode - FALSE, // IsDeployedModeRO, DeployedMode is RW - SETUP_MODE_DISABLE, // SetupMode - // SetupMode is always RO - SECURE_BOOT_MODE_ENABLE // SecureBoot - }, - // SETUP MODE - { - AUDIT_MODE_DISABLE, // AuditMode - FALSE, // IsAuditModeRO, AuditMode is RW - DEPLOYED_MODE_DISABLE, // DeployedMode - TRUE, // IsDeployedModeRO, DeployedMode is RO - SETUP_MODE_ENABLE, // SetupMode - // SetupMode is always RO - SECURE_BOOT_MODE_DISABLE // SecureBoot - }, - // AUDIT MODE - { - AUDIT_MODE_ENABLE, // AuditMode - TRUE, // AuditModeValAttr RO, AuditMode is RO - DEPLOYED_MODE_DISABLE, // DeployedMode - TRUE, // DeployedModeValAttr RO, DeployedMode is RO - SETUP_MODE_ENABLE, // SetupMode - // SetupMode is always RO - SECURE_BOOT_MODE_DISABLE // SecureBoot - }, - // DEPLOYED MODE - { - AUDIT_MODE_DISABLE, // AuditMode, AuditMode is RO - TRUE, // AuditModeValAttr RO - DEPLOYED_MODE_ENABLE, // DeployedMode - TRUE, // DeployedModeValAttr RO, DeployedMode is RO - SETUP_MODE_DISABLE, // SetupMode - // SetupMode is always RO - SECURE_BOOT_MODE_ENABLE // SecureBoot - } -}; - -SECURE_BOOT_MODE_TYPE mSecureBootMode; - /** Finds variable in storage blocks of volatile and non-volatile storage areas. @@ -221,976 +173,80 @@ AuthServiceInternalUpdateVariableWithMonotonicCount ( AuthVariableInfo.PubKeyIndex = KeyIndex; AuthVariableInfo.MonotonicCount = MonotonicCount; - return mAuthVarLibContextIn->UpdateVariable ( - &AuthVariableInfo - ); -} - -/** - Update the variable region with Variable information. - - @param[in] VariableName Name of variable. - @param[in] VendorGuid Guid of variable. - @param[in] Data Data pointer. - @param[in] DataSize Size of Data. - @param[in] Attributes Attribute value of the variable. - @param[in] TimeStamp Value of associated TimeStamp. - - @retval EFI_SUCCESS The update operation is success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_WRITE_PROTECTED Variable is write-protected. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -AuthServiceInternalUpdateVariableWithTimeStamp ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN VOID *Data, - IN UINTN DataSize, - IN UINT32 Attributes, - IN EFI_TIME *TimeStamp - ) -{ - EFI_STATUS FindStatus; - VOID *OrgData; - UINTN OrgDataSize; - AUTH_VARIABLE_INFO AuthVariableInfo; - - FindStatus = AuthServiceInternalFindVariable ( - VariableName, - VendorGuid, - &OrgData, - &OrgDataSize - ); - - // - // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable - // - if (!EFI_ERROR (FindStatus) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) { - if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && - ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) || - (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0))) || - (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) { - // - // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of - // EFI_SIGNATURE_DATA values that are already part of the existing variable value. - // - FilterSignatureList ( - OrgData, - OrgDataSize, - Data, - &DataSize - ); - } - } - - ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo)); - AuthVariableInfo.VariableName = VariableName; - AuthVariableInfo.VendorGuid = VendorGuid; - AuthVariableInfo.Data = Data; - AuthVariableInfo.DataSize = DataSize; - AuthVariableInfo.Attributes = Attributes; - AuthVariableInfo.TimeStamp = TimeStamp; - return mAuthVarLibContextIn->UpdateVariable ( - &AuthVariableInfo - ); -} - -/** - Initialize Secure Boot variables. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -InitSecureBootVariables ( - VOID - ) -{ - EFI_STATUS Status; - UINT8 *Data; - UINTN DataSize; - UINT32 SecureBoot; - UINT8 SecureBootEnable; - SECURE_BOOT_MODE_TYPE SecureBootMode; - BOOLEAN IsPkPresent; - - // - // Find "PK" variable - // - Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize); - if (EFI_ERROR (Status)) { - IsPkPresent = FALSE; - DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME)); - } else { - IsPkPresent = TRUE; - DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME)); - } - - // - // Init "SecureBootMode" variable. - // Initial case - // SecureBootMode doesn't exist. Init it with PK state - // 3 inconsistency cases need to sync - // 1.1 Add PK -> system break -> update SecureBootMode Var - // 1.2 Delete PK -> system break -> update SecureBootMode Var - // 1.3 Set AuditMode ->Delete PK -> system break -> Update SecureBootMode Var - // - Status = AuthServiceInternalFindVariable (EDKII_SECURE_BOOT_MODE_NAME, &gEdkiiSecureBootModeGuid, (VOID **)&Data, &DataSize); - if (EFI_ERROR(Status)) { - // - // Variable driver Initial Case - // - if (IsPkPresent) { - SecureBootMode = SecureBootModeTypeUserMode; - } else { - SecureBootMode = SecureBootModeTypeSetupMode; - } - } else { - // - // 3 inconsistency cases need to sync - // - SecureBootMode = (SECURE_BOOT_MODE_TYPE)*Data; - ASSERT(SecureBootMode < SecureBootModeTypeMax); - - if (IsPkPresent) { - // - // 3.1 Add PK -> system break -> update SecureBootMode Var - // - if (SecureBootMode == SecureBootModeTypeSetupMode) { - SecureBootMode = SecureBootModeTypeUserMode; - } else if (SecureBootMode == SecureBootModeTypeAuditMode) { - SecureBootMode = SecureBootModeTypeDeployedMode; - } - } else { - // - // 3.2 Delete PK -> system break -> update SecureBootMode Var - // 3.3 Set AuditMode ->Delete PK -> system break -> Update SecureBootMode Var. Reinit to be SetupMode - // - if ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode)) { - SecureBootMode = SecureBootModeTypeSetupMode; - } - } - } - - if (EFI_ERROR(Status) || (SecureBootMode != (SECURE_BOOT_MODE_TYPE)*Data)) { - // - // Update SecureBootMode Var - // - Status = AuthServiceInternalUpdateVariable ( - EDKII_SECURE_BOOT_MODE_NAME, - &gEdkiiSecureBootModeGuid, - &SecureBootMode, - sizeof (UINT8), - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - ); - if (EFI_ERROR(Status)) { - return Status; - } - } - - // - // Init "AuditMode" - // - Status = AuthServiceInternalUpdateVariable ( - EFI_AUDIT_MODE_NAME, - &gEfiGlobalVariableGuid, - &mSecureBootState[SecureBootMode].AuditMode, - sizeof(UINT8), - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - ); - if (EFI_ERROR(Status)) { - return Status; - } - - // - // Init "DeployedMode" - // - Status = AuthServiceInternalUpdateVariable ( - EFI_DEPLOYED_MODE_NAME, - &gEfiGlobalVariableGuid, - &mSecureBootState[SecureBootMode].DeployedMode, - sizeof(UINT8), - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - ); - if (EFI_ERROR(Status)) { - return Status; - } - - // - // Init "SetupMode" - // - Status = AuthServiceInternalUpdateVariable ( - EFI_SETUP_MODE_NAME, - &gEfiGlobalVariableGuid, - &mSecureBootState[SecureBootMode].SetupMode, - sizeof(UINT8), - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - ); - if (EFI_ERROR(Status)) { - return Status; - } - - // - // If "SecureBootEnable" variable exists, then update "SecureBoot" variable. - // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in User Mode or Deployed Mode, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE. - // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE. - // - SecureBootEnable = SECURE_BOOT_DISABLE; - Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **)&Data, &DataSize); - if (!EFI_ERROR(Status)) { - if (IsPkPresent) { - SecureBootEnable = *Data; - } - } else if ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode)) { - // - // "SecureBootEnable" not exist, initialize it in User Mode or Deployed Mode. - // - SecureBootEnable = SECURE_BOOT_ENABLE; - Status = AuthServiceInternalUpdateVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - &SecureBootEnable, - sizeof (UINT8), - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // Create "SecureBoot" variable with BS+RT attribute set. - // - if ((SecureBootEnable == SECURE_BOOT_ENABLE) - && ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode))) { - SecureBoot = SECURE_BOOT_MODE_ENABLE; - } else { - SecureBoot = SECURE_BOOT_MODE_DISABLE; - } - Status = AuthServiceInternalUpdateVariable ( - EFI_SECURE_BOOT_MODE_NAME, - &gEfiGlobalVariableGuid, - &SecureBoot, - sizeof (UINT8), - EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS - ); - - DEBUG ((EFI_D_INFO, "SecureBootMode is %x\n", SecureBootMode)); - DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBoot)); - DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable)); - - // - // Save SecureBootMode in global space - // - mSecureBootMode = SecureBootMode; - - return Status; -} - -/** - Update SecureBootMode variable. - - @param[in] NewMode New Secure Boot Mode. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -UpdateSecureBootMode( - IN SECURE_BOOT_MODE_TYPE NewMode - ) -{ - EFI_STATUS Status; - - // - // Update "SecureBootMode" variable to new Secure Boot Mode - // - Status = AuthServiceInternalUpdateVariable ( - EDKII_SECURE_BOOT_MODE_NAME, - &gEdkiiSecureBootModeGuid, - &NewMode, - sizeof (UINT8), - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - ); - - if (!EFI_ERROR(Status)) { - DEBUG((EFI_D_INFO, "SecureBootMode Update to %x\n", NewMode)); - mSecureBootMode = NewMode; - } else { - DEBUG((EFI_D_ERROR, "SecureBootMode Update failure %x\n", Status)); - } - - return Status; -} - -/** - Current secure boot mode is AuditMode. This function performs secure boot mode transition - to a new mode. - - @param[in] NewMode New Secure Boot Mode. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -TransitionFromAuditMode( - IN SECURE_BOOT_MODE_TYPE NewMode - ) -{ - EFI_STATUS Status; - VOID *AuditVarData; - VOID *DeployedVarData; - VOID *SetupVarData; - VOID *SecureBootVarData; - UINT8 SecureBootEnable; - UINTN DataSize; - - // - // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver - // they can be RW. but can't be deleted. so they can always be found. - // - Status = AuthServiceInternalFindVariable ( - EFI_AUDIT_MODE_NAME, - &gEfiGlobalVariableGuid, - &AuditVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_DEPLOYED_MODE_NAME, - &gEfiGlobalVariableGuid, - &DeployedVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SETUP_MODE_NAME, - &gEfiGlobalVariableGuid, - &SetupVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SECURE_BOOT_MODE_NAME, - &gEfiGlobalVariableGuid, - &SecureBootVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - // - // Make Secure Boot Mode transition ATOMIC - // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow. - // other tranisition logic are all memory operations. - // - Status = UpdateSecureBootMode(NewMode); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status)); - } - - if (NewMode == SecureBootModeTypeDeployedMode) { - // - // Since PK is enrolled, can't rollback, always update SecureBootMode in memory - // - mSecureBootMode = NewMode; - Status = EFI_SUCCESS; - - // - // AuditMode ----> DeployedMode - // Side Effects - // AuditMode =: 0 / DeployedMode := 1 / SetupMode := 0 - // - // Update the value of AuditMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8)); - // - // Update the value of DeployedMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8)); - // - // Update the value of SetupMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8)); - - if (mAuthVarLibContextIn->AtRuntime ()) { - // - // SecureBoot Variable indicates whether the platform firmware is operating - // in Secure boot mode (1) or not (0), so we should not change SecureBoot - // Variable in runtime. - // - return Status; - } - - // - // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8)); - - // - // Create "SecureBootEnable" variable as secure boot is enabled. - // - SecureBootEnable = SECURE_BOOT_ENABLE; - AuthServiceInternalUpdateVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - &SecureBootEnable, - sizeof (SecureBootEnable), - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS - ); - } else { - DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeAuditMode, NewMode)); - ASSERT(FALSE); - } - - return Status; -} - -/** - Current secure boot mode is DeployedMode. This function performs secure boot mode transition - to a new mode. - - @param[in] NewMode New Secure Boot Mode. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -TransitionFromDeployedMode( - IN SECURE_BOOT_MODE_TYPE NewMode - ) -{ - EFI_STATUS Status; - VOID *DeployedVarData; - VOID *SetupVarData; - VOID *SecureBootVarData; - UINT8 SecureBootEnable; - UINTN DataSize; - - // - // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver - // they can be RW. but can't be deleted. so they can always be found. - // - Status = AuthServiceInternalFindVariable ( - EFI_DEPLOYED_MODE_NAME, - &gEfiGlobalVariableGuid, - &DeployedVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SETUP_MODE_NAME, - &gEfiGlobalVariableGuid, - &SetupVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SECURE_BOOT_MODE_NAME, - &gEfiGlobalVariableGuid, - &SecureBootVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - // - // Make Secure Boot Mode transition ATOMIC - // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow. - // other tranisition logic are all memory operations. - // - Status = UpdateSecureBootMode(NewMode); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status)); - } - - switch(NewMode) { - case SecureBootModeTypeUserMode: - // - // DeployedMode ----> UserMode - // Side Effects - // DeployedMode := 0 - // - // Platform Specific DeployedMode clear. UpdateSecureBootMode fails and no other variables are updated before. rollback this transition - // - if (EFI_ERROR(Status)) { - return Status; - } - CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8)); - - break; - - case SecureBootModeTypeSetupMode: - // - // Since PK is processed before, can't rollback, still update SecureBootMode in memory - // - mSecureBootMode = NewMode; - Status = EFI_SUCCESS; - - // - // DeployedMode ----> SetupMode - // - // Platform Specific PKpub clear or Delete Pkpub - // Side Effects - // DeployedMode := 0 / SetupMode := 1 / SecureBoot := 0 - // - // Update the value of DeployedMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8)); - // - // Update the value of SetupMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8)); - - if (mAuthVarLibContextIn->AtRuntime ()) { - // - // SecureBoot Variable indicates whether the platform firmware is operating - // in Secure boot mode (1) or not (0), so we should not change SecureBoot - // Variable in runtime. - // - return Status; - } - - // - // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8)); - - // - // Delete the "SecureBootEnable" variable as secure boot is Disabled. - // - SecureBootEnable = SECURE_BOOT_DISABLE; - AuthServiceInternalUpdateVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - &SecureBootEnable, - 0, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS - ); - break; - - default: - DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeDeployedMode, NewMode)); - ASSERT(FALSE); - } - - return Status; -} - -/** - Current secure boot mode is UserMode. This function performs secure boot mode transition - to a new mode. - - @param[in] NewMode New Secure Boot Mode. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -TransitionFromUserMode( - IN SECURE_BOOT_MODE_TYPE NewMode - ) -{ - EFI_STATUS Status; - VOID *AuditVarData; - VOID *DeployedVarData; - VOID *SetupVarData; - VOID *PkVarData; - VOID *SecureBootVarData; - UINT8 SecureBootEnable; - UINTN DataSize; - VARIABLE_ENTRY_CONSISTENCY VariableEntry; - - // - // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver - // they can be RW. but can't be deleted. so they can always be found. - // - Status = AuthServiceInternalFindVariable ( - EFI_AUDIT_MODE_NAME, - &gEfiGlobalVariableGuid, - &AuditVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_DEPLOYED_MODE_NAME, - &gEfiGlobalVariableGuid, - &DeployedVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SETUP_MODE_NAME, - &gEfiGlobalVariableGuid, - &SetupVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SECURE_BOOT_MODE_NAME, - &gEfiGlobalVariableGuid, - &SecureBootVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - // - // Make Secure Boot Mode transition ATOMIC - // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow. - // Other tranisition logic are all memory operations and PK delete is assumed to be always successful. - // - if (NewMode != SecureBootModeTypeAuditMode) { - Status = UpdateSecureBootMode(NewMode); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status)); - } - } else { - // - // UserMode -----> AuditMode. Check RemainingSpace for SecureBootMode var first. - // Will update SecureBootMode after DeletePK logic - // - VariableEntry.VariableSize = sizeof(UINT8); - VariableEntry.Guid = &gEdkiiSecureBootModeGuid; - VariableEntry.Name = EDKII_SECURE_BOOT_MODE_NAME; - if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry, NULL)) { - return EFI_OUT_OF_RESOURCES; - } - } - - switch(NewMode) { - case SecureBootModeTypeDeployedMode: - // - // UpdateSecureBootMode fails and no other variables are updated before. rollback this transition - // - if (EFI_ERROR(Status)) { - return Status; - } - - // - // UserMode ----> DeployedMode - // Side Effects - // DeployedMode := 1 - // - CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8)); - break; - - case SecureBootModeTypeAuditMode: - // - // UserMode ----> AuditMode - // Side Effects - // Delete PKpub / SetupMode := 1 / SecureBoot := 0 - // - // Delete PKpub without verification. Should always succeed. - // - PkVarData = NULL; - Status = AuthServiceInternalUpdateVariable ( - EFI_PLATFORM_KEY_NAME, - &gEfiGlobalVariableGuid, - PkVarData, - 0, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS - ); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "UserMode -> AuditMode. Delete PK fail %x\n", Status)); - ASSERT(FALSE); - } - - // - // Update Private NV SecureBootMode Variable - // - Status = UpdateSecureBootMode(NewMode); - if (EFI_ERROR(Status)) { - // - // Since PK is deleted successfully, Doesn't break, continue to update other variable. - // - DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status)); - } - CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8)); - - // - // Fall into SetupMode logic - // - case SecureBootModeTypeSetupMode: - // - // Since PK is deleted before , can't rollback, still update SecureBootMode in memory - // - mSecureBootMode = NewMode; - Status = EFI_SUCCESS; - - // - // UserMode ----> SetupMode - // Side Effects - // DeployedMode :=0 / SetupMode :=1 / SecureBoot :=0 - // - // Update the value of SetupMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8)); - - if (mAuthVarLibContextIn->AtRuntime ()) { - // - // SecureBoot Variable indicates whether the platform firmware is operating - // in Secure boot mode (1) or not (0), so we should not change SecureBoot - // Variable in runtime. - // - return Status; - } - - // - // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8)); - - // - // Delete the "SecureBootEnable" variable as secure boot is Disabled. - // - SecureBootEnable = SECURE_BOOT_DISABLE; - AuthServiceInternalUpdateVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - &SecureBootEnable, - 0, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS - ); - - break; - - default: - DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeUserMode, NewMode)); - ASSERT(FALSE); - } - - return Status; -} - -/** - Current secure boot mode is SetupMode. This function performs secure boot mode transition - to a new mode. - - @param[in] NewMode New Secure Boot Mode. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -TransitionFromSetupMode( - IN SECURE_BOOT_MODE_TYPE NewMode - ) -{ - EFI_STATUS Status; - VOID *AuditVarData; - VOID *SetupVarData; - VOID *SecureBootVarData; - UINT8 SecureBootEnable; - UINTN DataSize; - - // - // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver - // they can be RW. but can't be deleted. so they can always be found. - // - Status = AuthServiceInternalFindVariable ( - EFI_AUDIT_MODE_NAME, - &gEfiGlobalVariableGuid, - &AuditVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SETUP_MODE_NAME, - &gEfiGlobalVariableGuid, - &SetupVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - Status = AuthServiceInternalFindVariable ( - EFI_SECURE_BOOT_MODE_NAME, - &gEfiGlobalVariableGuid, - &SecureBootVarData, - &DataSize - ); - if (EFI_ERROR (Status)) { - ASSERT(FALSE); - } - - // - // Make Secure Boot Mode transition ATOMIC - // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow. - // Other tranisition logic are all memory operations and PK delete is assumed to be always successful. - // - Status = UpdateSecureBootMode(NewMode); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status)); - } - - switch(NewMode) { - case SecureBootModeTypeAuditMode: - // - // UpdateSecureBootMode fails and no other variables are updated before. rollback this transition - // - if (EFI_ERROR(Status)) { - return Status; - } - - // - // SetupMode ----> AuditMode - // Side Effects - // AuditMode := 1 - // - // Update the value of AuditMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8)); - break; - - case SecureBootModeTypeUserMode: - // - // Since PK is enrolled before, can't rollback, still update SecureBootMode in memory - // - mSecureBootMode = NewMode; - Status = EFI_SUCCESS; - - // - // SetupMode ----> UserMode - // Side Effects - // SetupMode := 0 / SecureBoot := 1 - // - // Update the value of AuditMode variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8)); - - if (mAuthVarLibContextIn->AtRuntime ()) { - // - // SecureBoot Variable indicates whether the platform firmware is operating - // in Secure boot mode (1) or not (0), so we should not change SecureBoot - // Variable in runtime. - // - return Status; - } - - // - // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible - // variable storage reclaim at runtime. - // - CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8)); - - // - // Create the "SecureBootEnable" variable as secure boot is enabled. - // - SecureBootEnable = SECURE_BOOT_ENABLE; - AuthServiceInternalUpdateVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - &SecureBootEnable, - sizeof (SecureBootEnable), - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS - ); - break; - - default: - DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeSetupMode, NewMode)); - ASSERT(FALSE); - } - - return Status; + return mAuthVarLibContextIn->UpdateVariable ( + &AuthVariableInfo + ); } /** - This function performs main secure boot mode transition logic. + Update the variable region with Variable information. - @param[in] CurMode Current Secure Boot Mode. - @param[in] NewMode New Secure Boot Mode. + @param[in] VariableName Name of variable. + @param[in] VendorGuid Guid of variable. + @param[in] Data Data pointer. + @param[in] DataSize Size of Data. + @param[in] Attributes Attribute value of the variable. + @param[in] TimeStamp Value of associated TimeStamp. - @retval EFI_SUCCESS The initialization operation is successful. + @retval EFI_SUCCESS The update operation is success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_WRITE_PROTECTED Variable is write-protected. @retval EFI_OUT_OF_RESOURCES There is not enough resource. - @retval EFI_INVALID_PARAMETER The Current Secure Boot Mode is wrong. **/ EFI_STATUS -SecureBootModeTransition( - IN SECURE_BOOT_MODE_TYPE CurMode, - IN SECURE_BOOT_MODE_TYPE NewMode +AuthServiceInternalUpdateVariableWithTimeStamp ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes, + IN EFI_TIME *TimeStamp ) { - EFI_STATUS Status; + EFI_STATUS FindStatus; + VOID *OrgData; + UINTN OrgDataSize; + AUTH_VARIABLE_INFO AuthVariableInfo; + + FindStatus = AuthServiceInternalFindVariable ( + VariableName, + VendorGuid, + &OrgData, + &OrgDataSize + ); // - // SecureBootMode transition + // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable // - switch (CurMode) { - case SecureBootModeTypeUserMode: - Status = TransitionFromUserMode(NewMode); - break; - - case SecureBootModeTypeSetupMode: - Status = TransitionFromSetupMode(NewMode); - break; - - case SecureBootModeTypeAuditMode: - Status = TransitionFromAuditMode(NewMode); - break; - - case SecureBootModeTypeDeployedMode: - Status = TransitionFromDeployedMode(NewMode); - break; - - default: - Status = EFI_INVALID_PARAMETER; - ASSERT(FALSE); + if (!EFI_ERROR (FindStatus) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) { + if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && + ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) || + (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0))) || + (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) { + // + // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of + // EFI_SIGNATURE_DATA values that are already part of the existing variable value. + // + FilterSignatureList ( + OrgData, + OrgDataSize, + Data, + &DataSize + ); + } } - return Status; - + ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo)); + AuthVariableInfo.VariableName = VariableName; + AuthVariableInfo.VendorGuid = VendorGuid; + AuthVariableInfo.Data = Data; + AuthVariableInfo.DataSize = DataSize; + AuthVariableInfo.Attributes = Attributes; + AuthVariableInfo.TimeStamp = TimeStamp; + return mAuthVarLibContextIn->UpdateVariable ( + &AuthVariableInfo + ); } /** @@ -1541,6 +597,129 @@ Done: } } +/** + Update platform mode. + + @param[in] Mode SETUP_MODE or USER_MODE. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Update platform mode successfully. + +**/ +EFI_STATUS +UpdatePlatformMode ( + IN UINT32 Mode + ) +{ + EFI_STATUS Status; + VOID *Data; + UINTN DataSize; + UINT8 SecureBootMode; + UINT8 SecureBootEnable; + UINTN VariableDataSize; + + Status = AuthServiceInternalFindVariable ( + EFI_SETUP_MODE_NAME, + &gEfiGlobalVariableGuid, + &Data, + &DataSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update the value of SetupMode variable by a simple mem copy, this could avoid possible + // variable storage reclaim at runtime. + // + mPlatformMode = (UINT8) Mode; + CopyMem (Data, &mPlatformMode, sizeof(UINT8)); + + if (mAuthVarLibContextIn->AtRuntime ()) { + // + // SecureBoot Variable indicates whether the platform firmware is operating + // in Secure boot mode (1) or not (0), so we should not change SecureBoot + // Variable in runtime. + // + return Status; + } + + // + // Check "SecureBoot" variable's existence. + // If it doesn't exist, firmware has no capability to perform driver signing verification, + // then set "SecureBoot" to 0. + // + Status = AuthServiceInternalFindVariable ( + EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, + &Data, + &DataSize + ); + // + // If "SecureBoot" variable exists, then check "SetupMode" variable update. + // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1. + // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0. + // + if (EFI_ERROR (Status)) { + SecureBootMode = SECURE_BOOT_MODE_DISABLE; + } else { + if (mPlatformMode == USER_MODE) { + SecureBootMode = SECURE_BOOT_MODE_ENABLE; + } else if (mPlatformMode == SETUP_MODE) { + SecureBootMode = SECURE_BOOT_MODE_DISABLE; + } else { + return EFI_NOT_FOUND; + } + } + + Status = AuthServiceInternalUpdateVariable ( + EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, + &SecureBootMode, + sizeof(UINT8), + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature. + // + Status = AuthServiceInternalFindVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + &Data, + &DataSize + ); + + if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) { + // + // Create the "SecureBootEnable" variable as secure boot is enabled. + // + SecureBootEnable = SECURE_BOOT_ENABLE; + VariableDataSize = sizeof (SecureBootEnable); + } else { + // + // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot" + // variable is not in secure boot state. + // + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + SecureBootEnable = SECURE_BOOT_DISABLE; + VariableDataSize = 0; + } + + Status = AuthServiceInternalUpdateVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + &SecureBootEnable, + VariableDataSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + return Status; +} /** Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx/dbt variable. @@ -1700,121 +879,6 @@ VendorKeyIsModified ( ); } -/** - Process Secure Boot Mode variable. - - Caution: This function may receive untrusted input. - This function may be invoked in SMM mode, and datasize and data are external input. - This function will do basic validation, before parse the data. - This function will parse the authentication carefully to avoid security issues, like - buffer overflow, integer overflow. - This function will check attribute carefully to avoid authentication bypass. - - @param[in] VariableName Name of Variable to be found. - @param[in] VendorGuid Variable vendor GUID. - @param[in] Data Data pointer. - @param[in] DataSize Size of Data found. If size is less than the - data, this value contains the required size. - @param[in] Attributes Attribute value of the variable - - @return EFI_INVALID_PARAMETER Invalid parameter - @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation - check carried out by the firmware. - @return EFI_WRITE_PROTECTED Variable is Read-Only. - @return EFI_SUCCESS Variable passed validation successfully. - -**/ -EFI_STATUS -ProcessSecureBootModeVar ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN VOID *Data, - IN UINTN DataSize, - IN UINT32 Attributes OPTIONAL - ) -{ - EFI_STATUS Status; - VOID *VarData; - UINTN VarDataSize; - - // - // Check "AuditMode", "DeployedMode" Variable ReadWrite Attributes - // if in Runtime, Always RO - // if in Boottime, Depends on current Secure Boot Mode - // - if (mAuthVarLibContextIn->AtRuntime()) { - return EFI_WRITE_PROTECTED; - } - - // - // Delete not OK - // - if ((DataSize != sizeof(UINT8)) || (Attributes == 0)) { - return EFI_INVALID_PARAMETER; - } - - if (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0) { - if(mSecureBootState[mSecureBootMode].IsAuditModeRO) { - return EFI_WRITE_PROTECTED; - } - } else { - // - // Platform specific deployedMode clear. Set DeployedMode = RW - // - if (!InCustomMode() || !UserPhysicalPresent() || mSecureBootMode != SecureBootModeTypeDeployedMode) { - if(mSecureBootState[mSecureBootMode].IsDeployedModeRO) { - return EFI_WRITE_PROTECTED; - } - } - } - - if (*(UINT8 *)Data != 0 && *(UINT8 *)Data != 1) { - return EFI_INVALID_PARAMETER; - } - - // - // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver - // they can be RW. but can't be deleted. so they can always be found. - // - Status = AuthServiceInternalFindVariable ( - VariableName, - VendorGuid, - &VarData, - &VarDataSize - ); - if (EFI_ERROR(Status)) { - ASSERT(FALSE); - } - - // - // If AuditMode/DeployedMode is assigned same value. Simply return EFI_SUCCESS - // - if (*(UINT8 *)VarData == *(UINT8 *)Data) { - return EFI_SUCCESS; - } - - // - // Perform SecureBootMode transition - // - if (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0) { - DEBUG((EFI_D_INFO, "Current SecureBootMode %x Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeAuditMode)); - return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeAuditMode); - } else if (StrCmp (VariableName, EFI_DEPLOYED_MODE_NAME) == 0) { - if (mSecureBootMode == SecureBootModeTypeDeployedMode) { - // - // Platform specific DeployedMode clear. InCustomMode() && UserPhysicalPresent() is checked before - // - DEBUG((EFI_D_INFO, "Current SecureBootMode %x. Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeUserMode)); - return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeUserMode); - } else { - DEBUG((EFI_D_INFO, "Current SecureBootMode %x. Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeDeployedMode)); - return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeDeployedMode); - } - } - - return EFI_INVALID_PARAMETER; -} - /** Process variable with platform key for verification. @@ -1853,7 +917,6 @@ ProcessVarWithPk ( BOOLEAN Del; UINT8 *Payload; UINTN PayloadSize; - VARIABLE_ENTRY_CONSISTENCY VariableEntry[2]; if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 || (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) { @@ -1868,51 +931,18 @@ ProcessVarWithPk ( // Init state of Del. State may change due to secure check // Del = FALSE; - Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data); - PayloadSize = DataSize - AUTHINFO2_SIZE (Data); - if (PayloadSize == 0) { - Del = TRUE; - } - - // - // Check the variable space for both PKpub and SecureBootMode variable. - // - VariableEntry[0].VariableSize = PayloadSize; - VariableEntry[0].Guid = &gEfiGlobalVariableGuid; - VariableEntry[0].Name = EFI_PLATFORM_KEY_NAME; - - VariableEntry[1].VariableSize = sizeof(UINT8); - VariableEntry[1].Guid = &gEdkiiSecureBootModeGuid; - VariableEntry[1].Name = EDKII_SECURE_BOOT_MODE_NAME; - - if ((InCustomMode() && UserPhysicalPresent()) || - (((mSecureBootMode == SecureBootModeTypeSetupMode) || (mSecureBootMode == SecureBootModeTypeAuditMode)) && !IsPk)) { + if ((InCustomMode() && UserPhysicalPresent()) || (mPlatformMode == SETUP_MODE && !IsPk)) { + Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data); + PayloadSize = DataSize - AUTHINFO2_SIZE (Data); + if (PayloadSize == 0) { + Del = TRUE; + } Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize); if (EFI_ERROR (Status)) { return Status; } - // - // If delete PKpub, only check for "SecureBootMode" only - // if update / add PKpub, check both NewPKpub & "SecureBootMode" - // - if (IsPk) { - // - // Delete PKpub - // - if (Del && ((mSecureBootMode == SecureBootModeTypeUserMode) || (mSecureBootMode == SecureBootModeTypeDeployedMode)) - && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[1], NULL)){ - return EFI_OUT_OF_RESOURCES; - // - // Add PKpub - // - } else if (!Del && ((mSecureBootMode == SecureBootModeTypeSetupMode) || (mSecureBootMode == SecureBootModeTypeAuditMode)) - && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) { - return EFI_OUT_OF_RESOURCES; - } - } - Status = AuthServiceInternalUpdateVariableWithTimeStamp ( VariableName, VendorGuid, @@ -1925,17 +955,10 @@ ProcessVarWithPk ( return Status; } - if (((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) || IsPk) { + if ((mPlatformMode != SETUP_MODE) || IsPk) { Status = VendorKeyIsModified (); } - } else if (mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode) { - // - // If delete PKpub, check "SecureBootMode" only - // - if (IsPk && Del && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[1], NULL)){ - return EFI_OUT_OF_RESOURCES; - } - + } else if (mPlatformMode == USER_MODE) { // // Verify against X509 Cert in PK database. // @@ -1950,19 +973,8 @@ ProcessVarWithPk ( ); } else { // - // SetupMode or AuditMode to add PK // Verify against the certificate in data payload. // - // - // Check PKpub & SecureBootMode variable space consistency - // - if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) { - // - // No enough variable space to set PK successfully. - // - return EFI_OUT_OF_RESOURCES; - } - Status = VerifyTimeBasedPayloadAndUpdate ( VariableName, VendorGuid, @@ -1975,30 +987,16 @@ ProcessVarWithPk ( } if (!EFI_ERROR(Status) && IsPk) { - // - // Delete or Enroll PK causes SecureBootMode change - // - if (!Del) { - if (mSecureBootMode == SecureBootModeTypeSetupMode) { - // - // If enroll PK in setup mode, change to user mode. - // - Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeUserMode); - } else if (mSecureBootMode == SecureBootModeTypeAuditMode) { - // - // If enroll PK in Audit mode, change to Deployed mode. - // - Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeDeployedMode); - } else { - DEBUG((EFI_D_INFO, "PK is updated in %x mode. No SecureBootMode change.\n", mSecureBootMode)); - } - } else { - if ((mSecureBootMode == SecureBootModeTypeUserMode) || (mSecureBootMode == SecureBootModeTypeDeployedMode)) { - // - // If delete PK in User Mode or DeployedMode, change to Setup Mode. - // - Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeSetupMode); - } + if (mPlatformMode == SETUP_MODE && !Del) { + // + // If enroll PK in setup mode, need change to user mode. + // + Status = UpdatePlatformMode (USER_MODE); + } else if (mPlatformMode == USER_MODE && Del){ + // + // If delete PK in user mode, need change to setup mode. + // + Status = UpdatePlatformMode (SETUP_MODE); } } @@ -2051,8 +1049,7 @@ ProcessVarWithKek ( } Status = EFI_SUCCESS; - if ((mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode) - && !(InCustomMode() && UserPhysicalPresent())) { + if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) { // // Time-based, verify against X509 Cert KEK. // @@ -2089,7 +1086,7 @@ ProcessVarWithKek ( return Status; } - if ((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) { + if (mPlatformMode != SETUP_MODE) { Status = VendorKeyIsModified (); } } diff --git a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h index 83b0f23624..e7c4bf043d 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h +++ b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h @@ -120,54 +120,6 @@ typedef struct { } AUTH_CERT_DB_DATA; #pragma pack() -/// -/// "SecureBootMode" variable stores current secure boot mode. -/// The value type is SECURE_BOOT_MODE_TYPE. -/// -#define EDKII_SECURE_BOOT_MODE_NAME L"SecureBootMode" - -typedef enum { - SecureBootModeTypeUserMode, - SecureBootModeTypeSetupMode, - SecureBootModeTypeAuditMode, - SecureBootModeTypeDeployedMode, - SecureBootModeTypeMax -} SECURE_BOOT_MODE_TYPE; - -// -// Record status info of Customized Secure Boot Mode. -// -typedef struct { - /// - /// AuditMode variable value - /// - UINT8 AuditMode; - /// - /// AuditMode variable RW - /// - BOOLEAN IsAuditModeRO; - /// - /// DeployedMode variable value - /// - UINT8 DeployedMode; - /// - /// AuditMode variable RW - /// - BOOLEAN IsDeployedModeRO; - /// - /// SetupMode variable value - /// - UINT8 SetupMode; - /// - /// SetupMode is always RO. Skip IsSetupModeRO; - /// - - /// - /// SecureBoot variable value - /// - UINT8 SecureBoot; -} SECURE_BOOT_MODE; - extern UINT8 *mPubKeyStore; extern UINT32 mPubKeyNumber; extern UINT32 mMaxKeyNumber; @@ -181,17 +133,6 @@ extern VOID *mHashCtx; extern AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn; -/** - Initialize Secure Boot variables. - - @retval EFI_SUCCESS The initialization operation is successful. - @retval EFI_OUT_OF_RESOURCES There is not enough resource. - -**/ -EFI_STATUS -InitSecureBootVariables ( - VOID - ); /** Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set @@ -285,39 +226,6 @@ FilterSignatureList ( IN OUT UINTN *NewDataSize ); -/** - Process Secure Boot Mode variable. - - Caution: This function may receive untrusted input. - This function may be invoked in SMM mode, and datasize and data are external input. - This function will do basic validation, before parse the data. - This function will parse the authentication carefully to avoid security issues, like - buffer overflow, integer overflow. - This function will check attribute carefully to avoid authentication bypass. - - @param[in] VariableName Name of Variable to be found. - @param[in] VendorGuid Variable vendor GUID. - @param[in] Data Data pointer. - @param[in] DataSize Size of Data found. If size is less than the - data, this value contains the required size. - @param[in] Attributes Attribute value of the variable - - @return EFI_INVALID_PARAMETER Invalid parameter - @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation - check carried out by the firmware. - @return EFI_WRITE_PROTECTED Variable is Read-Only. - @return EFI_SUCCESS Variable passed validation successfully. - -**/ -EFI_STATUS -ProcessSecureBootModeVar ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN VOID *Data, - IN UINTN DataSize, - IN UINT32 Attributes OPTIONAL - ); - /** Process variable with platform key for verification. diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c index 6467c0695c..c4fbb649f1 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c @@ -33,6 +33,7 @@ UINT32 mMaxKeyNumber; UINT32 mMaxKeyDbSize; UINT8 *mCertDbStore; UINT32 mMaxCertDbSize; +UINT32 mPlatformMode; UINT8 mVendorKeyState; EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID}; @@ -109,17 +110,6 @@ VARIABLE_ENTRY_PROPERTY mAuthVarEntry[] = { MAX_UINTN } }, - { - &gEdkiiSecureBootModeGuid, - L"SecureBootMode", - { - VAR_CHECK_VARIABLE_PROPERTY_REVISION, - VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY, - VARIABLE_ATTRIBUTE_NV_BS_RT, - sizeof (UINT8), - sizeof (UINT8) - } - } }; VOID **mAuthVarAddressPointer[10]; @@ -153,6 +143,8 @@ AuthVariableLibInitialize ( UINT8 *Data; UINTN DataSize; UINTN CtxSize; + UINT8 SecureBootMode; + UINT8 SecureBootEnable; UINT8 CustomMode; UINT32 ListSize; @@ -228,11 +220,31 @@ AuthVariableLibInitialize ( mPubKeyNumber = (UINT32) (DataSize / sizeof (AUTHVAR_KEY_DB_DATA)); } + Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME)); + } else { + DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME)); + } + // - // Init Secure Boot variables + // Create "SetupMode" variable with BS+RT attribute set. // - Status = InitSecureBootVariables (); - + if (EFI_ERROR (Status)) { + mPlatformMode = SETUP_MODE; + } else { + mPlatformMode = USER_MODE; + } + Status = AuthServiceInternalUpdateVariable ( + EFI_SETUP_MODE_NAME, + &gEfiGlobalVariableGuid, + &mPlatformMode, + sizeof(UINT8), + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS + ); + if (EFI_ERROR (Status)) { + return Status; + } // // Create "SignatureSupport" variable with BS+RT attribute set. @@ -248,6 +260,57 @@ AuthVariableLibInitialize ( return Status; } + // + // If "SecureBootEnable" variable exists, then update "SecureBoot" variable. + // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE. + // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE. + // + SecureBootEnable = SECURE_BOOT_DISABLE; + Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **) &Data, &DataSize); + if (!EFI_ERROR (Status)) { + if (mPlatformMode == USER_MODE){ + SecureBootEnable = *(UINT8 *) Data; + } + } else if (mPlatformMode == USER_MODE) { + // + // "SecureBootEnable" not exist, initialize it in USER_MODE. + // + SecureBootEnable = SECURE_BOOT_ENABLE; + Status = AuthServiceInternalUpdateVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + &SecureBootEnable, + sizeof (UINT8), + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Create "SecureBoot" variable with BS+RT attribute set. + // + if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) { + SecureBootMode = SECURE_BOOT_MODE_ENABLE; + } else { + SecureBootMode = SECURE_BOOT_MODE_DISABLE; + } + Status = AuthServiceInternalUpdateVariable ( + EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, + &SecureBootMode, + sizeof (UINT8), + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, mPlatformMode)); + DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBootMode)); + DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable)); + // // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state. // @@ -408,16 +471,10 @@ AuthVariableLibProcessVariable ( { EFI_STATUS Status; - // - // Process PK, KEK, Sigdb, AuditMode, DeployedMode separately. - // if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){ Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, TRUE); } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) { Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, FALSE); - } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) - && (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0 || StrCmp (VariableName, EFI_DEPLOYED_MODE_NAME) == 0)) { - Status = ProcessSecureBootModeVar(VariableName, VendorGuid, Data, DataSize, Attributes); } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) || diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf index bf2c9f244d..572ba4e120 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf @@ -87,10 +87,6 @@ ## PRODUCES ## Variable:L"AuthVarKeyDatabase" gEfiAuthenticatedVariableGuid - ## CONSUMES ## Variable:L"SecureBootMode" - ## PRODUCES ## Variable:L"SecureBootMode" - gEdkiiSecureBootModeGuid - gEfiCertTypeRsa2048Sha256Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the certificate. gEfiCertPkcs7Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the certificate. gEfiCertX509Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature. diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 8cedb1bfb0..4b0e3f1fbd 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -711,58 +711,6 @@ GetImageExeInfoTableSize ( return TotalSize; } -/** - Create signature list based on input signature data and certificate type GUID. Caller is reposible - to free new created SignatureList. - - @param[in] SignatureData Signature data in SignatureList. - @param[in] SignatureDataSize Signature data size. - @param[in] CertType Certificate Type. - @param[out] SignatureList Created SignatureList. - @param[out] SignatureListSize Created SignatureListSize. - - @return EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. - @retval EFI_SUCCESS Successfully create signature list. - -**/ -EFI_STATUS -CreateSignatureList( - IN UINT8 *SignatureData, - IN UINTN SignatureDataSize, - IN EFI_GUID *CertType, - OUT EFI_SIGNATURE_LIST **SignatureList, - OUT UINTN *SignatureListSize - ) -{ - EFI_SIGNATURE_LIST *SignList; - UINTN SignListSize; - EFI_SIGNATURE_DATA *Signature; - - SignList = NULL; - *SignatureList = NULL; - - SignListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureDataSize; - SignList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignListSize); - if (SignList == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - SignList->SignatureHeaderSize = 0; - SignList->SignatureListSize = (UINT32) SignListSize; - SignList->SignatureSize = (UINT32) SignatureDataSize + sizeof (EFI_SIGNATURE_DATA) - 1; - CopyMem (&SignList->SignatureType, CertType, sizeof (EFI_GUID)); - - DEBUG((EFI_D_INFO, "SignatureDataSize %x\n", SignatureDataSize)); - Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignList + sizeof (EFI_SIGNATURE_LIST)); - CopyMem (Signature->SignatureData, SignatureData, SignatureDataSize); - - *SignatureList = SignList; - *SignatureListSize = SignListSize; - - return EFI_SUCCESS; - -} - /** Create an Image Execution Information Table entry and add it to system configuration table. @@ -1148,53 +1096,6 @@ IsTimeZero ( return FALSE; } -/** - Record multiple certificate list & verification state of a verified image to - IMAGE_EXECUTION_TABLE. - - @param[in] CertBuf Certificate list buffer. - @param[in] CertBufLength Certificate list buffer. - @param[in] Action Certificate list action to be record. - @param[in] ImageName Image name. - @param[in] ImageDevicePath Image device path. - -**/ -VOID -RecordCertListToImageExeuctionTable( - IN UINT8 *CertBuf, - IN UINTN CertBufLength, - IN EFI_IMAGE_EXECUTION_ACTION Action, - IN CHAR16 *ImageName OPTIONAL, - IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL - ) -{ - UINT8 CertNumber; - UINT8 *CertPtr; - UINTN Index; - UINT8 *Cert; - UINTN CertSize; - EFI_STATUS Status; - EFI_SIGNATURE_LIST *SignatureList; - UINTN SignatureListSize; - - CertNumber = (UINT8) (*CertBuf); - CertPtr = CertBuf + 1; - for (Index = 0; Index < CertNumber; Index++) { - CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr); - Cert = (UINT8 *)CertPtr + sizeof (UINT32); - - // - // Record all cert in cert chain to be passed - // - Status = CreateSignatureList(Cert, CertSize, &gEfiCertX509Guid, &SignatureList, &SignatureListSize); - if (!EFI_ERROR(Status)) { - AddImageExeInfo (Action, ImageName, ImageDevicePath, SignatureList, SignatureListSize); - FreePool (SignatureList); - } - } -} - - /** Check whether the timestamp signature is valid and the signing time is also earlier than the revocation time. @@ -1305,23 +1206,17 @@ Done: Check whether the image signature is forbidden by the forbidden database (dbx). The image is forbidden to load if any certificates for signing are revoked before signing time. - @param[in] AuthData Pointer to the Authenticode signature retrieved from the signed image. - @param[in] AuthDataSize Size of the Authenticode signature in bytes. - @param[in] IsAuditMode Whether system Secure Boot Mode is in AuditMode. - @param[in] ImageName Name of the image to verify. - @param[in] ImageDevicePath DevicePath of the image to verify. + @param[in] AuthData Pointer to the Authenticode signature retrieved from the signed image. + @param[in] AuthDataSize Size of the Authenticode signature in bytes. @retval TRUE Image is forbidden by dbx. @retval FALSE Image is not forbidden by dbx. **/ BOOLEAN -IsForbiddenByDbx ( - IN UINT8 *AuthData, - IN UINTN AuthDataSize, - IN BOOLEAN IsAuditMode, - IN CHAR16 *ImageName OPTIONAL, - IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL +IsForbiddenByDbx ( + IN UINT8 *AuthData, + IN UINTN AuthDataSize ) { EFI_STATUS Status; @@ -1344,10 +1239,6 @@ IsForbiddenByDbx ( UINT8 *Cert; UINTN CertSize; EFI_TIME RevocationTime; - UINT8 *SignerCert; - UINTN SignerCertLength; - UINT8 *UnchainCert; - UINTN UnchainCertLength; // // Variable Initialization // @@ -1362,10 +1253,6 @@ IsForbiddenByDbx ( BufferLength = 0; TrustedCert = NULL; TrustedCertLength = 0; - SignerCert = NULL; - SignerCertLength = 0; - UnchainCert = NULL; - UnchainCertLength = 0; // // The image will not be forbidden if dbx can't be got. @@ -1480,41 +1367,12 @@ IsForbiddenByDbx ( } Done: - if (IsForbidden && IsAuditMode) { - Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength); - - // - // Record all certs in image to be failed - // - if ((SignerCertLength != 0) && (SignerCert != NULL)) { - RecordCertListToImageExeuctionTable( - SignerCert, - SignerCertLength, - EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, - ImageName, - ImageDevicePath - ); - } - - if ((UnchainCertLength != 0) && (UnchainCert != NULL)) { - RecordCertListToImageExeuctionTable( - UnchainCert, - UnchainCertLength, - EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, - ImageName, - ImageDevicePath - ); - } - } - if (Data != NULL) { FreePool (Data); } Pkcs7FreeSigners (CertBuffer); Pkcs7FreeSigners (TrustedCert); - Pkcs7FreeSigners (SignerCert); - Pkcs7FreeSigners (UnchainCert); return IsForbidden; } @@ -1523,11 +1381,8 @@ Done: /** Check whether the image signature can be verified by the trusted certificates in DB database. - @param[in] AuthData Pointer to the Authenticode signature retrieved from signed image. - @param[in] AuthDataSize Size of the Authenticode signature in bytes. - @param[in] IsAuditMode Whether system Secure Boot Mode is in AuditMode. - @param[in] ImageName Name of the image to verify. - @param[in] ImageDevicePath DevicePath of the image to verify. + @param[in] AuthData Pointer to the Authenticode signature retrieved from signed image. + @param[in] AuthDataSize Size of the Authenticode signature in bytes. @retval TRUE Image passed verification using certificate in db. @retval FALSE Image didn't pass verification using certificate in db. @@ -1535,11 +1390,8 @@ Done: **/ BOOLEAN IsAllowedByDb ( - IN UINT8 *AuthData, - IN UINTN AuthDataSize, - IN BOOLEAN IsAuditMode, - IN CHAR16 *ImageName OPTIONAL, - IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL + IN UINT8 *AuthData, + IN UINTN AuthDataSize ) { EFI_STATUS Status; @@ -1555,10 +1407,6 @@ IsAllowedByDb ( UINTN DbxDataSize; UINT8 *DbxData; EFI_TIME RevocationTime; - UINT8 *SignerCert; - UINTN SignerCertLength; - UINT8 *UnchainCert; - UINTN UnchainCertLength; Data = NULL; CertList = NULL; @@ -1567,10 +1415,6 @@ IsAllowedByDb ( DbxData = NULL; RootCertSize = 0; VerifyStatus = FALSE; - SignerCert = NULL; - SignerCertLength = 0; - UnchainCert = NULL; - UnchainCertLength = 0; DataSize = 0; Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); @@ -1655,62 +1499,6 @@ Done: SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData); } - if (IsAuditMode) { - - Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength); - if (VerifyStatus) { - if ((SignerCertLength != 0) && (SignerCert != NULL)) { - // - // Record all cert in signer's cert chain to be passed - // - RecordCertListToImageExeuctionTable( - SignerCert, - SignerCertLength, - EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED, - ImageName, - ImageDevicePath - ); - } - - if ((UnchainCertLength != 0) && (UnchainCert != NULL)) { - // - // Record all certs in unchained certificates lists to be failed - // - RecordCertListToImageExeuctionTable( - UnchainCert, - UnchainCertLength, - EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, - ImageName, - ImageDevicePath - ); - } - } else { - // - // Record all certs in image to be failed - // - if ((SignerCertLength != 0) && (SignerCert != NULL)) { - RecordCertListToImageExeuctionTable( - SignerCert, - SignerCertLength, - EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, - ImageName, - ImageDevicePath - ); - } - - if ((UnchainCertLength != 0) && (UnchainCert != NULL)) { - RecordCertListToImageExeuctionTable( - UnchainCert, - UnchainCertLength, - EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, - ImageName, - ImageDevicePath - ); - } - } - } - - if (Data != NULL) { FreePool (Data); } @@ -1718,369 +1506,9 @@ Done: FreePool (DbxData); } - Pkcs7FreeSigners (SignerCert); - Pkcs7FreeSigners (UnchainCert); - return VerifyStatus; } -/** - Provide verification service for signed images in AuditMode, which include both signature validation - and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and - MSFT Authenticode type signatures are supported. - - In this implementation, only verify external executables when in AuditMode. - Executables from FV is bypass, so pass in AuthenticationStatus is ignored. Other authentication status - are record into IMAGE_EXECUTION_TABLE. - - The image verification policy is: - If the image is signed, - At least one valid signature or at least one hash value of the image must match a record - in the security database "db", and no valid signature nor any hash value of the image may - be reflected in the security database "dbx". - Otherwise, the image is not signed, - The SHA256 hash value of the image must match a record in the security database "db", and - not be reflected in the security data base "dbx". - - Caution: This function may receive untrusted input. - PE/COFF image is external input, so this function will validate its data structure - within this image buffer before use. - - @param[in] AuthenticationStatus - This is the authentication status returned from the security - measurement services for the input file. - @param[in] File This is a pointer to the device path of the file that is - being dispatched. This will optionally be used for logging. - @param[in] FileBuffer File buffer matches the input file device path. - @param[in] FileSize Size of File buffer matches the input file device path. - @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service. - - @retval EFI_SUCCESS The authenticate info is sucessfully stored for the file - specified by DevicePath and non-NULL FileBuffer - @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not - authenticate, and the platform policy dictates that the DXE - Foundation many not use File. - -**/ -EFI_STATUS -EFIAPI -ImageVerificationInAuditMode ( - IN UINT32 AuthenticationStatus, - IN CONST EFI_DEVICE_PATH_PROTOCOL *File, - IN VOID *FileBuffer, - IN UINTN FileSize, - IN BOOLEAN BootPolicy - ) -{ - EFI_STATUS Status; - UINT16 Magic; - EFI_IMAGE_DOS_HEADER *DosHdr; - EFI_SIGNATURE_LIST *SignatureList; - EFI_IMAGE_EXECUTION_ACTION Action; - WIN_CERTIFICATE *WinCertificate; - UINT32 Policy; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - UINT32 NumberOfRvaAndSizes; - WIN_CERTIFICATE_EFI_PKCS *PkcsCertData; - WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid; - UINT8 *AuthData; - UINTN AuthDataSize; - EFI_IMAGE_DATA_DIRECTORY *SecDataDir; - UINT32 OffSet; - CHAR16 *FilePathStr; - UINTN SignatureListSize; - - SignatureList = NULL; - WinCertificate = NULL; - SecDataDir = NULL; - PkcsCertData = NULL; - FilePathStr = NULL; - Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED; - Status = EFI_ACCESS_DENIED; - - - // - // Check the image type and get policy setting. - // - switch (GetImageType (File)) { - - case IMAGE_FROM_FV: - Policy = ALWAYS_EXECUTE; - break; - - case IMAGE_FROM_OPTION_ROM: - Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy); - break; - - case IMAGE_FROM_REMOVABLE_MEDIA: - Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy); - break; - - case IMAGE_FROM_FIXED_MEDIA: - Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy); - break; - - default: - Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION; - break; - } - - // - // If policy is always/never execute, return directly. - // - if (Policy == ALWAYS_EXECUTE) { - return EFI_SUCCESS; - } - - // - // Get Image Device Path Str - // - FilePathStr = ConvertDevicePathToText (File, FALSE, TRUE); - - // - // Authentication failed because of (unspecified) firmware security policy - // - if (Policy == NEVER_EXECUTE) { - // - // No signature, record FilePath/FilePathStr only - // - AddImageExeInfo (EFI_IMAGE_EXECUTION_POLICY_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, FilePathStr, File, NULL, 0); - goto END; - } - - // - // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION - // violates the UEFI spec and has been removed. - // - ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION); - if (Policy == QUERY_USER_ON_SECURITY_VIOLATION || Policy == ALLOW_EXECUTE_ON_SECURITY_VIOLATION) { - CpuDeadLoop (); - } - - // - // Read the Dos header. - // - if (FileBuffer == NULL) { - Status = EFI_INVALID_PARAMETER; - goto END; - } - - mImageBase = (UINT8 *) FileBuffer; - mImageSize = FileSize; - - ZeroMem (&ImageContext, sizeof (ImageContext)); - ImageContext.Handle = (VOID *) FileBuffer; - ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead; - - // - // Get information about the image being loaded - // - Status = PeCoffLoaderGetImageInfo (&ImageContext); - if (EFI_ERROR (Status)) { - // - // The information can't be got from the invalid PeImage - // - goto END; - } - - - DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase; - if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { - // - // DOS image header is present, - // so read the PE header after the DOS image header. - // - mPeCoffHeaderOffset = DosHdr->e_lfanew; - } else { - mPeCoffHeaderOffset = 0; - } - - // - // Check PE/COFF image. - // - mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset); - if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { - // - // It is not a valid Pe/Coff file. - // - Status = EFI_ACCESS_DENIED; - goto END; - } - - if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value - // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the - // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - // - Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; - } else { - // - // Get the magic value from the PE/COFF Optional Header - // - Magic = mNtHeader.Pe32->OptionalHeader.Magic; - } - - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset. - // - NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes; - if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { - SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; - } - } else { - // - // Use PE32+ offset. - // - NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; - if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { - SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; - } - } - - // - // Start Image Validation. - // - if (SecDataDir == NULL || SecDataDir->Size == 0) { - // - // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db", - // and not be reflected in the security data base "dbx". - // - if (!HashPeImage (HASHALG_SHA256)) { - Status = EFI_ACCESS_DENIED; - goto END; - } - - // - // Image Hash is in forbidden database (DBX). - // - if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) { - // - // Image Hash is in allowed database (DB). - // - if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) { - Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED; - } - } - - // - // Add HASH digest for image without signature - // - Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize); - if (!EFI_ERROR(Status)) { - AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize); - FreePool (SignatureList); - } - goto END; - } - - // - // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7 - // "Attribute Certificate Table". - // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file. - // - for (OffSet = SecDataDir->VirtualAddress; - OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size); - OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) { - WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet); - if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) || - (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) { - break; - } - - // - // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported. - // - if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { - // - // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the - // Authenticode specification. - // - PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate; - if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) { - break; - } - AuthData = PkcsCertData->CertData; - AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr); - } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) { - // - // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec. - // - WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate; - if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) { - break; - } - if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) { - continue; - } - AuthData = WinCertUefiGuid->CertData; - AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); - } else { - if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) { - break; - } - continue; - } - - Status = HashPeImageByType (AuthData, AuthDataSize); - if (EFI_ERROR (Status)) { - continue; - } - - Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED; - - // - // Check the digital signature against the revoked certificate in forbidden database (dbx). - // Check the digital signature against the valid certificate in allowed database (db). - // - if (!IsForbiddenByDbx (AuthData, AuthDataSize, TRUE, FilePathStr, File)) { - IsAllowedByDb (AuthData, AuthDataSize, TRUE, FilePathStr, File); - } - - // - // Check the image's hash value. - // - if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) { - if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) { - Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED; - } - } - - // - // Add HASH digest for image with signature - // - Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize); - - if (!EFI_ERROR(Status)) { - AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize); - FreePool (SignatureList); - } else { - goto END; - } - } - - - if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) { - // - // The Size in Certificate Table or the attribute certicate table is corrupted. - // - Status = EFI_ACCESS_DENIED; - } else { - Status = EFI_SUCCESS; - } - -END: - - if (FilePathStr != NULL) { - FreePool(FilePathStr); - FilePathStr = NULL; - } - - return Status; -} - /** Provide verification service for signed images, which include both signature validation and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and @@ -2148,9 +1576,7 @@ DxeImageVerificationHandler ( EFI_IMAGE_EXECUTION_ACTION Action; WIN_CERTIFICATE *WinCertificate; UINT32 Policy; - UINT8 *VarData; - UINT8 SecureBoot; - UINT8 AuditMode; + UINT8 *SecureBoot; PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; UINT32 NumberOfRvaAndSizes; WIN_CERTIFICATE_EFI_PKCS *PkcsCertData; @@ -2170,19 +1596,6 @@ DxeImageVerificationHandler ( Status = EFI_ACCESS_DENIED; VerifyStatus = EFI_ACCESS_DENIED; - GetEfiGlobalVariable2 (EFI_AUDIT_MODE_NAME, (VOID**)&VarData, NULL); - // - // Skip verification if AuditMode variable doesn't exist. AuditMode should always exist - // - if (VarData == NULL) { - return EFI_SUCCESS; - } - AuditMode = *VarData; - FreePool(VarData); - - if (AuditMode == AUDIT_MODE_ENABLE) { - return ImageVerificationInAuditMode(AuthenticationStatus, File, FileBuffer, FileSize, BootPolicy); - } // // Check the image type and get policy setting. @@ -2227,22 +1640,22 @@ DxeImageVerificationHandler ( CpuDeadLoop (); } - GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&VarData, NULL); + GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL); // // Skip verification if SecureBoot variable doesn't exist. // - if (VarData == NULL) { + if (SecureBoot == NULL) { return EFI_SUCCESS; } - SecureBoot = *VarData; - FreePool(VarData); // // Skip verification if SecureBoot is disabled but not AuditMode // - if (SecureBoot == SECURE_BOOT_MODE_DISABLE) { + if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) { + FreePool (SecureBoot); return EFI_SUCCESS; } + FreePool (SecureBoot); // // Read the Dos header. @@ -2413,7 +1826,7 @@ DxeImageVerificationHandler ( // // Check the digital signature against the revoked certificate in forbidden database (dbx). // - if (IsForbiddenByDbx (AuthData, AuthDataSize, FALSE, NULL, NULL)) { + if (IsForbiddenByDbx (AuthData, AuthDataSize)) { Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED; VerifyStatus = EFI_ACCESS_DENIED; break; @@ -2423,7 +1836,7 @@ DxeImageVerificationHandler ( // Check the digital signature against the valid certificate in allowed database (db). // if (EFI_ERROR (VerifyStatus)) { - if (IsAllowedByDb (AuthData, AuthDataSize, FALSE, NULL, NULL)) { + if (IsAllowedByDb (AuthData, AuthDataSize)) { VerifyStatus = EFI_SUCCESS; } }