123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- // Copyright 2020 The Chromium 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 "chromeos/dbus/tpm_manager/tpm_manager_client.h"
- #include <string>
- #include <utility>
- #include "base/test/task_environment.h"
- #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
- #include "dbus/mock_bus.h"
- #include "dbus/mock_object_proxy.h"
- #include "dbus/object_path.h"
- #include "dbus/object_proxy.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/cros_system_api/dbus/tpm_manager/dbus-constants.h"
- using ::testing::_;
- using ::testing::Invoke;
- using ::testing::Return;
- using ::testing::SaveArg;
- namespace chromeos {
- namespace {
- // Runs |callback| with |response|. Needed due to ResponseCallback expecting a
- // bare pointer rather than an std::unique_ptr.
- void RunResponseCallback(dbus::ObjectProxy::ResponseCallback callback,
- std::unique_ptr<dbus::Response> response) {
- std::move(callback).Run(response.get());
- }
- // The observer class used for testing to watch the invocation of the signal
- // callbacks.
- class TestObserver : public TpmManagerClient::Observer {
- public:
- // TpmManagerClient::Observer.
- void OnOwnershipTaken() override { ++signal_count_; }
- int signal_count() const { return signal_count_; }
- private:
- int signal_count_ = 0;
- };
- } // namespace
- class TpmManagerClientTest : public testing::Test {
- public:
- TpmManagerClientTest() = default;
- ~TpmManagerClientTest() override = default;
- void SetUp() override {
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SYSTEM;
- bus_ = new dbus::MockBus(options);
- dbus::ObjectPath tpm_manager_object_path =
- dbus::ObjectPath(::tpm_manager::kTpmManagerServicePath);
- proxy_ = new dbus::MockObjectProxy(bus_.get(),
- ::tpm_manager::kTpmManagerServiceName,
- tpm_manager_object_path);
- // Makes sure `GetObjectProxy()` is caled with the correct service name and
- // path.
- EXPECT_CALL(*bus_.get(),
- GetObjectProxy(::tpm_manager::kTpmManagerServiceName,
- tpm_manager_object_path))
- .WillRepeatedly(Return(proxy_.get()));
- EXPECT_CALL(*proxy_.get(), DoCallMethod(_, _, _))
- .WillRepeatedly(Invoke(this, &TpmManagerClientTest::OnCallMethod));
- EXPECT_CALL(*proxy_,
- DoConnectToSignal(::tpm_manager::kTpmManagerInterface,
- ::tpm_manager::kOwnershipTakenSignal, _, _))
- .WillOnce(SaveArg<2>(&ownership_taken_signal_callback_));
- TpmManagerClient::Initialize(bus_.get());
- // Execute callbacks posted by `client_->Init()`.
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(ownership_taken_signal_callback_.is_null());
- client_ = TpmManagerClient::Get();
- }
- void TearDown() override { TpmManagerClient::Shutdown(); }
- protected:
- void EmitOwnershipTakenSignal() {
- ::tpm_manager::OwnershipTakenSignal ownership_taken_signal;
- dbus::Signal signal(::tpm_manager::kTpmManagerInterface,
- ::tpm_manager::kOwnershipTakenSignal);
- dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(
- ownership_taken_signal);
- // Emit signal.
- ASSERT_FALSE(ownership_taken_signal_callback_.is_null());
- ownership_taken_signal_callback_.Run(&signal);
- }
- base::test::SingleThreadTaskEnvironment task_environment_;
- // Mock bus and proxy for simulating calls.
- scoped_refptr<dbus::MockBus> bus_;
- scoped_refptr<dbus::MockObjectProxy> proxy_;
- // Convenience pointer to the global instance.
- TpmManagerClient* client_;
- // The expected replies to the respective D-Bus calls.
- ::tpm_manager::GetTpmNonsensitiveStatusReply expected_status_reply_;
- ::tpm_manager::GetVersionInfoReply expected_version_info_reply_;
- ::tpm_manager::GetSupportedFeaturesReply expected_supported_features_reply_;
- ::tpm_manager::GetDictionaryAttackInfoReply expected_get_da_info_reply_;
- ::tpm_manager::TakeOwnershipReply expected_take_ownership_reply_;
- ::tpm_manager::ClearStoredOwnerPasswordReply expected_clear_password_reply_;
- // When it is set `true`, the parsing failure is expected to be translated by
- // proxy to status `STATUS_DBUS_ERROR`.
- bool shall_message_parsing_fail_ = false;
- private:
- // Handles calls to |proxy_|'s `CallMethod()`.
- void OnCallMethod(dbus::MethodCall* method_call,
- int timeout_ms,
- dbus::ObjectProxy::ResponseCallback* callback) {
- std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
- dbus::MessageWriter writer(response.get());
- if (shall_message_parsing_fail_) {
- // Append anything but a valid string that can be deserialized to any
- // protobuf messages that tpm manager could possibly sends. A numerical
- // type is chosen instead of a string in case the string can actually be
- // parsed into any ptotobuf message unexpectedly.
- writer.AppendUint32(0);
- } else if (method_call->GetMember() ==
- ::tpm_manager::kGetTpmNonsensitiveStatus) {
- writer.AppendProtoAsArrayOfBytes(expected_status_reply_);
- } else if (method_call->GetMember() == ::tpm_manager::kGetVersionInfo) {
- writer.AppendProtoAsArrayOfBytes(expected_version_info_reply_);
- } else if (method_call->GetMember() ==
- ::tpm_manager::kGetSupportedFeatures) {
- writer.AppendProtoAsArrayOfBytes(expected_supported_features_reply_);
- } else if (method_call->GetMember() ==
- ::tpm_manager::kGetDictionaryAttackInfo) {
- writer.AppendProtoAsArrayOfBytes(expected_get_da_info_reply_);
- } else if (method_call->GetMember() == ::tpm_manager::kTakeOwnership) {
- writer.AppendProtoAsArrayOfBytes(expected_take_ownership_reply_);
- } else if (method_call->GetMember() ==
- ::tpm_manager::kClearStoredOwnerPassword) {
- writer.AppendProtoAsArrayOfBytes(expected_clear_password_reply_);
- } else {
- ASSERT_FALSE(true) << "Unrecognized member: " << method_call->GetMember();
- }
- task_environment_.GetMainThreadTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(RunResponseCallback, std::move(*callback),
- std::move(response)));
- }
- dbus::ObjectProxy::SignalCallback ownership_taken_signal_callback_;
- };
- TEST_F(TpmManagerClientTest, GetTpmNonsensitiveStatus) {
- expected_status_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
- expected_status_reply_.set_is_owned(true);
- expected_status_reply_.set_is_enabled(true);
- ::tpm_manager::GetTpmNonsensitiveStatusReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetTpmNonsensitiveStatusReply* result_reply,
- const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetTpmNonsensitiveStatus(
- ::tpm_manager::GetTpmNonsensitiveStatusRequest(), std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_status_reply_.status(), result_reply.status());
- EXPECT_EQ(expected_status_reply_.is_owned(), result_reply.is_owned());
- EXPECT_EQ(expected_status_reply_.is_enabled(), result_reply.is_enabled());
- }
- TEST_F(TpmManagerClientTest, GetTpmNonsensitiveStatusDBusFailure) {
- shall_message_parsing_fail_ = true;
- ::tpm_manager::GetTpmNonsensitiveStatusReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetTpmNonsensitiveStatusReply* result_reply,
- const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetTpmNonsensitiveStatus(
- ::tpm_manager::GetTpmNonsensitiveStatusRequest(), std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
- }
- TEST_F(TpmManagerClientTest, GetVersionInfo) {
- expected_version_info_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
- expected_version_info_reply_.set_tpm_model(123);
- expected_version_info_reply_.set_family(456);
- ::tpm_manager::GetVersionInfoReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetVersionInfoReply* result_reply,
- const ::tpm_manager::GetVersionInfoReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetVersionInfo(::tpm_manager::GetVersionInfoRequest(),
- std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_version_info_reply_.status(), result_reply.status());
- EXPECT_EQ(expected_version_info_reply_.family(), result_reply.family());
- EXPECT_EQ(expected_version_info_reply_.tpm_model(), result_reply.tpm_model());
- }
- TEST_F(TpmManagerClientTest, GetVersionInfoDBusFailure) {
- shall_message_parsing_fail_ = true;
- ::tpm_manager::GetVersionInfoReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetVersionInfoReply* result_reply,
- const ::tpm_manager::GetVersionInfoReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetVersionInfo(::tpm_manager::GetVersionInfoRequest(),
- std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
- }
- TEST_F(TpmManagerClientTest, GetSupportedFeatures) {
- expected_supported_features_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
- expected_supported_features_reply_.set_support_u2f(true);
- ::tpm_manager::GetSupportedFeaturesReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetSupportedFeaturesReply* result_reply,
- const ::tpm_manager::GetSupportedFeaturesReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetSupportedFeatures(::tpm_manager::GetSupportedFeaturesRequest(),
- std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_supported_features_reply_.status(), result_reply.status());
- EXPECT_EQ(expected_supported_features_reply_.support_u2f(),
- result_reply.support_u2f());
- }
- TEST_F(TpmManagerClientTest, GetSupportedFeaturesDBusFailure) {
- shall_message_parsing_fail_ = true;
- ::tpm_manager::GetSupportedFeaturesReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetSupportedFeaturesReply* result_reply,
- const ::tpm_manager::GetSupportedFeaturesReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetSupportedFeatures(::tpm_manager::GetSupportedFeaturesRequest(),
- std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
- }
- TEST_F(TpmManagerClientTest, GetDictionaryAttackInfo) {
- expected_get_da_info_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
- expected_get_da_info_reply_.set_dictionary_attack_counter(123);
- expected_get_da_info_reply_.set_dictionary_attack_lockout_in_effect(true);
- ::tpm_manager::GetDictionaryAttackInfoReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetDictionaryAttackInfoReply* result_reply,
- const ::tpm_manager::GetDictionaryAttackInfoReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetDictionaryAttackInfo(
- ::tpm_manager::GetDictionaryAttackInfoRequest(), std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_get_da_info_reply_.status(), result_reply.status());
- EXPECT_EQ(expected_get_da_info_reply_.dictionary_attack_counter(),
- result_reply.dictionary_attack_counter());
- EXPECT_EQ(expected_get_da_info_reply_.dictionary_attack_lockout_in_effect(),
- result_reply.dictionary_attack_lockout_in_effect());
- }
- TEST_F(TpmManagerClientTest, GetDictionaryAttackInfoDBusFailure) {
- shall_message_parsing_fail_ = true;
- ::tpm_manager::GetDictionaryAttackInfoReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::GetDictionaryAttackInfoReply* result_reply,
- const ::tpm_manager::GetDictionaryAttackInfoReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->GetDictionaryAttackInfo(
- ::tpm_manager::GetDictionaryAttackInfoRequest(), std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
- }
- TEST_F(TpmManagerClientTest, TakeOwnership) {
- // Use a non-zero status value to make sure the value is correctly set.
- expected_take_ownership_reply_.set_status(::tpm_manager::STATUS_DEVICE_ERROR);
- ::tpm_manager::TakeOwnershipReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::TakeOwnershipReply* result_reply,
- const ::tpm_manager::TakeOwnershipReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->TakeOwnership(::tpm_manager::TakeOwnershipRequest(),
- std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_take_ownership_reply_.status(), result_reply.status());
- }
- TEST_F(TpmManagerClientTest, TakeOwnershipDBusFailure) {
- shall_message_parsing_fail_ = true;
- ::tpm_manager::TakeOwnershipReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::TakeOwnershipReply* result_reply,
- const ::tpm_manager::TakeOwnershipReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->TakeOwnership(::tpm_manager::TakeOwnershipRequest(),
- std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
- }
- TEST_F(TpmManagerClientTest, ClearStoredOwnerPassword) {
- // Use a non-zero status value to make sure the value is correctly set.
- expected_clear_password_reply_.set_status(::tpm_manager::STATUS_DEVICE_ERROR);
- ::tpm_manager::ClearStoredOwnerPasswordReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::ClearStoredOwnerPasswordReply* result_reply,
- const ::tpm_manager::ClearStoredOwnerPasswordReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->ClearStoredOwnerPassword(
- ::tpm_manager::ClearStoredOwnerPasswordRequest(), std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_clear_password_reply_.status(), result_reply.status());
- }
- TEST_F(TpmManagerClientTest, OnwershipTakenSignal) {
- TestObserver observer;
- ASSERT_EQ(observer.signal_count(), 0);
- client_->AddObserver(&observer);
- EmitOwnershipTakenSignal();
- EXPECT_EQ(observer.signal_count(), 1);
- client_->RemoveObserver(&observer);
- EmitOwnershipTakenSignal();
- EXPECT_EQ(observer.signal_count(), 1);
- }
- TEST_F(TpmManagerClientTest, ClearStoredOwnerPasswordDBusFailure) {
- shall_message_parsing_fail_ = true;
- ::tpm_manager::ClearStoredOwnerPasswordReply result_reply;
- auto callback = base::BindOnce(
- [](::tpm_manager::ClearStoredOwnerPasswordReply* result_reply,
- const ::tpm_manager::ClearStoredOwnerPasswordReply& reply) {
- *result_reply = reply;
- },
- &result_reply);
- client_->ClearStoredOwnerPassword(
- ::tpm_manager::ClearStoredOwnerPasswordRequest(), std::move(callback));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
- }
- } // namespace chromeos
|