| // |
| // 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/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(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( |
| 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)); |
| } |
| |
| 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.set_owner_password(local_data.owner_password()); |
| payload.set_endorsement_password(local_data.endorsement_password()); |
| |
| // 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 |