blob: 195bd1901d19e712ec63775b1c823a329ed2f4de [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <memory>
#include <string>
#include <base/bind.h>
#include <base/check.h>
#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/threading/thread_task_runner_handle.h>
#include <brillo/daemons/daemon.h>
#include <brillo/syslog_logging.h>
#include <crypto/sha2.h>
#include <tpm_manager/proto_bindings/tpm_manager.pb.h>
#include <tpm_manager-client/tpm_manager/dbus-proxies.h>
#include "tpm_manager/common/print_tpm_manager_proto.h"
namespace {
constexpr base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMinutes(2);
} // namespace
namespace tpm_manager {
constexpr char kGetTpmStatusCommand[] = "status";
constexpr char kGetVersionInfoCommand[] = "get_version_info";
constexpr char kGetDictionaryAttackInfoCommand[] = "get_da_info";
constexpr char kResetDictionaryAttackLockCommand[] = "reset_da_lock";
constexpr char kTakeOwnershipCommand[] = "take_ownership";
constexpr char kRemoveOwnerDependencyCommand[] = "remove_dependency";
constexpr char kClearStoredOwnerPasswordCommand[] = "clear_owner_password";
constexpr char kDefineSpaceCommand[] = "define_space";
constexpr char kDestroySpaceCommand[] = "destroy_space";
constexpr char kWriteSpaceCommand[] = "write_space";
constexpr char kReadSpaceCommand[] = "read_space";
constexpr char kLockSpaceCommand[] = "lock_space";
constexpr char kListSpacesCommand[] = "list_spaces";
constexpr char kGetSpaceInfoCommand[] = "get_space_info";
constexpr char kDependencySwitch[] = "dependency";
constexpr char kIndexSwitch[] = "index";
constexpr char kSizeSwitch[] = "size";
constexpr char kAttributesSwitch[] = "attributes";
constexpr char kPasswordSwitch[] = "password";
constexpr char kBindToPCR0Switch[] = "bind_to_pcr0";
constexpr char kFileSwitch[] = "file";
constexpr char kUseOwnerSwitch[] = "use_owner_authorization";
constexpr char kNonsensitiveSwitch[] = "nonsensitive";
constexpr char kIgnoreCacheSwitch[] = "ignore_cache";
constexpr char kLockRead[] = "lock_read";
constexpr char kLockWrite[] = "lock_write";
constexpr char kUsage[] = R"(
Usage: tpm_manager_client <command> [<arguments>]
Commands:
status
Prints TPM status information.
get_version_info
Prints TPM version information.
get_da_info
Prints TPM dictionary attack information.
reset_da_lock
Resets dictionary attack lock
take_ownership
Takes ownership of the Tpm with a random password.
remove_dependency --dependency=<owner_dependency>
Removes the named Tpm owner dependency. E.g. \"Nvram\" or \"Attestation\".
clear_owner_password
Clears stored owner password if all dependencies have been removed.
define_space --index=<index> --size=<size> [--attributes=<attribute_list>]
[--password=<password>] [--bind_to_pcr0]
Defines an NV space. The attribute format is a '|' separated list of:
PERSISTENT_WRITE_LOCK: Allow write lock; stay locked until destroyed.
BOOT_WRITE_LOCK: Allow write lock; stay locked until next boot.
BOOT_READ_LOCK: Allow read lock; stay locked until next boot.
WRITE_AUTHORIZATION: Require authorization to write.
READ_AUTHORIZATION: Require authorization to read.
WRITE_EXTEND: Allow only extend operations, not direct writes.
GLOBAL_LOCK: Engage write lock when the global lock is engaged.
PLATFORM_READ: Allow read with 'platform' authorization. Used by FWMP.
PLATFORM_WRITE: Allow write only with 'platform' authorization. This
is similar to the TPM 1.2 'physical presence' notion.
OWNER_WRITE: Allow write only with TPM owner authorization.
OWNER_READ: Allow read only with TPM owner authorization.
This command requires that owner authorization is available. If a password
is given it will be required only as specified by the attributes. E.g. if
READ_AUTHORIZATION is not listed, then the password will not be required
in order to read. Similarly, if the --bind_to_pcr0 option is given, the
current PCR0 value will be required only as specified by the attributes.
destroy_space --index=<index>
Destroys an NV space. This command requires that owner authorization is
available.
write_space --index=<index> --file=<input_file> [--password=<password>]
[--use_owner_authorization]
Writes data from a file to an NV space. Any existing data will be
overwritten.
read_space --index=<index> --file=<output_file> [--password=<password>]
[--use_owner_authorization]
Reads the entire contents of an NV space to a file.
lock_space --index=<index> [--lock_read] [--lock_write]
[--password=<password>] [--use_owner_authorization]
Locks an NV space for read and / or write.
list_spaces
Prints a list of all defined index values.
get_space_info --index=<index>
Prints public information about an NV space.
)";
constexpr char kKnownNVRAMSpaces[] = R"(
NVRAM Index Reference:
TPM 1.2 (32-bit values)
0x00001007 - Chrome OS Firmware Version Rollback Protection
0x00001008 - Chrome OS Kernel Version Rollback Protection
0x00001009 - Chrome OS Firmware Backup
0x0000100A - Chrome OS Firmware Management Parameters
0x0000100B - Chrome OS Firmware Recovery Hash Space
0x20000004 - Chrome OS Install Attributes (aka LockBox)
0x10000001 - Standard TPM_NV_INDEX_DIR (Permanent)
0x1000F000 - Endorsement Certificate (Permanent)
0x30000001 - Endorsement Authority Certificate (Permanent)
0x0000F004 - Standard Test Index (for testing TPM_NV_DefineSpace)
TPM 2.0 (24-bit values)
0x400000 and following - Reserved for Firmware
0x800000 and following - Reserved for Software
0xC00000 and following - Endorsement Certificates
)";
bool ReadFileToString(const std::string& filename, std::string* data) {
return base::ReadFileToString(base::FilePath(filename), data);
}
bool WriteStringToFile(const std::string& data, const std::string& filename) {
int result =
base::WriteFile(base::FilePath(filename), data.data(), data.size());
return (result != -1 && static_cast<size_t>(result) == data.size());
}
uint32_t StringToUint32(const std::string& s) {
return strtoul(s.c_str(), nullptr, 0);
}
uint32_t StringToNvramIndex(const std::string& s) {
return StringToUint32(s);
}
std::string GetAuthValueFromPassword(const std::string& password) {
// For NULL password auth, we should pass a Empty Buffer as authorization
// value to TPM. Otherwise, we use SHA256(password) to transform the
// variable-length password to fixed-length authorization value.
if (password.empty())
return "";
else
return crypto::SHA256HashString(password);
}
using ClientLoopBase = brillo::Daemon;
class ClientLoop : public ClientLoopBase {
public:
ClientLoop() = default;
ClientLoop(const ClientLoop&) = delete;
ClientLoop& operator=(const ClientLoop&) = delete;
~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;
}
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
bus_ = base::MakeRefCounted<dbus::Bus>(options);
CHECK(bus_->Connect()) << "Failed to connect to system D-Bus";
std::unique_ptr<org::chromium::TpmNvramProxy> nvram_proxy =
std::make_unique<org::chromium::TpmNvramProxy>(bus_);
std::unique_ptr<org::chromium::TpmManagerProxy> ownership_proxy =
std::make_unique<org::chromium::TpmManagerProxy>(bus_);
tpm_nvram_ = std::move(nvram_proxy);
tpm_ownership_ = std::move(ownership_proxy);
exit_code = ScheduleCommand();
if (exit_code == EX_USAGE) {
printf("%s%s", kUsage, kKnownNVRAMSpaces);
}
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") ||
command_line->GetArgs().size() == 0) {
return EX_USAGE;
}
std::string command = command_line->GetArgs()[0];
if (command == kGetTpmStatusCommand) {
if (!command_line->HasSwitch(kNonsensitiveSwitch)) {
task = base::Bind(&ClientLoop::HandleGetTpmStatus,
weak_factory_.GetWeakPtr(),
command_line->HasSwitch(kIgnoreCacheSwitch));
} else {
task = base::Bind(&ClientLoop::HandleGetTpmNonsensitiveStatus,
weak_factory_.GetWeakPtr(),
command_line->HasSwitch(kIgnoreCacheSwitch));
}
} else if (command == kGetVersionInfoCommand) {
task = base::Bind(&ClientLoop::HandleGetVersionInfo,
weak_factory_.GetWeakPtr());
} else if (command == kGetDictionaryAttackInfoCommand) {
task = base::Bind(&ClientLoop::HandleGetDictionaryAttackInfo,
weak_factory_.GetWeakPtr());
} else if (command == kResetDictionaryAttackLockCommand) {
task = base::Bind(&ClientLoop::HandleResetDictionaryAttackLock,
weak_factory_.GetWeakPtr());
} else if (command == kTakeOwnershipCommand) {
task = base::Bind(&ClientLoop::HandleTakeOwnership,
weak_factory_.GetWeakPtr());
} else if (command == kRemoveOwnerDependencyCommand) {
if (!command_line->HasSwitch(kDependencySwitch)) {
return EX_USAGE;
}
task = base::Bind(&ClientLoop::HandleRemoveOwnerDependency,
weak_factory_.GetWeakPtr(),
command_line->GetSwitchValueASCII(kDependencySwitch));
} else if (command == kClearStoredOwnerPasswordCommand) {
task = base::Bind(&ClientLoop::HandleClearStoredOwnerPassword,
weak_factory_.GetWeakPtr());
} else if (command == kDefineSpaceCommand) {
if (!command_line->HasSwitch(kIndexSwitch) ||
!command_line->HasSwitch(kSizeSwitch)) {
return EX_USAGE;
}
task = base::Bind(
&ClientLoop::HandleDefineSpace, weak_factory_.GetWeakPtr(),
StringToNvramIndex(command_line->GetSwitchValueASCII(kIndexSwitch)),
StringToUint32(command_line->GetSwitchValueASCII(kSizeSwitch)),
command_line->GetSwitchValueASCII(kAttributesSwitch),
command_line->GetSwitchValueASCII(kPasswordSwitch),
command_line->HasSwitch(kBindToPCR0Switch));
} else if (command == kDestroySpaceCommand) {
if (!command_line->HasSwitch(kIndexSwitch)) {
return EX_USAGE;
}
task = base::Bind(
&ClientLoop::HandleDestroySpace, weak_factory_.GetWeakPtr(),
StringToNvramIndex(command_line->GetSwitchValueASCII(kIndexSwitch)));
} else if (command == kWriteSpaceCommand) {
if (!command_line->HasSwitch(kIndexSwitch) ||
!command_line->HasSwitch(kFileSwitch)) {
return EX_USAGE;
}
task = base::Bind(
&ClientLoop::HandleWriteSpace, weak_factory_.GetWeakPtr(),
StringToNvramIndex(command_line->GetSwitchValueASCII(kIndexSwitch)),
command_line->GetSwitchValueASCII(kFileSwitch),
command_line->GetSwitchValueASCII(kPasswordSwitch),
command_line->HasSwitch(kUseOwnerSwitch));
} else if (command == kReadSpaceCommand) {
if (!command_line->HasSwitch(kIndexSwitch) ||
!command_line->HasSwitch(kFileSwitch)) {
return EX_USAGE;
}
task = base::Bind(
&ClientLoop::HandleReadSpace, weak_factory_.GetWeakPtr(),
StringToNvramIndex(command_line->GetSwitchValueASCII(kIndexSwitch)),
command_line->GetSwitchValueASCII(kFileSwitch),
command_line->GetSwitchValueASCII(kPasswordSwitch),
command_line->HasSwitch(kUseOwnerSwitch));
} else if (command == kLockSpaceCommand) {
if (!command_line->HasSwitch(kIndexSwitch)) {
return EX_USAGE;
}
task = base::Bind(
&ClientLoop::HandleLockSpace, weak_factory_.GetWeakPtr(),
StringToNvramIndex(command_line->GetSwitchValueASCII(kIndexSwitch)),
command_line->HasSwitch(kLockRead),
command_line->HasSwitch(kLockWrite),
command_line->GetSwitchValueASCII(kPasswordSwitch),
command_line->HasSwitch(kUseOwnerSwitch));
} else if (command == kListSpacesCommand) {
task =
base::Bind(&ClientLoop::HandleListSpaces, weak_factory_.GetWeakPtr());
} else if (command == kGetSpaceInfoCommand) {
if (!command_line->HasSwitch(kIndexSwitch)) {
return EX_USAGE;
}
task = base::Bind(
&ClientLoop::HandleGetSpaceInfo, weak_factory_.GetWeakPtr(),
StringToNvramIndex(command_line->GetSwitchValueASCII(kIndexSwitch)));
} else {
// Command line arguments did not match any valid commands.
return EX_USAGE;
}
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
return EX_OK;
}
// Template to print reply protobuf.
template <typename ProtobufType>
void PrintReplyAndQuit(const ProtobufType& reply) {
printf("Message Reply: %s\n", GetProtoDebugString(reply).c_str());
Quit();
}
void PrintErrorAndQuit(brillo::Error* error) {
printf("Error: %s\n", error->GetMessage().c_str());
Quit();
}
void HandleGetTpmStatus(bool ignore_cache) {
GetTpmStatusRequest request;
request.set_ignore_cache(ignore_cache);
tpm_ownership_->GetTpmStatusAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<GetTpmStatusReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleGetTpmNonsensitiveStatus(bool ignore_cache) {
GetTpmNonsensitiveStatusRequest request;
request.set_ignore_cache(ignore_cache);
tpm_ownership_->GetTpmNonsensitiveStatusAsync(
request,
base::Bind(
&ClientLoop::PrintReplyAndQuit<GetTpmNonsensitiveStatusReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleGetVersionInfo() {
GetVersionInfoRequest request;
tpm_ownership_->GetVersionInfoAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<GetVersionInfoReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleGetDictionaryAttackInfo() {
GetDictionaryAttackInfoRequest request;
tpm_ownership_->GetDictionaryAttackInfoAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<GetDictionaryAttackInfoReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleResetDictionaryAttackLock() {
ResetDictionaryAttackLockRequest request;
tpm_ownership_->ResetDictionaryAttackLockAsync(
request,
base::Bind(
&ClientLoop::PrintReplyAndQuit<ResetDictionaryAttackLockReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleTakeOwnership() {
TakeOwnershipRequest request;
tpm_ownership_->TakeOwnershipAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<TakeOwnershipReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleRemoveOwnerDependency(const std::string& owner_dependency) {
RemoveOwnerDependencyRequest request;
request.set_owner_dependency(owner_dependency);
tpm_ownership_->RemoveOwnerDependencyAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<RemoveOwnerDependencyReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleClearStoredOwnerPassword() {
ClearStoredOwnerPasswordRequest request;
tpm_ownership_->ClearStoredOwnerPasswordAsync(
request,
base::Bind(
&ClientLoop::PrintReplyAndQuit<ClearStoredOwnerPasswordReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
bool DecodeAttribute(const std::string& attribute_str,
NvramSpaceAttribute* attribute) {
if (attribute_str == "PERSISTENT_WRITE_LOCK") {
*attribute = NVRAM_PERSISTENT_WRITE_LOCK;
return true;
}
if (attribute_str == "BOOT_WRITE_LOCK") {
*attribute = NVRAM_BOOT_WRITE_LOCK;
return true;
}
if (attribute_str == "BOOT_READ_LOCK") {
*attribute = NVRAM_BOOT_READ_LOCK;
return true;
}
if (attribute_str == "WRITE_AUTHORIZATION") {
*attribute = NVRAM_WRITE_AUTHORIZATION;
return true;
}
if (attribute_str == "READ_AUTHORIZATION") {
*attribute = NVRAM_READ_AUTHORIZATION;
return true;
}
if (attribute_str == "WRITE_EXTEND") {
*attribute = NVRAM_WRITE_EXTEND;
return true;
}
if (attribute_str == "GLOBAL_LOCK") {
*attribute = NVRAM_GLOBAL_LOCK;
return true;
}
if (attribute_str == "PLATFORM_READ") {
*attribute = NVRAM_PLATFORM_READ;
return true;
}
if (attribute_str == "PLATFORM_WRITE") {
*attribute = NVRAM_PLATFORM_WRITE;
return true;
}
if (attribute_str == "OWNER_WRITE") {
*attribute = NVRAM_OWNER_WRITE;
return true;
}
if (attribute_str == "OWNER_READ") {
*attribute = NVRAM_OWNER_READ;
return true;
}
LOG(ERROR) << "Unrecognized attribute: " << attribute_str;
return false;
}
void HandleDefineSpace(uint32_t index,
size_t size,
const std::string& attributes,
const std::string& password,
bool bind_to_pcr0) {
DefineSpaceRequest request;
request.set_index(index);
request.set_size(size);
std::string::size_type pos = 0;
std::string::size_type next_pos = 0;
while (next_pos != std::string::npos) {
next_pos = attributes.find('|', pos);
std::string attribute_str;
if (next_pos == std::string::npos) {
attribute_str = attributes.substr(pos);
} else {
attribute_str = attributes.substr(pos, next_pos - pos);
}
if (!attribute_str.empty()) {
NvramSpaceAttribute attribute;
if (!DecodeAttribute(attribute_str, &attribute)) {
Quit();
return;
}
request.add_attributes(attribute);
}
pos = next_pos + 1;
}
request.set_authorization_value(GetAuthValueFromPassword(password));
request.set_policy(bind_to_pcr0 ? NVRAM_POLICY_PCR0 : NVRAM_POLICY_NONE);
tpm_nvram_->DefineSpaceAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<DefineSpaceReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleDestroySpace(uint32_t index) {
DestroySpaceRequest request;
request.set_index(index);
tpm_nvram_->DestroySpaceAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<DestroySpaceReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleWriteSpace(uint32_t index,
const std::string& input_file,
const std::string& password,
bool use_owner_authorization) {
WriteSpaceRequest request;
request.set_index(index);
std::string data;
if (!ReadFileToString(input_file, &data)) {
LOG(ERROR) << "Failed to read input file.";
Quit();
return;
}
request.set_data(data);
request.set_authorization_value(GetAuthValueFromPassword(password));
request.set_use_owner_authorization(use_owner_authorization);
tpm_nvram_->WriteSpaceAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<WriteSpaceReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleReadSpaceReply(const std::string& output_file,
const ReadSpaceReply& reply) {
if (!WriteStringToFile(reply.data(), output_file)) {
LOG(ERROR) << "Failed to write output file.";
}
LOG(INFO) << "Message Reply: " << GetProtoDebugString(reply);
Quit();
}
void HandleReadSpace(uint32_t index,
const std::string& output_file,
const std::string& password,
bool use_owner_authorization) {
ReadSpaceRequest request;
request.set_index(index);
request.set_authorization_value(GetAuthValueFromPassword(password));
request.set_use_owner_authorization(use_owner_authorization);
tpm_nvram_->ReadSpaceAsync(
request,
base::Bind(&ClientLoop::HandleReadSpaceReply,
weak_factory_.GetWeakPtr(), output_file),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleLockSpace(uint32_t index,
bool lock_read,
bool lock_write,
const std::string& password,
bool use_owner_authorization) {
LockSpaceRequest request;
request.set_index(index);
request.set_lock_read(lock_read);
request.set_lock_write(lock_write);
request.set_authorization_value(GetAuthValueFromPassword(password));
request.set_use_owner_authorization(use_owner_authorization);
tpm_nvram_->LockSpaceAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<LockSpaceReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleListSpaces() {
printf("%s\n", kKnownNVRAMSpaces);
ListSpacesRequest request;
tpm_nvram_->ListSpacesAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<ListSpacesReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
void HandleGetSpaceInfo(uint32_t index) {
GetSpaceInfoRequest request;
request.set_index(index);
tpm_nvram_->GetSpaceInfoAsync(
request,
base::Bind(&ClientLoop::PrintReplyAndQuit<GetSpaceInfoReply>,
weak_factory_.GetWeakPtr()),
base::Bind(&ClientLoop::PrintErrorAndQuit, weak_factory_.GetWeakPtr()),
kDefaultTimeout.InMilliseconds());
}
scoped_refptr<dbus::Bus> bus_;
// IPC proxy interfaces.
std::unique_ptr<org::chromium::TpmNvramProxyInterface> tpm_nvram_;
std::unique_ptr<org::chromium::TpmManagerProxyInterface> tpm_ownership_;
// Declared last so that weak pointers will be destroyed first.
base::WeakPtrFactory<ClientLoop> weak_factory_{this};
};
} // 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();
}