blob: 50c116c156be500f651a3e65844547bfb792add3 [file] [log] [blame]
// 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 <string>
#include <base/bind.h>
#include <base/stl_util.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-client/tpm_manager/dbus-constants.h>
#include "tpm_manager/common/mock_tpm_nvram_interface.h"
#include "tpm_manager/common/mock_tpm_ownership_interface.h"
#include "tpm_manager/common/tpm_nvram_dbus_interface.h"
#include "tpm_manager/server/dbus_service.h"
#include "tpm_manager/server/mock_local_data_store.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_,
&mock_data_store_));
}
void RegisterDBusObjectsAsync() {
scoped_refptr<brillo::dbus_utils::AsyncEventSequencer> sequencer(
new brillo::dbus_utils::AsyncEventSequencer());
dbus_service_->RegisterDBusObjectsAsync(sequencer.get());
}
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<MockLocalDataStore> mock_data_store_;
StrictMock<MockTpmNvramInterface> mock_nvram_service_;
StrictMock<MockTpmOwnershipInterface> mock_ownership_service_;
std::unique_ptr<DBusService> dbus_service_;
};
TEST_F(DBusServiceTest, CopyableCallback) {
RegisterDBusObjectsAsync();
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, kTpmManagerInterface);
}
TEST_F(DBusServiceTest, GetTpmStatus) {
RegisterDBusObjectsAsync();
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);
callback.Run(reply);
}));
GetTpmStatusReply reply;
ExecuteMethod(kGetTpmStatus, request, &reply, kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
EXPECT_TRUE(reply.enabled());
EXPECT_TRUE(reply.owned());
}
TEST_F(DBusServiceTest, GetTpmNonsensitiveStatus) {
RegisterDBusObjectsAsync();
GetTpmNonsensitiveStatusRequest request;
EXPECT_CALL(mock_ownership_service_, GetTpmNonsensitiveStatus(_, _))
.WillOnce(Invoke(
[](const GetTpmNonsensitiveStatusRequest& request,
const TpmOwnershipInterface::GetTpmNonsensitiveStatusCallback&
callback) {
GetTpmNonsensitiveStatusReply reply;
reply.set_status(STATUS_SUCCESS);
reply.set_is_enabled(true);
reply.set_is_owned(true);
reply.set_is_owner_password_present(true);
reply.set_has_reset_lock_permissions(true);
callback.Run(reply);
}));
GetTpmNonsensitiveStatusReply reply;
ExecuteMethod(kGetTpmNonsensitiveStatus, request, &reply,
kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
EXPECT_TRUE(reply.is_enabled());
EXPECT_TRUE(reply.is_owned());
EXPECT_TRUE(reply.is_owner_password_present());
EXPECT_TRUE(reply.has_reset_lock_permissions());
}
TEST_F(DBusServiceTest, GetVersionInfo) {
RegisterDBusObjectsAsync();
GetVersionInfoReply expected_version_info;
expected_version_info.set_status(STATUS_SUCCESS);
expected_version_info.set_family(1);
expected_version_info.set_spec_level(2);
expected_version_info.set_manufacturer(3);
expected_version_info.set_tpm_model(4);
expected_version_info.set_firmware_version(5);
expected_version_info.set_vendor_specific("ab");
GetVersionInfoRequest request;
EXPECT_CALL(mock_ownership_service_, GetVersionInfo(_, _))
.WillOnce(Invoke(
[&expected_version_info](
const GetVersionInfoRequest& request,
const TpmOwnershipInterface::GetVersionInfoCallback& callback) {
callback.Run(expected_version_info);
}));
GetVersionInfoReply actual_version_info;
ExecuteMethod(kGetVersionInfo, request, &actual_version_info,
kTpmManagerInterface);
EXPECT_EQ(actual_version_info.SerializeAsString(),
expected_version_info.SerializeAsString());
}
TEST_F(DBusServiceTest, GetDictionaryAttackInfo) {
RegisterDBusObjectsAsync();
GetDictionaryAttackInfoRequest request;
EXPECT_CALL(mock_ownership_service_, GetDictionaryAttackInfo(_, _))
.WillOnce(Invoke(
[](const GetDictionaryAttackInfoRequest& request,
const TpmOwnershipInterface::GetDictionaryAttackInfoCallback&
callback) {
GetDictionaryAttackInfoReply reply;
reply.set_status(STATUS_SUCCESS);
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);
}));
GetDictionaryAttackInfoReply reply;
ExecuteMethod(kGetDictionaryAttackInfo, request, &reply,
kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
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, ResetDictionaryAttackLock) {
RegisterDBusObjectsAsync();
ResetDictionaryAttackLockRequest request;
EXPECT_CALL(mock_ownership_service_, ResetDictionaryAttackLock(_, _))
.WillOnce(Invoke(
[](const ResetDictionaryAttackLockRequest& request,
const TpmOwnershipInterface::ResetDictionaryAttackLockCallback&
callback) {
ResetDictionaryAttackLockReply reply;
reply.set_status(STATUS_SUCCESS);
callback.Run(reply);
}));
ResetDictionaryAttackLockReply reply;
ExecuteMethod(kResetDictionaryAttackLock, request, &reply,
kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
}
TEST_F(DBusServiceTest, TakeOwnership) {
RegisterDBusObjectsAsync();
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, kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
}
TEST_F(DBusServiceTest, RemoveOwnerDependency) {
RegisterDBusObjectsAsync();
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, kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
}
TEST_F(DBusServiceTest, ClearStoredOwnerPassword) {
RegisterDBusObjectsAsync();
ClearStoredOwnerPasswordRequest request;
EXPECT_CALL(mock_ownership_service_, ClearStoredOwnerPassword(_, _))
.WillOnce(Invoke(
[](const ClearStoredOwnerPasswordRequest& request,
const TpmOwnershipInterface::ClearStoredOwnerPasswordCallback&
callback) {
ClearStoredOwnerPasswordReply reply;
reply.set_status(STATUS_SUCCESS);
callback.Run(reply);
}));
ClearStoredOwnerPasswordReply reply;
ExecuteMethod(kClearStoredOwnerPassword, request, &reply,
kTpmManagerInterface);
EXPECT_EQ(STATUS_SUCCESS, reply.status());
}
TEST_F(DBusServiceTest, DefineSpace) {
RegisterDBusObjectsAsync();
uint32_t nvram_index = 5;
size_t nvram_length = 32;
DefineSpaceRequest request;
request.set_index(nvram_index);
request.set_size(nvram_length);
EXPECT_CALL(mock_nvram_service_, DefineSpace(_, _))
.WillOnce(
Invoke([nvram_index, nvram_length](
const DefineSpaceRequest& request,
const TpmNvramInterface::DefineSpaceCallback& callback) {
EXPECT_TRUE(request.has_index());
EXPECT_EQ(nvram_index, request.index());
EXPECT_TRUE(request.has_size());
EXPECT_EQ(nvram_length, request.size());
DefineSpaceReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
callback.Run(reply);
}));
DefineSpaceReply reply;
ExecuteMethod(kDefineSpace, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
}
TEST_F(DBusServiceTest, DestroySpace) {
RegisterDBusObjectsAsync();
uint32_t nvram_index = 5;
DestroySpaceRequest request;
request.set_index(nvram_index);
EXPECT_CALL(mock_nvram_service_, DestroySpace(_, _))
.WillOnce(
Invoke([nvram_index](
const DestroySpaceRequest& request,
const TpmNvramInterface::DestroySpaceCallback& callback) {
EXPECT_TRUE(request.has_index());
EXPECT_EQ(nvram_index, request.index());
DestroySpaceReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
callback.Run(reply);
}));
DestroySpaceReply reply;
ExecuteMethod(kDestroySpace, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
}
TEST_F(DBusServiceTest, WriteSpace) {
RegisterDBusObjectsAsync();
uint32_t nvram_index = 5;
std::string nvram_data("nvram_data");
WriteSpaceRequest request;
request.set_index(nvram_index);
request.set_data(nvram_data);
EXPECT_CALL(mock_nvram_service_, WriteSpace(_, _))
.WillOnce(
Invoke([nvram_index, nvram_data](
const WriteSpaceRequest& request,
const TpmNvramInterface::WriteSpaceCallback& callback) {
EXPECT_TRUE(request.has_index());
EXPECT_EQ(nvram_index, request.index());
EXPECT_TRUE(request.has_data());
EXPECT_EQ(nvram_data, request.data());
WriteSpaceReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
callback.Run(reply);
}));
WriteSpaceReply reply;
ExecuteMethod(kWriteSpace, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
}
TEST_F(DBusServiceTest, ReadSpace) {
RegisterDBusObjectsAsync();
uint32_t nvram_index = 5;
std::string nvram_data("nvram_data");
ReadSpaceRequest request;
request.set_index(nvram_index);
EXPECT_CALL(mock_nvram_service_, ReadSpace(_, _))
.WillOnce(
Invoke([nvram_index, nvram_data](
const ReadSpaceRequest& request,
const TpmNvramInterface::ReadSpaceCallback& callback) {
EXPECT_TRUE(request.has_index());
EXPECT_EQ(nvram_index, request.index());
ReadSpaceReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
reply.set_data(nvram_data);
callback.Run(reply);
}));
ReadSpaceReply reply;
ExecuteMethod(kReadSpace, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
EXPECT_TRUE(reply.has_data());
EXPECT_EQ(nvram_data, reply.data());
}
TEST_F(DBusServiceTest, LockSpace) {
RegisterDBusObjectsAsync();
uint32_t nvram_index = 5;
LockSpaceRequest request;
request.set_index(nvram_index);
request.set_lock_read(true);
request.set_lock_write(true);
EXPECT_CALL(mock_nvram_service_, LockSpace(_, _))
.WillOnce(Invoke(
[nvram_index](const LockSpaceRequest& request,
const TpmNvramInterface::LockSpaceCallback& callback) {
EXPECT_TRUE(request.has_index());
EXPECT_EQ(nvram_index, request.index());
EXPECT_TRUE(request.lock_read());
EXPECT_TRUE(request.lock_write());
LockSpaceReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
callback.Run(reply);
}));
LockSpaceReply reply;
ExecuteMethod(kLockSpace, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
}
TEST_F(DBusServiceTest, ListSpaces) {
RegisterDBusObjectsAsync();
constexpr uint32_t nvram_index_list[] = {3, 4, 5};
ListSpacesRequest request;
EXPECT_CALL(mock_nvram_service_, ListSpaces(_, _))
.WillOnce(
Invoke([nvram_index_list](
const ListSpacesRequest& request,
const TpmNvramInterface::ListSpacesCallback& callback) {
ListSpacesReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
for (auto index : nvram_index_list) {
reply.add_index_list(index);
}
callback.Run(reply);
}));
ListSpacesReply reply;
ExecuteMethod(kListSpaces, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
EXPECT_EQ(base::size(nvram_index_list), reply.index_list_size());
for (size_t i = 0; i < 3; i++) {
EXPECT_EQ(nvram_index_list[i], reply.index_list(i));
}
}
TEST_F(DBusServiceTest, GetSpaceInfo) {
RegisterDBusObjectsAsync();
uint32_t nvram_index = 5;
size_t nvram_size = 32;
GetSpaceInfoRequest request;
request.set_index(nvram_index);
EXPECT_CALL(mock_nvram_service_, GetSpaceInfo(_, _))
.WillOnce(
Invoke([nvram_index, nvram_size](
const GetSpaceInfoRequest& request,
const TpmNvramInterface::GetSpaceInfoCallback& callback) {
EXPECT_TRUE(request.has_index());
EXPECT_EQ(nvram_index, request.index());
GetSpaceInfoReply reply;
reply.set_result(NVRAM_RESULT_SUCCESS);
reply.set_size(nvram_size);
reply.set_is_read_locked(true);
reply.set_is_write_locked(true);
callback.Run(reply);
}));
GetSpaceInfoReply reply;
ExecuteMethod(kGetSpaceInfo, request, &reply, kTpmNvramInterface);
EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
EXPECT_TRUE(reply.has_size());
EXPECT_EQ(nvram_size, reply.size());
EXPECT_TRUE(reply.is_read_locked());
EXPECT_TRUE(reply.is_write_locked());
}
TEST_F(DBusServiceTest, SendOwnershipTakenSignalAfterNotification) {
RegisterDBusObjectsAsync();
EXPECT_FALSE(dbus_service_->MaybeSendOwnershipTakenSignal());
dbus_service_->NotifyOwnershipIsTaken();
EXPECT_TRUE(dbus_service_->MaybeSendOwnershipTakenSignal());
}
TEST_F(DBusServiceTest, SendOwnershipTakenSignalError) {
ON_CALL(*mock_bus_, GetExportedObject(_)).WillByDefault(Return(nullptr));
RegisterDBusObjectsAsync();
dbus_service_->NotifyOwnershipIsTaken();
EXPECT_FALSE(dbus_service_->MaybeSendOwnershipTakenSignal());
}
TEST_F(DBusServiceTest, SendOwnershipTakenSignalAfterRegistration) {
dbus_service_->NotifyOwnershipIsTaken();
EXPECT_FALSE(dbus_service_->MaybeSendOwnershipTakenSignal());
RegisterDBusObjectsAsync();
EXPECT_TRUE(dbus_service_->MaybeSendOwnershipTakenSignal());
}
} // namespace tpm_manager