333 lines
12 KiB
C++
333 lines
12 KiB
C++
//
|
|
// 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();
|
|
}
|