• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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