| // Copyright 2015 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. |
| |
| // Unit tests for Tpm2Impl. |
| |
| #include "cryptohome/tpm2_impl.h" |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <tpm_manager/common/mock_tpm_nvram_interface.h> |
| #include <tpm_manager/common/mock_tpm_ownership_interface.h> |
| #include <tpm_manager/common/tpm_manager_constants.h> |
| #include <trunks/mock_authorization_delegate.h> |
| #include <trunks/mock_blob_parser.h> |
| #include <trunks/mock_hmac_session.h> |
| #include <trunks/mock_policy_session.h> |
| #include <trunks/mock_tpm.h> |
| #include <trunks/mock_tpm_state.h> |
| #include <trunks/mock_tpm_utility.h> |
| #include <trunks/tpm_constants.h> |
| #include <trunks/tpm_generated.h> |
| #include <trunks/trunks_factory.h> |
| #include <trunks/trunks_factory_for_test.h> |
| |
| #include "cryptohome/cryptolib.h" |
| |
| using brillo::SecureBlob; |
| using testing::_; |
| using testing::DoAll; |
| using testing::Invoke; |
| using testing::NiceMock; |
| using testing::Return; |
| using testing::SaveArg; |
| using testing::SetArgPointee; |
| using testing::WithArg; |
| using tpm_manager::NVRAM_RESULT_IPC_ERROR; |
| using trunks::TPM_RC; |
| using trunks::TPM_RC_FAILURE; |
| using trunks::TPM_RC_SUCCESS; |
| using trunks::TrunksFactory; |
| |
| namespace { |
| |
| const char kDefaultPassword[] = "password"; |
| const int kDefaultCounter = 3; |
| |
| } // namespace |
| |
| namespace cryptohome { |
| |
| class Tpm2Test : public testing::Test { |
| public: |
| Tpm2Test() {} |
| ~Tpm2Test() override {} |
| |
| void SetUp() override { |
| factory_.set_blob_parser(&mock_blob_parser_); |
| factory_.set_tpm(&mock_tpm_); |
| factory_.set_tpm_state(&mock_tpm_state_); |
| factory_.set_tpm_utility(&mock_tpm_utility_); |
| factory_.set_hmac_session(&mock_hmac_session_); |
| factory_.set_policy_session(&mock_policy_session_); |
| factory_.set_trial_session(&mock_trial_session_); |
| tpm_ = new Tpm2Impl(&factory_, &mock_tpm_owner_, &mock_tpm_nvram_); |
| // Setup default status data. |
| tpm_status_.set_status(tpm_manager::STATUS_SUCCESS); |
| tpm_status_.set_enabled(true); |
| tpm_status_.set_owned(true); |
| tpm_status_.mutable_local_data()->set_owner_password(kDefaultPassword); |
| tpm_status_.set_dictionary_attack_counter(kDefaultCounter); |
| ON_CALL(mock_tpm_owner_, GetTpmStatus(_, _)) |
| .WillByDefault(WithArg<1>(Invoke(this, &Tpm2Test::FakeGetTpmStatus))); |
| ON_CALL(mock_tpm_owner_, RemoveOwnerDependency(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeRemoveOwnerDependency)); |
| ON_CALL(mock_tpm_owner_, ClearStoredOwnerPassword(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeClearStoredOwnerPassword)); |
| SetupFakeNvram(); |
| } |
| |
| void SetupFakeNvram() { |
| ON_CALL(mock_tpm_nvram_, DefineSpace(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeDefineSpace)); |
| ON_CALL(mock_tpm_nvram_, DestroySpace(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeDestroySpace)); |
| ON_CALL(mock_tpm_nvram_, WriteSpace(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeWriteSpace)); |
| ON_CALL(mock_tpm_nvram_, ReadSpace(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeReadSpace)); |
| ON_CALL(mock_tpm_nvram_, LockSpace(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeLockSpace)); |
| ON_CALL(mock_tpm_nvram_, ListSpaces(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeListSpaces)); |
| ON_CALL(mock_tpm_nvram_, GetSpaceInfo(_, _)) |
| .WillByDefault(Invoke(this, &Tpm2Test::FakeGetSpaceInfo)); |
| } |
| |
| protected: |
| void FakeGetTpmStatus( |
| const tpm_manager::TpmOwnershipInterface::GetTpmStatusCallback& |
| callback) { |
| callback.Run(tpm_status_); |
| } |
| |
| void FakeRemoveOwnerDependency( |
| const tpm_manager::RemoveOwnerDependencyRequest& request, |
| const tpm_manager::TpmOwnershipInterface::RemoveOwnerDependencyCallback& |
| callback) { |
| last_remove_owner_dependency_request = request; |
| callback.Run(next_remove_owner_dependency_reply); |
| } |
| |
| void FakeClearStoredOwnerPassword( |
| const tpm_manager::ClearStoredOwnerPasswordRequest& /* request */, |
| const tpm_manager::TpmOwnershipInterface:: |
| ClearStoredOwnerPasswordCallback& callback) { |
| callback.Run(next_clear_stored_password_reply); |
| } |
| |
| void FakeDefineSpace( |
| const tpm_manager::DefineSpaceRequest& request, |
| const tpm_manager::TpmNvramInterface::DefineSpaceCallback& callback) { |
| last_define_space_request = request; |
| callback.Run(next_define_space_reply); |
| } |
| |
| void FakeDestroySpace( |
| const tpm_manager::DestroySpaceRequest& request, |
| const tpm_manager::TpmNvramInterface::DestroySpaceCallback& callback) { |
| last_destroy_space_request = request; |
| callback.Run(next_destroy_space_reply); |
| } |
| |
| void FakeWriteSpace( |
| const tpm_manager::WriteSpaceRequest& request, |
| const tpm_manager::TpmNvramInterface::WriteSpaceCallback& callback) { |
| last_write_space_request = request; |
| callback.Run(next_write_space_reply); |
| } |
| |
| void FakeReadSpace( |
| const tpm_manager::ReadSpaceRequest& request, |
| const tpm_manager::TpmNvramInterface::ReadSpaceCallback& callback) { |
| last_read_space_request = request; |
| callback.Run(next_read_space_reply); |
| } |
| |
| void FakeLockSpace( |
| const tpm_manager::LockSpaceRequest& request, |
| const tpm_manager::TpmNvramInterface::LockSpaceCallback& callback) { |
| last_lock_space_request = request; |
| callback.Run(next_lock_space_reply); |
| } |
| |
| void FakeListSpaces( |
| const tpm_manager::ListSpacesRequest& request, |
| const tpm_manager::TpmNvramInterface::ListSpacesCallback& callback) { |
| last_list_spaces_request = request; |
| callback.Run(next_list_spaces_reply); |
| } |
| |
| void FakeGetSpaceInfo( |
| const tpm_manager::GetSpaceInfoRequest& request, |
| const tpm_manager::TpmNvramInterface::GetSpaceInfoCallback& callback) { |
| last_get_space_info_request = request; |
| callback.Run(next_get_space_info_reply); |
| } |
| |
| tpm_manager::GetTpmStatusReply tpm_status_; |
| tpm_manager::DefineSpaceRequest last_define_space_request; |
| tpm_manager::DestroySpaceRequest last_destroy_space_request; |
| tpm_manager::WriteSpaceRequest last_write_space_request; |
| tpm_manager::ReadSpaceRequest last_read_space_request; |
| tpm_manager::LockSpaceRequest last_lock_space_request; |
| tpm_manager::ListSpacesRequest last_list_spaces_request; |
| tpm_manager::GetSpaceInfoRequest last_get_space_info_request; |
| tpm_manager::RemoveOwnerDependencyRequest |
| last_remove_owner_dependency_request; |
| tpm_manager::DefineSpaceReply next_define_space_reply; |
| tpm_manager::DestroySpaceReply next_destroy_space_reply; |
| tpm_manager::WriteSpaceReply next_write_space_reply; |
| tpm_manager::ReadSpaceReply next_read_space_reply; |
| tpm_manager::LockSpaceReply next_lock_space_reply; |
| tpm_manager::ListSpacesReply next_list_spaces_reply; |
| tpm_manager::GetSpaceInfoReply next_get_space_info_reply; |
| tpm_manager::RemoveOwnerDependencyReply next_remove_owner_dependency_reply; |
| tpm_manager::ClearStoredOwnerPasswordReply next_clear_stored_password_reply; |
| |
| trunks::TrunksFactoryForTest factory_; |
| Tpm* tpm_; |
| NiceMock<trunks::MockAuthorizationDelegate> mock_authorization_delegate_; |
| NiceMock<trunks::MockBlobParser> mock_blob_parser_; |
| NiceMock<trunks::MockTpm> mock_tpm_; |
| NiceMock<trunks::MockTpmState> mock_tpm_state_; |
| NiceMock<trunks::MockTpmUtility> mock_tpm_utility_; |
| NiceMock<trunks::MockHmacSession> mock_hmac_session_; |
| NiceMock<trunks::MockPolicySession> mock_policy_session_; |
| NiceMock<trunks::MockPolicySession> mock_trial_session_; |
| NiceMock<tpm_manager::MockTpmOwnershipInterface> mock_tpm_owner_; |
| NiceMock<tpm_manager::MockTpmNvramInterface> mock_tpm_nvram_; |
| }; |
| |
| TEST_F(Tpm2Test, GetOwnerPassword) { |
| brillo::SecureBlob owner_password; |
| EXPECT_TRUE(tpm_->GetOwnerPassword(&owner_password)); |
| EXPECT_EQ(kDefaultPassword, owner_password.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, EnabledOwnedCheckSuccess) { |
| bool enabled = false; |
| bool owned = false; |
| EXPECT_TRUE(tpm_->PerformEnabledOwnedCheck(&enabled, &owned)); |
| EXPECT_TRUE(enabled); |
| EXPECT_TRUE(owned); |
| } |
| |
| TEST_F(Tpm2Test, EnabledOwnedCheckStateError) { |
| tpm_status_.set_status(tpm_manager::STATUS_NOT_AVAILABLE); |
| bool enabled = false; |
| bool owned = false; |
| EXPECT_FALSE(tpm_->PerformEnabledOwnedCheck(&enabled, &owned)); |
| EXPECT_FALSE(enabled); |
| EXPECT_FALSE(owned); |
| } |
| |
| TEST_F(Tpm2Test, GetRandomDataSuccess) { |
| std::string random_data("random_data"); |
| size_t num_bytes = random_data.size(); |
| brillo::Blob data; |
| EXPECT_CALL(mock_tpm_utility_, GenerateRandom(num_bytes, _, _)) |
| .WillOnce(DoAll(SetArgPointee<2>(random_data), Return(TPM_RC_SUCCESS))); |
| EXPECT_TRUE(tpm_->GetRandomData(num_bytes, &data)); |
| EXPECT_EQ(data.size(), num_bytes); |
| std::string tpm_data(data.begin(), data.end()); |
| EXPECT_EQ(tpm_data, random_data); |
| } |
| |
| TEST_F(Tpm2Test, GetRandomDataFailure) { |
| brillo::Blob data; |
| size_t num_bytes = 5; |
| EXPECT_CALL(mock_tpm_utility_, GenerateRandom(num_bytes, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->GetRandomData(num_bytes, &data)); |
| } |
| |
| TEST_F(Tpm2Test, GetRandomDataBadLength) { |
| std::string random_data("random_data"); |
| brillo::Blob data; |
| size_t num_bytes = random_data.size() + 1; |
| EXPECT_CALL(mock_tpm_utility_, GenerateRandom(num_bytes, _, _)) |
| .WillOnce(DoAll(SetArgPointee<2>(random_data), Return(TPM_RC_SUCCESS))); |
| EXPECT_FALSE(tpm_->GetRandomData(num_bytes, &data)); |
| } |
| |
| TEST_F(Tpm2Test, DefineNvramSuccess) { |
| uint32_t index = 2; |
| size_t length = 5; |
| EXPECT_TRUE(tpm_->DefineNvram( |
| index, length, Tpm::kTpmNvramWriteDefine)); |
| EXPECT_EQ(index, last_define_space_request.index()); |
| EXPECT_EQ(length, last_define_space_request.size()); |
| ASSERT_EQ(1, last_define_space_request.attributes_size()); |
| EXPECT_EQ(tpm_manager::NVRAM_PERSISTENT_WRITE_LOCK, |
| last_define_space_request.attributes(0)); |
| EXPECT_EQ(tpm_manager::NVRAM_POLICY_NONE, last_define_space_request.policy()); |
| } |
| |
| TEST_F(Tpm2Test, DefineNvramSuccessWithPolicy) { |
| uint32_t index = 2; |
| size_t length = 5; |
| EXPECT_TRUE(tpm_->DefineNvram( |
| index, length, Tpm::kTpmNvramWriteDefine | Tpm::kTpmNvramBindToPCR0)); |
| EXPECT_EQ(index, last_define_space_request.index()); |
| EXPECT_EQ(length, last_define_space_request.size()); |
| ASSERT_EQ(1, last_define_space_request.attributes_size()); |
| EXPECT_EQ(tpm_manager::NVRAM_PERSISTENT_WRITE_LOCK, |
| last_define_space_request.attributes(0)); |
| EXPECT_EQ(tpm_manager::NVRAM_POLICY_PCR0, last_define_space_request.policy()); |
| } |
| |
| TEST_F(Tpm2Test, DefineNvramSuccessFirmwareReadable) { |
| uint32_t index = 2; |
| size_t length = 5; |
| EXPECT_TRUE(tpm_->DefineNvram( |
| index, length, |
| Tpm::kTpmNvramWriteDefine | Tpm::kTpmNvramFirmwareReadable)); |
| EXPECT_EQ(index, last_define_space_request.index()); |
| EXPECT_EQ(length, last_define_space_request.size()); |
| ASSERT_EQ(2, last_define_space_request.attributes_size()); |
| EXPECT_EQ(tpm_manager::NVRAM_PERSISTENT_WRITE_LOCK, |
| last_define_space_request.attributes(0)); |
| EXPECT_EQ(tpm_manager::NVRAM_PLATFORM_READ, |
| last_define_space_request.attributes(1)); |
| EXPECT_EQ(tpm_manager::NVRAM_POLICY_NONE, last_define_space_request.policy()); |
| } |
| |
| TEST_F(Tpm2Test, DefineNvramFailure) { |
| next_define_space_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| EXPECT_FALSE(tpm_->DefineNvram(0, 0, 0)); |
| } |
| |
| TEST_F(Tpm2Test, DestroyNvramSuccess) { |
| uint32_t index = 2; |
| EXPECT_TRUE(tpm_->DestroyNvram(index)); |
| EXPECT_EQ(index, last_destroy_space_request.index()); |
| } |
| |
| TEST_F(Tpm2Test, DestroyNvramFailure) { |
| next_destroy_space_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| EXPECT_FALSE(tpm_->DestroyNvram(0)); |
| } |
| |
| TEST_F(Tpm2Test, WriteNvramSuccess) { |
| uint32_t index = 2; |
| std::string data("nvram_data"); |
| EXPECT_TRUE(tpm_->WriteNvram(index, SecureBlob(data))); |
| EXPECT_EQ(index, last_write_space_request.index()); |
| EXPECT_EQ(data, last_write_space_request.data()); |
| } |
| |
| TEST_F(Tpm2Test, WriteNvramFailure) { |
| next_write_space_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| EXPECT_FALSE(tpm_->WriteNvram(0, SecureBlob())); |
| } |
| |
| TEST_F(Tpm2Test, WriteLockNvramSuccess) { |
| uint32_t index = 2; |
| EXPECT_TRUE(tpm_->WriteLockNvram(index)); |
| EXPECT_EQ(index, last_lock_space_request.index()); |
| EXPECT_TRUE(last_lock_space_request.lock_write()); |
| EXPECT_FALSE(last_lock_space_request.lock_read()); |
| } |
| |
| TEST_F(Tpm2Test, WriteLockNvramFailure) { |
| next_lock_space_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| EXPECT_FALSE(tpm_->WriteLockNvram(0)); |
| } |
| |
| TEST_F(Tpm2Test, ReadNvramSuccess) { |
| uint32_t index = 2; |
| SecureBlob read_data; |
| std::string nvram_data("nvram_data"); |
| next_read_space_reply.set_data(nvram_data); |
| EXPECT_TRUE(tpm_->ReadNvram(index, &read_data)); |
| EXPECT_EQ(nvram_data, read_data.to_string()); |
| EXPECT_EQ(index, last_read_space_request.index()); |
| } |
| |
| TEST_F(Tpm2Test, ReadNvramFailure) { |
| next_read_space_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| SecureBlob read_data; |
| EXPECT_FALSE(tpm_->ReadNvram(0, &read_data)); |
| } |
| |
| TEST_F(Tpm2Test, IsNvramDefinedSuccess) { |
| uint32_t index = 2; |
| next_list_spaces_reply.add_index_list(index); |
| EXPECT_TRUE(tpm_->IsNvramDefined(index)); |
| } |
| |
| TEST_F(Tpm2Test, IsNvramDefinedFailure) { |
| uint32_t index = 2; |
| next_list_spaces_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| next_list_spaces_reply.add_index_list(index); |
| EXPECT_FALSE(tpm_->IsNvramDefined(index)); |
| } |
| |
| TEST_F(Tpm2Test, IsNvramDefinedUnknownHandle) { |
| uint32_t index = 2; |
| next_list_spaces_reply.add_index_list(index + 1); |
| EXPECT_FALSE(tpm_->IsNvramDefined(index)); |
| } |
| |
| TEST_F(Tpm2Test, IsNvramLockedSuccess) { |
| uint32_t index = 2; |
| next_get_space_info_reply.set_is_write_locked(true); |
| EXPECT_TRUE(tpm_->IsNvramLocked(index)); |
| EXPECT_EQ(index, last_get_space_info_request.index()); |
| } |
| |
| TEST_F(Tpm2Test, IsNvramLockedNotLocked) { |
| next_get_space_info_reply.set_is_write_locked(false); |
| EXPECT_FALSE(tpm_->IsNvramLocked(0)); |
| } |
| |
| TEST_F(Tpm2Test, IsNvramLockedFailure) { |
| next_get_space_info_reply.set_is_write_locked(true); |
| next_get_space_info_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| EXPECT_FALSE(tpm_->IsNvramLocked(0)); |
| } |
| |
| TEST_F(Tpm2Test, GetNvramSizeSuccess) { |
| uint32_t index = 2; |
| unsigned int size = 42; |
| next_get_space_info_reply.set_size(size); |
| EXPECT_EQ(tpm_->GetNvramSize(index), size); |
| } |
| |
| TEST_F(Tpm2Test, GetNvramSizeFailure) { |
| uint32_t index = 2; |
| unsigned int size = 42; |
| next_get_space_info_reply.set_size(size); |
| next_get_space_info_reply.set_result(NVRAM_RESULT_IPC_ERROR); |
| EXPECT_EQ(tpm_->GetNvramSize(index), 0); |
| } |
| |
| TEST_F(Tpm2Test, SealToPCR0Success) { |
| SecureBlob value("value"); |
| SecureBlob sealed_value; |
| std::string policy_digest("digest"); |
| EXPECT_CALL(mock_tpm_utility_, GetPolicyDigestForPcrValue(0, _, _)) |
| .WillOnce(DoAll(SetArgPointee<2>(policy_digest), Return(TPM_RC_SUCCESS))); |
| std::string data_to_seal; |
| EXPECT_CALL(mock_tpm_utility_, SealData(_, policy_digest, _, _)) |
| .WillOnce(DoAll(SaveArg<0>(&data_to_seal), Return(TPM_RC_SUCCESS))); |
| EXPECT_TRUE(tpm_->SealToPCR0(value, &sealed_value)); |
| EXPECT_EQ(data_to_seal, value.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, SealToPCR0PolicyFailure) { |
| SecureBlob value("value"); |
| SecureBlob sealed_value; |
| EXPECT_CALL(mock_tpm_utility_, GetPolicyDigestForPcrValue(0, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->SealToPCR0(value, &sealed_value)); |
| } |
| |
| TEST_F(Tpm2Test, SealToPCR0Failure) { |
| SecureBlob value("value"); |
| SecureBlob sealed_value; |
| EXPECT_CALL(mock_tpm_utility_, SealData(_, _, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->SealToPCR0(value, &sealed_value)); |
| } |
| |
| TEST_F(Tpm2Test, UnsealSuccess) { |
| SecureBlob sealed_value("sealed"); |
| SecureBlob value; |
| std::string unsealed_data("unsealed"); |
| EXPECT_CALL(mock_tpm_utility_, UnsealData(_, _, _)) |
| .WillOnce(DoAll(SetArgPointee<2>(unsealed_data), Return(TPM_RC_SUCCESS))); |
| EXPECT_TRUE(tpm_->Unseal(sealed_value, &value)); |
| EXPECT_EQ(unsealed_data, value.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, UnsealStartPolicySessionFail) { |
| SecureBlob sealed_value("sealed"); |
| SecureBlob value; |
| EXPECT_CALL(mock_policy_session_, StartUnboundSession(false)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->Unseal(sealed_value, &value)); |
| } |
| |
| TEST_F(Tpm2Test, UnsealPolicyPCRFailure) { |
| SecureBlob sealed_value("sealed"); |
| SecureBlob value; |
| EXPECT_CALL(mock_policy_session_, PolicyPCR(0, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->Unseal(sealed_value, &value)); |
| } |
| |
| TEST_F(Tpm2Test, UnsealFailure) { |
| SecureBlob sealed_value("sealed"); |
| SecureBlob value; |
| EXPECT_CALL(mock_tpm_utility_, UnsealData(_, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->Unseal(sealed_value, &value)); |
| } |
| |
| TEST_F(Tpm2Test, SignPolicySuccess) { |
| int pcr_index = 5; |
| EXPECT_CALL(mock_policy_session_, PolicyPCR(pcr_index, _)) |
| .WillOnce(Return(TPM_RC_SUCCESS)); |
| EXPECT_CALL(mock_policy_session_, GetDelegate()) |
| .WillOnce(Return(&mock_authorization_delegate_)); |
| std::string tpm_signature(32, 'b'); |
| EXPECT_CALL(mock_tpm_utility_, |
| Sign(_, _, _, _, _, &mock_authorization_delegate_, _)) |
| .WillOnce(DoAll(SetArgPointee<6>(tpm_signature), Return(TPM_RC_SUCCESS))); |
| SecureBlob signature; |
| EXPECT_TRUE(tpm_->Sign(SecureBlob("key_blob"), SecureBlob("input"), pcr_index, |
| &signature)); |
| EXPECT_EQ(signature.to_string(), tpm_signature); |
| } |
| |
| TEST_F(Tpm2Test, SignHmacSuccess) { |
| EXPECT_CALL(mock_hmac_session_, GetDelegate()) |
| .WillOnce(Return(&mock_authorization_delegate_)); |
| std::string tpm_signature(32, 'b'); |
| EXPECT_CALL(mock_tpm_utility_, |
| Sign(_, _, _, _, _, &mock_authorization_delegate_, _)) |
| .WillOnce(DoAll(SetArgPointee<6>(tpm_signature), Return(TPM_RC_SUCCESS))); |
| |
| SecureBlob signature; |
| EXPECT_TRUE( |
| tpm_->Sign(SecureBlob("key_blob"), SecureBlob("input"), -1, &signature)); |
| EXPECT_EQ(signature.to_string(), tpm_signature); |
| } |
| |
| TEST_F(Tpm2Test, SignLoadFailure) { |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillRepeatedly(Return(TPM_RC_FAILURE)); |
| |
| SecureBlob signature; |
| EXPECT_FALSE( |
| tpm_->Sign(SecureBlob("key_blob"), SecureBlob("input"), -1, &signature)); |
| } |
| |
| TEST_F(Tpm2Test, SignFailure) { |
| uint32_t handle = 42; |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillRepeatedly(DoAll(SetArgPointee<2>(handle), Return(TPM_RC_SUCCESS))); |
| EXPECT_CALL(mock_tpm_utility_, Sign(handle, _, _, _, _, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| |
| SecureBlob signature; |
| EXPECT_FALSE( |
| tpm_->Sign(SecureBlob("key_blob"), SecureBlob("input"), -1, &signature)); |
| } |
| |
| TEST_F(Tpm2Test, CreatePCRBoundKeySuccess) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| uint32_t modulus = 2048; |
| uint32_t exponent = 0x10001; |
| EXPECT_CALL(mock_tpm_utility_, |
| CreateRSAKeyPair(_, modulus, exponent, _, _, true, _, _, _, _)) |
| .WillOnce(Return(TPM_RC_SUCCESS)); |
| EXPECT_TRUE(tpm_->CreatePCRBoundKey(index, pcr_value, &key_blob, nullptr, |
| &creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, CreatePCRBoundKeyPolicyFailure) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| EXPECT_CALL(mock_tpm_utility_, GetPolicyDigestForPcrValue(index, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->CreatePCRBoundKey(index, pcr_value, &key_blob, nullptr, |
| &creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, CreatePCRBoundKeyFailure) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| EXPECT_CALL(mock_tpm_utility_, CreateRSAKeyPair(_, _, _, _, _, _, _, _, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->CreatePCRBoundKey(index, pcr_value, &key_blob, nullptr, |
| &creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeySuccess) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| std::string pcr_policy_value; |
| EXPECT_CALL(mock_trial_session_, PolicyPCR(index, _)) |
| .WillOnce(DoAll(SaveArg<1>(&pcr_policy_value), Return(TPM_RC_SUCCESS))); |
| std::string policy_digest(32, 'a'); |
| EXPECT_CALL(mock_trial_session_, GetDigest(_)) |
| .WillOnce(DoAll(SetArgPointee<0>(policy_digest), Return(TPM_RC_SUCCESS))); |
| trunks::TPMT_PUBLIC public_area; |
| public_area.auth_policy.size = policy_digest.size(); |
| memcpy(public_area.auth_policy.buffer, policy_digest.data(), |
| policy_digest.size()); |
| public_area.object_attributes &= (~trunks::kUserWithAuth); |
| EXPECT_CALL(mock_tpm_utility_, GetKeyPublicArea(_, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(public_area), Return(TPM_RC_SUCCESS))); |
| ASSERT_TRUE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| EXPECT_EQ(pcr_policy_value, pcr_value.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadCreationBlob) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadCreationDataCount) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| creation_data.creation_data.pcr_select.count = 0; |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadCreationPCRBank) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA1; |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadCreationPCR) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 0xFF; |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadCreationPCRDigest) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(SecureBlob("")).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyImportedKey) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| |
| EXPECT_CALL(mock_tpm_utility_, CertifyCreation(_, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadSession) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| |
| EXPECT_CALL(mock_trial_session_, StartUnboundSession(true)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadPolicy) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| |
| EXPECT_CALL(mock_trial_session_, PolicyPCR(index, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadDigest) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| |
| EXPECT_CALL(mock_trial_session_, GetDigest(_)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadPolicyDigest) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| |
| std::string policy_digest(32, 'a'); |
| EXPECT_CALL(mock_trial_session_, GetDigest(_)) |
| .WillOnce(DoAll(SetArgPointee<0>(policy_digest), Return(TPM_RC_SUCCESS))); |
| |
| trunks::TPMT_PUBLIC public_area; |
| public_area.auth_policy.size = 2; |
| public_area.object_attributes &= (~trunks::kUserWithAuth); |
| EXPECT_CALL(mock_tpm_utility_, GetKeyPublicArea(_, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(public_area), Return(TPM_RC_SUCCESS))); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, VerifyPCRBoundKeyBadAttributes) { |
| int index = 2; |
| SecureBlob pcr_value("pcr_value"); |
| SecureBlob key_blob; |
| SecureBlob creation_blob; |
| |
| trunks::TPM2B_CREATION_DATA creation_data; |
| trunks::TPML_PCR_SELECTION& pcr_select = |
| creation_data.creation_data.pcr_select; |
| pcr_select.count = 1; |
| pcr_select.pcr_selections[0].hash = trunks::TPM_ALG_SHA256; |
| pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8); |
| creation_data.creation_data.pcr_digest = |
| trunks::Make_TPM2B_DIGEST(CryptoLib::Sha256(pcr_value).to_string()); |
| EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(creation_data), Return(true))); |
| |
| std::string policy_digest(32, 'a'); |
| EXPECT_CALL(mock_trial_session_, GetDigest(_)) |
| .WillOnce(DoAll(SetArgPointee<0>(policy_digest), Return(TPM_RC_SUCCESS))); |
| |
| trunks::TPMT_PUBLIC public_area; |
| public_area.auth_policy.size = policy_digest.size(); |
| memcpy(public_area.auth_policy.buffer, policy_digest.data(), |
| policy_digest.size()); |
| public_area.object_attributes = trunks::kUserWithAuth; |
| EXPECT_CALL(mock_tpm_utility_, GetKeyPublicArea(_, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(public_area), Return(TPM_RC_SUCCESS))); |
| EXPECT_FALSE( |
| tpm_->VerifyPCRBoundKey(index, pcr_value, key_blob, creation_blob)); |
| } |
| |
| TEST_F(Tpm2Test, ExtendPCRSuccess) { |
| int index = 5; |
| SecureBlob extension("extension"); |
| std::string pcr_value; |
| EXPECT_CALL(mock_tpm_utility_, ExtendPCR(index, _, _)) |
| .WillOnce(DoAll(SaveArg<1>(&pcr_value), Return(TPM_RC_SUCCESS))); |
| EXPECT_TRUE(tpm_->ExtendPCR(index, extension)); |
| EXPECT_EQ(pcr_value, extension.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, ExtendPCRFailure) { |
| int index = 5; |
| SecureBlob extension("extension"); |
| EXPECT_CALL(mock_tpm_utility_, ExtendPCR(index, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->ExtendPCR(index, extension)); |
| } |
| |
| TEST_F(Tpm2Test, ReadPCRSuccess) { |
| int index = 5; |
| SecureBlob pcr_value; |
| std::string pcr_digest("digest"); |
| EXPECT_CALL(mock_tpm_utility_, ReadPCR(index, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(pcr_digest), Return(TPM_RC_SUCCESS))); |
| EXPECT_TRUE(tpm_->ReadPCR(index, &pcr_value)); |
| EXPECT_EQ(pcr_digest, pcr_value.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, ReadPCRFailure) { |
| int index = 5; |
| SecureBlob pcr_value; |
| EXPECT_CALL(mock_tpm_utility_, ReadPCR(index, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->ReadPCR(index, &pcr_value)); |
| } |
| |
| TEST_F(Tpm2Test, WrapRsaKeySuccess) { |
| std::string key_blob("key_blob"); |
| SecureBlob modulus; |
| SecureBlob prime_factor; |
| EXPECT_CALL(mock_tpm_utility_, ImportRSAKey(_, _, _, _, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<6>(key_blob), Return(TPM_RC_SUCCESS))); |
| SecureBlob wrapped_key; |
| EXPECT_TRUE(tpm_->WrapRsaKey(modulus, prime_factor, &wrapped_key)); |
| EXPECT_EQ(key_blob, wrapped_key.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, WrapRsaKeyFailure) { |
| SecureBlob wrapped_key; |
| EXPECT_CALL(mock_tpm_utility_, ImportRSAKey(_, _, _, _, _, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_FALSE(tpm_->WrapRsaKey(SecureBlob(), SecureBlob(), &wrapped_key)); |
| } |
| |
| TEST_F(Tpm2Test, LoadWrappedKeySuccess) { |
| SecureBlob wrapped_key("wrapped_key"); |
| trunks::TPM_HANDLE handle = trunks::TPM_RH_FIRST; |
| std::string loaded_key; |
| ScopedKeyHandle key_handle; |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillOnce(DoAll(SaveArg<0>(&loaded_key), SetArgPointee<2>(handle), |
| Return(TPM_RC_SUCCESS))); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), Tpm::kTpmRetryNone); |
| EXPECT_EQ(handle, key_handle.value()); |
| EXPECT_EQ(loaded_key, wrapped_key.to_string()); |
| } |
| |
| TEST_F(Tpm2Test, LoadWrappedKeyFailure) { |
| SecureBlob wrapped_key("wrapped_key"); |
| ScopedKeyHandle key_handle; |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), |
| Tpm::kTpmRetryFailNoRetry); |
| } |
| |
| TEST_F(Tpm2Test, LoadWrappedKeyTransientDevWriteFailure) { |
| SecureBlob wrapped_key("wrapped_key"); |
| ScopedKeyHandle key_handle; |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillOnce(Return(trunks::TRUNKS_RC_WRITE_ERROR)); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), |
| Tpm::kTpmRetryCommFailure); |
| EXPECT_TRUE(tpm_->IsTransient(Tpm::kTpmRetryCommFailure)); |
| } |
| |
| TEST_F(Tpm2Test, LoadWrappedKeyRetryActions) { |
| constexpr TPM_RC error_code_fmt0 = trunks::TPM_RC_REFERENCE_H0; |
| constexpr TPM_RC error_code_fmt1 = trunks::TPM_RC_HANDLE | trunks::TPM_RC_2; |
| SecureBlob wrapped_key("wrapped_key"); |
| ScopedKeyHandle key_handle; |
| // For hardware TPM and Resource Manager, should use the error number to |
| // determine the corresponding retry action. |
| for (TPM_RC layer_code : {trunks::kResourceManagerTpmErrorBase, TPM_RC(0)}) { |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillOnce(Return(error_code_fmt0 | layer_code)) |
| .WillOnce(Return(error_code_fmt1 | layer_code)) |
| .RetiresOnSaturation(); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), |
| Tpm::kTpmRetryInvalidHandle); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), |
| Tpm::kTpmRetryInvalidHandle); |
| } |
| // For response codes produced by other layers (e.g. trunks, SAPI), should |
| // always return FailNoRetry, even if lower 12 bits match hardware TPM errors. |
| for (TPM_RC layer_code : {trunks::kSapiErrorBase, trunks::kTrunksErrorBase}) { |
| EXPECT_CALL(mock_tpm_utility_, LoadKey(_, _, _)) |
| .WillOnce(Return(error_code_fmt0 | layer_code)) |
| .WillOnce(Return(error_code_fmt1 | layer_code)) |
| .RetiresOnSaturation(); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), |
| Tpm::kTpmRetryFailNoRetry); |
| EXPECT_EQ(tpm_->LoadWrappedKey(wrapped_key, &key_handle), |
| Tpm::kTpmRetryFailNoRetry); |
| } |
| } |
| |
| TEST_F(Tpm2Test, CloseHandle) { |
| TpmKeyHandle key_handle = 42; |
| EXPECT_CALL(mock_tpm_, FlushContextSync(key_handle, _)) |
| .WillRepeatedly(Return(TPM_RC_SUCCESS)); |
| tpm_->CloseHandle(key_handle); |
| } |
| |
| TEST_F(Tpm2Test, EncryptBlobSuccess) { |
| TpmKeyHandle handle = 42; |
| std::string tpm_ciphertext(32, 'a'); |
| SecureBlob key(32, 'b'); |
| SecureBlob plaintext("plaintext"); |
| EXPECT_CALL(mock_tpm_utility_, AsymmetricEncrypt(handle, _, _, _, _, _)) |
| .WillOnce( |
| DoAll(SetArgPointee<5>(tpm_ciphertext), Return(TPM_RC_SUCCESS))); |
| SecureBlob ciphertext; |
| EXPECT_EQ(Tpm::kTpmRetryNone, |
| tpm_->EncryptBlob(handle, plaintext, key, &ciphertext)); |
| } |
| |
| TEST_F(Tpm2Test, EncryptBlobBadAesKey) { |
| TpmKeyHandle handle = 42; |
| std::string tpm_ciphertext(32, 'a'); |
| SecureBlob key(16, 'b'); |
| SecureBlob plaintext("plaintext"); |
| EXPECT_CALL(mock_tpm_utility_, AsymmetricEncrypt(handle, _, _, _, _, _)) |
| .WillOnce( |
| DoAll(SetArgPointee<5>(tpm_ciphertext), Return(TPM_RC_SUCCESS))); |
| SecureBlob ciphertext; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->EncryptBlob(handle, plaintext, key, &ciphertext)); |
| } |
| |
| TEST_F(Tpm2Test, EncryptBlobBadTpmEncrypt) { |
| TpmKeyHandle handle = 42; |
| std::string tpm_ciphertext(16, 'a'); |
| SecureBlob key(32, 'b'); |
| SecureBlob plaintext("plaintext"); |
| EXPECT_CALL(mock_tpm_utility_, AsymmetricEncrypt(handle, _, _, _, _, _)) |
| .WillOnce( |
| DoAll(SetArgPointee<5>(tpm_ciphertext), Return(TPM_RC_SUCCESS))); |
| SecureBlob ciphertext; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->EncryptBlob(handle, plaintext, key, &ciphertext)); |
| } |
| |
| TEST_F(Tpm2Test, EncryptBlobFailure) { |
| TpmKeyHandle handle = 42; |
| SecureBlob key(32, 'b'); |
| SecureBlob plaintext("plaintext"); |
| EXPECT_CALL(mock_tpm_utility_, AsymmetricEncrypt(handle, _, _, _, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| SecureBlob ciphertext; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->EncryptBlob(handle, plaintext, key, &ciphertext)); |
| } |
| |
| TEST_F(Tpm2Test, DecryptBlobSuccess) { |
| TpmKeyHandle handle = 42; |
| SecureBlob key(32, 'a'); |
| SecureBlob ciphertext(32, 'b'); |
| std::string tpm_plaintext("plaintext"); |
| EXPECT_CALL(mock_tpm_utility_, AsymmetricDecrypt(handle, _, _, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<5>(tpm_plaintext), Return(TPM_RC_SUCCESS))); |
| SecureBlob plaintext; |
| EXPECT_EQ(Tpm::kTpmRetryNone, |
| tpm_->DecryptBlob(handle, ciphertext, key, &plaintext)); |
| } |
| |
| TEST_F(Tpm2Test, DecryptBlobBadAesKey) { |
| TpmKeyHandle handle = 42; |
| SecureBlob key(16, 'a'); |
| SecureBlob ciphertext(32, 'b'); |
| SecureBlob plaintext; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->DecryptBlob(handle, ciphertext, key, &plaintext)); |
| } |
| |
| TEST_F(Tpm2Test, DecryptBlobBadCiphertext) { |
| TpmKeyHandle handle = 42; |
| SecureBlob key(32, 'a'); |
| SecureBlob ciphertext(16, 'b'); |
| SecureBlob plaintext; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->DecryptBlob(handle, ciphertext, key, &plaintext)); |
| } |
| |
| TEST_F(Tpm2Test, DecryptBlobFailure) { |
| TpmKeyHandle handle = 42; |
| SecureBlob key(32, 'a'); |
| SecureBlob ciphertext(32, 'b'); |
| EXPECT_CALL(mock_tpm_utility_, AsymmetricDecrypt(handle, _, _, _, _, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| SecureBlob plaintext; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->DecryptBlob(handle, ciphertext, key, &plaintext)); |
| } |
| |
| TEST_F(Tpm2Test, GetPublicKeyHashSuccess) { |
| TpmKeyHandle handle = 42; |
| trunks::TPMT_PUBLIC public_data; |
| SecureBlob public_key("hello"); |
| public_data.unique.rsa = |
| trunks::Make_TPM2B_PUBLIC_KEY_RSA(public_key.to_string()); |
| EXPECT_CALL(mock_tpm_utility_, GetKeyPublicArea(handle, _)) |
| .WillOnce(DoAll(SetArgPointee<1>(public_data), Return(TPM_RC_SUCCESS))); |
| SecureBlob public_key_hash; |
| EXPECT_EQ(Tpm::kTpmRetryNone, |
| tpm_->GetPublicKeyHash(handle, &public_key_hash)); |
| SecureBlob expected_key_hash = CryptoLib::Sha256(public_key); |
| EXPECT_EQ(expected_key_hash, public_key_hash); |
| } |
| |
| TEST_F(Tpm2Test, GetPublicKeyHashFailure) { |
| TpmKeyHandle handle = 42; |
| EXPECT_CALL(mock_tpm_utility_, GetKeyPublicArea(handle, _)) |
| .WillOnce(Return(TPM_RC_FAILURE)); |
| SecureBlob public_key_hash; |
| EXPECT_EQ(Tpm::kTpmRetryFailNoRetry, |
| tpm_->GetPublicKeyHash(handle, &public_key_hash)); |
| } |
| |
| TEST_F(Tpm2Test, DeclareTpmFirmwareStable) { |
| EXPECT_CALL(mock_tpm_utility_, DeclareTpmFirmwareStable()) |
| .Times(2) |
| .WillOnce(Return(TPM_RC_FAILURE)) |
| .WillOnce(Return(TPM_RC_SUCCESS)); |
| // First attempt shall call TpmUtility since we haven't called it yet. |
| tpm_->DeclareTpmFirmwareStable(); |
| // Second attempt shall call TpmUtility since the first attempt failed. |
| tpm_->DeclareTpmFirmwareStable(); |
| // Subsequent attempts shall do nothing since we already succeeded on the |
| // second attempt. |
| tpm_->DeclareTpmFirmwareStable(); |
| tpm_->DeclareTpmFirmwareStable(); |
| } |
| |
| TEST_F(Tpm2Test, RemoveOwnerDependencySuccess) { |
| EXPECT_TRUE(tpm_->RemoveOwnerDependency( |
| Tpm::TpmOwnerDependency::kInstallAttributes)); |
| EXPECT_EQ(tpm_manager::kTpmOwnerDependency_Nvram, |
| last_remove_owner_dependency_request.owner_dependency()); |
| EXPECT_TRUE(tpm_->RemoveOwnerDependency( |
| Tpm::TpmOwnerDependency::kAttestation)); |
| EXPECT_EQ(tpm_manager::kTpmOwnerDependency_Attestation, |
| last_remove_owner_dependency_request.owner_dependency()); |
| } |
| |
| TEST_F(Tpm2Test, RemoveOwnerDependencyFailure) { |
| next_remove_owner_dependency_reply.set_status( |
| tpm_manager::STATUS_DEVICE_ERROR); |
| EXPECT_FALSE(tpm_->RemoveOwnerDependency( |
| Tpm::TpmOwnerDependency::kInstallAttributes)); |
| EXPECT_EQ(tpm_manager::kTpmOwnerDependency_Nvram, |
| last_remove_owner_dependency_request.owner_dependency()); |
| } |
| |
| TEST_F(Tpm2Test, RemoveOwnerDependencyUnknown) { |
| Tpm::TpmOwnerDependency unknown_dep = |
| static_cast<Tpm::TpmOwnerDependency>(100); |
| EXPECT_CALL(mock_tpm_owner_, RemoveOwnerDependency(_, _)) |
| .Times(0); |
| EXPECT_TRUE(tpm_->RemoveOwnerDependency(unknown_dep)); |
| } |
| |
| TEST_F(Tpm2Test, ClearStoredPasswordSuccess) { |
| EXPECT_CALL(mock_tpm_owner_, ClearStoredOwnerPassword(_, _)) |
| .Times(1); |
| EXPECT_CALL(mock_tpm_owner_, GetTpmStatus(_, _)) |
| .Times(1); |
| EXPECT_TRUE(tpm_->ClearStoredPassword()); |
| } |
| |
| TEST_F(Tpm2Test, ClearStoredPasswordFailure) { |
| next_clear_stored_password_reply.set_status( |
| tpm_manager::STATUS_DEVICE_ERROR); |
| EXPECT_CALL(mock_tpm_owner_, ClearStoredOwnerPassword(_, _)) |
| .Times(1); |
| EXPECT_CALL(mock_tpm_owner_, GetTpmStatus(_, _)) |
| .Times(0); |
| EXPECT_FALSE(tpm_->ClearStoredPassword()); |
| } |
| |
| } // namespace cryptohome |