// // 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 <string> #include <brillo/bind_lambda.h> #include <brillo/dbus/dbus_object_test_helpers.h> #include <dbus/mock_bus.h> #include <dbus/mock_exported_object.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include "tpm_manager/common/mock_tpm_nvram_interface.h" #include "tpm_manager/common/mock_tpm_ownership_interface.h" #include "tpm_manager/common/tpm_manager_constants.h" #include "tpm_manager/common/tpm_nvram_dbus_interface.h" #include "tpm_manager/common/tpm_ownership_dbus_interface.h" #include "tpm_manager/server/dbus_service.h" using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::StrictMock; using testing::WithArgs; namespace tpm_manager { class DBusServiceTest : public testing::Test { public: ~DBusServiceTest() override = default; void SetUp() override { dbus::Bus::Options options; mock_bus_ = new NiceMock<dbus::MockBus>(options); dbus::ObjectPath path(kTpmManagerServicePath); mock_exported_object_ = new NiceMock<dbus::MockExportedObject>( mock_bus_.get(), path); ON_CALL(*mock_bus_, GetExportedObject(path)) .WillByDefault(Return(mock_exported_object_.get())); dbus_service_.reset(new DBusService(mock_bus_, &mock_nvram_service_, &mock_ownership_service_)); dbus_service_->Register(brillo::dbus_utils::AsyncEventSequencer:: GetDefaultCompletionAction()); } template<typename RequestProtobufType, typename ReplyProtobufType> void ExecuteMethod(const std::string& method_name, const RequestProtobufType& request, ReplyProtobufType* reply, const std::string& interface) { std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name, interface); dbus::MessageWriter writer(call.get()); writer.AppendProtoAsArrayOfBytes(request); auto response = brillo::dbus_utils::testing::CallMethod( dbus_service_->dbus_object_, call.get()); dbus::MessageReader reader(response.get()); EXPECT_TRUE(reader.PopArrayOfBytesAsProto(reply)); } protected: std::unique_ptr<dbus::MethodCall> CreateMethodCall( const std::string& method_name, const std::string& interface) { std::unique_ptr<dbus::MethodCall> call(new dbus::MethodCall( interface, method_name)); call->SetSerial(1); return call; } scoped_refptr<dbus::MockBus> mock_bus_; scoped_refptr<dbus::MockExportedObject> mock_exported_object_; StrictMock<MockTpmNvramInterface> mock_nvram_service_; StrictMock<MockTpmOwnershipInterface> mock_ownership_service_; std::unique_ptr<DBusService> dbus_service_; }; TEST_F(DBusServiceTest, CopyableCallback) { EXPECT_CALL(mock_ownership_service_, GetTpmStatus(_, _)) .WillOnce(WithArgs<1>(Invoke([]( const TpmOwnershipInterface::GetTpmStatusCallback& callback) { // Copy the callback, then call the original. GetTpmStatusReply reply; base::Closure copy = base::Bind(callback, reply); callback.Run(reply); }))); GetTpmStatusRequest request; GetTpmStatusReply reply; ExecuteMethod(kGetTpmStatus, request, &reply, kTpmOwnershipInterface); } TEST_F(DBusServiceTest, GetTpmStatus) { GetTpmStatusRequest request; EXPECT_CALL(mock_ownership_service_, GetTpmStatus(_, _)) .WillOnce(Invoke([]( const GetTpmStatusRequest& request, const TpmOwnershipInterface::GetTpmStatusCallback& callback) { GetTpmStatusReply reply; reply.set_status(STATUS_SUCCESS); reply.set_enabled(true); reply.set_owned(true); reply.set_dictionary_attack_counter(3); reply.set_dictionary_attack_threshold(4); reply.set_dictionary_attack_lockout_in_effect(true); reply.set_dictionary_attack_lockout_seconds_remaining(5); callback.Run(reply); })); GetTpmStatusReply reply; ExecuteMethod(kGetTpmStatus, request, &reply, kTpmOwnershipInterface); EXPECT_EQ(STATUS_SUCCESS, reply.status()); EXPECT_TRUE(reply.enabled()); EXPECT_TRUE(reply.owned()); EXPECT_EQ(3, reply.dictionary_attack_counter()); EXPECT_EQ(4, reply.dictionary_attack_threshold()); EXPECT_TRUE(reply.dictionary_attack_lockout_in_effect()); EXPECT_EQ(5, reply.dictionary_attack_lockout_seconds_remaining()); } TEST_F(DBusServiceTest, TakeOwnership) { EXPECT_CALL(mock_ownership_service_, TakeOwnership(_, _)) .WillOnce(Invoke([]( const TakeOwnershipRequest& request, const TpmOwnershipInterface::TakeOwnershipCallback& callback) { TakeOwnershipReply reply; reply.set_status(STATUS_SUCCESS); callback.Run(reply); })); TakeOwnershipRequest request; TakeOwnershipReply reply; ExecuteMethod(kTakeOwnership, request, &reply, kTpmOwnershipInterface); EXPECT_EQ(STATUS_SUCCESS, reply.status()); } TEST_F(DBusServiceTest, RemoveOwnerDependency) { std::string owner_dependency("owner_dependency"); RemoveOwnerDependencyRequest request; request.set_owner_dependency(owner_dependency); EXPECT_CALL(mock_ownership_service_, RemoveOwnerDependency(_, _)) .WillOnce(Invoke([&owner_dependency]( const RemoveOwnerDependencyRequest& request, const TpmOwnershipInterface::RemoveOwnerDependencyCallback& callback) { EXPECT_TRUE(request.has_owner_dependency()); EXPECT_EQ(owner_dependency, request.owner_dependency()); RemoveOwnerDependencyReply reply; reply.set_status(STATUS_SUCCESS); callback.Run(reply); })); RemoveOwnerDependencyReply reply; ExecuteMethod(kRemoveOwnerDependency, request, &reply, kTpmOwnershipInterface); 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_nvram_service_, DefineNvram(_, _)) .WillOnce(Invoke([nvram_index, nvram_length]( const DefineNvramRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); 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_nvram_service_, DestroyNvram(_, _)) .WillOnce(Invoke([nvram_index]( const DestroyNvramRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); 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_nvram_service_, WriteNvram(_, _)) .WillOnce(Invoke([nvram_index, nvram_data]( const WriteNvramRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); 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_nvram_service_, ReadNvram(_, _)) .WillOnce(Invoke([nvram_index, nvram_data]( const ReadNvramRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); 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_nvram_service_, IsNvramDefined(_, _)) .WillOnce(Invoke([nvram_index, nvram_defined]( const IsNvramDefinedRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); 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_nvram_service_, IsNvramLocked(_, _)) .WillOnce(Invoke([nvram_index, nvram_locked]( const IsNvramLockedRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); 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_nvram_service_, GetNvramSize(_, _)) .WillOnce(Invoke([nvram_index, nvram_size]( const GetNvramSizeRequest& request, const TpmNvramInterface::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, kTpmNvramInterface); EXPECT_EQ(STATUS_SUCCESS, reply.status()); EXPECT_TRUE(reply.has_size()); EXPECT_EQ(nvram_size, reply.size()); } } // namespace tpm_manager