1 // Copyright 2018 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 #ifndef DEVICE_FIDO_CABLE_FIDO_CABLE_DEVICE_H_
6 #define DEVICE_FIDO_CABLE_FIDO_CABLE_DEVICE_H_
7
8 #include <array>
9 #include <memory>
10 #include <string>
11 #include <vector>
12
13 #include "base/component_export.h"
14 #include "base/containers/span.h"
15 #include "base/macros.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/optional.h"
18 #include "crypto/aead.h"
19 #include "device/fido/cable/fido_ble_connection.h"
20 #include "device/fido/cable/fido_ble_transaction.h"
21 #include "device/fido/fido_device.h"
22
23 namespace device {
24
25 class BluetoothAdapter;
26 class FidoBleFrame;
27
COMPONENT_EXPORT(DEVICE_FIDO)28 class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDevice : public FidoDevice {
29 public:
30 using FrameCallback = FidoBleTransaction::FrameCallback;
31
32 class Observer {
33 public:
34 virtual void FidoCableDeviceConnected(FidoCableDevice* device,
35 bool success) {}
36 virtual void FidoCableDeviceTimeout(FidoCableDevice* device) {}
37 };
38
39 FidoCableDevice(BluetoothAdapter* adapter, std::string address);
40 // Constructor used for testing purposes.
41 FidoCableDevice(std::unique_ptr<FidoBleConnection> connection);
42 ~FidoCableDevice() override;
43
44 // Returns FidoDevice::GetId() for a given FidoBleConnection address.
45 static std::string GetIdForAddress(const std::string& ble_address);
46
47 std::string GetAddress();
48 void Connect();
49 void SendPing(std::vector<uint8_t> data, DeviceCallback callback);
50 FidoBleConnection::ReadCallback GetReadCallbackForTesting();
51 void set_observer(Observer* observer);
52
53 // FidoDevice:
54 void Cancel(CancelToken token) override;
55 std::string GetId() const override;
56 base::string16 GetDisplayName() const override;
57 FidoTransportProtocol DeviceTransport() const override;
58 CancelToken DeviceTransact(std::vector<uint8_t> command,
59 DeviceCallback callback) override;
60
61 void SendHandshakeMessage(std::vector<uint8_t> handshake_message,
62 DeviceCallback callback);
63
64 // Configure caBLE v1 keys.
65 void SetV1EncryptionData(base::span<const uint8_t, 32> session_key,
66 base::span<const uint8_t, 8> nonce);
67
68 // SetCountersForTesting allows tests to set the message counters. Non-test
69 // code must not call this function.
70 void SetSequenceNumbersForTesting(uint32_t read_counter,
71 uint32_t write_counter);
72
73 base::WeakPtr<FidoDevice> GetWeakPtr() override;
74
75 private:
76 struct PendingFrame {
77 PendingFrame(FidoBleFrame frame, FrameCallback callback, CancelToken token);
78 PendingFrame(PendingFrame&&);
79 ~PendingFrame();
80
81 FidoBleFrame frame;
82 FrameCallback callback;
83 CancelToken token;
84 };
85
86 // Encapsulates state FidoCableDevice maintains to encrypt and decrypt
87 // data within FidoBleFrame.
88 struct EncryptionData {
89 EncryptionData();
90 ~EncryptionData();
91
92 std::array<uint8_t, 32> read_key;
93 std::array<uint8_t, 32> write_key;
94 std::array<uint8_t, 8> nonce;
95 uint32_t write_sequence_num = 0;
96 uint32_t read_sequence_num = 0;
97 };
98
99 void OnResponseFrame(FrameCallback callback,
100 base::Optional<FidoBleFrame> frame);
101 void Transition();
102 CancelToken AddToPendingFrames(FidoBleDeviceCommand cmd,
103 std::vector<uint8_t> request,
104 DeviceCallback callback);
105 void ResetTransaction();
106
107 void OnConnected(bool success);
108 void OnStatusMessage(std::vector<uint8_t> data);
109
110 void OnReadControlPointLength(base::Optional<uint16_t> length);
111
112 void SendRequestFrame(FidoBleFrame frame, FrameCallback callback);
113
114 void StartTimeout();
115 void StopTimeout();
116 void OnTimeout();
117
118 void OnBleResponseReceived(DeviceCallback callback,
119 base::Optional<FidoBleFrame> frame);
120 void ProcessBleDeviceError(base::span<const uint8_t> data);
121
122 bool EncryptOutgoingMessage(std::vector<uint8_t>* message_to_encrypt);
123 bool DecryptIncomingMessage(FidoBleFrame* incoming_frame);
124
125 base::OneShotTimer timer_;
126
127 std::unique_ptr<FidoBleConnection> connection_;
128 uint16_t control_point_length_ = 0;
129
130 // pending_frames_ contains frames that have not yet been sent, i.e. the
131 // current frame is not included at the head of the list.
132 std::list<PendingFrame> pending_frames_;
133 // current_token_ contains the cancelation token of the currently running
134 // request, or else is empty if no request is currently pending.
135 base::Optional<CancelToken> current_token_;
136 base::Optional<FidoBleTransaction> transaction_;
137 Observer* observer_ = nullptr;
138
139 base::Optional<EncryptionData> encryption_data_;
140 base::WeakPtrFactory<FidoCableDevice> weak_factory_{this};
141
142 DISALLOW_COPY_AND_ASSIGN(FidoCableDevice);
143 };
144
145 } // namespace device
146
147 #endif // DEVICE_FIDO_CABLE_FIDO_CABLE_DEVICE_H_
148