1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chromeos/dbus/fake_easy_unlock_client.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace {
13
14// Callback for |GenerateEcP256KeyPair| method. Saves keys returned by the
15// method in |private_key_target| and |public_key_target|.
16void RecordKeyPair(std::string* private_key_target,
17                   std::string* public_key_target,
18                   const std::string& private_key_source,
19                   const std::string& public_key_source) {
20  *private_key_target = private_key_source;
21  *public_key_target = public_key_source;
22}
23
24// Callback for |EasyUnlockClient| methods that return a single piece of data.
25// It saves the returned data in |data_target|.
26void RecordData(std::string* data_target,
27                const std::string& data_source) {
28  *data_target = data_source;
29}
30
31TEST(FakeEasyUnlockClientTest, GenerateEcP256KeyPair) {
32  chromeos::FakeEasyUnlockClient client;
33
34  std::string private_key_1;
35  std::string public_key_1;
36  client.GenerateEcP256KeyPair(
37      base::Bind(&RecordKeyPair, &private_key_1, &public_key_1));
38  ASSERT_EQ("{\"ec_p256_private_key\": 1}", private_key_1);
39  ASSERT_EQ("{\"ec_p256_public_key\": 1}", public_key_1);
40
41  std::string private_key_2;
42  std::string public_key_2;
43  client.GenerateEcP256KeyPair(
44      base::Bind(&RecordKeyPair, &private_key_2, &public_key_2));
45  ASSERT_EQ("{\"ec_p256_private_key\": 2}", private_key_2);
46  ASSERT_EQ("{\"ec_p256_public_key\": 2}", public_key_2);
47
48  EXPECT_NE(private_key_1, private_key_2);
49  EXPECT_NE(public_key_1, public_key_2);
50}
51
52TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair) {
53  ASSERT_TRUE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
54      "{\"ec_p256_private_key\": 12}",
55      "{\"ec_p256_public_key\": 12}"));
56}
57
58TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_KeysFromDiffrentPairs) {
59  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
60      "{\"ec_p256_private_key\": 12}",
61      "{\"ec_p256_public_key\": 34}"));
62}
63
64TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_KeyOrderSwitched) {
65  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
66      "{\"ec_p256_public_key\": 34}",
67      "{\"ec_p256_private_key\": 34}"));
68}
69
70TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PrivateKeyInvalidFormat) {
71  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
72      "\"ec_p256_private_key\": 12",
73      "{\"ec_p256_public_key\": 12}"));
74}
75
76TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PublicKeyInvalidFormat) {
77  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
78      "{\"ec_p256_private_key\": 12}",
79      "\"ec_p256_public_key\": 12"));
80}
81
82TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PrivateKeyInvalidDictKey) {
83  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
84      "{\"invalid\": 12}",
85      "{\"ec_p256_public_key\": 12}"));
86}
87
88TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PublicKeyInvalidDictKey) {
89  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
90      "{\"ec_p256_private_key\": 12}",
91      "{\"invalid\": 12}"));
92}
93
94TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_InvalidDictValues) {
95  ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair(
96      "{\"ec_p256_private_key\": \"12\"}",
97      "{\"ec_p256_public_key\": \"12\"}"));
98}
99
100// Verifies the fake |PerformECDHKeyAgreement| method is symetric in respect to
101// key pairs from which private and public key used in the key agreement
102// originate.
103TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementSuccess) {
104  chromeos::FakeEasyUnlockClient client;
105
106  // (Fake) key pairs used in the test to generate fake shared keys.
107  const std::string private_key_1 = "{\"ec_p256_private_key\": 32}";
108  const std::string public_key_1 = "{\"ec_p256_public_key\": 32}";
109
110  const std::string private_key_2 = "{\"ec_p256_private_key\": 352}";
111  const std::string public_key_2 = "{\"ec_p256_public_key\": 352}";
112
113  const std::string private_key_3 = "{\"ec_p256_private_key\": 432}";
114  const std::string public_key_3 = "{\"ec_p256_public_key\": 432}";
115
116  // Generate shared key for key pairs 1 and 2, using private key from the
117  // second key pair and public key from the first key pair.
118  std::string shared_key_1;
119  client.PerformECDHKeyAgreement(private_key_2,
120                                 public_key_1,
121                                 base::Bind(&RecordData, &shared_key_1));
122  EXPECT_FALSE(shared_key_1.empty());
123
124  // Generate shared key for key pairs 1 and 2, using private key from the
125  // first key pair and public key from the second key pair.
126  std::string shared_key_2;
127  client.PerformECDHKeyAgreement(private_key_1,
128                                 public_key_2,
129                                 base::Bind(&RecordData, &shared_key_2));
130  EXPECT_FALSE(shared_key_2.empty());
131
132  // The generated keys should be equal. They were generated using keys from
133  // the same key pairs, even though key pairs from which private and public key
134  // originate were switched.
135  EXPECT_EQ(shared_key_1, shared_key_2);
136
137  // Generate a key using key pairs 1 and 3.
138  std::string shared_key_3;
139  client.PerformECDHKeyAgreement(private_key_1,
140                                 public_key_3,
141                                 base::Bind(&RecordData, &shared_key_3));
142  EXPECT_FALSE(shared_key_3.empty());
143
144  // The new key should be different from the previously generated ones, since
145  // the used key pairs are different.
146  EXPECT_NE(shared_key_3, shared_key_1);
147  EXPECT_NE(shared_key_3, shared_key_1);
148}
149
150TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyOrderSwitched) {
151  chromeos::FakeEasyUnlockClient client;
152
153  const std::string private_key = "{\"ec_p256_private_key\": 415}";
154  const std::string public_key = "{\"ec_p256_public_key\": 345}";
155
156  std::string shared_key;
157  client.PerformECDHKeyAgreement(public_key,
158                                 private_key,
159                                 base::Bind(&RecordData, &shared_key));
160  EXPECT_TRUE(shared_key.empty());
161}
162
163TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyDictKeyInvalid) {
164  chromeos::FakeEasyUnlockClient client;
165
166  const std::string private_key = "{\"ec_p256_private_key_invalid\": 415}";
167  const std::string public_key = "{\"ec_p256_public_key_invalid\": 345}";
168
169  std::string shared_key;
170  client.PerformECDHKeyAgreement(private_key,
171                                 public_key,
172                                 base::Bind(&RecordData, &shared_key));
173  EXPECT_TRUE(shared_key.empty());
174}
175
176TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyDictValueInvalid) {
177  chromeos::FakeEasyUnlockClient client;
178
179  const std::string private_key = "{\"ec_p256_private_key\": 415}";
180  const std::string public_key = "{\"ec_p256_public_key\": \"345__\"}";
181
182  std::string shared_key;
183  client.PerformECDHKeyAgreement(private_key,
184                                 public_key,
185                                 base::Bind(&RecordData, &shared_key));
186  EXPECT_TRUE(shared_key.empty());
187}
188
189TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyFormatInvalid) {
190  chromeos::FakeEasyUnlockClient client;
191
192  const std::string private_key = "invalid";
193  const std::string public_key = "{\"ec_p256_public_key\": 345}";
194
195  std::string shared_key;
196  client.PerformECDHKeyAgreement(private_key,
197                                 public_key,
198                                 base::Bind(&RecordData, &shared_key));
199  EXPECT_TRUE(shared_key.empty());
200}
201
202TEST(FakeEasyUnlockClientTest, CreateSecureMessage) {
203  chromeos::FakeEasyUnlockClient client;
204
205  std::string message;
206
207  chromeos::EasyUnlockClient::CreateSecureMessageOptions options;
208  options.key = "KEY";
209  options.associated_data = "ASSOCIATED_DATA";
210  options.public_metadata = "PUBLIC_METADATA";
211  options.verification_key_id = "VERIFICATION_KEY_ID";
212  options.decryption_key_id = "DECRYPTION_KEY_ID";
213  options.encryption_type = "ENCRYPTION_TYPE";
214  options.signature_type = "SIGNATURE_TYPE";
215
216  client.CreateSecureMessage(
217      "PAYLOAD",
218      options,
219      base::Bind(&RecordData, &message));
220
221  const std::string expected_message(
222      "{\"securemessage\": {"
223          "\"payload\": \"PAYLOAD\","
224          "\"key\": \"KEY\","
225          "\"associated_data\": \"ASSOCIATED_DATA\","
226          "\"public_metadata\": \"PUBLIC_METADATA\","
227          "\"verification_key_id\": \"VERIFICATION_KEY_ID\","
228          "\"decryption_key_id\": \"DECRYPTION_KEY_ID\","
229          "\"encryption_type\": \"ENCRYPTION_TYPE\","
230          "\"signature_type\": \"SIGNATURE_TYPE\"}"
231      "}");
232  ASSERT_EQ(expected_message, message);
233}
234
235TEST(FakeEasyUnlockClientTest, UnwrapSecureMessage) {
236  chromeos::FakeEasyUnlockClient client;
237
238  std::string message;
239
240  chromeos::EasyUnlockClient::UnwrapSecureMessageOptions options;
241  options.key = "KEY";
242  options.associated_data = "ASSOCIATED_DATA";
243  options.encryption_type = "ENCRYPTION_TYPE";
244  options.signature_type = "SIGNATURE_TYPE";
245
246  client.UnwrapSecureMessage(
247      "MESSAGE",
248      options,
249      base::Bind(&RecordData, &message));
250
251  const std::string expected_message(
252      "{\"unwrapped_securemessage\": {"
253          "\"message\": \"MESSAGE\","
254          "\"key\": \"KEY\","
255          "\"associated_data\": \"ASSOCIATED_DATA\","
256          "\"encryption_type\": \"ENCRYPTION_TYPE\","
257          "\"signature_type\": \"SIGNATURE_TYPE\"}"
258      "}");
259  ASSERT_EQ(expected_message, message);
260}
261
262}  // namespace
263
264