| // Copyright (c) 2019 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cryptohome/tpm_new_impl.h" |
| |
| #include <brillo/secure_blob.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <libhwsec/test_utils/tpm1/test_fixture.h> |
| #include <tpm_manager/client/mock_tpm_manager_utility.h> |
| #include <tpm_manager/proto_bindings/tpm_manager.pb.h> |
| #include <tpm_manager-client/tpm_manager/dbus-constants.h> |
| |
| namespace { |
| |
| using ::testing::_; |
| using ::testing::ByRef; |
| using ::testing::DoAll; |
| using ::testing::ElementsAreArray; |
| using ::testing::NiceMock; |
| using ::testing::Return; |
| using ::testing::SetArgPointee; |
| |
| using brillo::Blob; |
| using brillo::BlobToString; |
| using brillo::SecureBlob; |
| using tpm_manager::LocalData; |
| using tpm_manager::MockTpmManagerUtility; |
| |
| } // namespace |
| |
| namespace cryptohome { |
| |
| class TpmNewImplTest : public ::hwsec::Tpm1HwsecTest { |
| public: |
| TpmNewImplTest() = default; |
| ~TpmNewImplTest() override = default; |
| |
| protected: |
| NiceMock<MockTpmManagerUtility> mock_tpm_manager_utility_; |
| TpmNewImpl tpm_{&mock_tpm_manager_utility_}; |
| Tpm* GetTpm() { return &tpm_; } |
| }; |
| |
| TEST_F(TpmNewImplTest, TakeOwnership) { |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillRepeatedly(Return(false)); |
| EXPECT_CALL(mock_tpm_manager_utility_, TakeOwnership()) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->TakeOwnership(0, SecureBlob{})); |
| EXPECT_CALL(mock_tpm_manager_utility_, TakeOwnership()) |
| .WillOnce(Return(true)); |
| EXPECT_TRUE(GetTpm()->TakeOwnership(0, SecureBlob{})); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(true), Return(true))); |
| EXPECT_CALL(mock_tpm_manager_utility_, TakeOwnership()).Times(0); |
| EXPECT_TRUE(GetTpm()->TakeOwnership(0, SecureBlob{})); |
| } |
| |
| TEST_F(TpmNewImplTest, Enabled) { |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .Times(0); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->IsEnabled()); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<0>(false), Return(true))); |
| EXPECT_FALSE(GetTpm()->IsEnabled()); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<0>(true), Return(true))); |
| EXPECT_TRUE(GetTpm()->IsEnabled()); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(0); |
| EXPECT_TRUE(GetTpm()->IsEnabled()); |
| } |
| |
| TEST_F(TpmNewImplTest, OwnedWithoutSignal) { |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillRepeatedly(Return(false)); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->IsOwned()); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(false), Return(true))); |
| EXPECT_FALSE(GetTpm()->IsOwned()); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(true), Return(true))); |
| EXPECT_TRUE(GetTpm()->IsOwned()); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(0); |
| EXPECT_TRUE(GetTpm()->IsOwned()); |
| } |
| |
| TEST_F(TpmNewImplTest, GetOwnerPasswordWithoutSignal) { |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillRepeatedly(Return(false)); |
| SecureBlob result_owner_password; |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| LocalData expected_local_data; |
| expected_local_data.set_owner_password("owner password"); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<0>(true), SetArgPointee<1>(true), |
| SetArgPointee<2>(expected_local_data), Return(true))); |
| EXPECT_TRUE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_EQ(result_owner_password.to_string(), |
| expected_local_data.owner_password()); |
| |
| result_owner_password.clear(); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(0); |
| EXPECT_TRUE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_EQ(result_owner_password.to_string(), |
| expected_local_data.owner_password()); |
| } |
| |
| TEST_F(TpmNewImplTest, GetOwnerPasswordEmpty) { |
| SecureBlob result_owner_password; |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<0>(true), SetArgPointee<1>(true), |
| SetArgPointee<2>(LocalData{}), Return(true))); |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| } |
| |
| TEST_F(TpmNewImplTest, GetDelegateWithoutSignal) { |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillRepeatedly(Return(false)); |
| Blob result_blob; |
| Blob result_secret; |
| bool result_has_reset_lock_permissions = false; |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| LocalData expected_local_data; |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillRepeatedly(DoAll(SetArgPointee<0>(true), SetArgPointee<1>(true), |
| SetArgPointee<2>(ByRef(expected_local_data)), |
| Return(true))); |
| EXPECT_FALSE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| |
| expected_local_data.mutable_owner_delegate()->set_blob("blob"); |
| expected_local_data.mutable_owner_delegate()->set_secret("secret"); |
| expected_local_data.mutable_owner_delegate()->set_has_reset_lock_permissions( |
| true); |
| EXPECT_TRUE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| EXPECT_THAT(result_blob, |
| ElementsAreArray(expected_local_data.owner_delegate().blob())); |
| EXPECT_THAT(result_secret, |
| ElementsAreArray(expected_local_data.owner_delegate().secret())); |
| EXPECT_TRUE(result_has_reset_lock_permissions); |
| } |
| |
| TEST_F(TpmNewImplTest, GetDictionaryAttackInfo) { |
| int result_counter = 0; |
| int result_threshold = 0; |
| bool result_lockout = false; |
| int result_seconds_remaining = 0; |
| EXPECT_CALL(mock_tpm_manager_utility_, GetDictionaryAttackInfo(_, _, _, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->GetDictionaryAttackInfo( |
| &result_counter, &result_threshold, &result_lockout, |
| &result_seconds_remaining)); |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetDictionaryAttackInfo(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<0>(123), SetArgPointee<1>(456), |
| SetArgPointee<2>(true), SetArgPointee<3>(789), |
| Return(true))); |
| EXPECT_TRUE(GetTpm()->GetDictionaryAttackInfo( |
| &result_counter, &result_threshold, &result_lockout, |
| &result_seconds_remaining)); |
| EXPECT_EQ(result_counter, 123); |
| EXPECT_EQ(result_threshold, 456); |
| EXPECT_TRUE(result_lockout); |
| EXPECT_EQ(result_seconds_remaining, 789); |
| } |
| |
| TEST_F(TpmNewImplTest, ResetDictionaryAttackMitigation) { |
| EXPECT_CALL(mock_tpm_manager_utility_, ResetDictionaryAttackLock()) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->ResetDictionaryAttackMitigation(Blob{}, Blob{})); |
| EXPECT_CALL(mock_tpm_manager_utility_, ResetDictionaryAttackLock()) |
| .WillOnce(Return(true)); |
| EXPECT_TRUE(GetTpm()->ResetDictionaryAttackMitigation(Blob{}, Blob{})); |
| } |
| |
| TEST_F(TpmNewImplTest, SignalCache) { |
| brillo::SecureBlob result_owner_password; |
| brillo::Blob result_blob, result_secret; |
| bool result_has_reset_lock_permissions; |
| ON_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)) |
| .WillByDefault(Return(false)); |
| |
| ON_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillByDefault(Return(false)); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(2); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .Times(2); |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_FALSE(GetTpm()->IsOwned()); |
| |
| // |GetDelegate| doesn't fully rely on the signal. Thus, expects to call |
| // |GetTpmStatus| but not |GetOwnershipTakenSignalStatus| when the auth |
| // delegate is not found. |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(1); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .Times(0); |
| EXPECT_FALSE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| |
| ON_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillByDefault(DoAll(SetArgPointee<0>(false), Return(true))); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(3); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .Times(2); |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_FALSE(GetTpm()->IsOwned()); |
| EXPECT_FALSE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| |
| ON_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillByDefault( |
| DoAll(SetArgPointee<0>(true), SetArgPointee<1>(false), Return(true))); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(1); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .Times(2); |
| EXPECT_FALSE(GetTpm()->IsOwned()); |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(1); |
| EXPECT_FALSE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| |
| tpm_manager::LocalData expected_local_data; |
| expected_local_data.set_owner_password("owner password"); |
| expected_local_data.mutable_owner_delegate()->set_blob("blob"); |
| expected_local_data.mutable_owner_delegate()->set_secret("secret"); |
| expected_local_data.mutable_owner_delegate()->set_has_reset_lock_permissions( |
| true); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetOwnershipTakenSignalStatus(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<0>(true), SetArgPointee<1>(true), |
| SetArgPointee<2>(expected_local_data), Return(true))); |
| EXPECT_CALL(mock_tpm_manager_utility_, GetTpmStatus(_, _, _)).Times(0); |
| EXPECT_TRUE(GetTpm()->IsOwned()); |
| EXPECT_TRUE(GetTpm()->IsEnabled()); |
| EXPECT_TRUE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_TRUE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| EXPECT_THAT(result_owner_password, |
| ElementsAreArray(expected_local_data.owner_password())); |
| EXPECT_THAT(result_blob, |
| ElementsAreArray(expected_local_data.owner_delegate().blob())); |
| EXPECT_THAT(result_secret, |
| ElementsAreArray(expected_local_data.owner_delegate().secret())); |
| EXPECT_EQ(result_has_reset_lock_permissions, |
| expected_local_data.owner_delegate().has_reset_lock_permissions()); |
| } |
| |
| TEST_F(TpmNewImplTest, RemoveTpmOwnerDependency) { |
| EXPECT_CALL(mock_tpm_manager_utility_, |
| RemoveOwnerDependency(tpm_manager::kTpmOwnerDependency_Nvram)) |
| .WillOnce(Return(true)); |
| EXPECT_TRUE(GetTpm()->RemoveOwnerDependency( |
| TpmPersistentState::TpmOwnerDependency::kInstallAttributes)); |
| EXPECT_CALL( |
| mock_tpm_manager_utility_, |
| RemoveOwnerDependency(tpm_manager::kTpmOwnerDependency_Attestation)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->RemoveOwnerDependency( |
| TpmPersistentState::TpmOwnerDependency::kAttestation)); |
| } |
| |
| TEST_F(TpmNewImplTest, RemoveTpmOwnerDependencyInvalidEnum) { |
| EXPECT_DEBUG_DEATH(GetTpm()->RemoveOwnerDependency( |
| static_cast<TpmPersistentState::TpmOwnerDependency>(999)), |
| ".*Unexpected enum class value: 999"); |
| } |
| |
| TEST_F(TpmNewImplTest, ClearStoredPassword) { |
| EXPECT_CALL(mock_tpm_manager_utility_, |
| ClearStoredOwnerPassword()) |
| .WillOnce(Return(true)); |
| EXPECT_TRUE(GetTpm()->ClearStoredPassword()); |
| EXPECT_CALL( |
| mock_tpm_manager_utility_, |
| ClearStoredOwnerPassword()) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(GetTpm()->ClearStoredPassword()); |
| } |
| |
| TEST_F(TpmNewImplTest, GetVersionInfoCache) { |
| Tpm::TpmVersionInfo expected_version_info; |
| expected_version_info.family = 1; |
| expected_version_info.spec_level = 2; |
| expected_version_info.manufacturer = 3; |
| expected_version_info.tpm_model = 4; |
| expected_version_info.firmware_version = 5; |
| expected_version_info.vendor_specific = "aa"; |
| |
| EXPECT_CALL(mock_tpm_manager_utility_, GetVersionInfo(_, _, _, _, _, _)) |
| .WillOnce(Return(false)) |
| .WillOnce(DoAll( |
| SetArgPointee<0>(expected_version_info.family), |
| SetArgPointee<1>(expected_version_info.spec_level), |
| SetArgPointee<2>(expected_version_info.manufacturer), |
| SetArgPointee<3>(expected_version_info.tpm_model), |
| SetArgPointee<4>(expected_version_info.firmware_version), |
| SetArgPointee<5>(expected_version_info.vendor_specific), |
| Return(true))); |
| |
| Tpm::TpmVersionInfo actual_version_info; |
| // Requests from tpm_manager, failed, not cached |
| EXPECT_FALSE(GetTpm()->GetVersionInfo(&actual_version_info)); |
| |
| // Requests from tpm_manager, succeeded, cached |
| EXPECT_TRUE(GetTpm()->GetVersionInfo(&actual_version_info)); |
| EXPECT_EQ(expected_version_info.GetFingerprint(), |
| actual_version_info.GetFingerprint()); |
| |
| // Returns from cache |
| EXPECT_TRUE(GetTpm()->GetVersionInfo(&actual_version_info)); |
| EXPECT_EQ(expected_version_info.GetFingerprint(), |
| actual_version_info.GetFingerprint()); |
| } |
| |
| TEST_F(TpmNewImplTest, GetVersionInfoBadInput) { |
| EXPECT_CALL(mock_tpm_manager_utility_, GetVersionInfo(_, _, _, _, _, _)) |
| .Times(0); |
| EXPECT_FALSE(GetTpm()->GetVersionInfo(nullptr)); |
| } |
| |
| TEST_F(TpmNewImplTest, BadTpmManagerUtility) { |
| EXPECT_CALL(mock_tpm_manager_utility_, Initialize()) |
| .WillRepeatedly(Return(false)); |
| EXPECT_FALSE(GetTpm()->TakeOwnership(0, SecureBlob{})); |
| SecureBlob result_owner_password; |
| EXPECT_FALSE(GetTpm()->GetOwnerPassword(&result_owner_password)); |
| EXPECT_FALSE(GetTpm()->IsEnabled()); |
| EXPECT_FALSE(GetTpm()->IsOwned()); |
| EXPECT_FALSE(GetTpm()->ResetDictionaryAttackMitigation(Blob{}, Blob{})); |
| int result_counter; |
| int result_threshold; |
| bool result_lockout; |
| int result_seconds_remaining; |
| EXPECT_FALSE(GetTpm()->GetDictionaryAttackInfo( |
| &result_counter, &result_threshold, &result_lockout, |
| &result_seconds_remaining)); |
| Blob result_blob; |
| Blob result_secret; |
| bool result_has_reset_lock_permissions; |
| EXPECT_FALSE(GetTpm()->GetDelegate(&result_blob, &result_secret, |
| &result_has_reset_lock_permissions)); |
| } |
| |
| } // namespace cryptohome |