// // 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 #include #include 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( request, callback, &TpmManagerService::GetTpmStatusTask); } void TpmManagerService::GetTpmStatusTask( const GetTpmStatusRequest& request, const std::shared_ptr& 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( request, callback, &TpmManagerService::TakeOwnershipTask); } void TpmManagerService::TakeOwnershipTask( const TakeOwnershipRequest& request, const std::shared_ptr& 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( request, callback, &TpmManagerService::RemoveOwnerDependencyTask); } void TpmManagerService::RemoveOwnerDependencyTask( const RemoveOwnerDependencyRequest& request, const std::shared_ptr& 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* 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(request, callback, &TpmManagerService::DefineSpaceTask); } void TpmManagerService::DefineSpaceTask( const DefineSpaceRequest& request, const std::shared_ptr& reply) { VLOG(1) << __func__; std::vector 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( request, callback, &TpmManagerService::DestroySpaceTask); } void TpmManagerService::DestroySpaceTask( const DestroySpaceRequest& request, const std::shared_ptr& reply) { VLOG(1) << __func__; reply->set_result(tpm_nvram_->DestroySpace(request.index())); } void TpmManagerService::WriteSpace(const WriteSpaceRequest& request, const WriteSpaceCallback& callback) { PostTaskToWorkerThread(request, callback, &TpmManagerService::WriteSpaceTask); } void TpmManagerService::WriteSpaceTask( const WriteSpaceRequest& request, const std::shared_ptr& 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(request, callback, &TpmManagerService::ReadSpaceTask); } void TpmManagerService::ReadSpaceTask( const ReadSpaceRequest& request, const std::shared_ptr& 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(request, callback, &TpmManagerService::LockSpaceTask); } void TpmManagerService::LockSpaceTask( const LockSpaceRequest& request, const std::shared_ptr& 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(request, callback, &TpmManagerService::ListSpacesTask); } void TpmManagerService::ListSpacesTask( const ListSpacesRequest& request, const std::shared_ptr& reply) { VLOG(1) << __func__; std::vector 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( request, callback, &TpmManagerService::GetSpaceInfoTask); } void TpmManagerService::GetSpaceInfoTask( const GetSpaceInfoRequest& request, const std::shared_ptr& reply) { VLOG(1) << __func__; std::vector 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 void TpmManagerService::TaskRelayCallback( const base::Callback callback, const std::shared_ptr& reply) { callback.Run(*reply); } template void TpmManagerService::PostTaskToWorkerThread(RequestProtobufType& request, ReplyCallbackType& callback, TaskType task) { auto result = std::make_shared(); base::Closure background_task = base::Bind(task, base::Unretained(this), request, result); base::Closure reply = base::Bind(&TpmManagerService::TaskRelayCallback, weak_factory_.GetWeakPtr(), callback, result); worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, background_task, reply); } } // namespace tpm_manager