Home | History | Annotate | Download | only in client
      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:
     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 
    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.
    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>
    221   void PrintReplyAndQuit(const ProtobufType& reply) {
    222     LOG(INFO) << "Message Reply: " << GetProtoDebugString(reply);
    223     Quit();
    224   }
    225 
    226   void HandleGetTpmStatus() {
    227     GetTpmStatusRequest request;
    228     tpm_ownership_->GetTpmStatus(
    229         request,
    230         base::Bind(&ClientLoop::PrintReplyAndQuit<GetTpmStatusReply>,
    231                    weak_factory_.GetWeakPtr()));
    232   }
    233 
    234   void HandleTakeOwnership() {
    235     TakeOwnershipRequest request;
    236     tpm_ownership_->TakeOwnership(
    237         request,
    238         base::Bind(&ClientLoop::PrintReplyAndQuit<TakeOwnershipReply>,
    239                    weak_factory_.GetWeakPtr()));
    240   }
    241 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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