Rename GetIconID to GetIconId
[chromium-blink-merge.git] / components / proximity_auth / device_to_device_authenticator_unittest.cc
blob17c260c826dbdace7a800e9384601b7771a83f5f
1 // Copyright 2015 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.
5 #include "components/proximity_auth/device_to_device_authenticator.h"
7 #include "base/bind.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/rand_util.h"
10 #include "base/timer/mock_timer.h"
11 #include "components/proximity_auth/connection.h"
12 #include "components/proximity_auth/cryptauth/base64url.h"
13 #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
14 #include "components/proximity_auth/device_to_device_responder_operations.h"
15 #include "components/proximity_auth/secure_context.h"
16 #include "components/proximity_auth/wire_message.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace proximity_auth {
22 namespace {
24 // The account id of the user.
25 const char kAccountId[] = "example@gmail.com";
27 // Attributes of the connected remote device.
28 const char kRemoteDeviceName[] = "iPhone 6";
29 const char kRemoteDevicePublicKey[] = "remote public key";
30 const char kRemoteDeviceBluetoothAddress[] = "AA:BB:CC:DD:EE:FF";
31 const char kRemoteDevicePersistentSymmetricKey[] = "PSK";
33 // The initiator's session public key in base64url form. Note that this is
34 // actually a serialized proto.
35 const char kInitiatorSessionPublicKeyBase64[] =
36 "CAESRQogOlH8DgPMQu7eAt-b6yoTXcazG8mAl6SPC5Ds-LTULIcSIQDZDMqsoYRO4tNMej1FB"
37 "El1sTiTiVDqrcGq-CkYCzDThw==";
39 // The initiator's session public key in base64url form. Note that this is
40 // actually a serialized proto.
41 const char kResponderSessionPublicKeyBase64[] =
42 "CAESRgohAN9QYU5HySO14Gi9PDIClacBnC0C8wqPwXsNHUNG_vXlEiEAggzU80ZOd9DWuCBdp"
43 "6bzpGcC-oj1yrwdVCHGg_yeaAQ=";
45 // Callback saving a string from |result| to |result_out|.
46 void SaveStringResult(std::string* result_out, const std::string& result) {
47 *result_out = result;
50 // Callback saving a boolean from |result| to |result_out|.
51 void SaveBooleanResult(bool* result_out, bool result) {
52 *result_out = result;
55 // Callback saving the result of ValidateHelloMessage().
56 void SaveValidateHelloMessageResult(bool* validated_out,
57 std::string* public_key_out,
58 bool validated,
59 const std::string& public_key) {
60 *validated_out = validated;
61 *public_key_out = public_key;
64 // Connection implementation for testing.
65 class FakeConnection : public Connection {
66 public:
67 FakeConnection(const RemoteDevice& remote_device)
68 : Connection(remote_device), connection_blocked_(false) {}
69 ~FakeConnection() override {}
71 // Connection:
72 void Connect() override { SetStatus(Connection::Status::CONNECTED); }
73 void Disconnect() override { SetStatus(Connection::Status::DISCONNECTED); }
75 using Connection::OnBytesReceived;
77 void ClearMessageBuffer() { message_buffer_.clear(); }
79 const ScopedVector<WireMessage>& message_buffer() { return message_buffer_; }
81 void set_connection_blocked(bool connection_blocked) {
82 connection_blocked_ = connection_blocked;
85 bool connection_blocked() { return connection_blocked_; }
87 protected:
88 // Connection:
89 void SendMessageImpl(scoped_ptr<WireMessage> message) override {
90 const WireMessage& message_alias = *message;
91 message_buffer_.push_back(message.Pass());
92 OnDidSendMessage(message_alias, !connection_blocked_);
95 private:
96 ScopedVector<WireMessage> message_buffer_;
98 bool connection_blocked_;
100 DISALLOW_COPY_AND_ASSIGN(FakeConnection);
103 // Harness for testing DeviceToDeviceAuthenticator.
104 class DeviceToDeviceAuthenticatorForTest : public DeviceToDeviceAuthenticator {
105 public:
106 DeviceToDeviceAuthenticatorForTest(
107 Connection* connection,
108 scoped_ptr<SecureMessageDelegate> secure_message_delegate)
109 : DeviceToDeviceAuthenticator(connection,
110 kAccountId,
111 secure_message_delegate.Pass()),
112 timer_(nullptr) {}
113 ~DeviceToDeviceAuthenticatorForTest() override {}
115 base::MockTimer* timer() { return timer_; }
117 private:
118 // DeviceToDeviceAuthenticator:
119 scoped_ptr<base::Timer> CreateTimer() override {
120 bool retain_user_task = false;
121 bool is_repeating = false;
123 scoped_ptr<base::MockTimer> timer(
124 new base::MockTimer(retain_user_task, is_repeating));
126 timer_ = timer.get();
127 return timer.Pass();
130 // This instance is owned by the super class.
131 base::MockTimer* timer_;
133 DISALLOW_COPY_AND_ASSIGN(DeviceToDeviceAuthenticatorForTest);
136 } // namespace
138 class ProximityAuthDeviceToDeviceAuthenticatorTest : public testing::Test {
139 public:
140 ProximityAuthDeviceToDeviceAuthenticatorTest()
141 : remote_device_(kRemoteDeviceName,
142 kRemoteDevicePublicKey,
143 kRemoteDeviceBluetoothAddress,
144 kRemoteDevicePersistentSymmetricKey),
145 connection_(remote_device_),
146 secure_message_delegate_(new FakeSecureMessageDelegate),
147 authenticator_(&connection_,
148 make_scoped_ptr(secure_message_delegate_)) {}
149 ~ProximityAuthDeviceToDeviceAuthenticatorTest() override {}
151 void SetUp() override {
152 // Set up the session asymmetric keys for both the local and remote devices.
153 Base64UrlDecode(kInitiatorSessionPublicKeyBase64,
154 &local_session_public_key_);
155 Base64UrlDecode(kResponderSessionPublicKeyBase64,
156 &remote_session_public_key_);
157 remote_session_private_key_ =
158 secure_message_delegate_->GetPrivateKeyForPublicKey(
159 remote_session_public_key_),
161 secure_message_delegate_->set_next_public_key(local_session_public_key_);
162 connection_.Connect();
164 secure_message_delegate_->DeriveKey(
165 remote_session_private_key_, local_session_public_key_,
166 base::Bind(&SaveStringResult, &session_symmetric_key_));
169 // Begins authentication, and returns the [Hello] message sent from the local
170 // device to the remote device.
171 std::string BeginAuthentication() {
172 authenticator_.Authenticate(base::Bind(
173 &ProximityAuthDeviceToDeviceAuthenticatorTest::OnAuthenticationResult,
174 base::Unretained(this)));
176 EXPECT_EQ(1u, connection_.message_buffer().size());
177 EXPECT_EQ(std::string("permit://google.com/easyunlock/v1/") + kAccountId,
178 connection_.message_buffer()[0]->permit_id());
179 std::string hello_message = connection_.message_buffer()[0]->payload();
180 connection_.ClearMessageBuffer();
182 bool validated = false;
183 std::string local_session_public_key;
184 DeviceToDeviceResponderOperations::ValidateHelloMessage(
185 hello_message, remote_device_.persistent_symmetric_key,
186 secure_message_delegate_,
187 base::Bind(&SaveValidateHelloMessageResult, &validated,
188 &local_session_public_key));
190 EXPECT_TRUE(validated);
191 EXPECT_EQ(local_session_public_key_, local_session_public_key);
193 return hello_message;
196 // Simulate receiving a valid [Responder Auth] message from the remote device.
197 std::string SimulateResponderAuth(const std::string& hello_message) {
198 std::string remote_device_private_key =
199 secure_message_delegate_->GetPrivateKeyForPublicKey(
200 kRemoteDevicePublicKey);
202 std::string responder_auth_message;
203 DeviceToDeviceResponderOperations::CreateResponderAuthMessage(
204 hello_message, remote_session_public_key_, remote_session_private_key_,
205 remote_device_private_key, remote_device_.persistent_symmetric_key,
206 secure_message_delegate_,
207 base::Bind(&SaveStringResult, &responder_auth_message));
208 EXPECT_FALSE(responder_auth_message.empty());
210 WireMessage wire_message(responder_auth_message);
211 connection_.OnBytesReceived(wire_message.Serialize());
213 return responder_auth_message;
216 void OnAuthenticationResult(Authenticator::Result result,
217 scoped_ptr<SecureContext> secure_context) {
218 secure_context_ = secure_context.Pass();
219 OnAuthenticationResultProxy(result);
222 MOCK_METHOD1(OnAuthenticationResultProxy, void(Authenticator::Result result));
224 // Contains information about the remote device.
225 const RemoteDevice remote_device_;
227 // Simulates the connection to the remote device.
228 FakeConnection connection_;
230 // The SecureMessageDelegate used by the authenticator.
231 // Owned by |authenticator_|.
232 FakeSecureMessageDelegate* secure_message_delegate_;
234 // The DeviceToDeviceAuthenticator under test.
235 DeviceToDeviceAuthenticatorForTest authenticator_;
237 // The session keys in play during authentication.
238 std::string local_session_public_key_;
239 std::string remote_session_public_key_;
240 std::string remote_session_private_key_;
241 std::string session_symmetric_key_;
243 // Stores the SecureContext returned after authentication succeeds.
244 scoped_ptr<SecureContext> secure_context_;
246 DISALLOW_COPY_AND_ASSIGN(ProximityAuthDeviceToDeviceAuthenticatorTest);
249 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest, AuthenticateSucceeds) {
250 // Starts the authentication protocol and grab [Hello] message.
251 std::string hello_message = BeginAuthentication();
253 // Simulate receiving a valid [Responder Auth] from the remote device.
254 EXPECT_CALL(*this,
255 OnAuthenticationResultProxy(Authenticator::Result::SUCCESS));
256 std::string responder_auth_message = SimulateResponderAuth(hello_message);
257 EXPECT_TRUE(secure_context_);
259 // Validate the local device sends a valid [Initiator Auth] message.
260 ASSERT_EQ(1u, connection_.message_buffer().size());
261 std::string initiator_auth = connection_.message_buffer()[0]->payload();
263 bool initiator_auth_validated = false;
264 DeviceToDeviceResponderOperations::ValidateInitiatorAuthMessage(
265 initiator_auth, session_symmetric_key_,
266 remote_device_.persistent_symmetric_key, responder_auth_message,
267 secure_message_delegate_,
268 base::Bind(&SaveBooleanResult, &initiator_auth_validated));
269 ASSERT_TRUE(initiator_auth_validated);
272 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest, ResponderRejectsHello) {
273 std::string hello_message = BeginAuthentication();
275 // If the responder could not validate the [Hello message], it essentially
276 // sends random bytes back for privacy reasons.
277 WireMessage wire_message(base::RandBytesAsString(300u));
278 EXPECT_CALL(*this,
279 OnAuthenticationResultProxy(Authenticator::Result::FAILURE));
280 connection_.OnBytesReceived(wire_message.Serialize());
281 EXPECT_FALSE(secure_context_);
284 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest, ResponderAuthTimesOut) {
285 // Starts the authentication protocol and grab [Hello] message.
286 std::string hello_message = BeginAuthentication();
287 ASSERT_TRUE(authenticator_.timer());
288 EXPECT_CALL(*this,
289 OnAuthenticationResultProxy(Authenticator::Result::FAILURE));
290 authenticator_.timer()->Fire();
291 EXPECT_FALSE(secure_context_);
294 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest,
295 DisconnectsWaitingForResponderAuth) {
296 std::string hello_message = BeginAuthentication();
297 EXPECT_CALL(*this,
298 OnAuthenticationResultProxy(Authenticator::Result::DISCONNECTED));
299 connection_.Disconnect();
300 EXPECT_FALSE(secure_context_);
303 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest, NotConnectedInitially) {
304 connection_.Disconnect();
305 EXPECT_CALL(*this,
306 OnAuthenticationResultProxy(Authenticator::Result::DISCONNECTED));
307 authenticator_.Authenticate(base::Bind(
308 &ProximityAuthDeviceToDeviceAuthenticatorTest::OnAuthenticationResult,
309 base::Unretained(this)));
310 EXPECT_FALSE(secure_context_);
313 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest, FailToSendHello) {
314 connection_.set_connection_blocked(true);
315 EXPECT_CALL(*this,
316 OnAuthenticationResultProxy(Authenticator::Result::FAILURE));
317 authenticator_.Authenticate(base::Bind(
318 &ProximityAuthDeviceToDeviceAuthenticatorTest::OnAuthenticationResult,
319 base::Unretained(this)));
320 EXPECT_FALSE(secure_context_);
323 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest, FailToSendInitiatorAuth) {
324 std::string hello_message = BeginAuthentication();
326 connection_.set_connection_blocked(true);
327 EXPECT_CALL(*this,
328 OnAuthenticationResultProxy(Authenticator::Result::FAILURE));
329 SimulateResponderAuth(hello_message);
330 EXPECT_FALSE(secure_context_);
333 TEST_F(ProximityAuthDeviceToDeviceAuthenticatorTest,
334 SendMessagesAfterAuthenticationSuccess) {
335 std::string hello_message = BeginAuthentication();
336 EXPECT_CALL(*this,
337 OnAuthenticationResultProxy(Authenticator::Result::SUCCESS));
338 SimulateResponderAuth(hello_message);
340 // Test that the authenticator is properly cleaned up after authentication
341 // completes.
342 WireMessage wire_message(base::RandBytesAsString(300u));
343 connection_.SendMessage(
344 make_scoped_ptr(new WireMessage(base::RandBytesAsString(300u))));
345 connection_.OnBytesReceived(wire_message.Serialize());
346 connection_.SendMessage(
347 make_scoped_ptr(new WireMessage(base::RandBytesAsString(300u))));
348 connection_.OnBytesReceived(wire_message.Serialize());
351 } // namespace proximity_auth