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