| // Copyright 2016 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 TpmInit. |
| |
| #include "cryptohome/tpm_init.h" |
| |
| #include <map> |
| #include <string> |
| |
| #include <base/files/file_path.h> |
| #include <brillo/secure_blob.h> |
| |
| #include "cryptohome/mock_platform.h" |
| #include "cryptohome/mock_tpm.h" |
| |
| using ::testing::_; |
| using ::testing::Invoke; |
| using ::testing::NiceMock; |
| using ::testing::Return; |
| |
| namespace cryptohome { |
| |
| extern const base::FilePath kTpmOwnedFile; |
| const base::FilePath kTpmStatusFile("/mnt/stateful_partition/.tpm_status"); |
| const base::FilePath kDefaultCryptohomeKeyFile("/home/.shadow/cryptohome.key"); |
| const TpmKeyHandle kTestKeyHandle = 17; // any non-zero value |
| |
| // Tests that need to do more setup work before calling Service::Initialize can |
| // use this instead of ServiceTest. |
| class TpmInitTest : public ::testing::Test { |
| public: |
| TpmInitTest() |
| : is_tpm_owned_(false), |
| is_tpm_being_owned_(false), |
| is_tpm_initialized_(false), |
| tpm_init_(&tpm_, &platform_) {} |
| TpmInitTest(const TpmInitTest&) = delete; |
| TpmInitTest& operator=(const TpmInitTest&) = delete; |
| |
| ~TpmInitTest() override = default; |
| |
| // Default mock implementations for |tpm_| methods. |
| // For TPM-related flags: enabled is always true, other flags are settable. |
| bool IsTpmOwned() const { return is_tpm_owned_; } |
| void SetIsTpmOwned(bool is_tpm_owned) { is_tpm_owned_ = is_tpm_owned; } |
| bool IsTpmBeingOwned() const { return is_tpm_being_owned_; } |
| void SetIsTpmBeingOwned(bool is_tpm_being_owned) { |
| is_tpm_being_owned_ = is_tpm_being_owned; |
| } |
| bool IsTpmInitialized() { return is_tpm_initialized_; } |
| void SetIsTpmInitialized(bool is_tpm_initialized) { |
| is_tpm_initialized_ = is_tpm_initialized; |
| } |
| bool PerformTpmEnabledOwnedCheck(bool* is_enabled, bool* is_owned) { |
| *is_enabled = true; |
| *is_owned = is_tpm_owned_; |
| return true; |
| } |
| bool GetRandomDataBlob(size_t length, brillo::Blob* data) const { |
| data->resize(length, 0); |
| return true; |
| } |
| bool GetRandomDataSecureBlob(size_t length, brillo::SecureBlob* data) const { |
| data->resize(length, 0); |
| return true; |
| } |
| |
| // Default mock implementations for |platform_| methods. |
| // Files are emulated using |files_| map: <file path> -> <file contents>. |
| bool FileExists(const base::FilePath& path) const { |
| return files_.count(path) > 0; |
| } |
| bool FileMove(const base::FilePath& from, const base::FilePath& to) { |
| if (!FileExists(from)) { |
| return false; |
| } |
| if (FileExists(to)) { |
| return false; |
| } |
| files_[to] = files_[from]; |
| return FileDelete(from); |
| } |
| bool FileDelete(const base::FilePath& path) { |
| return files_.erase(path) == 1; |
| } |
| bool FileTouch(const base::FilePath& path) { |
| files_.emplace(path, brillo::Blob()); |
| return FileExists(path); |
| } |
| bool GetFileSize(const base::FilePath& path, int64_t* size) { |
| if (!FileExists(path)) { |
| return false; |
| } |
| *size = files_[path].size(); |
| return true; |
| } |
| bool FileRead(const base::FilePath& path, brillo::Blob* blob) { |
| if (!FileExists(path)) { |
| return false; |
| } |
| *blob = files_[path]; |
| return true; |
| } |
| bool FileReadToString(const base::FilePath& path, std::string* str) { |
| brillo::Blob blob; |
| if (!FileRead(path, &blob)) { |
| return false; |
| } |
| str->assign(reinterpret_cast<char*>(blob.data()), blob.size()); |
| return true; |
| } |
| bool FileReadToSecureBlob(const base::FilePath& path, |
| brillo::SecureBlob* sblob) { |
| if (!FileExists(path)) { |
| return false; |
| } |
| brillo::Blob temp = files_[path]; |
| sblob->assign(temp.begin(), temp.end()); |
| return true; |
| } |
| bool FileWrite(const base::FilePath& path, const brillo::Blob& blob) { |
| files_[path] = blob; |
| return true; |
| } |
| bool FileWriteFromSecureBlob(const base::FilePath& path, |
| const brillo::SecureBlob& sblob) { |
| brillo::Blob blob(sblob.begin(), sblob.end()); |
| files_[path] = blob; |
| return true; |
| } |
| bool FileWriteAtomic(const base::FilePath& path, |
| const brillo::SecureBlob& sblob, |
| mode_t /* mode */) { |
| return FileWriteFromSecureBlob(path, sblob); |
| } |
| bool FileWriteString(const base::FilePath& path, const std::string& str) { |
| brillo::Blob blob(str.begin(), str.end()); |
| return FileWrite(path, blob); |
| } |
| |
| void SetTpmStatus(const TpmStatus& tpm_status) { |
| brillo::Blob file_data(tpm_status.ByteSizeLong()); |
| tpm_status.SerializeWithCachedSizesToArray(file_data.data()); |
| EXPECT_TRUE(FileWrite(kTpmStatusFile, file_data)); |
| } |
| |
| void GetTpmStatus(TpmStatus* tpm_status) { |
| brillo::Blob file_data; |
| tpm_status->Clear(); |
| EXPECT_TRUE(FileRead(kTpmStatusFile, &file_data)); |
| EXPECT_TRUE(tpm_status->ParseFromArray(file_data.data(), file_data.size())); |
| } |
| |
| void SetTpmReady() { |
| SetIsTpmOwned(true); |
| SetIsTpmBeingOwned(false); |
| FileTouch(kTpmOwnedFile); |
| ASSERT_TRUE(tpm_init_.IsTpmReady()); |
| } |
| |
| void SetUp() override { |
| ON_CALL(tpm_, IsEnabled()).WillByDefault(Return(true)); |
| ON_CALL(tpm_, IsOwned()) |
| .WillByDefault(Invoke(this, &TpmInitTest::IsTpmOwned)); |
| ON_CALL(tpm_, SetIsOwned(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::SetIsTpmOwned)); |
| ON_CALL(tpm_, IsBeingOwned()) |
| .WillByDefault(Invoke(this, &TpmInitTest::IsTpmBeingOwned)); |
| ON_CALL(tpm_, SetIsBeingOwned(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::SetIsTpmBeingOwned)); |
| ON_CALL(tpm_, IsInitialized()) |
| .WillByDefault(Invoke(this, &TpmInitTest::IsTpmInitialized)); |
| ON_CALL(tpm_, SetIsInitialized(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::SetIsTpmInitialized)); |
| ON_CALL(tpm_, PerformEnabledOwnedCheck(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::PerformTpmEnabledOwnedCheck)); |
| |
| ON_CALL(tpm_, GetRandomDataBlob(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::GetRandomDataBlob)); |
| ON_CALL(tpm_, GetRandomDataSecureBlob(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::GetRandomDataSecureBlob)); |
| |
| ON_CALL(platform_, FileExists(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileExists)); |
| ON_CALL(platform_, Move(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileMove)); |
| ON_CALL(platform_, DeleteFile(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileDelete)); |
| ON_CALL(platform_, DeletePathRecursively(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileDelete)); |
| ON_CALL(platform_, DeleteFileDurable(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileDelete)); |
| ON_CALL(platform_, TouchFileDurable(_)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileTouch)); |
| ON_CALL(platform_, GetFileSize(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::GetFileSize)); |
| ON_CALL(platform_, ReadFile(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileRead)); |
| ON_CALL(platform_, ReadFileToSecureBlob(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileReadToSecureBlob)); |
| ON_CALL(platform_, WriteSecureBlobToFile(_, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileWriteFromSecureBlob)); |
| ON_CALL(platform_, WriteSecureBlobToFileAtomic(_, _, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileWriteAtomic)); |
| ON_CALL(platform_, WriteSecureBlobToFileAtomicDurable(_, _, _)) |
| .WillByDefault(Invoke(this, &TpmInitTest::FileWriteAtomic)); |
| ON_CALL(platform_, DataSyncFile(_)).WillByDefault(Return(true)); |
| } |
| |
| void TearDown() override {} |
| |
| protected: |
| bool is_tpm_owned_; |
| bool is_tpm_being_owned_; |
| bool is_tpm_initialized_; |
| std::map<base::FilePath, brillo::Blob> files_; |
| NiceMock<MockTpm> tpm_; |
| NiceMock<MockPlatform> platform_; |
| |
| // Declare tpm_init_ last, so it gets destroyed before all the mocks. |
| TpmInit tpm_init_; |
| }; |
| |
| MATCHER_P(HasStoredCryptohomeKey, str, "") { |
| std::string stored_key; |
| if (!arg->FileReadToString(kDefaultCryptohomeKeyFile, &stored_key)) { |
| *result_listener << "has no stored cryptohome key"; |
| return false; |
| } |
| if (stored_key != str) { |
| *result_listener << "has stored cryptohome key \"" << stored_key << "\""; |
| return false; |
| } |
| return true; |
| } |
| |
| MATCHER_P(HasLoadedCryptohomeKey, handle, "") { |
| if (!arg->HasCryptohomeKey()) { |
| *result_listener << "has no loaded cryptohome key"; |
| return false; |
| } |
| TpmKeyHandle loaded_handle = arg->GetCryptohomeKey(); |
| if (loaded_handle != handle) { |
| *result_listener << "has loaded cryptohome key " << loaded_handle; |
| return false; |
| } |
| return true; |
| } |
| |
| MATCHER(HasNoLoadedCryptohomeKey, "") { |
| TpmKeyHandle loaded_handle = arg->GetCryptohomeKey(); |
| *result_listener << "has loaded cryptohome key " << loaded_handle; |
| return !arg->HasCryptohomeKey() && loaded_handle == kInvalidKeyHandle; |
| } |
| |
| ACTION_P(GenerateWrappedKey, wrapped_key) { |
| *arg2 = brillo::SecureBlob(wrapped_key); |
| return true; |
| } |
| |
| ACTION_P(LoadWrappedKeyToHandle, handle) { |
| arg1->reset(nullptr, handle); |
| return Tpm::kTpmRetryNone; |
| } |
| |
| TEST_F(TpmInitTest, AlreadyOwnedSuccess) { |
| bool took_ownership = false; |
| SetIsTpmOwned(true); |
| FileTouch(kTpmOwnedFile); |
| ASSERT_TRUE(tpm_init_.TakeOwnership(&took_ownership)); |
| ASSERT_FALSE(took_ownership); |
| } |
| |
| TEST_F(TpmInitTest, TakeOwnershipMonolithicSuccess) { |
| // Setup TPM. |
| EXPECT_CALL(tpm_, SetIsOwned(false)).Times(1); |
| EXPECT_CALL(tpm_, SetIsEnabled(true)).Times(1); |
| EXPECT_TRUE(tpm_init_.SetupTpm(false)); |
| EXPECT_TRUE(IsTpmInitialized()); |
| EXPECT_FALSE(IsTpmOwned()); |
| EXPECT_FALSE(FileExists(kTpmOwnedFile)); |
| ::testing::Mock::VerifyAndClearExpectations(&tpm_); |
| |
| // Take Ownership. |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).WillOnce(Return(false)); |
| EXPECT_CALL(tpm_, IsEndorsementKeyAvailable()) |
| .WillOnce(Return(false)) |
| .WillRepeatedly(Return(true)); |
| EXPECT_CALL(tpm_, CreateEndorsementKey()).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, TakeOwnership(_, _)).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, TestTpmAuth(_)).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, InitializeSrk(_)).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, ChangeOwnerPassword(_, _)).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, SetOwnerPassword(_)).Times(1); |
| |
| bool took_ownership = false; |
| EXPECT_TRUE(tpm_init_.TakeOwnership(&took_ownership)); |
| EXPECT_TRUE(took_ownership); |
| EXPECT_TRUE(IsTpmOwned()); |
| EXPECT_FALSE(IsTpmBeingOwned()); |
| EXPECT_TRUE(FileExists(kTpmOwnedFile)); |
| } |
| |
| TEST_F(TpmInitTest, TakeOwnershipDistributedSuccess) { |
| // Set initial TPM states. |
| SetIsTpmOwned(false); |
| SetIsTpmInitialized(true); |
| SetIsTpmBeingOwned(false); |
| |
| // Take Ownership. |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, IsEndorsementKeyAvailable()) |
| .WillOnce(Return(false)) |
| .WillRepeatedly(Return(true)); |
| EXPECT_CALL(tpm_, CreateEndorsementKey()).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, TakeOwnership(_, _)).WillOnce(Return(true)); |
| EXPECT_CALL(tpm_, TestTpmAuth(_)).Times(0); |
| EXPECT_CALL(tpm_, InitializeSrk(_)).Times(0); |
| EXPECT_CALL(tpm_, ChangeOwnerPassword(_, _)).Times(0); |
| EXPECT_CALL(tpm_, SetOwnerPassword(_)).Times(0); |
| |
| bool took_ownership = false; |
| EXPECT_TRUE(tpm_init_.TakeOwnership(&took_ownership)); |
| EXPECT_TRUE(took_ownership); |
| EXPECT_TRUE(IsTpmOwned()); |
| EXPECT_FALSE(IsTpmBeingOwned()); |
| EXPECT_TRUE(FileExists(kTpmOwnedFile)); |
| } |
| |
| TEST_F(TpmInitTest, RemoveTpmOwnerDependencySuccess) { |
| TpmStatus tpm_status; |
| tpm_status.set_flags(TpmStatus::ATTESTATION_NEEDS_OWNER | |
| TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER); |
| SetTpmStatus(tpm_status); |
| auto dependency = TpmPersistentState::TpmOwnerDependency::kAttestation; |
| EXPECT_CALL(tpm_, RemoveOwnerDependency(dependency)).WillOnce(Return(true)); |
| EXPECT_CALL(platform_, |
| WriteSecureBlobToFileAtomicDurable(kTpmStatusFile, _, _)) |
| .Times(1); |
| tpm_init_.RemoveTpmOwnerDependency(dependency); |
| GetTpmStatus(&tpm_status); |
| EXPECT_EQ(TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER, tpm_status.flags()); |
| } |
| |
| TEST_F(TpmInitTest, RemoveTpmOwnerDependencyAlreadyRemoved) { |
| TpmStatus tpm_status; |
| tpm_status.set_flags(TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER); |
| SetTpmStatus(tpm_status); |
| auto dependency = TpmPersistentState::TpmOwnerDependency::kAttestation; |
| EXPECT_CALL(tpm_, RemoveOwnerDependency(dependency)).WillOnce(Return(true)); |
| EXPECT_CALL(platform_, |
| WriteSecureBlobToFileAtomicDurable(kTpmStatusFile, _, _)) |
| .Times(0); |
| tpm_init_.RemoveTpmOwnerDependency(dependency); |
| GetTpmStatus(&tpm_status); |
| EXPECT_EQ(TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER, tpm_status.flags()); |
| } |
| |
| TEST_F(TpmInitTest, RemoveTpmOwnerDependencyTpmFailure) { |
| TpmStatus tpm_status; |
| tpm_status.set_flags(TpmStatus::ATTESTATION_NEEDS_OWNER); |
| SetTpmStatus(tpm_status); |
| auto dependency = TpmPersistentState::TpmOwnerDependency::kAttestation; |
| EXPECT_CALL(tpm_, RemoveOwnerDependency(dependency)).WillOnce(Return(false)); |
| EXPECT_CALL(platform_, |
| WriteSecureBlobToFileAtomicDurable(kTpmStatusFile, _, _)) |
| .Times(0); |
| tpm_init_.RemoveTpmOwnerDependency(dependency); |
| GetTpmStatus(&tpm_status); |
| EXPECT_EQ(TpmStatus::ATTESTATION_NEEDS_OWNER, tpm_status.flags()); |
| } |
| |
| TEST_F(TpmInitTest, RemoveTpmOwnerDependencyNoTpmStatus) { |
| auto dependency = TpmPersistentState::TpmOwnerDependency::kAttestation; |
| EXPECT_CALL(tpm_, RemoveOwnerDependency(dependency)).WillOnce(Return(true)); |
| EXPECT_CALL(platform_, |
| WriteSecureBlobToFileAtomicDurable(kTpmStatusFile, _, _)) |
| .Times(0); |
| tpm_init_.RemoveTpmOwnerDependency(dependency); |
| } |
| |
| TEST_F(TpmInitTest, LoadCryptohomeKeySuccess) { |
| SetIsTpmInitialized(true); |
| FileTouch(kDefaultCryptohomeKeyFile); |
| EXPECT_CALL(tpm_, LoadWrappedKey(_, _)) |
| .WillOnce(LoadWrappedKeyToHandle(kTestKeyHandle)); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasLoadedCryptohomeKey(kTestKeyHandle)); |
| } |
| |
| TEST_F(TpmInitTest, LoadCryptohomeKeyTransientFailure) { |
| // Transient failure on the first attempt leads to key not being loaded. |
| // But the key is not re-created. Success on the second attempt loads the |
| // old key. |
| SetIsTpmInitialized(true); |
| FileWriteString(kDefaultCryptohomeKeyFile, "old-key"); |
| EXPECT_CALL(tpm_, LoadWrappedKey(_, _)) |
| .WillOnce(Return(Tpm::kTpmRetryCommFailure)) |
| .WillOnce(LoadWrappedKeyToHandle(kTestKeyHandle)); |
| EXPECT_CALL(tpm_, WrapRsaKey(_, _, _)).Times(0); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasNoLoadedCryptohomeKey()); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasLoadedCryptohomeKey(kTestKeyHandle)); |
| EXPECT_THAT(this, HasStoredCryptohomeKey("old-key")); |
| } |
| |
| TEST_F(TpmInitTest, ReCreateCryptohomeKeyAfterLoadFailure) { |
| // Permanent failure while loading the key leads to re-creating, storing |
| // and loading the new key. |
| SetTpmReady(); |
| SetIsTpmInitialized(true); |
| FileWriteString(kDefaultCryptohomeKeyFile, "old-key"); |
| EXPECT_CALL(tpm_, LoadWrappedKey(_, _)) |
| .WillOnce(Return(Tpm::kTpmRetryFailNoRetry)) |
| .WillOnce(LoadWrappedKeyToHandle(kTestKeyHandle)); |
| EXPECT_CALL(tpm_, WrapRsaKey(_, _, _)) |
| .WillOnce(GenerateWrappedKey("new-key")); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasLoadedCryptohomeKey(kTestKeyHandle)); |
| EXPECT_THAT(this, HasStoredCryptohomeKey("new-key")); |
| } |
| |
| TEST_F(TpmInitTest, ReCreateCryptohomeKeyFailureDuringKeyCreation) { |
| // Permanent failure while loading the key leads to an attempt to re-create |
| // the key. Which fails. So, nothing new is stored or loaded. |
| SetTpmReady(); |
| SetIsTpmInitialized(true); |
| FileWriteString(kDefaultCryptohomeKeyFile, "old-key"); |
| EXPECT_CALL(tpm_, LoadWrappedKey(_, _)) |
| .WillOnce(Return(Tpm::kTpmRetryFailNoRetry)); |
| EXPECT_CALL(tpm_, WrapRsaKey(_, _, _)).WillOnce(Return(false)); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasNoLoadedCryptohomeKey()); |
| EXPECT_THAT(this, HasStoredCryptohomeKey("old-key")); |
| } |
| |
| TEST_F(TpmInitTest, ReCreateCryptohomeKeyFailureDuringKeyLoading) { |
| // Permanent failure while loading the key leads to re-creating the key. |
| // It is stored. But then loading fails. |
| // Still, on the next attempt, the key is loaded, and not re-created again. |
| SetTpmReady(); |
| SetIsTpmInitialized(true); |
| FileWriteString(kDefaultCryptohomeKeyFile, "old-key"); |
| EXPECT_CALL(tpm_, LoadWrappedKey(_, _)) |
| .WillOnce(Return(Tpm::kTpmRetryFailNoRetry)) |
| .WillOnce(Return(Tpm::kTpmRetryFailNoRetry)) |
| .WillOnce(LoadWrappedKeyToHandle(kTestKeyHandle)); |
| EXPECT_CALL(tpm_, WrapRsaKey(_, _, _)) |
| .WillOnce(GenerateWrappedKey("new-key")); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasNoLoadedCryptohomeKey()); |
| EXPECT_THAT(this, HasStoredCryptohomeKey("new-key")); |
| tpm_init_.SetupTpm(true); |
| EXPECT_THAT(&tpm_init_, HasLoadedCryptohomeKey(kTestKeyHandle)); |
| EXPECT_THAT(this, HasStoredCryptohomeKey("new-key")); |
| } |
| |
| TEST_F(TpmInitTest, IsTpmReadyWithOwnedFile) { |
| FileTouch(kTpmOwnedFile); |
| |
| SetIsTpmOwned(true); |
| SetIsTpmBeingOwned(false); |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).WillOnce(Return(false)); |
| EXPECT_TRUE(tpm_init_.IsTpmReady()); |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).WillOnce(Return(true)); |
| EXPECT_TRUE(tpm_init_.IsTpmReady()); |
| |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).Times(0); |
| |
| SetIsTpmOwned(false); |
| EXPECT_FALSE(tpm_init_.IsTpmReady()); |
| |
| SetIsTpmOwned(true); |
| SetIsTpmBeingOwned(true); |
| EXPECT_FALSE(tpm_init_.IsTpmReady()); |
| } |
| |
| TEST_F(TpmInitTest, IsTpmReadyNoOwnedFile) { |
| FileDelete(kTpmOwnedFile); |
| SetIsTpmOwned(true); |
| SetIsTpmBeingOwned(false); |
| |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).WillOnce(Return(false)); |
| EXPECT_FALSE(tpm_init_.IsTpmReady()); |
| |
| EXPECT_CALL(tpm_, DoesUseTpmManager()).WillOnce(Return(true)); |
| EXPECT_TRUE(tpm_init_.IsTpmReady()); |
| } |
| |
| } // namespace cryptohome |