1//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <string>
18
19#include <brillo/bind_lambda.h>
20#include <brillo/dbus/dbus_object_test_helpers.h>
21#include <dbus/mock_bus.h>
22#include <dbus/mock_exported_object.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
25
26#include "tpm_manager/common/mock_tpm_nvram_interface.h"
27#include "tpm_manager/common/mock_tpm_ownership_interface.h"
28#include "tpm_manager/common/tpm_manager_constants.h"
29#include "tpm_manager/common/tpm_nvram_dbus_interface.h"
30#include "tpm_manager/common/tpm_ownership_dbus_interface.h"
31#include "tpm_manager/server/dbus_service.h"
32
33using testing::_;
34using testing::Invoke;
35using testing::NiceMock;
36using testing::Return;
37using testing::StrictMock;
38using testing::WithArgs;
39
40namespace tpm_manager {
41
42class DBusServiceTest : public testing::Test {
43 public:
44  ~DBusServiceTest() override = default;
45  void SetUp() override {
46    dbus::Bus::Options options;
47    mock_bus_ = new NiceMock<dbus::MockBus>(options);
48    dbus::ObjectPath path(kTpmManagerServicePath);
49    mock_exported_object_ =
50        new NiceMock<dbus::MockExportedObject>(mock_bus_.get(), path);
51    ON_CALL(*mock_bus_, GetExportedObject(path))
52        .WillByDefault(Return(mock_exported_object_.get()));
53    dbus_service_.reset(new DBusService(mock_bus_, &mock_nvram_service_,
54                                        &mock_ownership_service_));
55    scoped_refptr<brillo::dbus_utils::AsyncEventSequencer> sequencer(
56        new brillo::dbus_utils::AsyncEventSequencer());
57    dbus_service_->RegisterDBusObjectsAsync(sequencer.get());
58  }
59
60  template <typename RequestProtobufType, typename ReplyProtobufType>
61  void ExecuteMethod(const std::string& method_name,
62                     const RequestProtobufType& request,
63                     ReplyProtobufType* reply,
64                     const std::string& interface) {
65    std::unique_ptr<dbus::MethodCall> call =
66        CreateMethodCall(method_name, interface);
67    dbus::MessageWriter writer(call.get());
68    writer.AppendProtoAsArrayOfBytes(request);
69    auto response = brillo::dbus_utils::testing::CallMethod(
70        dbus_service_->dbus_object_, call.get());
71    dbus::MessageReader reader(response.get());
72    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(reply));
73  }
74
75 protected:
76  std::unique_ptr<dbus::MethodCall> CreateMethodCall(
77      const std::string& method_name,
78      const std::string& interface) {
79    std::unique_ptr<dbus::MethodCall> call(
80        new dbus::MethodCall(interface, method_name));
81    call->SetSerial(1);
82    return call;
83  }
84
85  scoped_refptr<dbus::MockBus> mock_bus_;
86  scoped_refptr<dbus::MockExportedObject> mock_exported_object_;
87  StrictMock<MockTpmNvramInterface> mock_nvram_service_;
88  StrictMock<MockTpmOwnershipInterface> mock_ownership_service_;
89  std::unique_ptr<DBusService> dbus_service_;
90};
91
92TEST_F(DBusServiceTest, CopyableCallback) {
93  EXPECT_CALL(mock_ownership_service_, GetTpmStatus(_, _))
94      .WillOnce(WithArgs<1>(Invoke(
95          [](const TpmOwnershipInterface::GetTpmStatusCallback& callback) {
96            // Copy the callback, then call the original.
97            GetTpmStatusReply reply;
98            base::Closure copy = base::Bind(callback, reply);
99            callback.Run(reply);
100          })));
101  GetTpmStatusRequest request;
102  GetTpmStatusReply reply;
103  ExecuteMethod(kGetTpmStatus, request, &reply, kTpmOwnershipInterface);
104}
105
106TEST_F(DBusServiceTest, GetTpmStatus) {
107  GetTpmStatusRequest request;
108  EXPECT_CALL(mock_ownership_service_, GetTpmStatus(_, _))
109      .WillOnce(Invoke(
110          [](const GetTpmStatusRequest& request,
111             const TpmOwnershipInterface::GetTpmStatusCallback& callback) {
112            GetTpmStatusReply reply;
113            reply.set_status(STATUS_SUCCESS);
114            reply.set_enabled(true);
115            reply.set_owned(true);
116            reply.set_dictionary_attack_counter(3);
117            reply.set_dictionary_attack_threshold(4);
118            reply.set_dictionary_attack_lockout_in_effect(true);
119            reply.set_dictionary_attack_lockout_seconds_remaining(5);
120            callback.Run(reply);
121          }));
122  GetTpmStatusReply reply;
123  ExecuteMethod(kGetTpmStatus, request, &reply, kTpmOwnershipInterface);
124  EXPECT_EQ(STATUS_SUCCESS, reply.status());
125  EXPECT_TRUE(reply.enabled());
126  EXPECT_TRUE(reply.owned());
127  EXPECT_EQ(3, reply.dictionary_attack_counter());
128  EXPECT_EQ(4, reply.dictionary_attack_threshold());
129  EXPECT_TRUE(reply.dictionary_attack_lockout_in_effect());
130  EXPECT_EQ(5, reply.dictionary_attack_lockout_seconds_remaining());
131}
132
133TEST_F(DBusServiceTest, TakeOwnership) {
134  EXPECT_CALL(mock_ownership_service_, TakeOwnership(_, _))
135      .WillOnce(Invoke(
136          [](const TakeOwnershipRequest& request,
137             const TpmOwnershipInterface::TakeOwnershipCallback& callback) {
138            TakeOwnershipReply reply;
139            reply.set_status(STATUS_SUCCESS);
140            callback.Run(reply);
141          }));
142  TakeOwnershipRequest request;
143  TakeOwnershipReply reply;
144  ExecuteMethod(kTakeOwnership, request, &reply, kTpmOwnershipInterface);
145  EXPECT_EQ(STATUS_SUCCESS, reply.status());
146}
147
148TEST_F(DBusServiceTest, RemoveOwnerDependency) {
149  std::string owner_dependency("owner_dependency");
150  RemoveOwnerDependencyRequest request;
151  request.set_owner_dependency(owner_dependency);
152  EXPECT_CALL(mock_ownership_service_, RemoveOwnerDependency(_, _))
153      .WillOnce(Invoke([&owner_dependency](
154          const RemoveOwnerDependencyRequest& request,
155          const TpmOwnershipInterface::RemoveOwnerDependencyCallback&
156              callback) {
157        EXPECT_TRUE(request.has_owner_dependency());
158        EXPECT_EQ(owner_dependency, request.owner_dependency());
159        RemoveOwnerDependencyReply reply;
160        reply.set_status(STATUS_SUCCESS);
161        callback.Run(reply);
162      }));
163  RemoveOwnerDependencyReply reply;
164  ExecuteMethod(kRemoveOwnerDependency, request, &reply,
165                kTpmOwnershipInterface);
166  EXPECT_EQ(STATUS_SUCCESS, reply.status());
167}
168
169TEST_F(DBusServiceTest, DefineSpace) {
170  uint32_t nvram_index = 5;
171  size_t nvram_length = 32;
172  DefineSpaceRequest request;
173  request.set_index(nvram_index);
174  request.set_size(nvram_length);
175  EXPECT_CALL(mock_nvram_service_, DefineSpace(_, _))
176      .WillOnce(Invoke([nvram_index, nvram_length](
177          const DefineSpaceRequest& request,
178          const TpmNvramInterface::DefineSpaceCallback& callback) {
179        EXPECT_TRUE(request.has_index());
180        EXPECT_EQ(nvram_index, request.index());
181        EXPECT_TRUE(request.has_size());
182        EXPECT_EQ(nvram_length, request.size());
183        DefineSpaceReply reply;
184        reply.set_result(NVRAM_RESULT_SUCCESS);
185        callback.Run(reply);
186      }));
187  DefineSpaceReply reply;
188  ExecuteMethod(kDefineSpace, request, &reply, kTpmNvramInterface);
189  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
190}
191
192TEST_F(DBusServiceTest, DestroySpace) {
193  uint32_t nvram_index = 5;
194  DestroySpaceRequest request;
195  request.set_index(nvram_index);
196  EXPECT_CALL(mock_nvram_service_, DestroySpace(_, _))
197      .WillOnce(Invoke([nvram_index](
198          const DestroySpaceRequest& request,
199          const TpmNvramInterface::DestroySpaceCallback& callback) {
200        EXPECT_TRUE(request.has_index());
201        EXPECT_EQ(nvram_index, request.index());
202        DestroySpaceReply reply;
203        reply.set_result(NVRAM_RESULT_SUCCESS);
204        callback.Run(reply);
205      }));
206  DestroySpaceReply reply;
207  ExecuteMethod(kDestroySpace, request, &reply, kTpmNvramInterface);
208  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
209}
210
211TEST_F(DBusServiceTest, WriteSpace) {
212  uint32_t nvram_index = 5;
213  std::string nvram_data("nvram_data");
214  WriteSpaceRequest request;
215  request.set_index(nvram_index);
216  request.set_data(nvram_data);
217  EXPECT_CALL(mock_nvram_service_, WriteSpace(_, _))
218      .WillOnce(Invoke([nvram_index, nvram_data](
219          const WriteSpaceRequest& request,
220          const TpmNvramInterface::WriteSpaceCallback& callback) {
221        EXPECT_TRUE(request.has_index());
222        EXPECT_EQ(nvram_index, request.index());
223        EXPECT_TRUE(request.has_data());
224        EXPECT_EQ(nvram_data, request.data());
225        WriteSpaceReply reply;
226        reply.set_result(NVRAM_RESULT_SUCCESS);
227        callback.Run(reply);
228      }));
229  WriteSpaceReply reply;
230  ExecuteMethod(kWriteSpace, request, &reply, kTpmNvramInterface);
231  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
232}
233
234TEST_F(DBusServiceTest, ReadSpace) {
235  uint32_t nvram_index = 5;
236  std::string nvram_data("nvram_data");
237  ReadSpaceRequest request;
238  request.set_index(nvram_index);
239  EXPECT_CALL(mock_nvram_service_, ReadSpace(_, _))
240      .WillOnce(Invoke([nvram_index, nvram_data](
241          const ReadSpaceRequest& request,
242          const TpmNvramInterface::ReadSpaceCallback& callback) {
243        EXPECT_TRUE(request.has_index());
244        EXPECT_EQ(nvram_index, request.index());
245        ReadSpaceReply reply;
246        reply.set_result(NVRAM_RESULT_SUCCESS);
247        reply.set_data(nvram_data);
248        callback.Run(reply);
249      }));
250  ReadSpaceReply reply;
251  ExecuteMethod(kReadSpace, request, &reply, kTpmNvramInterface);
252  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
253  EXPECT_TRUE(reply.has_data());
254  EXPECT_EQ(nvram_data, reply.data());
255}
256
257TEST_F(DBusServiceTest, LockSpace) {
258  uint32_t nvram_index = 5;
259  LockSpaceRequest request;
260  request.set_index(nvram_index);
261  request.set_lock_read(true);
262  request.set_lock_write(true);
263  EXPECT_CALL(mock_nvram_service_, LockSpace(_, _))
264      .WillOnce(Invoke(
265          [nvram_index](const LockSpaceRequest& request,
266                        const TpmNvramInterface::LockSpaceCallback& callback) {
267            EXPECT_TRUE(request.has_index());
268            EXPECT_EQ(nvram_index, request.index());
269            EXPECT_TRUE(request.lock_read());
270            EXPECT_TRUE(request.lock_write());
271            LockSpaceReply reply;
272            reply.set_result(NVRAM_RESULT_SUCCESS);
273            callback.Run(reply);
274          }));
275  LockSpaceReply reply;
276  ExecuteMethod(kLockSpace, request, &reply, kTpmNvramInterface);
277  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
278}
279
280TEST_F(DBusServiceTest, ListSpaces) {
281  constexpr uint32_t nvram_index_list[] = {3, 4, 5};
282  ListSpacesRequest request;
283  EXPECT_CALL(mock_nvram_service_, ListSpaces(_, _))
284      .WillOnce(Invoke([nvram_index_list](
285          const ListSpacesRequest& request,
286          const TpmNvramInterface::ListSpacesCallback& callback) {
287        ListSpacesReply reply;
288        reply.set_result(NVRAM_RESULT_SUCCESS);
289        for (auto index : nvram_index_list) {
290          reply.add_index_list(index);
291        }
292        callback.Run(reply);
293      }));
294  ListSpacesReply reply;
295  ExecuteMethod(kListSpaces, request, &reply, kTpmNvramInterface);
296  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
297  EXPECT_EQ(arraysize(nvram_index_list), reply.index_list_size());
298  for (size_t i = 0; i < 3; i++) {
299    EXPECT_EQ(nvram_index_list[i], reply.index_list(i));
300  }
301}
302
303TEST_F(DBusServiceTest, GetSpaceInfo) {
304  uint32_t nvram_index = 5;
305  size_t nvram_size = 32;
306  GetSpaceInfoRequest request;
307  request.set_index(nvram_index);
308  EXPECT_CALL(mock_nvram_service_, GetSpaceInfo(_, _))
309      .WillOnce(Invoke([nvram_index, nvram_size](
310          const GetSpaceInfoRequest& request,
311          const TpmNvramInterface::GetSpaceInfoCallback& callback) {
312        EXPECT_TRUE(request.has_index());
313        EXPECT_EQ(nvram_index, request.index());
314        GetSpaceInfoReply reply;
315        reply.set_result(NVRAM_RESULT_SUCCESS);
316        reply.set_size(nvram_size);
317        reply.set_is_read_locked(true);
318        reply.set_is_write_locked(true);
319        callback.Run(reply);
320      }));
321  GetSpaceInfoReply reply;
322  ExecuteMethod(kGetSpaceInfo, request, &reply, kTpmNvramInterface);
323  EXPECT_EQ(NVRAM_RESULT_SUCCESS, reply.result());
324  EXPECT_TRUE(reply.has_size());
325  EXPECT_EQ(nvram_size, reply.size());
326  EXPECT_TRUE(reply.is_read_locked());
327  EXPECT_TRUE(reply.is_write_locked());
328}
329
330}  // namespace tpm_manager
331