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, dbus::ObjectPath(trunks::kTrunksServicePath));
53   origin_thread_id_ = base::PlatformThread::CurrentId();
54   return (object_proxy_ != nullptr);
55 }
56 
SendCommand(const std::string & command,const ResponseCallback & callback)57 void TrunksDBusProxy::SendCommand(const std::string& command,
58                                   const ResponseCallback& callback) {
59   if (origin_thread_id_ != base::PlatformThread::CurrentId()) {
60     LOG(ERROR) << "Error TrunksDBusProxy cannot be shared by multiple threads.";
61     callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
62   }
63   SendCommandRequest tpm_command_proto;
64   tpm_command_proto.set_command(command);
65   auto on_success = [callback](const SendCommandResponse& response) {
66     callback.Run(response.response());
67   };
68   auto on_error = [callback](brillo::Error* error) {
69     SendCommandResponse response;
70     response.set_response(CreateErrorResponse(SAPI_RC_NO_RESPONSE_RECEIVED));
71     callback.Run(response.response());
72   };
73   brillo::dbus_utils::CallMethodWithTimeout(
74       kDBusMaxTimeout, object_proxy_, trunks::kTrunksInterface,
75       trunks::kSendCommand, base::Bind(on_success), base::Bind(on_error),
76       tpm_command_proto);
77 }
78 
SendCommandAndWait(const std::string & command)79 std::string TrunksDBusProxy::SendCommandAndWait(const std::string& command) {
80   if (origin_thread_id_ != base::PlatformThread::CurrentId()) {
81     LOG(ERROR) << "Error TrunksDBusProxy cannot be shared by multiple threads.";
82     return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
83   }
84   SendCommandRequest tpm_command_proto;
85   tpm_command_proto.set_command(command);
86   brillo::ErrorPtr error;
87   std::unique_ptr<dbus::Response> dbus_response =
88       brillo::dbus_utils::CallMethodAndBlockWithTimeout(
89           kDBusMaxTimeout, object_proxy_, trunks::kTrunksInterface,
90           trunks::kSendCommand, &error, tpm_command_proto);
91   SendCommandResponse tpm_response_proto;
92   if (dbus_response.get() &&
93       brillo::dbus_utils::ExtractMethodCallResults(dbus_response.get(), &error,
94                                                    &tpm_response_proto)) {
95     return tpm_response_proto.response();
96   } else {
97     LOG(ERROR) << "TrunksProxy could not parse response: "
98                << error->GetMessage();
99     return CreateErrorResponse(SAPI_RC_MALFORMED_RESPONSE);
100   }
101 }
102 
103 }  // namespace trunks
104