• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2015 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 <stdio.h>
18 #include <stdlib.h>
19 #include <sysexits.h>
20 
21 #include <memory>
22 #include <string>
23 
24 #include <base/command_line.h>
25 #include <base/logging.h>
26 #include <base/message_loop/message_loop.h>
27 #include <brillo/bind_lambda.h>
28 #include <brillo/daemons/daemon.h>
29 #include <brillo/syslog_logging.h>
30 
31 #include "tpm_manager/client/tpm_nvram_dbus_proxy.h"
32 #include "tpm_manager/client/tpm_ownership_dbus_proxy.h"
33 #include "tpm_manager/common/print_tpm_ownership_interface_proto.h"
34 #include "tpm_manager/common/print_tpm_nvram_interface_proto.h"
35 #include "tpm_manager/common/tpm_ownership_interface.pb.h"
36 #include "tpm_manager/common/tpm_nvram_interface.pb.h"
37 
38 namespace tpm_manager {
39 
40 const char kGetTpmStatusCommand[] = "status";
41 const char kTakeOwnershipCommand[] = "take_ownership";
42 const char kRemoveOwnerDependencyCommand[] = "remove_dependency";
43 const char kDefineNvramCommand[] = "define_nvram";
44 const char kDestroyNvramCommand[] = "destroy_nvram";
45 const char kWriteNvramCommand[] = "write_nvram";
46 const char kReadNvramCommand[] = "read_nvram";
47 const char kIsNvramDefinedCommand[] = "is_nvram_defined";
48 const char kIsNvramLockedCommand[] = "is_nvram_locked";
49 const char kGetNvramSizeCommand[] = "get_nvram_size";
50 
51 const char kNvramIndexArg[] = "nvram_index";
52 const char kNvramLengthArg[] = "nvram_length";
53 const char kNvramDataArg[] = "nvram_data";
54 
55 const char kUsage[] = R"(
56 Usage: tpm_manager_client <command> [<arguments>]
57 Commands (used as switches):
58   --status
59       Prints the current status of the Tpm.
60   --take_ownership
61       Takes ownership of the Tpm with a random password.
62   --remove_dependency=<owner_dependency>
63       Removes the provided Tpm owner dependency.
64   --define_nvram
65       Defines an NV space at |nvram_index| with length |nvram_length|.
66   --destroy_nvram
67       Destroys the NV space at |nvram_index|.
68   --write_nvram
69       Writes the NV space at |nvram_index| with |nvram_data|.
70   --read_nvram
71       Prints the contents of the NV space at |nvram_index|.
72   --is_nvram_defined
73       Prints whether the NV space at |nvram_index| is defined.
74   --is_nvram_locked
75       Prints whether the NV space at |nvram_index|  is locked for writing.
76   --get_nvram_size
77       Prints the size of the NV space at |nvram_index|.
78 Arguments (used as switches):
79   --nvram_index=<index>
80       Index of NV space to operate on.
81   --nvram_length=<length>
82       Size in bytes of the NV space to be created.
83   --nvram_data=<data>
84       Data to write to NV space.
85 )";
86 
87 using ClientLoopBase = brillo::Daemon;
88 class ClientLoop : public ClientLoopBase {
89  public:
90   ClientLoop() = default;
91   ~ClientLoop() override = default;
92 
93  protected:
OnInit()94   int OnInit() override {
95     int exit_code = ClientLoopBase::OnInit();
96     if (exit_code != EX_OK) {
97       LOG(ERROR) << "Error initializing tpm_manager_client.";
98       return exit_code;
99     }
100     TpmNvramDBusProxy* nvram_proxy = new TpmNvramDBusProxy();
101     if (!nvram_proxy->Initialize()) {
102       LOG(ERROR) << "Error initializing proxy to nvram interface.";
103       return EX_UNAVAILABLE;
104     }
105     TpmOwnershipDBusProxy* ownership_proxy = new TpmOwnershipDBusProxy();
106     if (!ownership_proxy->Initialize()) {
107       LOG(ERROR) << "Error initializing proxy to ownership interface.";
108       return EX_UNAVAILABLE;
109     }
110     tpm_nvram_.reset(nvram_proxy);
111     tpm_ownership_.reset(ownership_proxy);
112     exit_code = ScheduleCommand();
113     if (exit_code == EX_USAGE) {
114       printf("%s", kUsage);
115     }
116     return exit_code;
117   }
118 
OnShutdown(int * exit_code)119   void OnShutdown(int* exit_code) override {
120     tpm_nvram_.reset();
121     tpm_ownership_.reset();
122     ClientLoopBase::OnShutdown(exit_code);
123   }
124 
125  private:
126   // Posts tasks on to the message loop based on command line flags.
ScheduleCommand()127   int ScheduleCommand() {
128     base::Closure task;
129     base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
130     if (command_line->HasSwitch("help") || command_line->HasSwitch("h")) {
131       return EX_USAGE;
132     } else if (command_line->HasSwitch(kGetTpmStatusCommand)) {
133       task = base::Bind(&ClientLoop::HandleGetTpmStatus,
134                         weak_factory_.GetWeakPtr());
135     } else if (command_line->HasSwitch(kTakeOwnershipCommand)) {
136       task = base::Bind(&ClientLoop::HandleTakeOwnership,
137                         weak_factory_.GetWeakPtr());
138     } else if (command_line->HasSwitch(kRemoveOwnerDependencyCommand)) {
139       task = base::Bind(
140           &ClientLoop::HandleRemoveOwnerDependency,
141           weak_factory_.GetWeakPtr(),
142           command_line->GetSwitchValueASCII(kRemoveOwnerDependencyCommand));
143     } else if (command_line->HasSwitch(kDefineNvramCommand)) {
144       if (!command_line->HasSwitch(kNvramIndexArg) ||
145           !command_line->HasSwitch(kNvramLengthArg)) {
146         LOG(ERROR) << "Cannot define nvram without a valid index and length.";
147         return EX_USAGE;
148       }
149       task = base::Bind(
150           &ClientLoop::HandleDefineNvram,
151           weak_factory_.GetWeakPtr(),
152           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()),
153           atoi(command_line->GetSwitchValueASCII(kNvramLengthArg).c_str()));
154     } else if (command_line->HasSwitch(kDestroyNvramCommand)) {
155       if (!command_line->HasSwitch(kNvramIndexArg)) {
156         LOG(ERROR) << "Cannot destroy nvram without a valid index.";
157         return EX_USAGE;
158       }
159       task = base::Bind(
160           &ClientLoop::HandleDestroyNvram,
161           weak_factory_.GetWeakPtr(),
162           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
163     } else if (command_line->HasSwitch(kWriteNvramCommand)) {
164       if (!command_line->HasSwitch(kNvramIndexArg) ||
165           !command_line->HasSwitch(kNvramDataArg)) {
166         LOG(ERROR) << "Cannot write nvram without a valid index and data.";
167         return EX_USAGE;
168       }
169       task = base::Bind(
170           &ClientLoop::HandleWriteNvram,
171           weak_factory_.GetWeakPtr(),
172           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()),
173           command_line->GetSwitchValueASCII(kNvramDataArg));
174     } else if (command_line->HasSwitch(kReadNvramCommand)) {
175       if (!command_line->HasSwitch(kNvramIndexArg)) {
176         LOG(ERROR) << "Cannot read nvram without a valid index.";
177         return EX_USAGE;
178       }
179       task = base::Bind(
180           &ClientLoop::HandleReadNvram,
181           weak_factory_.GetWeakPtr(),
182           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
183     } else if (command_line->HasSwitch(kIsNvramDefinedCommand)) {
184       if (!command_line->HasSwitch(kNvramIndexArg)) {
185         LOG(ERROR) << "Cannot query nvram without a valid index.";
186         return EX_USAGE;
187       }
188       task = base::Bind(
189           &ClientLoop::HandleIsNvramDefined,
190           weak_factory_.GetWeakPtr(),
191           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
192     } else if (command_line->HasSwitch(kIsNvramLockedCommand)) {
193       if (!command_line->HasSwitch(kNvramIndexArg)) {
194         LOG(ERROR) << "Cannot query nvram without a valid index.";
195         return EX_USAGE;
196       }
197       task = base::Bind(
198           &ClientLoop::HandleIsNvramLocked,
199           weak_factory_.GetWeakPtr(),
200           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
201     } else if (command_line->HasSwitch(kGetNvramSizeCommand)) {
202       if (!command_line->HasSwitch(kNvramIndexArg)) {
203         LOG(ERROR) << "Cannot query nvram without a valid index.";
204         return EX_USAGE;
205       }
206       task = base::Bind(
207           &ClientLoop::HandleGetNvramSize,
208           weak_factory_.GetWeakPtr(),
209           atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
210     } else {
211       // Command line arguments did not match any valid commands.
212       LOG(ERROR) << "No Valid Command selected.";
213       return EX_USAGE;
214     }
215     base::MessageLoop::current()->PostTask(FROM_HERE, task);
216     return EX_OK;
217   }
218 
219   // Template to print reply protobuf.
220   template <typename ProtobufType>
PrintReplyAndQuit(const ProtobufType & reply)221   void PrintReplyAndQuit(const ProtobufType& reply) {
222     LOG(INFO) << "Message Reply: " << GetProtoDebugString(reply);
223     Quit();
224   }
225 
HandleGetTpmStatus()226   void HandleGetTpmStatus() {
227     GetTpmStatusRequest request;
228     tpm_ownership_->GetTpmStatus(
229         request,
230         base::Bind(&ClientLoop::PrintReplyAndQuit<GetTpmStatusReply>,
231                    weak_factory_.GetWeakPtr()));
232   }
233 
HandleTakeOwnership()234   void HandleTakeOwnership() {
235     TakeOwnershipRequest request;
236     tpm_ownership_->TakeOwnership(
237         request,
238         base::Bind(&ClientLoop::PrintReplyAndQuit<TakeOwnershipReply>,
239                    weak_factory_.GetWeakPtr()));
240   }
241 
HandleRemoveOwnerDependency(const std::string & owner_dependency)242   void HandleRemoveOwnerDependency(const std::string& owner_dependency) {
243     RemoveOwnerDependencyRequest request;
244     request.set_owner_dependency(owner_dependency);
245     tpm_ownership_->RemoveOwnerDependency(
246         request,
247         base::Bind(&ClientLoop::PrintReplyAndQuit<RemoveOwnerDependencyReply>,
248                    weak_factory_.GetWeakPtr()));
249   }
250 
HandleDefineNvram(uint32_t index,size_t length)251   void HandleDefineNvram(uint32_t index, size_t length) {
252     DefineNvramRequest request;
253     request.set_index(index);
254     request.set_length(length);
255     tpm_nvram_->DefineNvram(
256         request,
257         base::Bind(&ClientLoop::PrintReplyAndQuit<DefineNvramReply>,
258                    weak_factory_.GetWeakPtr()));
259   }
260 
HandleDestroyNvram(uint32_t index)261   void HandleDestroyNvram(uint32_t index) {
262     DestroyNvramRequest request;
263     request.set_index(index);
264     tpm_nvram_->DestroyNvram(
265         request,
266         base::Bind(&ClientLoop::PrintReplyAndQuit<DestroyNvramReply>,
267                    weak_factory_.GetWeakPtr()));
268   }
269 
HandleWriteNvram(uint32_t index,const std::string & data)270   void HandleWriteNvram(uint32_t index, const std::string& data) {
271     WriteNvramRequest request;
272     request.set_index(index);
273     request.set_data(data);
274     tpm_nvram_->WriteNvram(
275         request,
276         base::Bind(&ClientLoop::PrintReplyAndQuit<WriteNvramReply>,
277                    weak_factory_.GetWeakPtr()));
278   }
279 
HandleReadNvram(uint32_t index)280   void HandleReadNvram(uint32_t index) {
281     ReadNvramRequest request;
282     request.set_index(index);
283     tpm_nvram_->ReadNvram(
284         request,
285         base::Bind(&ClientLoop::PrintReplyAndQuit<ReadNvramReply>,
286                    weak_factory_.GetWeakPtr()));
287   }
288 
HandleIsNvramDefined(uint32_t index)289   void HandleIsNvramDefined(uint32_t index) {
290     IsNvramDefinedRequest request;
291     request.set_index(index);
292     tpm_nvram_->IsNvramDefined(
293         request,
294         base::Bind(&ClientLoop::PrintReplyAndQuit<IsNvramDefinedReply>,
295                    weak_factory_.GetWeakPtr()));
296   }
297 
HandleIsNvramLocked(uint32_t index)298   void HandleIsNvramLocked(uint32_t index) {
299     IsNvramLockedRequest request;
300     request.set_index(index);
301     tpm_nvram_->IsNvramLocked(
302         request,
303         base::Bind(&ClientLoop::PrintReplyAndQuit<IsNvramLockedReply>,
304                    weak_factory_.GetWeakPtr()));
305   }
306 
HandleGetNvramSize(uint32_t index)307   void HandleGetNvramSize(uint32_t index) {
308     GetNvramSizeRequest request;
309     request.set_index(index);
310     tpm_nvram_->GetNvramSize(
311         request,
312         base::Bind(&ClientLoop::PrintReplyAndQuit<GetNvramSizeReply>,
313                    weak_factory_.GetWeakPtr()));
314   }
315 
316   // Pointer to a DBus proxy to tpm_managerd.
317   std::unique_ptr<tpm_manager::TpmNvramInterface> tpm_nvram_;
318   std::unique_ptr<tpm_manager::TpmOwnershipInterface> tpm_ownership_;
319 
320   // Declared last so that weak pointers will be destroyed first.
321   base::WeakPtrFactory<ClientLoop> weak_factory_{this};
322 
323   DISALLOW_COPY_AND_ASSIGN(ClientLoop);
324 };
325 
326 }  // namespace tpm_manager
327 
main(int argc,char * argv[])328 int main(int argc, char* argv[]) {
329   base::CommandLine::Init(argc, argv);
330   brillo::InitLog(brillo::kLogToStderr);
331   tpm_manager::ClientLoop loop;
332   return loop.Run();
333 }
334