tpm_manager_client.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 <utility>
  6. #include <google/protobuf/message_lite.h>
  7. #include "base/bind.h"
  8. #include "base/check_op.h"
  9. #include "base/command_line.h"
  10. #include "base/location.h"
  11. #include "base/logging.h"
  12. #include "base/memory/raw_ptr.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/observer_list.h"
  15. #include "base/threading/thread_task_runner_handle.h"
  16. #include "base/time/time.h"
  17. #include "chromeos/dbus/constants/dbus_switches.h"
  18. #include "chromeos/dbus/tpm_manager/fake_tpm_manager_client.h"
  19. #include "dbus/bus.h"
  20. #include "dbus/message.h"
  21. #include "dbus/object_path.h"
  22. #include "dbus/object_proxy.h"
  23. #include "third_party/cros_system_api/dbus/tpm_manager/dbus-constants.h"
  24. namespace chromeos {
  25. namespace {
  26. // An arbitrary timeout for taking ownership.
  27. constexpr base::TimeDelta kTakeOwnershipTimeout = base::Seconds(80);
  28. TpmManagerClient* g_instance = nullptr;
  29. // Tries to parse a proto message from |response| into |proto|.
  30. // Returns false if |response| is nullptr or the message cannot be parsed.
  31. bool ParseProto(dbus::Response* response,
  32. google::protobuf::MessageLite* proto) {
  33. if (!response) {
  34. LOG(ERROR) << "Failed to call tpm_managerd";
  35. return false;
  36. }
  37. dbus::MessageReader reader(response);
  38. if (!reader.PopArrayOfBytesAsProto(proto)) {
  39. LOG(ERROR) << "Failed to parse response message from tpm_managerd";
  40. return false;
  41. }
  42. return true;
  43. }
  44. void OnSignalConnected(const std::string& interface_name,
  45. const std::string& signal_name,
  46. bool success) {
  47. DCHECK_EQ(interface_name, ::tpm_manager::kTpmManagerInterface);
  48. LOG_IF(DFATAL, !success) << "Failed to connect to D-Bus signal; interface: "
  49. << interface_name << "; signal: " << signal_name;
  50. }
  51. // "Real" implementation of TpmManagerClient talking to the TpmManager daemon
  52. // on the Chrome OS side.
  53. class TpmManagerClientImpl : public TpmManagerClient {
  54. public:
  55. TpmManagerClientImpl() = default;
  56. ~TpmManagerClientImpl() override = default;
  57. // Not copyable or movable.
  58. TpmManagerClientImpl(const TpmManagerClientImpl&) = delete;
  59. TpmManagerClientImpl& operator=(const TpmManagerClientImpl&) = delete;
  60. TpmManagerClientImpl(TpmManagerClientImpl&&) = delete;
  61. TpmManagerClientImpl& operator=(TpmManagerClientImpl&&) = delete;
  62. // TpmManagerClient overrides:
  63. void GetTpmNonsensitiveStatus(
  64. const ::tpm_manager::GetTpmNonsensitiveStatusRequest& request,
  65. GetTpmNonsensitiveStatusCallback callback) override {
  66. CallProtoMethod(::tpm_manager::kGetTpmNonsensitiveStatus, request,
  67. std::move(callback));
  68. }
  69. void GetVersionInfo(const ::tpm_manager::GetVersionInfoRequest& request,
  70. GetVersionInfoCallback callback) override {
  71. CallProtoMethod(::tpm_manager::kGetVersionInfo, request,
  72. std::move(callback));
  73. }
  74. void GetSupportedFeatures(
  75. const ::tpm_manager::GetSupportedFeaturesRequest& request,
  76. GetSupportedFeaturesCallback callback) override {
  77. CallProtoMethod(::tpm_manager::kGetSupportedFeatures, request,
  78. std::move(callback));
  79. }
  80. void GetDictionaryAttackInfo(
  81. const ::tpm_manager::GetDictionaryAttackInfoRequest& request,
  82. GetDictionaryAttackInfoCallback callback) override {
  83. CallProtoMethod(::tpm_manager::kGetDictionaryAttackInfo, request,
  84. std::move(callback));
  85. }
  86. void TakeOwnership(const ::tpm_manager::TakeOwnershipRequest& request,
  87. TakeOwnershipCallback callback) override {
  88. // Use a longer timeout for TPM ownership operation.
  89. CallProtoMethodWithTimeout(::tpm_manager::kTakeOwnership,
  90. kTakeOwnershipTimeout.InMilliseconds(), request,
  91. std::move(callback));
  92. }
  93. void ClearStoredOwnerPassword(
  94. const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
  95. ClearStoredOwnerPasswordCallback callback) override {
  96. CallProtoMethod(::tpm_manager::kClearStoredOwnerPassword, request,
  97. std::move(callback));
  98. }
  99. void AddObserver(Observer* observer) override {
  100. observer_list_.AddObserver(observer);
  101. }
  102. void RemoveObserver(Observer* observer) override {
  103. observer_list_.RemoveObserver(observer);
  104. }
  105. void Init(dbus::Bus* bus) {
  106. proxy_ = bus->GetObjectProxy(
  107. ::tpm_manager::kTpmManagerServiceName,
  108. dbus::ObjectPath(::tpm_manager::kTpmManagerServicePath));
  109. ConnectToOwnershipTakenSignal();
  110. }
  111. private:
  112. TestInterface* GetTestInterface() override { return nullptr; }
  113. // Calls tpm_managerd's |method_name| method, passing in |request| as input
  114. // with |timeout_ms|. Once the (asynchronous) call finishes, |callback| is
  115. // called with the response proto.
  116. template <typename RequestType, typename ReplyType>
  117. void CallProtoMethodWithTimeout(
  118. const char* method_name,
  119. int timeout_ms,
  120. const RequestType& request,
  121. base::OnceCallback<void(const ReplyType&)> callback) {
  122. dbus::MethodCall method_call(::tpm_manager::kTpmManagerInterface,
  123. method_name);
  124. dbus::MessageWriter writer(&method_call);
  125. if (!writer.AppendProtoAsArrayOfBytes(request)) {
  126. ReplyType reply;
  127. reply.set_status(::tpm_manager::STATUS_DBUS_ERROR);
  128. base::ThreadTaskRunnerHandle::Get()->PostTask(
  129. FROM_HERE, base::BindOnce(std::move(callback), reply));
  130. return;
  131. }
  132. // Bind with the weak pointer of |this| so the response is not
  133. // handled once |this| is already destroyed.
  134. proxy_->CallMethod(
  135. &method_call, timeout_ms,
  136. base::BindOnce(&TpmManagerClientImpl::HandleResponse<ReplyType>,
  137. weak_factory_.GetWeakPtr(), std::move(callback)));
  138. }
  139. // Calls tpm_managerd's |method_name| method, passing in |request| as input
  140. // with the default timeout. Once the (asynchronous) call finishes, |callback|
  141. // is called with the response proto.
  142. template <typename RequestType, typename ReplyType>
  143. void CallProtoMethod(const char* method_name,
  144. const RequestType& request,
  145. base::OnceCallback<void(const ReplyType&)> callback) {
  146. CallProtoMethodWithTimeout(method_name,
  147. dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, request,
  148. std::move(callback));
  149. }
  150. // Parses the response proto message from |response| and calls |callback| with
  151. // the decoded message. Calls |callback| with an |STATUS_DBUS_ERROR| message
  152. // on error, including timeout.
  153. template <typename ReplyType>
  154. void HandleResponse(base::OnceCallback<void(const ReplyType&)> callback,
  155. dbus::Response* response) {
  156. ReplyType reply_proto;
  157. if (!ParseProto(response, &reply_proto))
  158. reply_proto.set_status(::tpm_manager::STATUS_DBUS_ERROR);
  159. std::move(callback).Run(reply_proto);
  160. }
  161. // Called when receiving ownership taken signal.
  162. void OnOwnershipTakenSignal(dbus::Signal*) {
  163. for (auto& observer : observer_list_) {
  164. observer.OnOwnershipTaken();
  165. }
  166. }
  167. // Connects to ownership taken signal.
  168. void ConnectToOwnershipTakenSignal() {
  169. proxy_->ConnectToSignal(
  170. ::tpm_manager::kTpmManagerInterface,
  171. ::tpm_manager::kOwnershipTakenSignal,
  172. base::BindRepeating(&TpmManagerClientImpl::OnOwnershipTakenSignal,
  173. weak_factory_.GetWeakPtr()),
  174. base::BindOnce(&OnSignalConnected));
  175. }
  176. // D-Bus proxy for the TpmManager daemon, not owned.
  177. raw_ptr<dbus::ObjectProxy> proxy_ = nullptr;
  178. // The observer list of ownership taken signal.
  179. base::ObserverList<Observer> observer_list_;
  180. base::WeakPtrFactory<TpmManagerClientImpl> weak_factory_{this};
  181. };
  182. } // namespace
  183. TpmManagerClient::TpmManagerClient() {
  184. CHECK(!g_instance);
  185. g_instance = this;
  186. }
  187. TpmManagerClient::~TpmManagerClient() {
  188. CHECK_EQ(this, g_instance);
  189. g_instance = nullptr;
  190. }
  191. // static
  192. void TpmManagerClient::Initialize(dbus::Bus* bus) {
  193. CHECK(bus);
  194. (new TpmManagerClientImpl())->Init(bus);
  195. }
  196. // static
  197. void TpmManagerClient::InitializeFake() {
  198. // Do not create a new instance if it was initialized early in a browser test
  199. // (for early setup calls dependent on TpmManagerClient).
  200. if (!FakeTpmManagerClient::Get())
  201. new FakeTpmManagerClient();
  202. }
  203. // static
  204. void TpmManagerClient::Shutdown() {
  205. CHECK(g_instance);
  206. delete g_instance;
  207. // The destructor resets |g_instance|.
  208. DCHECK(!g_instance);
  209. }
  210. // static
  211. TpmManagerClient* TpmManagerClient::Get() {
  212. return g_instance;
  213. }
  214. } // namespace chromeos