| // 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 "tpm_manager/server/dbus_service.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include <base/bind.h> |
| #include <brillo/daemons/dbus_daemon.h> |
| #include <brillo/dbus/async_event_sequencer.h> |
| #include <dbus/bus.h> |
| #include <dbus/object_path.h> |
| #include <tpm_manager-client/tpm_manager/dbus-constants.h> |
| |
| #include "tpm_manager/common/tpm_nvram_dbus_interface.h" |
| #include "tpm_manager/common/tpm_ownership_dbus_interface.h" |
| |
| namespace tpm_manager { |
| |
| using brillo::dbus_utils::DBusObject; |
| |
| DBusService::DBusService( |
| std::unique_ptr<TpmManagerService>&& tpm_manager_service, |
| LocalDataStore* local_data_store) |
| : DBusService(tpm_manager_service.get(), |
| tpm_manager_service.get(), |
| local_data_store) { |
| tpm_manager_service->SetOwnershipTakenCallback( |
| base::Bind(&DBusService::NotifyOwnershipIsTaken, base::Unretained(this))); |
| tpm_manager_service_ = std::move(tpm_manager_service); |
| } |
| |
| DBusService::DBusService(TpmNvramInterface* nvram_service, |
| TpmOwnershipInterface* ownership_service, |
| LocalDataStore* local_data_store) |
| : brillo::DBusServiceDaemon(tpm_manager::kTpmManagerServiceName), |
| nvram_service_(nvram_service), |
| ownership_service_(ownership_service), |
| local_data_store_(local_data_store) { |
| CHECK(nvram_service_); |
| CHECK(ownership_service_); |
| CHECK(local_data_store_); |
| } |
| |
| DBusService::DBusService(scoped_refptr<dbus::Bus> bus, |
| TpmNvramInterface* nvram_service, |
| TpmOwnershipInterface* ownership_service, |
| LocalDataStore* local_data_store) |
| : brillo::DBusServiceDaemon(tpm_manager::kTpmManagerServiceName), |
| dbus_object_(new DBusObject(nullptr, |
| bus, |
| dbus::ObjectPath(kTpmManagerServicePath))), |
| nvram_service_(nvram_service), |
| ownership_service_(ownership_service), |
| local_data_store_(local_data_store) |
| {} |
| |
| void DBusService::RegisterDBusObjectsAsync( |
| brillo::dbus_utils::AsyncEventSequencer* sequencer) { |
| if (!dbus_object_.get()) { |
| // At this point bus_ should be valid. |
| CHECK(bus_.get()); |
| dbus_object_.reset(new DBusObject( |
| nullptr, bus_, dbus::ObjectPath(kTpmManagerServicePath))); |
| } |
| brillo::dbus_utils::DBusInterface* ownership_dbus_interface = |
| dbus_object_->AddOrGetInterface(kTpmOwnershipInterface); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kGetTpmStatus, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| GetTpmStatusRequest, GetTpmStatusReply, |
| &TpmOwnershipInterface::GetTpmStatus>); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kGetVersionInfo, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| GetVersionInfoRequest, GetVersionInfoReply, |
| &TpmOwnershipInterface::GetVersionInfo>); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kGetDictionaryAttackInfo, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| GetDictionaryAttackInfoRequest, GetDictionaryAttackInfoReply, |
| &TpmOwnershipInterface::GetDictionaryAttackInfo>); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kResetDictionaryAttackLock, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| ResetDictionaryAttackLockRequest, ResetDictionaryAttackLockReply, |
| &TpmOwnershipInterface::ResetDictionaryAttackLock>); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kTakeOwnership, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| TakeOwnershipRequest, TakeOwnershipReply, |
| &TpmOwnershipInterface::TakeOwnership>); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kRemoveOwnerDependency, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| RemoveOwnerDependencyRequest, RemoveOwnerDependencyReply, |
| &TpmOwnershipInterface::RemoveOwnerDependency>); |
| |
| ownership_dbus_interface->AddMethodHandler( |
| kClearStoredOwnerPassword, base::Unretained(this), |
| &DBusService::HandleOwnershipDBusMethod< |
| ClearStoredOwnerPasswordRequest, ClearStoredOwnerPasswordReply, |
| &TpmOwnershipInterface::ClearStoredOwnerPassword>); |
| |
| ownership_taken_signal_ = |
| ownership_dbus_interface->RegisterSignal<OwnershipTakenSignal>( |
| kOwnershipTakenSignal); |
| |
| brillo::dbus_utils::DBusInterface* nvram_dbus_interface = |
| dbus_object_->AddOrGetInterface(kTpmNvramInterface); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kDefineSpace, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<DefineSpaceRequest, DefineSpaceReply, |
| &TpmNvramInterface::DefineSpace>); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kDestroySpace, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<DestroySpaceRequest, |
| DestroySpaceReply, |
| &TpmNvramInterface::DestroySpace>); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kWriteSpace, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<WriteSpaceRequest, WriteSpaceReply, |
| &TpmNvramInterface::WriteSpace>); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kReadSpace, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<ReadSpaceRequest, ReadSpaceReply, |
| &TpmNvramInterface::ReadSpace>); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kLockSpace, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<LockSpaceRequest, LockSpaceReply, |
| &TpmNvramInterface::LockSpace>); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kListSpaces, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<ListSpacesRequest, ListSpacesReply, |
| &TpmNvramInterface::ListSpaces>); |
| |
| nvram_dbus_interface->AddMethodHandler( |
| kGetSpaceInfo, base::Unretained(this), |
| &DBusService::HandleNvramDBusMethod<GetSpaceInfoRequest, |
| GetSpaceInfoReply, |
| &TpmNvramInterface::GetSpaceInfo>); |
| |
| dbus_object_->RegisterAsync( |
| sequencer->GetHandler("Failed to register D-Bus object.", true)); |
| } |
| |
| int DBusService::OnInit() { |
| int ret = brillo::DBusServiceDaemon::OnInit(); |
| // Initializes TpmManagerService only when we have ownership of it. This must |
| // go after brillo::DBusServiceDaemon::OnInit() so the asynchronous signal |
| // handling works as expected. |
| if (tpm_manager_service_) { |
| CHECK(tpm_manager_service_->Initialize()); |
| } |
| return ret; |
| } |
| |
| void DBusService::NotifyOwnershipIsTaken() { |
| ownership_already_taken_ = true; |
| |
| // Send the signal if it's registered in the ownership dbus interface. |
| MaybeSendOwnershipTakenSignal(); |
| } |
| |
| bool DBusService::MaybeSendOwnershipTakenSignal() { |
| if (already_sent_ownership_taken_signal_) { |
| return false; |
| } |
| |
| if (!ownership_already_taken_) { |
| return false; |
| } |
| |
| // We have to check if ownership_taken_signal_ is ready here because |
| // TpmInitializer may try to take TPM ownership in another thread before |
| // RegisterDBusObjectsAsync is called. |
| auto signal = ownership_taken_signal_.lock(); |
| if (!signal) { |
| LOG(INFO) << "Ownership taken signal has not been initialized yet."; |
| return false; |
| } |
| |
| LocalData local_data; |
| if (!local_data_store_->Read(&local_data)) { |
| LOG(ERROR) << "Failed to read local data."; |
| return false; |
| } |
| |
| OwnershipTakenSignal payload; |
| *payload.mutable_local_data() = local_data; |
| |
| // The proto message |payload| will be converted to array of bytes by Send(). |
| if (!signal->Send(payload)) { |
| LOG(ERROR) << "Failed to send ownership taken signal!"; |
| return false; |
| } |
| |
| already_sent_ownership_taken_signal_ = true; |
| LOG(INFO) << "Ownership taken signal is sent."; |
| return true; |
| } |
| |
| template <typename RequestProtobufType, |
| typename ReplyProtobufType, |
| DBusService::HandlerFunction<RequestProtobufType, |
| ReplyProtobufType, |
| TpmNvramInterface> func> |
| void DBusService::HandleNvramDBusMethod( |
| std::unique_ptr<DBusMethodResponse<const ReplyProtobufType&>> response, |
| const RequestProtobufType& request) { |
| // Convert |response| to a shared_ptr so |nvram_service_| can safely copy the |
| // callback. |
| using SharedResponsePointer = |
| std::shared_ptr<DBusMethodResponse<const ReplyProtobufType&>>; |
| // A callback that sends off the reply protobuf. |
| auto callback = [](const SharedResponsePointer& response, |
| const ReplyProtobufType& reply) { |
| response->Return(reply); |
| }; |
| (nvram_service_->*func)( |
| request, |
| base::Bind(callback, SharedResponsePointer(std::move(response)))); |
| } |
| |
| template <typename RequestProtobufType, |
| typename ReplyProtobufType, |
| DBusService::HandlerFunction<RequestProtobufType, |
| ReplyProtobufType, |
| TpmOwnershipInterface> func> |
| void DBusService::HandleOwnershipDBusMethod( |
| std::unique_ptr<DBusMethodResponse<const ReplyProtobufType&>> response, |
| const RequestProtobufType& request) { |
| // Convert |response| to a shared_ptr so |ownership_service_| can safely |
| // copy the callback. |
| using SharedResponsePointer = |
| std::shared_ptr<DBusMethodResponse<const ReplyProtobufType&>>; |
| // A callback that sends off the reply protobuf. |
| auto callback = [](const SharedResponsePointer& response, |
| const ReplyProtobufType& reply) { |
| response->Return(reply); |
| }; |
| (ownership_service_->*func)( |
| request, |
| base::Bind(callback, SharedResponsePointer(std::move(response)))); |
| } |
| |
| } // namespace tpm_manager |