You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
12 KiB
339 lines
12 KiB
// |
|
// 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 "tpm_manager/server/tpm_manager_service.h" |
|
|
|
#include <base/callback.h> |
|
#include <base/command_line.h> |
|
#include <brillo/bind_lambda.h> |
|
|
|
namespace tpm_manager { |
|
|
|
TpmManagerService::TpmManagerService(bool wait_for_ownership, |
|
LocalDataStore* local_data_store, |
|
TpmStatus* tpm_status, |
|
TpmInitializer* tpm_initializer, |
|
TpmNvram* tpm_nvram) |
|
: local_data_store_(local_data_store), |
|
tpm_status_(tpm_status), |
|
tpm_initializer_(tpm_initializer), |
|
tpm_nvram_(tpm_nvram), |
|
wait_for_ownership_(wait_for_ownership), |
|
weak_factory_(this) {} |
|
|
|
bool TpmManagerService::Initialize() { |
|
worker_thread_.reset(new base::Thread("TpmManager Service Worker")); |
|
worker_thread_->StartWithOptions( |
|
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
|
base::Closure task = |
|
base::Bind(&TpmManagerService::InitializeTask, base::Unretained(this)); |
|
worker_thread_->task_runner()->PostNonNestableTask(FROM_HERE, task); |
|
VLOG(1) << "Worker thread started."; |
|
return true; |
|
} |
|
|
|
void TpmManagerService::InitializeTask() { |
|
VLOG(1) << "Initializing service..."; |
|
if (!tpm_status_->IsTpmEnabled()) { |
|
LOG(WARNING) << __func__ << ": TPM is disabled."; |
|
return; |
|
} |
|
tpm_initializer_->VerifiedBootHelper(); |
|
if (!wait_for_ownership_) { |
|
VLOG(1) << "Initializing TPM."; |
|
if (!tpm_initializer_->InitializeTpm()) { |
|
LOG(WARNING) << __func__ << ": TPM initialization failed."; |
|
return; |
|
} |
|
} |
|
} |
|
|
|
void TpmManagerService::GetTpmStatus(const GetTpmStatusRequest& request, |
|
const GetTpmStatusCallback& callback) { |
|
PostTaskToWorkerThread<GetTpmStatusReply>( |
|
request, callback, &TpmManagerService::GetTpmStatusTask); |
|
} |
|
|
|
void TpmManagerService::GetTpmStatusTask( |
|
const GetTpmStatusRequest& request, |
|
const std::shared_ptr<GetTpmStatusReply>& reply) { |
|
VLOG(1) << __func__; |
|
reply->set_enabled(tpm_status_->IsTpmEnabled()); |
|
reply->set_owned(tpm_status_->IsTpmOwned()); |
|
LocalData local_data; |
|
if (local_data_store_ && local_data_store_->Read(&local_data)) { |
|
*reply->mutable_local_data() = local_data; |
|
} |
|
int counter; |
|
int threshold; |
|
bool lockout; |
|
int lockout_time_remaining; |
|
if (tpm_status_->GetDictionaryAttackInfo(&counter, &threshold, &lockout, |
|
&lockout_time_remaining)) { |
|
reply->set_dictionary_attack_counter(counter); |
|
reply->set_dictionary_attack_threshold(threshold); |
|
reply->set_dictionary_attack_lockout_in_effect(lockout); |
|
reply->set_dictionary_attack_lockout_seconds_remaining( |
|
lockout_time_remaining); |
|
} |
|
reply->set_status(STATUS_SUCCESS); |
|
} |
|
|
|
void TpmManagerService::TakeOwnership(const TakeOwnershipRequest& request, |
|
const TakeOwnershipCallback& callback) { |
|
PostTaskToWorkerThread<TakeOwnershipReply>( |
|
request, callback, &TpmManagerService::TakeOwnershipTask); |
|
} |
|
|
|
void TpmManagerService::TakeOwnershipTask( |
|
const TakeOwnershipRequest& request, |
|
const std::shared_ptr<TakeOwnershipReply>& reply) { |
|
VLOG(1) << __func__; |
|
if (!tpm_status_->IsTpmEnabled()) { |
|
reply->set_status(STATUS_NOT_AVAILABLE); |
|
return; |
|
} |
|
if (!tpm_initializer_->InitializeTpm()) { |
|
reply->set_status(STATUS_DEVICE_ERROR); |
|
return; |
|
} |
|
reply->set_status(STATUS_SUCCESS); |
|
} |
|
|
|
void TpmManagerService::RemoveOwnerDependency( |
|
const RemoveOwnerDependencyRequest& request, |
|
const RemoveOwnerDependencyCallback& callback) { |
|
PostTaskToWorkerThread<RemoveOwnerDependencyReply>( |
|
request, callback, &TpmManagerService::RemoveOwnerDependencyTask); |
|
} |
|
|
|
void TpmManagerService::RemoveOwnerDependencyTask( |
|
const RemoveOwnerDependencyRequest& request, |
|
const std::shared_ptr<RemoveOwnerDependencyReply>& reply) { |
|
VLOG(1) << __func__; |
|
LocalData local_data; |
|
if (!local_data_store_->Read(&local_data)) { |
|
reply->set_status(STATUS_DEVICE_ERROR); |
|
return; |
|
} |
|
RemoveOwnerDependency(request.owner_dependency(), &local_data); |
|
if (!local_data_store_->Write(local_data)) { |
|
reply->set_status(STATUS_DEVICE_ERROR); |
|
return; |
|
} |
|
reply->set_status(STATUS_SUCCESS); |
|
} |
|
|
|
void TpmManagerService::RemoveOwnerDependency( |
|
const std::string& owner_dependency, |
|
LocalData* local_data) { |
|
google::protobuf::RepeatedPtrField<std::string>* dependencies = |
|
local_data->mutable_owner_dependency(); |
|
for (int i = 0; i < dependencies->size(); i++) { |
|
if (dependencies->Get(i) == owner_dependency) { |
|
dependencies->SwapElements(i, (dependencies->size() - 1)); |
|
dependencies->RemoveLast(); |
|
break; |
|
} |
|
} |
|
if (dependencies->empty()) { |
|
local_data->clear_owner_password(); |
|
local_data->clear_endorsement_password(); |
|
local_data->clear_lockout_password(); |
|
} |
|
} |
|
|
|
void TpmManagerService::DefineSpace(const DefineSpaceRequest& request, |
|
const DefineSpaceCallback& callback) { |
|
PostTaskToWorkerThread<DefineSpaceReply>(request, callback, |
|
&TpmManagerService::DefineSpaceTask); |
|
} |
|
|
|
void TpmManagerService::DefineSpaceTask( |
|
const DefineSpaceRequest& request, |
|
const std::shared_ptr<DefineSpaceReply>& reply) { |
|
VLOG(1) << __func__; |
|
std::vector<NvramSpaceAttribute> attributes; |
|
for (int i = 0; i < request.attributes_size(); ++i) { |
|
attributes.push_back(request.attributes(i)); |
|
} |
|
reply->set_result( |
|
tpm_nvram_->DefineSpace(request.index(), request.size(), attributes, |
|
request.authorization_value(), request.policy())); |
|
} |
|
|
|
void TpmManagerService::DestroySpace(const DestroySpaceRequest& request, |
|
const DestroySpaceCallback& callback) { |
|
PostTaskToWorkerThread<DestroySpaceReply>( |
|
request, callback, &TpmManagerService::DestroySpaceTask); |
|
} |
|
|
|
void TpmManagerService::DestroySpaceTask( |
|
const DestroySpaceRequest& request, |
|
const std::shared_ptr<DestroySpaceReply>& reply) { |
|
VLOG(1) << __func__; |
|
reply->set_result(tpm_nvram_->DestroySpace(request.index())); |
|
} |
|
|
|
void TpmManagerService::WriteSpace(const WriteSpaceRequest& request, |
|
const WriteSpaceCallback& callback) { |
|
PostTaskToWorkerThread<WriteSpaceReply>(request, callback, |
|
&TpmManagerService::WriteSpaceTask); |
|
} |
|
|
|
void TpmManagerService::WriteSpaceTask( |
|
const WriteSpaceRequest& request, |
|
const std::shared_ptr<WriteSpaceReply>& reply) { |
|
VLOG(1) << __func__; |
|
std::string authorization_value = request.authorization_value(); |
|
if (request.use_owner_authorization()) { |
|
authorization_value = GetOwnerPassword(); |
|
if (authorization_value.empty()) { |
|
reply->set_result(NVRAM_RESULT_ACCESS_DENIED); |
|
return; |
|
} |
|
} |
|
reply->set_result(tpm_nvram_->WriteSpace(request.index(), request.data(), |
|
authorization_value)); |
|
} |
|
|
|
void TpmManagerService::ReadSpace(const ReadSpaceRequest& request, |
|
const ReadSpaceCallback& callback) { |
|
PostTaskToWorkerThread<ReadSpaceReply>(request, callback, |
|
&TpmManagerService::ReadSpaceTask); |
|
} |
|
|
|
void TpmManagerService::ReadSpaceTask( |
|
const ReadSpaceRequest& request, |
|
const std::shared_ptr<ReadSpaceReply>& reply) { |
|
VLOG(1) << __func__; |
|
std::string authorization_value = request.authorization_value(); |
|
if (request.use_owner_authorization()) { |
|
authorization_value = GetOwnerPassword(); |
|
if (authorization_value.empty()) { |
|
reply->set_result(NVRAM_RESULT_ACCESS_DENIED); |
|
return; |
|
} |
|
} |
|
reply->set_result(tpm_nvram_->ReadSpace( |
|
request.index(), reply->mutable_data(), authorization_value)); |
|
} |
|
|
|
void TpmManagerService::LockSpace(const LockSpaceRequest& request, |
|
const LockSpaceCallback& callback) { |
|
PostTaskToWorkerThread<LockSpaceReply>(request, callback, |
|
&TpmManagerService::LockSpaceTask); |
|
} |
|
|
|
void TpmManagerService::LockSpaceTask( |
|
const LockSpaceRequest& request, |
|
const std::shared_ptr<LockSpaceReply>& reply) { |
|
VLOG(1) << __func__; |
|
std::string authorization_value = request.authorization_value(); |
|
if (request.use_owner_authorization()) { |
|
authorization_value = GetOwnerPassword(); |
|
if (authorization_value.empty()) { |
|
reply->set_result(NVRAM_RESULT_ACCESS_DENIED); |
|
return; |
|
} |
|
} |
|
reply->set_result(tpm_nvram_->LockSpace(request.index(), request.lock_read(), |
|
request.lock_write(), |
|
authorization_value)); |
|
} |
|
|
|
void TpmManagerService::ListSpaces(const ListSpacesRequest& request, |
|
const ListSpacesCallback& callback) { |
|
PostTaskToWorkerThread<ListSpacesReply>(request, callback, |
|
&TpmManagerService::ListSpacesTask); |
|
} |
|
|
|
void TpmManagerService::ListSpacesTask( |
|
const ListSpacesRequest& request, |
|
const std::shared_ptr<ListSpacesReply>& reply) { |
|
VLOG(1) << __func__; |
|
std::vector<uint32_t> index_list; |
|
reply->set_result(tpm_nvram_->ListSpaces(&index_list)); |
|
if (reply->result() == NVRAM_RESULT_SUCCESS) { |
|
for (auto index : index_list) { |
|
reply->add_index_list(index); |
|
} |
|
} |
|
} |
|
|
|
void TpmManagerService::GetSpaceInfo(const GetSpaceInfoRequest& request, |
|
const GetSpaceInfoCallback& callback) { |
|
PostTaskToWorkerThread<GetSpaceInfoReply>( |
|
request, callback, &TpmManagerService::GetSpaceInfoTask); |
|
} |
|
|
|
void TpmManagerService::GetSpaceInfoTask( |
|
const GetSpaceInfoRequest& request, |
|
const std::shared_ptr<GetSpaceInfoReply>& reply) { |
|
VLOG(1) << __func__; |
|
std::vector<NvramSpaceAttribute> attributes; |
|
size_t size = 0; |
|
bool is_read_locked = false; |
|
bool is_write_locked = false; |
|
NvramSpacePolicy policy = NVRAM_POLICY_NONE; |
|
reply->set_result(tpm_nvram_->GetSpaceInfo(request.index(), &size, |
|
&is_read_locked, &is_write_locked, |
|
&attributes, &policy)); |
|
if (reply->result() == NVRAM_RESULT_SUCCESS) { |
|
reply->set_size(size); |
|
reply->set_is_read_locked(is_read_locked); |
|
reply->set_is_write_locked(is_write_locked); |
|
for (auto attribute : attributes) { |
|
reply->add_attributes(attribute); |
|
} |
|
reply->set_policy(policy); |
|
} |
|
} |
|
|
|
std::string TpmManagerService::GetOwnerPassword() { |
|
LocalData local_data; |
|
if (local_data_store_ && local_data_store_->Read(&local_data)) { |
|
return local_data.owner_password(); |
|
} |
|
LOG(ERROR) << "TPM owner password requested but not available."; |
|
return std::string(); |
|
} |
|
|
|
template <typename ReplyProtobufType> |
|
void TpmManagerService::TaskRelayCallback( |
|
const base::Callback<void(const ReplyProtobufType&)> callback, |
|
const std::shared_ptr<ReplyProtobufType>& reply) { |
|
callback.Run(*reply); |
|
} |
|
|
|
template <typename ReplyProtobufType, |
|
typename RequestProtobufType, |
|
typename ReplyCallbackType, |
|
typename TaskType> |
|
void TpmManagerService::PostTaskToWorkerThread(RequestProtobufType& request, |
|
ReplyCallbackType& callback, |
|
TaskType task) { |
|
auto result = std::make_shared<ReplyProtobufType>(); |
|
base::Closure background_task = |
|
base::Bind(task, base::Unretained(this), request, result); |
|
base::Closure reply = |
|
base::Bind(&TpmManagerService::TaskRelayCallback<ReplyProtobufType>, |
|
weak_factory_.GetWeakPtr(), callback, result); |
|
worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, background_task, |
|
reply); |
|
} |
|
|
|
} // namespace tpm_manager
|
|
|