// // 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() { LOG(INFO) << "TpmManager service started."; 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); return true; } void TpmManagerService::InitializeTask() { if (!tpm_status_->IsTpmEnabled()) { LOG(WARNING) << __func__ << ": TPM is disabled."; return; } 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>& result) { VLOG(1) << __func__; result->set_enabled(tpm_status_->IsTpmEnabled()); result->set_owned(tpm_status_->IsTpmOwned()); LocalData local_data; if (local_data_store_ && local_data_store_->Read(&local_data)) { *result->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)) { result->set_dictionary_attack_counter(counter); result->set_dictionary_attack_threshold(threshold); result->set_dictionary_attack_lockout_in_effect(lockout); result->set_dictionary_attack_lockout_seconds_remaining( lockout_time_remaining); } result->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>& result) { VLOG(1) << __func__; if (!tpm_status_->IsTpmEnabled()) { result->set_status(STATUS_NOT_AVAILABLE); return; } if (!tpm_initializer_->InitializeTpm()) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->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>& result) { VLOG(1) << __func__; LocalData local_data; if (!local_data_store_->Read(&local_data)) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } RemoveOwnerDependency(request.owner_dependency(), &local_data); if (!local_data_store_->Write(local_data)) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->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::DefineNvram(const DefineNvramRequest& request, const DefineNvramCallback& callback) { PostTaskToWorkerThread<DefineNvramReply>( request, callback, &TpmManagerService::DefineNvramTask); } void TpmManagerService::DefineNvramTask( const DefineNvramRequest& request, const std::shared_ptr<DefineNvramReply>& result) { VLOG(1) << __func__; if (!tpm_nvram_->DefineNvram(request.index(), request.length())) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_status(STATUS_SUCCESS); } void TpmManagerService::DestroyNvram(const DestroyNvramRequest& request, const DestroyNvramCallback& callback) { PostTaskToWorkerThread<DestroyNvramReply>( request, callback, &TpmManagerService::DestroyNvramTask); } void TpmManagerService::DestroyNvramTask( const DestroyNvramRequest& request, const std::shared_ptr<DestroyNvramReply>& result) { VLOG(1) << __func__; if (!tpm_nvram_->DestroyNvram(request.index())) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_status(STATUS_SUCCESS); } void TpmManagerService::WriteNvram(const WriteNvramRequest& request, const WriteNvramCallback& callback) { PostTaskToWorkerThread<WriteNvramReply>( request, callback, &TpmManagerService::WriteNvramTask); } void TpmManagerService::WriteNvramTask( const WriteNvramRequest& request, const std::shared_ptr<WriteNvramReply>& result) { VLOG(1) << __func__; if (!tpm_nvram_->WriteNvram(request.index(), request.data())) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_status(STATUS_SUCCESS); } void TpmManagerService::ReadNvram(const ReadNvramRequest& request, const ReadNvramCallback& callback) { PostTaskToWorkerThread<ReadNvramReply>( request, callback, &TpmManagerService::ReadNvramTask); } void TpmManagerService::ReadNvramTask( const ReadNvramRequest& request, const std::shared_ptr<ReadNvramReply>& result) { VLOG(1) << __func__; if (!tpm_nvram_->ReadNvram(request.index(), result->mutable_data())) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_status(STATUS_SUCCESS); } void TpmManagerService::IsNvramDefined(const IsNvramDefinedRequest& request, const IsNvramDefinedCallback& callback) { PostTaskToWorkerThread<IsNvramDefinedReply>( request, callback, &TpmManagerService::IsNvramDefinedTask); } void TpmManagerService::IsNvramDefinedTask( const IsNvramDefinedRequest& request, const std::shared_ptr<IsNvramDefinedReply>& result) { VLOG(1) << __func__; bool defined; if (!tpm_nvram_->IsNvramDefined(request.index(), &defined)) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_is_defined(defined); result->set_status(STATUS_SUCCESS); } void TpmManagerService::IsNvramLocked(const IsNvramLockedRequest& request, const IsNvramLockedCallback& callback) { PostTaskToWorkerThread<IsNvramLockedReply>( request, callback, &TpmManagerService::IsNvramLockedTask); } void TpmManagerService::IsNvramLockedTask( const IsNvramLockedRequest& request, const std::shared_ptr<IsNvramLockedReply>& result) { VLOG(1) << __func__; bool locked; if (!tpm_nvram_->IsNvramLocked(request.index(), &locked)) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_is_locked(locked); result->set_status(STATUS_SUCCESS); } void TpmManagerService::GetNvramSize(const GetNvramSizeRequest& request, const GetNvramSizeCallback& callback) { PostTaskToWorkerThread<GetNvramSizeReply>( request, callback, &TpmManagerService::GetNvramSizeTask); } void TpmManagerService::GetNvramSizeTask( const GetNvramSizeRequest& request, const std::shared_ptr<GetNvramSizeReply>& result) { VLOG(1) << __func__; size_t size; if (!tpm_nvram_->GetNvramSize(request.index(), &size)) { result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR); return; } result->set_size(size); result->set_status(STATUS_SUCCESS); } 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