// // Copyright (C) 2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include <stdio.h> #include <stdlib.h> #include <sysexits.h> #include <memory> #include <string> #include <base/command_line.h> #include <base/logging.h> #include <base/message_loop/message_loop.h> #include <brillo/bind_lambda.h> #include <brillo/daemons/daemon.h> #include <brillo/syslog_logging.h> #include "tpm_manager/client/tpm_nvram_dbus_proxy.h" #include "tpm_manager/client/tpm_ownership_dbus_proxy.h" #include "tpm_manager/common/print_tpm_ownership_interface_proto.h" #include "tpm_manager/common/print_tpm_nvram_interface_proto.h" #include "tpm_manager/common/tpm_ownership_interface.pb.h" #include "tpm_manager/common/tpm_nvram_interface.pb.h" namespace tpm_manager { const char kGetTpmStatusCommand[] = "status"; const char kTakeOwnershipCommand[] = "take_ownership"; const char kRemoveOwnerDependencyCommand[] = "remove_dependency"; const char kDefineNvramCommand[] = "define_nvram"; const char kDestroyNvramCommand[] = "destroy_nvram"; const char kWriteNvramCommand[] = "write_nvram"; const char kReadNvramCommand[] = "read_nvram"; const char kIsNvramDefinedCommand[] = "is_nvram_defined"; const char kIsNvramLockedCommand[] = "is_nvram_locked"; const char kGetNvramSizeCommand[] = "get_nvram_size"; const char kNvramIndexArg[] = "nvram_index"; const char kNvramLengthArg[] = "nvram_length"; const char kNvramDataArg[] = "nvram_data"; const char kUsage[] = R"( Usage: tpm_manager_client <command> [<arguments>] Commands (used as switches): --status Prints the current status of the Tpm. --take_ownership Takes ownership of the Tpm with a random password. --remove_dependency=<owner_dependency> Removes the provided Tpm owner dependency. --define_nvram Defines an NV space at |nvram_index| with length |nvram_length|. --destroy_nvram Destroys the NV space at |nvram_index|. --write_nvram Writes the NV space at |nvram_index| with |nvram_data|. --read_nvram Prints the contents of the NV space at |nvram_index|. --is_nvram_defined Prints whether the NV space at |nvram_index| is defined. --is_nvram_locked Prints whether the NV space at |nvram_index| is locked for writing. --get_nvram_size Prints the size of the NV space at |nvram_index|. Arguments (used as switches): --nvram_index=<index> Index of NV space to operate on. --nvram_length=<length> Size in bytes of the NV space to be created. --nvram_data=<data> Data to write to NV space. )"; using ClientLoopBase = brillo::Daemon; class ClientLoop : public ClientLoopBase { public: ClientLoop() = default; ~ClientLoop() override = default; protected: int OnInit() override { int exit_code = ClientLoopBase::OnInit(); if (exit_code != EX_OK) { LOG(ERROR) << "Error initializing tpm_manager_client."; return exit_code; } TpmNvramDBusProxy* nvram_proxy = new TpmNvramDBusProxy(); if (!nvram_proxy->Initialize()) { LOG(ERROR) << "Error initializing proxy to nvram interface."; return EX_UNAVAILABLE; } TpmOwnershipDBusProxy* ownership_proxy = new TpmOwnershipDBusProxy(); if (!ownership_proxy->Initialize()) { LOG(ERROR) << "Error initializing proxy to ownership interface."; return EX_UNAVAILABLE; } tpm_nvram_.reset(nvram_proxy); tpm_ownership_.reset(ownership_proxy); exit_code = ScheduleCommand(); if (exit_code == EX_USAGE) { printf("%s", kUsage); } return exit_code; } void OnShutdown(int* exit_code) override { tpm_nvram_.reset(); tpm_ownership_.reset(); ClientLoopBase::OnShutdown(exit_code); } private: // Posts tasks on to the message loop based on command line flags. int ScheduleCommand() { base::Closure task; base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch("help") || command_line->HasSwitch("h")) { return EX_USAGE; } else if (command_line->HasSwitch(kGetTpmStatusCommand)) { task = base::Bind(&ClientLoop::HandleGetTpmStatus, weak_factory_.GetWeakPtr()); } else if (command_line->HasSwitch(kTakeOwnershipCommand)) { task = base::Bind(&ClientLoop::HandleTakeOwnership, weak_factory_.GetWeakPtr()); } else if (command_line->HasSwitch(kRemoveOwnerDependencyCommand)) { task = base::Bind( &ClientLoop::HandleRemoveOwnerDependency, weak_factory_.GetWeakPtr(), command_line->GetSwitchValueASCII(kRemoveOwnerDependencyCommand)); } else if (command_line->HasSwitch(kDefineNvramCommand)) { if (!command_line->HasSwitch(kNvramIndexArg) || !command_line->HasSwitch(kNvramLengthArg)) { LOG(ERROR) << "Cannot define nvram without a valid index and length."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleDefineNvram, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()), atoi(command_line->GetSwitchValueASCII(kNvramLengthArg).c_str())); } else if (command_line->HasSwitch(kDestroyNvramCommand)) { if (!command_line->HasSwitch(kNvramIndexArg)) { LOG(ERROR) << "Cannot destroy nvram without a valid index."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleDestroyNvram, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str())); } else if (command_line->HasSwitch(kWriteNvramCommand)) { if (!command_line->HasSwitch(kNvramIndexArg) || !command_line->HasSwitch(kNvramDataArg)) { LOG(ERROR) << "Cannot write nvram without a valid index and data."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleWriteNvram, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()), command_line->GetSwitchValueASCII(kNvramDataArg)); } else if (command_line->HasSwitch(kReadNvramCommand)) { if (!command_line->HasSwitch(kNvramIndexArg)) { LOG(ERROR) << "Cannot read nvram without a valid index."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleReadNvram, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str())); } else if (command_line->HasSwitch(kIsNvramDefinedCommand)) { if (!command_line->HasSwitch(kNvramIndexArg)) { LOG(ERROR) << "Cannot query nvram without a valid index."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleIsNvramDefined, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str())); } else if (command_line->HasSwitch(kIsNvramLockedCommand)) { if (!command_line->HasSwitch(kNvramIndexArg)) { LOG(ERROR) << "Cannot query nvram without a valid index."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleIsNvramLocked, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str())); } else if (command_line->HasSwitch(kGetNvramSizeCommand)) { if (!command_line->HasSwitch(kNvramIndexArg)) { LOG(ERROR) << "Cannot query nvram without a valid index."; return EX_USAGE; } task = base::Bind( &ClientLoop::HandleGetNvramSize, weak_factory_.GetWeakPtr(), atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str())); } else { // Command line arguments did not match any valid commands. LOG(ERROR) << "No Valid Command selected."; return EX_USAGE; } base::MessageLoop::current()->PostTask(FROM_HERE, task); return EX_OK; } // Template to print reply protobuf. template <typename ProtobufType> void PrintReplyAndQuit(const ProtobufType& reply) { LOG(INFO) << "Message Reply: " << GetProtoDebugString(reply); Quit(); } void HandleGetTpmStatus() { GetTpmStatusRequest request; tpm_ownership_->GetTpmStatus( request, base::Bind(&ClientLoop::PrintReplyAndQuit<GetTpmStatusReply>, weak_factory_.GetWeakPtr())); } void HandleTakeOwnership() { TakeOwnershipRequest request; tpm_ownership_->TakeOwnership( request, base::Bind(&ClientLoop::PrintReplyAndQuit<TakeOwnershipReply>, weak_factory_.GetWeakPtr())); } void HandleRemoveOwnerDependency(const std::string& owner_dependency) { RemoveOwnerDependencyRequest request; request.set_owner_dependency(owner_dependency); tpm_ownership_->RemoveOwnerDependency( request, base::Bind(&ClientLoop::PrintReplyAndQuit<RemoveOwnerDependencyReply>, weak_factory_.GetWeakPtr())); } void HandleDefineNvram(uint32_t index, size_t length) { DefineNvramRequest request; request.set_index(index); request.set_length(length); tpm_nvram_->DefineNvram( request, base::Bind(&ClientLoop::PrintReplyAndQuit<DefineNvramReply>, weak_factory_.GetWeakPtr())); } void HandleDestroyNvram(uint32_t index) { DestroyNvramRequest request; request.set_index(index); tpm_nvram_->DestroyNvram( request, base::Bind(&ClientLoop::PrintReplyAndQuit<DestroyNvramReply>, weak_factory_.GetWeakPtr())); } void HandleWriteNvram(uint32_t index, const std::string& data) { WriteNvramRequest request; request.set_index(index); request.set_data(data); tpm_nvram_->WriteNvram( request, base::Bind(&ClientLoop::PrintReplyAndQuit<WriteNvramReply>, weak_factory_.GetWeakPtr())); } void HandleReadNvram(uint32_t index) { ReadNvramRequest request; request.set_index(index); tpm_nvram_->ReadNvram( request, base::Bind(&ClientLoop::PrintReplyAndQuit<ReadNvramReply>, weak_factory_.GetWeakPtr())); } void HandleIsNvramDefined(uint32_t index) { IsNvramDefinedRequest request; request.set_index(index); tpm_nvram_->IsNvramDefined( request, base::Bind(&ClientLoop::PrintReplyAndQuit<IsNvramDefinedReply>, weak_factory_.GetWeakPtr())); } void HandleIsNvramLocked(uint32_t index) { IsNvramLockedRequest request; request.set_index(index); tpm_nvram_->IsNvramLocked( request, base::Bind(&ClientLoop::PrintReplyAndQuit<IsNvramLockedReply>, weak_factory_.GetWeakPtr())); } void HandleGetNvramSize(uint32_t index) { GetNvramSizeRequest request; request.set_index(index); tpm_nvram_->GetNvramSize( request, base::Bind(&ClientLoop::PrintReplyAndQuit<GetNvramSizeReply>, weak_factory_.GetWeakPtr())); } // Pointer to a DBus proxy to tpm_managerd. std::unique_ptr<tpm_manager::TpmNvramInterface> tpm_nvram_; std::unique_ptr<tpm_manager::TpmOwnershipInterface> tpm_ownership_; // Declared last so that weak pointers will be destroyed first. base::WeakPtrFactory<ClientLoop> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ClientLoop); }; } // namespace tpm_manager int main(int argc, char* argv[]) { base::CommandLine::Init(argc, argv); brillo::InitLog(brillo::kLogToStderr); tpm_manager::ClientLoop loop; return loop.Run(); }