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 <dbus/mock_object_proxy.h>
21#include <gmock/gmock.h>
22#include <gtest/gtest.h>
23
24#include "attestation/client/dbus_proxy.h"
25
26using testing::_;
27using testing::Invoke;
28using testing::StrictMock;
29using testing::WithArgs;
30
31namespace attestation {
32
33class DBusProxyTest : public testing::Test {
34 public:
35  ~DBusProxyTest() override = default;
36  void SetUp() override {
37    mock_object_proxy_ = new StrictMock<dbus::MockObjectProxy>(
38        nullptr, "", dbus::ObjectPath(""));
39    proxy_.set_object_proxy(mock_object_proxy_.get());
40  }
41
42 protected:
43  scoped_refptr<StrictMock<dbus::MockObjectProxy>> mock_object_proxy_;
44  DBusProxy proxy_;
45};
46
47TEST_F(DBusProxyTest, CreateGoogleAttestedKey) {
48  auto fake_dbus_call = [](
49      dbus::MethodCall* method_call,
50      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
51    // Verify request protobuf.
52    dbus::MessageReader reader(method_call);
53    CreateGoogleAttestedKeyRequest request_proto;
54    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
55    EXPECT_EQ("label", request_proto.key_label());
56    EXPECT_EQ(KEY_TYPE_ECC, request_proto.key_type());
57    EXPECT_EQ(KEY_USAGE_SIGN, request_proto.key_usage());
58    EXPECT_EQ(ENTERPRISE_MACHINE_CERTIFICATE,
59              request_proto.certificate_profile());
60    EXPECT_EQ("user", request_proto.username());
61    EXPECT_EQ("origin", request_proto.origin());
62    // Create reply protobuf.
63    auto response = dbus::Response::CreateEmpty();
64    dbus::MessageWriter writer(response.get());
65    CreateGoogleAttestedKeyReply reply_proto;
66    reply_proto.set_status(STATUS_SUCCESS);
67    reply_proto.set_certificate_chain("certificate");
68    reply_proto.set_server_error("server_error");
69    writer.AppendProtoAsArrayOfBytes(reply_proto);
70    response_callback.Run(response.release());
71  };
72  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
73      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
74
75  // Set expectations on the outputs.
76  int callback_count = 0;
77  auto callback = [&callback_count](const CreateGoogleAttestedKeyReply& reply) {
78    callback_count++;
79    EXPECT_EQ(STATUS_SUCCESS, reply.status());
80    EXPECT_EQ("certificate", reply.certificate_chain());
81    EXPECT_EQ("server_error", reply.server_error());
82  };
83  CreateGoogleAttestedKeyRequest request;
84  request.set_key_label("label");
85  request.set_key_type(KEY_TYPE_ECC);
86  request.set_key_usage(KEY_USAGE_SIGN);
87  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
88  request.set_username("user");
89  request.set_origin("origin");
90  proxy_.CreateGoogleAttestedKey(request, base::Bind(callback));
91  EXPECT_EQ(1, callback_count);
92}
93
94TEST_F(DBusProxyTest, GetKeyInfo) {
95  auto fake_dbus_call = [](
96      dbus::MethodCall* method_call,
97      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
98    // Verify request protobuf.
99    dbus::MessageReader reader(method_call);
100    GetKeyInfoRequest request_proto;
101    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
102    EXPECT_EQ("label", request_proto.key_label());
103    EXPECT_EQ("username", request_proto.username());
104    // Create reply protobuf.
105    auto response = dbus::Response::CreateEmpty();
106    dbus::MessageWriter writer(response.get());
107    GetKeyInfoReply reply_proto;
108    reply_proto.set_status(STATUS_SUCCESS);
109    reply_proto.set_key_type(KEY_TYPE_ECC);
110    reply_proto.set_key_usage(KEY_USAGE_SIGN);
111    reply_proto.set_public_key("public_key");
112    reply_proto.set_certify_info("certify_info");
113    reply_proto.set_certify_info_signature("signature");
114    reply_proto.set_certificate("certificate");
115    writer.AppendProtoAsArrayOfBytes(reply_proto);
116    response_callback.Run(response.release());
117  };
118  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
119      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
120
121  // Set expectations on the outputs.
122  int callback_count = 0;
123  auto callback = [&callback_count](const GetKeyInfoReply& reply) {
124    callback_count++;
125    EXPECT_EQ(STATUS_SUCCESS, reply.status());
126    EXPECT_EQ(KEY_TYPE_ECC, reply.key_type());
127    EXPECT_EQ(KEY_USAGE_SIGN, reply.key_usage());
128    EXPECT_EQ("public_key", reply.public_key());
129    EXPECT_EQ("certify_info", reply.certify_info());
130    EXPECT_EQ("signature", reply.certify_info_signature());
131    EXPECT_EQ("certificate", reply.certificate());
132  };
133  GetKeyInfoRequest request;
134  request.set_key_label("label");
135  request.set_username("username");
136  proxy_.GetKeyInfo(request, base::Bind(callback));
137  EXPECT_EQ(1, callback_count);
138}
139
140TEST_F(DBusProxyTest, GetEndorsementInfo) {
141  auto fake_dbus_call = [](
142      dbus::MethodCall* method_call,
143      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
144    // Verify request protobuf.
145    dbus::MessageReader reader(method_call);
146    GetEndorsementInfoRequest request_proto;
147    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
148    EXPECT_EQ(KEY_TYPE_ECC, request_proto.key_type());
149    // Create reply protobuf.
150    auto response = dbus::Response::CreateEmpty();
151    dbus::MessageWriter writer(response.get());
152    GetEndorsementInfoReply reply_proto;
153    reply_proto.set_status(STATUS_SUCCESS);
154    reply_proto.set_ek_public_key("public_key");
155    reply_proto.set_ek_certificate("certificate");
156    writer.AppendProtoAsArrayOfBytes(reply_proto);
157    response_callback.Run(response.release());
158  };
159  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
160      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
161
162  // Set expectations on the outputs.
163  int callback_count = 0;
164  auto callback = [&callback_count](const GetEndorsementInfoReply& reply) {
165    callback_count++;
166    EXPECT_EQ(STATUS_SUCCESS, reply.status());
167    EXPECT_EQ("public_key", reply.ek_public_key());
168    EXPECT_EQ("certificate", reply.ek_certificate());
169  };
170  GetEndorsementInfoRequest request;
171  request.set_key_type(KEY_TYPE_ECC);
172  proxy_.GetEndorsementInfo(request, base::Bind(callback));
173  EXPECT_EQ(1, callback_count);
174}
175
176TEST_F(DBusProxyTest, GetAttestationKeyInfo) {
177  auto fake_dbus_call = [](
178      dbus::MethodCall* method_call,
179      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
180    // Verify request protobuf.
181    dbus::MessageReader reader(method_call);
182    GetAttestationKeyInfoRequest request_proto;
183    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
184    EXPECT_EQ(KEY_TYPE_ECC, request_proto.key_type());
185    // Create reply protobuf.
186    auto response = dbus::Response::CreateEmpty();
187    dbus::MessageWriter writer(response.get());
188    GetAttestationKeyInfoReply reply_proto;
189    reply_proto.set_status(STATUS_SUCCESS);
190    reply_proto.set_public_key("public_key");
191    reply_proto.set_public_key_tpm_format("public_key_tpm_format");
192    reply_proto.set_certificate("certificate");
193    reply_proto.mutable_pcr0_quote()->set_quote("pcr0");
194    reply_proto.mutable_pcr1_quote()->set_quote("pcr1");
195    writer.AppendProtoAsArrayOfBytes(reply_proto);
196    response_callback.Run(response.release());
197  };
198  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
199      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
200
201  // Set expectations on the outputs.
202  int callback_count = 0;
203  auto callback = [&callback_count](const GetAttestationKeyInfoReply& reply) {
204    callback_count++;
205    EXPECT_EQ(STATUS_SUCCESS, reply.status());
206    EXPECT_EQ("public_key", reply.public_key());
207    EXPECT_EQ("public_key_tpm_format", reply.public_key_tpm_format());
208    EXPECT_EQ("certificate", reply.certificate());
209    EXPECT_EQ("pcr0", reply.pcr0_quote().quote());
210    EXPECT_EQ("pcr1", reply.pcr1_quote().quote());
211  };
212  GetAttestationKeyInfoRequest request;
213  request.set_key_type(KEY_TYPE_ECC);
214  proxy_.GetAttestationKeyInfo(request, base::Bind(callback));
215  EXPECT_EQ(1, callback_count);
216}
217
218TEST_F(DBusProxyTest, ActivateAttestationKey) {
219  auto fake_dbus_call = [](
220      dbus::MethodCall* method_call,
221      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
222    // Verify request protobuf.
223    dbus::MessageReader reader(method_call);
224    ActivateAttestationKeyRequest request_proto;
225    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
226    EXPECT_EQ(KEY_TYPE_ECC, request_proto.key_type());
227    EXPECT_EQ("encrypted1",
228              request_proto.encrypted_certificate().asym_ca_contents());
229    EXPECT_EQ("encrypted2",
230              request_proto.encrypted_certificate().sym_ca_attestation());
231    EXPECT_TRUE(request_proto.save_certificate());
232    // Create reply protobuf.
233    auto response = dbus::Response::CreateEmpty();
234    dbus::MessageWriter writer(response.get());
235    ActivateAttestationKeyReply reply_proto;
236    reply_proto.set_status(STATUS_SUCCESS);
237    reply_proto.set_certificate("certificate");
238    writer.AppendProtoAsArrayOfBytes(reply_proto);
239    response_callback.Run(response.release());
240  };
241  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
242      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
243
244  // Set expectations on the outputs.
245  int callback_count = 0;
246  auto callback = [&callback_count](const ActivateAttestationKeyReply& reply) {
247    callback_count++;
248    EXPECT_EQ(STATUS_SUCCESS, reply.status());
249    EXPECT_EQ("certificate", reply.certificate());
250  };
251  ActivateAttestationKeyRequest request;
252  request.set_key_type(KEY_TYPE_ECC);
253  request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1");
254  request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2");
255  request.set_save_certificate(true);
256  proxy_.ActivateAttestationKey(request, base::Bind(callback));
257  EXPECT_EQ(1, callback_count);
258}
259
260TEST_F(DBusProxyTest, CreateCertifiableKey) {
261  auto fake_dbus_call = [](
262      dbus::MethodCall* method_call,
263      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
264    // Verify request protobuf.
265    dbus::MessageReader reader(method_call);
266    CreateCertifiableKeyRequest request_proto;
267    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
268    EXPECT_EQ("label", request_proto.key_label());
269    EXPECT_EQ(KEY_TYPE_ECC, request_proto.key_type());
270    EXPECT_EQ(KEY_USAGE_SIGN, request_proto.key_usage());
271    EXPECT_EQ("user", request_proto.username());
272    // Create reply protobuf.
273    auto response = dbus::Response::CreateEmpty();
274    dbus::MessageWriter writer(response.get());
275    CreateCertifiableKeyReply reply_proto;
276    reply_proto.set_status(STATUS_SUCCESS);
277    reply_proto.set_public_key("public_key");
278    reply_proto.set_certify_info("certify_info");
279    reply_proto.set_certify_info_signature("signature");
280    writer.AppendProtoAsArrayOfBytes(reply_proto);
281    response_callback.Run(response.release());
282  };
283  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
284      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
285
286  // Set expectations on the outputs.
287  int callback_count = 0;
288  auto callback = [&callback_count](const CreateCertifiableKeyReply& reply) {
289    callback_count++;
290    EXPECT_EQ(STATUS_SUCCESS, reply.status());
291    EXPECT_EQ("public_key", reply.public_key());
292    EXPECT_EQ("certify_info", reply.certify_info());
293    EXPECT_EQ("signature", reply.certify_info_signature());
294  };
295  CreateCertifiableKeyRequest request;
296  request.set_key_label("label");
297  request.set_key_type(KEY_TYPE_ECC);
298  request.set_key_usage(KEY_USAGE_SIGN);
299  request.set_username("user");
300  proxy_.CreateCertifiableKey(request, base::Bind(callback));
301  EXPECT_EQ(1, callback_count);
302}
303
304TEST_F(DBusProxyTest, Decrypt) {
305  auto fake_dbus_call = [](
306      dbus::MethodCall* method_call,
307      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
308    // Verify request protobuf.
309    dbus::MessageReader reader(method_call);
310    DecryptRequest request_proto;
311    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
312    EXPECT_EQ("label", request_proto.key_label());
313    EXPECT_EQ("user", request_proto.username());
314    EXPECT_EQ("data", request_proto.encrypted_data());
315    // Create reply protobuf.
316    scoped_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
317    dbus::MessageWriter writer(response.get());
318    DecryptReply reply_proto;
319    reply_proto.set_status(STATUS_SUCCESS);
320    reply_proto.set_decrypted_data("data");
321    writer.AppendProtoAsArrayOfBytes(reply_proto);
322    response_callback.Run(response.release());
323  };
324  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
325      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
326
327  // Set expectations on the outputs.
328  int callback_count = 0;
329  auto callback = [&callback_count](const DecryptReply& reply) {
330    callback_count++;
331    EXPECT_EQ(STATUS_SUCCESS, reply.status());
332    EXPECT_EQ("data", reply.decrypted_data());
333  };
334  DecryptRequest request;
335  request.set_key_label("label");
336  request.set_username("user");
337  request.set_encrypted_data("data");
338  proxy_.Decrypt(request, base::Bind(callback));
339  EXPECT_EQ(1, callback_count);
340}
341
342TEST_F(DBusProxyTest, Sign) {
343  auto fake_dbus_call = [](
344      dbus::MethodCall* method_call,
345      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
346    // Verify request protobuf.
347    dbus::MessageReader reader(method_call);
348    SignRequest request_proto;
349    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
350    EXPECT_EQ("label", request_proto.key_label());
351    EXPECT_EQ("user", request_proto.username());
352    EXPECT_EQ("data", request_proto.data_to_sign());
353    // Create reply protobuf.
354    auto response = dbus::Response::CreateEmpty();
355    dbus::MessageWriter writer(response.get());
356    SignReply reply_proto;
357    reply_proto.set_status(STATUS_SUCCESS);
358    reply_proto.set_signature("signature");
359    writer.AppendProtoAsArrayOfBytes(reply_proto);
360    response_callback.Run(response.release());
361  };
362  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
363      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
364
365  // Set expectations on the outputs.
366  int callback_count = 0;
367  auto callback = [&callback_count](const SignReply& reply) {
368    callback_count++;
369    EXPECT_EQ(STATUS_SUCCESS, reply.status());
370    EXPECT_EQ("signature", reply.signature());
371  };
372  SignRequest request;
373  request.set_key_label("label");
374  request.set_username("user");
375  request.set_data_to_sign("data");
376  proxy_.Sign(request, base::Bind(callback));
377  EXPECT_EQ(1, callback_count);
378}
379
380TEST_F(DBusProxyTest, RegisterKeyWithChapsToken) {
381  auto fake_dbus_call = [](
382      dbus::MethodCall* method_call,
383      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
384    // Verify request protobuf.
385    dbus::MessageReader reader(method_call);
386    RegisterKeyWithChapsTokenRequest request_proto;
387    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request_proto));
388    EXPECT_EQ("label", request_proto.key_label());
389    EXPECT_EQ("user", request_proto.username());
390    // Create reply protobuf.
391    auto response = dbus::Response::CreateEmpty();
392    dbus::MessageWriter writer(response.get());
393    RegisterKeyWithChapsTokenReply reply_proto;
394    reply_proto.set_status(STATUS_SUCCESS);
395    writer.AppendProtoAsArrayOfBytes(reply_proto);
396    response_callback.Run(response.release());
397  };
398  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
399      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
400
401  // Set expectations on the outputs.
402  int callback_count = 0;
403  auto callback =
404      [&callback_count](const RegisterKeyWithChapsTokenReply& reply) {
405        callback_count++;
406        EXPECT_EQ(STATUS_SUCCESS, reply.status());
407      };
408  RegisterKeyWithChapsTokenRequest request;
409  request.set_key_label("label");
410  request.set_username("user");
411  proxy_.RegisterKeyWithChapsToken(request, base::Bind(callback));
412  EXPECT_EQ(1, callback_count);
413}
414
415}  // namespace attestation
416