diff options
author | Utkarsh Sanghi <usanghi@google.com> | 2015-10-01 10:45:24 -0700 |
---|---|---|
committer | Utkarsh Sanghi <usanghi@google.com> | 2015-10-06 10:39:03 -0700 |
commit | 98ad76f641c31a4e3ca99a6c2631305d53013484 (patch) | |
tree | 4c7e35f3a9c66c94f6f0fb52413cf1f306a950f3 | |
parent | c1871b10f64f774fc7c6364e3f5a6edb12b251f1 (diff) | |
download | tpm-98ad76f641c31a4e3ca99a6c2631305d53013484.tar.gz |
tpm_manager: Expose server side NVRAM API
This CL adds the server side implementation of the NVRAM api to receive
and process NVRAM methods on the server side
Bug: 24059574
TEST=FEATURES=test emerge-link tpm_manager
Change-Id: Id248c17f21adcb17d2142aa18738635df90f592e
-rw-r--r-- | common/tpm_manager_interface.h | 1 | ||||
-rw-r--r-- | server/dbus_service.cc | 111 | ||||
-rw-r--r-- | server/dbus_service.h | 28 | ||||
-rw-r--r-- | server/dbus_service_test.cc | 202 |
4 files changed, 275 insertions, 67 deletions
diff --git a/common/tpm_manager_interface.h b/common/tpm_manager_interface.h index 967f2a2..f16ec93 100644 --- a/common/tpm_manager_interface.h +++ b/common/tpm_manager_interface.h @@ -26,6 +26,7 @@ namespace tpm_manager { // This is the main TpmManager interface that is implemented by the proxies // and services. +// TODO(usanghi): Break up the DBus interface (b/24659038). class TPM_MANAGER_EXPORT TpmManagerInterface { public: virtual ~TpmManagerInterface() = default; diff --git a/server/dbus_service.cc b/server/dbus_service.cc index e2b6d4a..2520232 100644 --- a/server/dbus_service.cc +++ b/server/dbus_service.cc @@ -25,8 +25,6 @@ #include "tpm_manager/common/dbus_interface.h" -using chromeos::dbus_utils::DBusMethodResponse; - namespace tpm_manager { DBusService::DBusService(const scoped_refptr<dbus::Bus>& bus, @@ -38,43 +36,98 @@ void DBusService::Register(const CompletionAction& callback) { chromeos::dbus_utils::DBusInterface* dbus_interface = dbus_object_.AddOrGetInterface(kTpmManagerInterface); - dbus_interface->AddMethodHandler(kGetTpmStatus, base::Unretained(this), - &DBusService::HandleGetTpmStatus); - dbus_interface->AddMethodHandler(kTakeOwnership, base::Unretained(this), - &DBusService::HandleTakeOwnership); - dbus_object_.RegisterAsync(callback); -} + dbus_interface->AddMethodHandler( + kGetTpmStatus, + base::Unretained(this), + &DBusService::HandleDBusMethod< + GetTpmStatusRequest, + GetTpmStatusReply, + &TpmManagerInterface::GetTpmStatus>); -void DBusService::HandleGetTpmStatus( - std::unique_ptr<DBusMethodResponse<const GetTpmStatusReply&>> response, - const GetTpmStatusRequest& request) { - // Convert |response| to a shared_ptr so |service_| can safely copy the - // callback. - using SharedResponsePointer = std::shared_ptr< - DBusMethodResponse<const GetTpmStatusReply&>>; - // A callback that sends off the reply protobuf. - auto callback = [](const SharedResponsePointer& response, - const GetTpmStatusReply& reply) { - response->Return(reply); - }; - service_->GetTpmStatus( - request, - base::Bind(callback, SharedResponsePointer(std::move(response)))); + dbus_interface->AddMethodHandler( + kTakeOwnership, + base::Unretained(this), + &DBusService::HandleDBusMethod< + TakeOwnershipRequest, + TakeOwnershipReply, + &TpmManagerInterface::TakeOwnership>); + + dbus_interface->AddMethodHandler( + kDefineNvram, + base::Unretained(this), + &DBusService::HandleDBusMethod< + DefineNvramRequest, + DefineNvramReply, + &TpmManagerInterface::DefineNvram>); + + dbus_interface->AddMethodHandler( + kDestroyNvram, + base::Unretained(this), + &DBusService::HandleDBusMethod< + DestroyNvramRequest, + DestroyNvramReply, + &TpmManagerInterface::DestroyNvram>); + + dbus_interface->AddMethodHandler( + kWriteNvram, + base::Unretained(this), + &DBusService::HandleDBusMethod< + WriteNvramRequest, + WriteNvramReply, + &TpmManagerInterface::WriteNvram>); + + dbus_interface->AddMethodHandler( + kReadNvram, + base::Unretained(this), + &DBusService::HandleDBusMethod< + ReadNvramRequest, + ReadNvramReply, + &TpmManagerInterface::ReadNvram>); + + dbus_interface->AddMethodHandler( + kIsNvramDefined, + base::Unretained(this), + &DBusService::HandleDBusMethod< + IsNvramDefinedRequest, + IsNvramDefinedReply, + &TpmManagerInterface::IsNvramDefined>); + + dbus_interface->AddMethodHandler( + kIsNvramLocked, + base::Unretained(this), + &DBusService::HandleDBusMethod< + IsNvramLockedRequest, + IsNvramLockedReply, + &TpmManagerInterface::IsNvramLocked>); + + dbus_interface->AddMethodHandler( + kGetNvramSize, + base::Unretained(this), + &DBusService::HandleDBusMethod< + GetNvramSizeRequest, + GetNvramSizeReply, + &TpmManagerInterface::GetNvramSize>); + + dbus_object_.RegisterAsync(callback); } -void DBusService::HandleTakeOwnership( - std::unique_ptr<DBusMethodResponse<const TakeOwnershipReply&>> response, - const TakeOwnershipRequest& request) { +template<typename RequestProtobufType, + typename ReplyProtobufType, + DBusService::HandlerFunction<RequestProtobufType, + ReplyProtobufType> func> +void DBusService::HandleDBusMethod( + std::unique_ptr<DBusMethodResponse<const ReplyProtobufType&>> response, + const RequestProtobufType& request) { // Convert |response| to a shared_ptr so |service_| can safely copy the // callback. using SharedResponsePointer = std::shared_ptr< - DBusMethodResponse<const TakeOwnershipReply&>>; + DBusMethodResponse<const ReplyProtobufType&>>; // A callback that sends off the reply protobuf. auto callback = [](const SharedResponsePointer& response, - const TakeOwnershipReply& reply) { + const ReplyProtobufType& reply) { response->Return(reply); }; - service_->TakeOwnership( + (service_->*func)( request, base::Bind(callback, SharedResponsePointer(std::move(response)))); } diff --git a/server/dbus_service.h b/server/dbus_service.h index fb15fab..61d6219 100644 --- a/server/dbus_service.h +++ b/server/dbus_service.h @@ -27,6 +27,7 @@ namespace tpm_manager { +using chromeos::dbus_utils::DBusMethodResponse; using CompletionAction = chromeos::dbus_utils::AsyncEventSequencer::CompletionAction; @@ -42,24 +43,23 @@ class DBusService { // Connects to D-Bus system bus and exports TpmManager methods. void Register(const CompletionAction& callback); - void set_service(TpmManagerInterface* service) { - service_ = service; - } - private: friend class DBusServiceTest; - // Handles the GetTpmStatus D-Bus call. - void HandleGetTpmStatus( - std::unique_ptr<chromeos::dbus_utils::DBusMethodResponse< - const GetTpmStatusReply&>> response, - const GetTpmStatusRequest& request); + template<typename RequestProtobufType, + typename ReplyProtobufType> + using HandlerFunction = void(TpmManagerInterface::*)( + const RequestProtobufType&, + const base::Callback<void(const ReplyProtobufType&)>&); - // Handles the TakeOwnership D-Bus call. - void HandleTakeOwnership( - std::unique_ptr<chromeos::dbus_utils::DBusMethodResponse< - const TakeOwnershipReply&>> response, - const TakeOwnershipRequest& request); + // Template to handle D-Bus calls. + template<typename RequestProtobufType, + typename ReplyProtobufType, + DBusService::HandlerFunction<RequestProtobufType, + ReplyProtobufType> func> + void HandleDBusMethod( + std::unique_ptr<DBusMethodResponse<const ReplyProtobufType&>> response, + const RequestProtobufType& request); chromeos::dbus_utils::DBusObject dbus_object_; TpmManagerInterface* service_; diff --git a/server/dbus_service_test.cc b/server/dbus_service_test.cc index 058e968..1c41056 100644 --- a/server/dbus_service_test.cc +++ b/server/dbus_service_test.cc @@ -52,6 +52,19 @@ class DBusServiceTest : public testing::Test { GetDefaultCompletionAction()); } + template<typename RequestProtobufType, typename ReplyProtobufType> + void ExecuteMethod(const std::string& method_name, + const RequestProtobufType& request, + ReplyProtobufType* reply) { + std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name); + dbus::MessageWriter writer(call.get()); + writer.AppendProtoAsArrayOfBytes(request); + auto response = CallMethod(call.get()); + dbus::MessageReader reader(response.get()); + EXPECT_TRUE(reader.PopArrayOfBytesAsProto(reply)); + } + + protected: std::unique_ptr<dbus::Response> CallMethod(dbus::MethodCall* method_call) { return chromeos::dbus_utils::testing::CallMethod( dbus_service_->dbus_object_, method_call); @@ -65,7 +78,6 @@ class DBusServiceTest : public testing::Test { return call; } - protected: scoped_refptr<dbus::MockBus> mock_bus_; scoped_refptr<dbus::MockExportedObject> mock_exported_object_; StrictMock<MockTpmManagerInterface> mock_service_; @@ -81,14 +93,9 @@ TEST_F(DBusServiceTest, CopyableCallback) { base::Closure copy = base::Bind(callback, reply); callback.Run(reply); }))); - std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kGetTpmStatus); GetTpmStatusRequest request; - dbus::MessageWriter writer(call.get()); - writer.AppendProtoAsArrayOfBytes(request); - auto response = CallMethod(call.get()); - dbus::MessageReader reader(response.get()); GetTpmStatusReply reply; - EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); + ExecuteMethod(kGetTpmStatus, request, &reply); } TEST_F(DBusServiceTest, GetTpmStatus) { @@ -98,7 +105,7 @@ TEST_F(DBusServiceTest, GetTpmStatus) { const GetTpmStatusRequest& request, const TpmManagerInterface::GetTpmStatusCallback& callback) { GetTpmStatusReply reply; - reply.set_status(STATUS_NOT_AVAILABLE); + reply.set_status(STATUS_SUCCESS); reply.set_enabled(true); reply.set_owned(true); reply.mutable_local_data()->set_owned_by_this_install(true); @@ -108,14 +115,9 @@ TEST_F(DBusServiceTest, GetTpmStatus) { reply.set_dictionary_attack_lockout_seconds_remaining(5); callback.Run(reply); })); - std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kGetTpmStatus); - dbus::MessageWriter writer(call.get()); - writer.AppendProtoAsArrayOfBytes(request); - auto response = CallMethod(call.get()); - dbus::MessageReader reader(response.get()); GetTpmStatusReply reply; - EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); - EXPECT_EQ(STATUS_NOT_AVAILABLE, reply.status()); + ExecuteMethod(kGetTpmStatus, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); EXPECT_TRUE(reply.enabled()); EXPECT_TRUE(reply.owned()); EXPECT_TRUE(reply.local_data().owned_by_this_install()); @@ -126,23 +128,175 @@ TEST_F(DBusServiceTest, GetTpmStatus) { } TEST_F(DBusServiceTest, TakeOwnership) { - TakeOwnershipRequest request; EXPECT_CALL(mock_service_, TakeOwnership(_, _)) .WillOnce(Invoke([]( const TakeOwnershipRequest& request, const TpmManagerInterface::TakeOwnershipCallback& callback) { TakeOwnershipReply reply; - reply.set_status(STATUS_NOT_AVAILABLE); + reply.set_status(STATUS_SUCCESS); callback.Run(reply); })); - std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kTakeOwnership); - dbus::MessageWriter writer(call.get()); - writer.AppendProtoAsArrayOfBytes(request); - auto response = CallMethod(call.get()); - dbus::MessageReader reader(response.get()); + TakeOwnershipRequest request; TakeOwnershipReply reply; - EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); - EXPECT_EQ(STATUS_NOT_AVAILABLE, reply.status()); + ExecuteMethod(kTakeOwnership, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); +} + +TEST_F(DBusServiceTest, DefineNvram) { + uint32_t nvram_index = 5; + size_t nvram_length = 32; + DefineNvramRequest request; + request.set_index(nvram_index); + request.set_length(nvram_length); + EXPECT_CALL(mock_service_, DefineNvram(_, _)) + .WillOnce(Invoke([nvram_index, nvram_length]( + const DefineNvramRequest& request, + const TpmManagerInterface::DefineNvramCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + EXPECT_TRUE(request.has_length()); + EXPECT_EQ(nvram_length, request.length()); + DefineNvramReply reply; + reply.set_status(STATUS_SUCCESS); + callback.Run(reply); + })); + DefineNvramReply reply; + ExecuteMethod(kDefineNvram, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); +} + +TEST_F(DBusServiceTest, DestroyNvram) { + uint32_t nvram_index = 5; + DestroyNvramRequest request; + request.set_index(nvram_index); + EXPECT_CALL(mock_service_, DestroyNvram(_, _)) + .WillOnce(Invoke([nvram_index]( + const DestroyNvramRequest& request, + const TpmManagerInterface::DestroyNvramCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + DestroyNvramReply reply; + reply.set_status(STATUS_SUCCESS); + callback.Run(reply); + })); + DestroyNvramReply reply; + ExecuteMethod(kDestroyNvram, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); +} + +TEST_F(DBusServiceTest, WriteNvram) { + uint32_t nvram_index = 5; + std::string nvram_data("nvram_data"); + WriteNvramRequest request; + request.set_index(nvram_index); + request.set_data(nvram_data); + EXPECT_CALL(mock_service_, WriteNvram(_, _)) + .WillOnce(Invoke([nvram_index, nvram_data]( + const WriteNvramRequest& request, + const TpmManagerInterface::WriteNvramCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + EXPECT_TRUE(request.has_data()); + EXPECT_EQ(nvram_data, request.data()); + WriteNvramReply reply; + reply.set_status(STATUS_SUCCESS); + callback.Run(reply); + })); + WriteNvramReply reply; + ExecuteMethod(kWriteNvram, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); +} + +TEST_F(DBusServiceTest, ReadNvram) { + uint32_t nvram_index = 5; + std::string nvram_data("nvram_data"); + ReadNvramRequest request; + request.set_index(nvram_index); + EXPECT_CALL(mock_service_, ReadNvram(_, _)) + .WillOnce(Invoke([nvram_index, nvram_data]( + const ReadNvramRequest& request, + const TpmManagerInterface::ReadNvramCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + ReadNvramReply reply; + reply.set_status(STATUS_SUCCESS); + reply.set_data(nvram_data); + callback.Run(reply); + })); + ReadNvramReply reply; + ExecuteMethod(kReadNvram, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); + EXPECT_TRUE(reply.has_data()); + EXPECT_EQ(nvram_data, reply.data()); +} + +TEST_F(DBusServiceTest, IsNvramDefined) { + uint32_t nvram_index = 5; + bool nvram_defined = true; + IsNvramDefinedRequest request; + request.set_index(nvram_index); + EXPECT_CALL(mock_service_, IsNvramDefined(_, _)) + .WillOnce(Invoke([nvram_index, nvram_defined]( + const IsNvramDefinedRequest& request, + const TpmManagerInterface::IsNvramDefinedCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + IsNvramDefinedReply reply; + reply.set_status(STATUS_SUCCESS); + reply.set_is_defined(nvram_defined); + callback.Run(reply); + })); + IsNvramDefinedReply reply; + ExecuteMethod(kIsNvramDefined, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); + EXPECT_TRUE(reply.has_is_defined()); + EXPECT_EQ(nvram_defined, reply.is_defined()); +} + +TEST_F(DBusServiceTest, IsNvramLocked) { + uint32_t nvram_index = 5; + bool nvram_locked = true; + IsNvramLockedRequest request; + request.set_index(nvram_index); + EXPECT_CALL(mock_service_, IsNvramLocked(_, _)) + .WillOnce(Invoke([nvram_index, nvram_locked]( + const IsNvramLockedRequest& request, + const TpmManagerInterface::IsNvramLockedCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + IsNvramLockedReply reply; + reply.set_status(STATUS_SUCCESS); + reply.set_is_locked(nvram_locked); + callback.Run(reply); + })); + IsNvramLockedReply reply; + ExecuteMethod(kIsNvramLocked, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); + EXPECT_TRUE(reply.has_is_locked()); + EXPECT_EQ(nvram_locked, reply.is_locked()); +} + +TEST_F(DBusServiceTest, GetNvramSize) { + uint32_t nvram_index = 5; + size_t nvram_size = 32; + GetNvramSizeRequest request; + request.set_index(nvram_index); + EXPECT_CALL(mock_service_, GetNvramSize(_, _)) + .WillOnce(Invoke([nvram_index, nvram_size]( + const GetNvramSizeRequest& request, + const TpmManagerInterface::GetNvramSizeCallback& callback) { + EXPECT_TRUE(request.has_index()); + EXPECT_EQ(nvram_index, request.index()); + GetNvramSizeReply reply; + reply.set_status(STATUS_SUCCESS); + reply.set_size(nvram_size); + callback.Run(reply); + })); + GetNvramSizeReply reply; + ExecuteMethod(kGetNvramSize, request, &reply); + EXPECT_EQ(STATUS_SUCCESS, reply.status()); + EXPECT_TRUE(reply.has_size()); + EXPECT_EQ(nvram_size, reply.size()); } } // namespace tpm_manager |