tpm_manager_client_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/test/task_environment.h"
  8. #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
  9. #include "dbus/mock_bus.h"
  10. #include "dbus/mock_object_proxy.h"
  11. #include "dbus/object_path.h"
  12. #include "dbus/object_proxy.h"
  13. #include "testing/gmock/include/gmock/gmock.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #include "third_party/cros_system_api/dbus/tpm_manager/dbus-constants.h"
  16. using ::testing::_;
  17. using ::testing::Invoke;
  18. using ::testing::Return;
  19. using ::testing::SaveArg;
  20. namespace chromeos {
  21. namespace {
  22. // Runs |callback| with |response|. Needed due to ResponseCallback expecting a
  23. // bare pointer rather than an std::unique_ptr.
  24. void RunResponseCallback(dbus::ObjectProxy::ResponseCallback callback,
  25. std::unique_ptr<dbus::Response> response) {
  26. std::move(callback).Run(response.get());
  27. }
  28. // The observer class used for testing to watch the invocation of the signal
  29. // callbacks.
  30. class TestObserver : public TpmManagerClient::Observer {
  31. public:
  32. // TpmManagerClient::Observer.
  33. void OnOwnershipTaken() override { ++signal_count_; }
  34. int signal_count() const { return signal_count_; }
  35. private:
  36. int signal_count_ = 0;
  37. };
  38. } // namespace
  39. class TpmManagerClientTest : public testing::Test {
  40. public:
  41. TpmManagerClientTest() = default;
  42. ~TpmManagerClientTest() override = default;
  43. void SetUp() override {
  44. dbus::Bus::Options options;
  45. options.bus_type = dbus::Bus::SYSTEM;
  46. bus_ = new dbus::MockBus(options);
  47. dbus::ObjectPath tpm_manager_object_path =
  48. dbus::ObjectPath(::tpm_manager::kTpmManagerServicePath);
  49. proxy_ = new dbus::MockObjectProxy(bus_.get(),
  50. ::tpm_manager::kTpmManagerServiceName,
  51. tpm_manager_object_path);
  52. // Makes sure `GetObjectProxy()` is caled with the correct service name and
  53. // path.
  54. EXPECT_CALL(*bus_.get(),
  55. GetObjectProxy(::tpm_manager::kTpmManagerServiceName,
  56. tpm_manager_object_path))
  57. .WillRepeatedly(Return(proxy_.get()));
  58. EXPECT_CALL(*proxy_.get(), DoCallMethod(_, _, _))
  59. .WillRepeatedly(Invoke(this, &TpmManagerClientTest::OnCallMethod));
  60. EXPECT_CALL(*proxy_,
  61. DoConnectToSignal(::tpm_manager::kTpmManagerInterface,
  62. ::tpm_manager::kOwnershipTakenSignal, _, _))
  63. .WillOnce(SaveArg<2>(&ownership_taken_signal_callback_));
  64. TpmManagerClient::Initialize(bus_.get());
  65. // Execute callbacks posted by `client_->Init()`.
  66. base::RunLoop().RunUntilIdle();
  67. ASSERT_FALSE(ownership_taken_signal_callback_.is_null());
  68. client_ = TpmManagerClient::Get();
  69. }
  70. void TearDown() override { TpmManagerClient::Shutdown(); }
  71. protected:
  72. void EmitOwnershipTakenSignal() {
  73. ::tpm_manager::OwnershipTakenSignal ownership_taken_signal;
  74. dbus::Signal signal(::tpm_manager::kTpmManagerInterface,
  75. ::tpm_manager::kOwnershipTakenSignal);
  76. dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(
  77. ownership_taken_signal);
  78. // Emit signal.
  79. ASSERT_FALSE(ownership_taken_signal_callback_.is_null());
  80. ownership_taken_signal_callback_.Run(&signal);
  81. }
  82. base::test::SingleThreadTaskEnvironment task_environment_;
  83. // Mock bus and proxy for simulating calls.
  84. scoped_refptr<dbus::MockBus> bus_;
  85. scoped_refptr<dbus::MockObjectProxy> proxy_;
  86. // Convenience pointer to the global instance.
  87. TpmManagerClient* client_;
  88. // The expected replies to the respective D-Bus calls.
  89. ::tpm_manager::GetTpmNonsensitiveStatusReply expected_status_reply_;
  90. ::tpm_manager::GetVersionInfoReply expected_version_info_reply_;
  91. ::tpm_manager::GetSupportedFeaturesReply expected_supported_features_reply_;
  92. ::tpm_manager::GetDictionaryAttackInfoReply expected_get_da_info_reply_;
  93. ::tpm_manager::TakeOwnershipReply expected_take_ownership_reply_;
  94. ::tpm_manager::ClearStoredOwnerPasswordReply expected_clear_password_reply_;
  95. // When it is set `true`, the parsing failure is expected to be translated by
  96. // proxy to status `STATUS_DBUS_ERROR`.
  97. bool shall_message_parsing_fail_ = false;
  98. private:
  99. // Handles calls to |proxy_|'s `CallMethod()`.
  100. void OnCallMethod(dbus::MethodCall* method_call,
  101. int timeout_ms,
  102. dbus::ObjectProxy::ResponseCallback* callback) {
  103. std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
  104. dbus::MessageWriter writer(response.get());
  105. if (shall_message_parsing_fail_) {
  106. // Append anything but a valid string that can be deserialized to any
  107. // protobuf messages that tpm manager could possibly sends. A numerical
  108. // type is chosen instead of a string in case the string can actually be
  109. // parsed into any ptotobuf message unexpectedly.
  110. writer.AppendUint32(0);
  111. } else if (method_call->GetMember() ==
  112. ::tpm_manager::kGetTpmNonsensitiveStatus) {
  113. writer.AppendProtoAsArrayOfBytes(expected_status_reply_);
  114. } else if (method_call->GetMember() == ::tpm_manager::kGetVersionInfo) {
  115. writer.AppendProtoAsArrayOfBytes(expected_version_info_reply_);
  116. } else if (method_call->GetMember() ==
  117. ::tpm_manager::kGetSupportedFeatures) {
  118. writer.AppendProtoAsArrayOfBytes(expected_supported_features_reply_);
  119. } else if (method_call->GetMember() ==
  120. ::tpm_manager::kGetDictionaryAttackInfo) {
  121. writer.AppendProtoAsArrayOfBytes(expected_get_da_info_reply_);
  122. } else if (method_call->GetMember() == ::tpm_manager::kTakeOwnership) {
  123. writer.AppendProtoAsArrayOfBytes(expected_take_ownership_reply_);
  124. } else if (method_call->GetMember() ==
  125. ::tpm_manager::kClearStoredOwnerPassword) {
  126. writer.AppendProtoAsArrayOfBytes(expected_clear_password_reply_);
  127. } else {
  128. ASSERT_FALSE(true) << "Unrecognized member: " << method_call->GetMember();
  129. }
  130. task_environment_.GetMainThreadTaskRunner()->PostTask(
  131. FROM_HERE, base::BindOnce(RunResponseCallback, std::move(*callback),
  132. std::move(response)));
  133. }
  134. dbus::ObjectProxy::SignalCallback ownership_taken_signal_callback_;
  135. };
  136. TEST_F(TpmManagerClientTest, GetTpmNonsensitiveStatus) {
  137. expected_status_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
  138. expected_status_reply_.set_is_owned(true);
  139. expected_status_reply_.set_is_enabled(true);
  140. ::tpm_manager::GetTpmNonsensitiveStatusReply result_reply;
  141. auto callback = base::BindOnce(
  142. [](::tpm_manager::GetTpmNonsensitiveStatusReply* result_reply,
  143. const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply) {
  144. *result_reply = reply;
  145. },
  146. &result_reply);
  147. client_->GetTpmNonsensitiveStatus(
  148. ::tpm_manager::GetTpmNonsensitiveStatusRequest(), std::move(callback));
  149. base::RunLoop().RunUntilIdle();
  150. EXPECT_EQ(expected_status_reply_.status(), result_reply.status());
  151. EXPECT_EQ(expected_status_reply_.is_owned(), result_reply.is_owned());
  152. EXPECT_EQ(expected_status_reply_.is_enabled(), result_reply.is_enabled());
  153. }
  154. TEST_F(TpmManagerClientTest, GetTpmNonsensitiveStatusDBusFailure) {
  155. shall_message_parsing_fail_ = true;
  156. ::tpm_manager::GetTpmNonsensitiveStatusReply result_reply;
  157. auto callback = base::BindOnce(
  158. [](::tpm_manager::GetTpmNonsensitiveStatusReply* result_reply,
  159. const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply) {
  160. *result_reply = reply;
  161. },
  162. &result_reply);
  163. client_->GetTpmNonsensitiveStatus(
  164. ::tpm_manager::GetTpmNonsensitiveStatusRequest(), std::move(callback));
  165. base::RunLoop().RunUntilIdle();
  166. EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
  167. }
  168. TEST_F(TpmManagerClientTest, GetVersionInfo) {
  169. expected_version_info_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
  170. expected_version_info_reply_.set_tpm_model(123);
  171. expected_version_info_reply_.set_family(456);
  172. ::tpm_manager::GetVersionInfoReply result_reply;
  173. auto callback = base::BindOnce(
  174. [](::tpm_manager::GetVersionInfoReply* result_reply,
  175. const ::tpm_manager::GetVersionInfoReply& reply) {
  176. *result_reply = reply;
  177. },
  178. &result_reply);
  179. client_->GetVersionInfo(::tpm_manager::GetVersionInfoRequest(),
  180. std::move(callback));
  181. base::RunLoop().RunUntilIdle();
  182. EXPECT_EQ(expected_version_info_reply_.status(), result_reply.status());
  183. EXPECT_EQ(expected_version_info_reply_.family(), result_reply.family());
  184. EXPECT_EQ(expected_version_info_reply_.tpm_model(), result_reply.tpm_model());
  185. }
  186. TEST_F(TpmManagerClientTest, GetVersionInfoDBusFailure) {
  187. shall_message_parsing_fail_ = true;
  188. ::tpm_manager::GetVersionInfoReply result_reply;
  189. auto callback = base::BindOnce(
  190. [](::tpm_manager::GetVersionInfoReply* result_reply,
  191. const ::tpm_manager::GetVersionInfoReply& reply) {
  192. *result_reply = reply;
  193. },
  194. &result_reply);
  195. client_->GetVersionInfo(::tpm_manager::GetVersionInfoRequest(),
  196. std::move(callback));
  197. base::RunLoop().RunUntilIdle();
  198. EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
  199. }
  200. TEST_F(TpmManagerClientTest, GetSupportedFeatures) {
  201. expected_supported_features_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
  202. expected_supported_features_reply_.set_support_u2f(true);
  203. ::tpm_manager::GetSupportedFeaturesReply result_reply;
  204. auto callback = base::BindOnce(
  205. [](::tpm_manager::GetSupportedFeaturesReply* result_reply,
  206. const ::tpm_manager::GetSupportedFeaturesReply& reply) {
  207. *result_reply = reply;
  208. },
  209. &result_reply);
  210. client_->GetSupportedFeatures(::tpm_manager::GetSupportedFeaturesRequest(),
  211. std::move(callback));
  212. base::RunLoop().RunUntilIdle();
  213. EXPECT_EQ(expected_supported_features_reply_.status(), result_reply.status());
  214. EXPECT_EQ(expected_supported_features_reply_.support_u2f(),
  215. result_reply.support_u2f());
  216. }
  217. TEST_F(TpmManagerClientTest, GetSupportedFeaturesDBusFailure) {
  218. shall_message_parsing_fail_ = true;
  219. ::tpm_manager::GetSupportedFeaturesReply result_reply;
  220. auto callback = base::BindOnce(
  221. [](::tpm_manager::GetSupportedFeaturesReply* result_reply,
  222. const ::tpm_manager::GetSupportedFeaturesReply& reply) {
  223. *result_reply = reply;
  224. },
  225. &result_reply);
  226. client_->GetSupportedFeatures(::tpm_manager::GetSupportedFeaturesRequest(),
  227. std::move(callback));
  228. base::RunLoop().RunUntilIdle();
  229. EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
  230. }
  231. TEST_F(TpmManagerClientTest, GetDictionaryAttackInfo) {
  232. expected_get_da_info_reply_.set_status(::tpm_manager::STATUS_SUCCESS);
  233. expected_get_da_info_reply_.set_dictionary_attack_counter(123);
  234. expected_get_da_info_reply_.set_dictionary_attack_lockout_in_effect(true);
  235. ::tpm_manager::GetDictionaryAttackInfoReply result_reply;
  236. auto callback = base::BindOnce(
  237. [](::tpm_manager::GetDictionaryAttackInfoReply* result_reply,
  238. const ::tpm_manager::GetDictionaryAttackInfoReply& reply) {
  239. *result_reply = reply;
  240. },
  241. &result_reply);
  242. client_->GetDictionaryAttackInfo(
  243. ::tpm_manager::GetDictionaryAttackInfoRequest(), std::move(callback));
  244. base::RunLoop().RunUntilIdle();
  245. EXPECT_EQ(expected_get_da_info_reply_.status(), result_reply.status());
  246. EXPECT_EQ(expected_get_da_info_reply_.dictionary_attack_counter(),
  247. result_reply.dictionary_attack_counter());
  248. EXPECT_EQ(expected_get_da_info_reply_.dictionary_attack_lockout_in_effect(),
  249. result_reply.dictionary_attack_lockout_in_effect());
  250. }
  251. TEST_F(TpmManagerClientTest, GetDictionaryAttackInfoDBusFailure) {
  252. shall_message_parsing_fail_ = true;
  253. ::tpm_manager::GetDictionaryAttackInfoReply result_reply;
  254. auto callback = base::BindOnce(
  255. [](::tpm_manager::GetDictionaryAttackInfoReply* result_reply,
  256. const ::tpm_manager::GetDictionaryAttackInfoReply& reply) {
  257. *result_reply = reply;
  258. },
  259. &result_reply);
  260. client_->GetDictionaryAttackInfo(
  261. ::tpm_manager::GetDictionaryAttackInfoRequest(), std::move(callback));
  262. base::RunLoop().RunUntilIdle();
  263. EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
  264. }
  265. TEST_F(TpmManagerClientTest, TakeOwnership) {
  266. // Use a non-zero status value to make sure the value is correctly set.
  267. expected_take_ownership_reply_.set_status(::tpm_manager::STATUS_DEVICE_ERROR);
  268. ::tpm_manager::TakeOwnershipReply result_reply;
  269. auto callback = base::BindOnce(
  270. [](::tpm_manager::TakeOwnershipReply* result_reply,
  271. const ::tpm_manager::TakeOwnershipReply& reply) {
  272. *result_reply = reply;
  273. },
  274. &result_reply);
  275. client_->TakeOwnership(::tpm_manager::TakeOwnershipRequest(),
  276. std::move(callback));
  277. base::RunLoop().RunUntilIdle();
  278. EXPECT_EQ(expected_take_ownership_reply_.status(), result_reply.status());
  279. }
  280. TEST_F(TpmManagerClientTest, TakeOwnershipDBusFailure) {
  281. shall_message_parsing_fail_ = true;
  282. ::tpm_manager::TakeOwnershipReply result_reply;
  283. auto callback = base::BindOnce(
  284. [](::tpm_manager::TakeOwnershipReply* result_reply,
  285. const ::tpm_manager::TakeOwnershipReply& reply) {
  286. *result_reply = reply;
  287. },
  288. &result_reply);
  289. client_->TakeOwnership(::tpm_manager::TakeOwnershipRequest(),
  290. std::move(callback));
  291. base::RunLoop().RunUntilIdle();
  292. EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
  293. }
  294. TEST_F(TpmManagerClientTest, ClearStoredOwnerPassword) {
  295. // Use a non-zero status value to make sure the value is correctly set.
  296. expected_clear_password_reply_.set_status(::tpm_manager::STATUS_DEVICE_ERROR);
  297. ::tpm_manager::ClearStoredOwnerPasswordReply result_reply;
  298. auto callback = base::BindOnce(
  299. [](::tpm_manager::ClearStoredOwnerPasswordReply* result_reply,
  300. const ::tpm_manager::ClearStoredOwnerPasswordReply& reply) {
  301. *result_reply = reply;
  302. },
  303. &result_reply);
  304. client_->ClearStoredOwnerPassword(
  305. ::tpm_manager::ClearStoredOwnerPasswordRequest(), std::move(callback));
  306. base::RunLoop().RunUntilIdle();
  307. EXPECT_EQ(expected_clear_password_reply_.status(), result_reply.status());
  308. }
  309. TEST_F(TpmManagerClientTest, OnwershipTakenSignal) {
  310. TestObserver observer;
  311. ASSERT_EQ(observer.signal_count(), 0);
  312. client_->AddObserver(&observer);
  313. EmitOwnershipTakenSignal();
  314. EXPECT_EQ(observer.signal_count(), 1);
  315. client_->RemoveObserver(&observer);
  316. EmitOwnershipTakenSignal();
  317. EXPECT_EQ(observer.signal_count(), 1);
  318. }
  319. TEST_F(TpmManagerClientTest, ClearStoredOwnerPasswordDBusFailure) {
  320. shall_message_parsing_fail_ = true;
  321. ::tpm_manager::ClearStoredOwnerPasswordReply result_reply;
  322. auto callback = base::BindOnce(
  323. [](::tpm_manager::ClearStoredOwnerPasswordReply* result_reply,
  324. const ::tpm_manager::ClearStoredOwnerPasswordReply& reply) {
  325. *result_reply = reply;
  326. },
  327. &result_reply);
  328. client_->ClearStoredOwnerPassword(
  329. ::tpm_manager::ClearStoredOwnerPasswordRequest(), std::move(callback));
  330. base::RunLoop().RunUntilIdle();
  331. EXPECT_EQ(::tpm_manager::STATUS_DBUS_ERROR, result_reply.status());
  332. }
  333. } // namespace chromeos