blob: 5afaf2a1e3864eae70e0ea27e69377c047b073eb [file] [log] [blame]
// Copyright 2019 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 "tpm_manager/client/tpm_manager_utility.h"
#include <base/bind.h>
#include <base/logging.h>
namespace tpm_manager {
TpmManagerUtility::TpmManagerUtility(
tpm_manager::TpmOwnershipInterface* tpm_owner,
tpm_manager::TpmNvramInterface* tpm_nvram)
: tpm_owner_(tpm_owner), tpm_nvram_(tpm_nvram) {}
bool TpmManagerUtility::Initialize() {
if (!tpm_manager_thread_.IsRunning() &&
!tpm_manager_thread_.StartWithOptions(base::Thread::Options(
base::MessageLoopForIO::TYPE_IO, 0 /* Uses default stack size. */))) {
LOG(ERROR) << "Failed to start tpm_manager thread.";
return false;
}
if (!tpm_owner_ || !tpm_nvram_) {
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
tpm_manager_thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(&TpmManagerUtility::InitializationTask,
base::Unretained(this), &event));
event.Wait();
}
if (!tpm_owner_ || !tpm_nvram_) {
LOG(ERROR) << "Failed to initialize tpm_managerd clients.";
return false;
}
return true;
}
bool TpmManagerUtility::TakeOwnership() {
tpm_manager::TakeOwnershipReply reply;
tpm_manager::TakeOwnershipRequest request;
SendTpmManagerRequestAndWait(
base::Bind(&tpm_manager::TpmOwnershipInterface::TakeOwnership,
base::Unretained(tpm_owner_), request),
&reply);
if (reply.status() != tpm_manager::STATUS_SUCCESS) {
LOG(ERROR) << __func__ << ": Failed to take ownership.";
return false;
}
return true;
}
bool TpmManagerUtility::GetTpmStatus(bool* is_enabled,
bool* is_owned,
LocalData* local_data) {
tpm_manager::GetTpmStatusReply tpm_status;
SendTpmManagerRequestAndWait(
base::Bind(&tpm_manager::TpmOwnershipInterface::GetTpmStatus,
base::Unretained(tpm_owner_),
tpm_manager::GetTpmStatusRequest()),
&tpm_status);
if (tpm_status.status() != tpm_manager::STATUS_SUCCESS) {
LOG(ERROR) << __func__ << ": Failed to read TPM state from tpm_managerd.";
return false;
}
*is_enabled = tpm_status.enabled();
*is_owned = tpm_status.owned();
tpm_status.mutable_local_data()->Swap(local_data);
return true;
}
bool TpmManagerUtility::RemoveOwnerDependency(const std::string& dependency) {
tpm_manager::RemoveOwnerDependencyReply reply;
tpm_manager::RemoveOwnerDependencyRequest request;
request.set_owner_dependency(dependency);
SendTpmManagerRequestAndWait(
base::Bind(&tpm_manager::TpmOwnershipInterface::RemoveOwnerDependency,
base::Unretained(tpm_owner_), request),
&reply);
if (reply.status() != tpm_manager::STATUS_SUCCESS) {
LOG(ERROR) << __func__ << ": Failed to remove the dependency of "
<< dependency << ".";
return false;
}
return true;
}
void TpmManagerUtility::InitializationTask(base::WaitableEvent* completion) {
CHECK(completion);
CHECK(tpm_manager_thread_.task_runner()->RunsTasksOnCurrentThread());
default_tpm_owner_ = std::make_unique<tpm_manager::TpmOwnershipDBusProxy>();
default_tpm_nvram_ = std::make_unique<tpm_manager::TpmNvramDBusProxy>();
if (default_tpm_owner_->Initialize()) {
tpm_owner_ = default_tpm_owner_.get();
}
if (default_tpm_nvram_->Initialize()) {
tpm_nvram_ = default_tpm_nvram_.get();
}
completion->Signal();
}
template <typename ReplyProtoType, typename MethodType>
void TpmManagerUtility::SendTpmManagerRequestAndWait(
const MethodType& method, ReplyProtoType* reply_proto) {
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
auto callback = base::Bind(
[](ReplyProtoType* target, base::WaitableEvent* completion,
const ReplyProtoType& reply) {
*target = reply;
completion->Signal();
},
reply_proto, &event);
tpm_manager_thread_.task_runner()->PostTask(FROM_HERE,
base::Bind(method, callback));
event.Wait();
}
void TpmManagerUtility::ShutdownTask() {
tpm_owner_ = nullptr;
tpm_nvram_ = nullptr;
default_tpm_owner_.reset(nullptr);
default_tpm_nvram_.reset(nullptr);
}
bool TpmManagerUtility::ReadSpace(uint32_t index,
bool use_owner_auth,
std::string* output) {
// TODO(cylai): implement this function and test it once the server side
// implementation is ready.
DCHECK(false) << "Not implemented";
return false;
}
} // namespace tpm_manager