1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "trunks/trunks_dbus_proxy.h"
18
19 #include <base/bind.h>
20 #include <brillo/bind_lambda.h>
21 #include <brillo/dbus/dbus_method_invoker.h>
22
23 #include "trunks/dbus_interface.h"
24 #include "trunks/error_codes.h"
25 #include "trunks/interface.pb.h"
26
27 namespace {
28
29 // Use a five minute timeout because some commands on some TPM hardware can take
30 // a very long time. If a few lengthy operations are already in the queue, a
31 // subsequent command needs to wait for all of them. Timeouts are always
32 // possible but under normal conditions 5 minutes seems to be plenty.
33 const int kDBusMaxTimeout = 5 * 60 * 1000;
34
35 } // namespace
36
37 namespace trunks {
38
TrunksDBusProxy()39 TrunksDBusProxy::TrunksDBusProxy() : weak_factory_(this) {}
40
~TrunksDBusProxy()41 TrunksDBusProxy::~TrunksDBusProxy() {
42 if (bus_) {
43 bus_->ShutdownAndBlock();
44 }
45 }
46
Init()47 bool TrunksDBusProxy::Init() {
48 dbus::Bus::Options options;
49 options.bus_type = dbus::Bus::SYSTEM;
50 bus_ = new dbus::Bus(options);
51 object_proxy_ = bus_->GetObjectProxy(
52 trunks::kTrunksServiceName,
53 dbus::ObjectPath(trunks::kTrunksServicePath));
54 origin_thread_id_ = base::PlatformThread::CurrentId();
55 return (object_proxy_ != nullptr);
56 }
57
SendCommand(const std::string & command,const ResponseCallback & callback)58 void TrunksDBusProxy::SendCommand(const std::string& command,
59 const ResponseCallback& callback) {
60 if (origin_thread_id_ != base::PlatformThread::CurrentId()) {
61 LOG(ERROR) << "Error TrunksDBusProxy cannot be shared by multiple threads.";
62 callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
63 }
64 SendCommandRequest tpm_command_proto;
65 tpm_command_proto.set_command(command);
66 auto on_success = [callback](const SendCommandResponse& response) {
67 callback.Run(response.response());
68 };
69 auto on_error = [callback](brillo::Error* error) {
70 SendCommandResponse response;
71 response.set_response(CreateErrorResponse(SAPI_RC_NO_RESPONSE_RECEIVED));
72 callback.Run(response.response());
73 };
74 brillo::dbus_utils::CallMethodWithTimeout(
75 kDBusMaxTimeout,
76 object_proxy_,
77 trunks::kTrunksInterface,
78 trunks::kSendCommand,
79 base::Bind(on_success),
80 base::Bind(on_error),
81 tpm_command_proto);
82 }
83
SendCommandAndWait(const std::string & command)84 std::string TrunksDBusProxy::SendCommandAndWait(const std::string& command) {
85 if (origin_thread_id_ != base::PlatformThread::CurrentId()) {
86 LOG(ERROR) << "Error TrunksDBusProxy cannot be shared by multiple threads.";
87 return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
88 }
89 SendCommandRequest tpm_command_proto;
90 tpm_command_proto.set_command(command);
91 brillo::ErrorPtr error;
92 std::unique_ptr<dbus::Response> dbus_response =
93 brillo::dbus_utils::CallMethodAndBlockWithTimeout(
94 kDBusMaxTimeout,
95 object_proxy_,
96 trunks::kTrunksInterface,
97 trunks::kSendCommand,
98 &error,
99 tpm_command_proto);
100 SendCommandResponse tpm_response_proto;
101 if (dbus_response.get() && brillo::dbus_utils::ExtractMethodCallResults(
102 dbus_response.get(), &error, &tpm_response_proto)) {
103 return tpm_response_proto.response();
104 } else {
105 LOG(ERROR) << "TrunksProxy could not parse response: "
106 << error->GetMessage();
107 return CreateErrorResponse(SAPI_RC_MALFORMED_RESPONSE);
108 }
109 }
110
111
112 } // namespace trunks
113