1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PROXIMITY_DEVICE_TO_DEVICE_AUTHENTICATOR_H
#define COMPONENTS_PROXIMITY_DEVICE_TO_DEVICE_AUTHENTICATOR_H
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/proximity_auth/authenticator.h"
#include "components/proximity_auth/connection_observer.h"
namespace base {
class Timer;
};
namespace proximity_auth {
class Connection;
class SecureMessageDelegate;
// Authenticator implementation using the "device to device" protocol, which is
// in turn built on top of the SecureMessage library.
// This protocol contains the following steps (local device is the initiator):
// 1. Both initiator and responder devices generate a temporary key pair for
// the session.
// 2. Initiator sends [Hello] message to responder device, which contains the
// initiator's session public key.
// 3. Responder responds with a [Responder Auth] message, containing its
// session public key and data that allows the initiator to assert the
// identity of the responder.
// 4. Initiator sends [Initiator Auth] message, containing data allowing the
// responder to assert the identity of the initiator.
// 5. Both devices derive a symmetric key by running a key agreement protocol
// session public keys they obtain from from the messages above. This
// symmetric key is used in the subsequent SecureContext.
// The authentication protocol fails if any of the steps above fail.
// This protocol requires exclusive use of the connection. No other message
// should be sent or received while authentication is in progress.
class DeviceToDeviceAuthenticator : public Authenticator,
public ConnectionObserver {
public:
// Creates the instance:
// |connection|: The connection to the remote device, which must be in a
// connected state. Not owned.
// |account_id|: The canonical account id of the user who is the owner of both
// the local and remote devices.
// |secure_message_delegate|: Handles the SecureMessage crypto operations.
DeviceToDeviceAuthenticator(
Connection* connection,
const std::string& account_id,
scoped_ptr<SecureMessageDelegate> secure_message_delegate);
~DeviceToDeviceAuthenticator() override;
// Authenticator:
void Authenticate(const AuthenticationCallback& callback) override;
protected:
// Creates a base::Timer instance. Exposed for testing.
virtual scoped_ptr<base::Timer> CreateTimer();
private:
// The current state of the authentication flow.
enum class State {
NOT_STARTED,
GENERATING_SESSION_KEYS,
SENDING_HELLO,
SENT_HELLO,
RECEIVED_RESPONDER_AUTH,
VALIDATED_RESPONDER_AUTH,
SENT_INITIATOR_AUTH,
AUTHENTICATION_SUCCESS,
AUTHENTICATION_FAILURE,
};
// Callback when the session key pair is generated.
void OnKeyPairGenerated(const std::string& public_key,
const std::string& private_key);
// Callback when [Hello] is created.
void OnHelloMessageCreated(const std::string& message);
// Callback when waiting for [Remote Auth] times out.
void OnResponderAuthTimedOut();
// Callback for validating the received [Remote Auth].
void OnResponderAuthValidated(bool validated,
const std::string& session_symmetric_key);
// Callback when [Initiator Auth] is created.
void OnInitiatorAuthCreated(const std::string& message);
// Callback when the session symmetric key is derived.
void OnKeyDerived(const std::string& session_symmetric_key);
// Called when the authentication flow fails, and logs |error_message|. The
// overloaded version specifies the Result to be reported;
// otherwise, a FAILURE result will be reported.
void Fail(const std::string& error_message);
void Fail(const std::string& error_message, Result result);
// Called when the authentication flow succeeds.
void Succeed();
// ConnectionObserver:
void OnConnectionStatusChanged(Connection* connection,
Connection::Status old_status,
Connection::Status new_status) override;
void OnMessageReceived(const Connection& connection,
const WireMessage& message) override;
void OnSendCompleted(const Connection& connection,
const WireMessage& message,
bool success) override;
// The connection to the remote device. It is expected to be in the CONNECTED
// state at all times during authentication.
// Not owned, and must outlive this instance.
Connection* const connection_;
// The account id of the user who owns the local and remote devices. This is
// normally an email address, and should be canonicalized.
const std::string account_id_;
// Handles SecureMessage crypto operations.
scoped_ptr<SecureMessageDelegate> secure_message_delegate_;
// The current state in the authentication flow.
State state_;
// Callback to invoke when authentication completes.
AuthenticationCallback callback_;
// Used for timing out when waiting for [Remote Auth] from the remote device.
scoped_ptr<base::Timer> timer_;
// The bytes of the [Hello] message sent to the remote device.
std::string hello_message_;
// The bytes of the [Responder Auth] message received from the remote device.
std::string responder_auth_message_;
// The private key generated for the session.
std::string local_session_private_key_;
// The derived symmetric key for the session.
std::string session_symmetric_key_;
base::WeakPtrFactory<DeviceToDeviceAuthenticator> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DeviceToDeviceAuthenticator);
};
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_DEVICE_TO_DEVICE_AUTHENTICATOR_H
|