fido_tunnel_device.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // Copyright 2020 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. #ifndef DEVICE_FIDO_CABLE_FIDO_TUNNEL_DEVICE_H_
  5. #define DEVICE_FIDO_CABLE_FIDO_TUNNEL_DEVICE_H_
  6. #include <array>
  7. #include <vector>
  8. #include "base/callback_forward.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/memory/scoped_refptr.h"
  11. #include "base/sequence_checker.h"
  12. #include "base/timer/timer.h"
  13. #include "device/fido/cable/v2_constants.h"
  14. #include "device/fido/cable/websocket_adapter.h"
  15. #include "device/fido/fido_constants.h"
  16. #include "device/fido/fido_device.h"
  17. #include "third_party/abseil-cpp/absl/types/variant.h"
  18. namespace network {
  19. namespace mojom {
  20. class NetworkContext;
  21. }
  22. } // namespace network
  23. namespace device {
  24. namespace cablev2 {
  25. class Crypter;
  26. class WebSocketAdapter;
  27. struct Pairing;
  28. class COMPONENT_EXPORT(DEVICE_FIDO) FidoTunnelDevice : public FidoDevice {
  29. public:
  30. // This constructor is used for QR-initiated connections.
  31. FidoTunnelDevice(
  32. network::mojom::NetworkContext* network_context,
  33. absl::optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
  34. pairing_callback,
  35. base::span<const uint8_t> secret,
  36. base::span<const uint8_t, kQRSeedSize> local_identity_seed,
  37. const CableEidArray& decrypted_eid);
  38. // This constructor is used for pairing-initiated connections. If the given
  39. // |Pairing| is reported by the tunnel server to be invalid (which can happen
  40. // if the user opts to unlink all devices) then |pairing_is_invalid| is
  41. // run.
  42. FidoTunnelDevice(FidoRequestType request_type,
  43. network::mojom::NetworkContext* network_context,
  44. std::unique_ptr<Pairing> pairing,
  45. base::OnceClosure pairing_is_invalid);
  46. FidoTunnelDevice(const FidoTunnelDevice&) = delete;
  47. FidoTunnelDevice& operator=(const FidoTunnelDevice&) = delete;
  48. ~FidoTunnelDevice() override;
  49. // MatchAdvert is only valid for a pairing-initiated connection. It returns
  50. // true if the given |advert| matched this pending tunnel and thus this device
  51. // is now ready.
  52. bool MatchAdvert(const std::array<uint8_t, kAdvertSize>& advert);
  53. // FidoDevice:
  54. CancelToken DeviceTransact(std::vector<uint8_t> command,
  55. DeviceCallback callback) override;
  56. void Cancel(CancelToken token) override;
  57. std::string GetId() const override;
  58. FidoTransportProtocol DeviceTransport() const override;
  59. base::WeakPtr<FidoDevice> GetWeakPtr() override;
  60. // GetNumEstablishedConnectionInstancesForTesting returns the current number
  61. // of live |EstablishedConnection| objects. This is only for testing that
  62. // they aren't leaking.
  63. static int GetNumEstablishedConnectionInstancesForTesting();
  64. private:
  65. enum class State {
  66. // QR (or server-link) handshakes advance through the states like this:
  67. //
  68. // kConnecting
  69. // |
  70. // (Tunnel server connection completes and handshake is sent)
  71. // |
  72. // V
  73. // kHandshakeSent
  74. // |
  75. // (Handshake reply is received)
  76. // |
  77. // V
  78. // kWaitingForPostHandshakeMessage
  79. // |
  80. // (Post-handshake message is received)
  81. // |
  82. // V
  83. // kReady
  84. //
  85. //
  86. // Paired connections are similar, but there's a race between the tunnel
  87. // connection completing and the BLE advert being received.
  88. //
  89. // kConnecting -------------------------------------
  90. // | |
  91. // (Tunnel server connection completes) |
  92. // | (BLE advert is received _then_
  93. // V tunnel connection completes.)
  94. // kWaitingForEID |
  95. // | |
  96. // (BLE advert is received and handshake is sent) |
  97. // | |
  98. // V |
  99. // kHandshakeSent <------------------------------
  100. // |
  101. // (Handshake reply is received)
  102. // |
  103. // V
  104. // kWaitingForPostHandshakeMessage
  105. // |
  106. // (Post-handshake message is received)
  107. // |
  108. // V
  109. // kReady
  110. kConnecting,
  111. kHandshakeSent,
  112. kWaitingForEID,
  113. kWaitingForPostHandshakeMessage,
  114. kReady,
  115. kError,
  116. };
  117. struct QRInfo {
  118. QRInfo();
  119. ~QRInfo();
  120. QRInfo(const QRInfo&) = delete;
  121. QRInfo& operator=(const QRInfo&) = delete;
  122. CableEidArray decrypted_eid;
  123. std::array<uint8_t, 32> psk;
  124. absl::optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
  125. pairing_callback;
  126. std::array<uint8_t, kQRSeedSize> local_identity_seed;
  127. tunnelserver::KnownDomainID tunnel_server_domain;
  128. };
  129. struct PairedInfo {
  130. PairedInfo();
  131. ~PairedInfo();
  132. PairedInfo(const PairedInfo&) = delete;
  133. PairedInfo& operator=(const PairedInfo&) = delete;
  134. std::array<uint8_t, kEIDKeySize> eid_encryption_key;
  135. std::array<uint8_t, kP256X962Length> peer_identity;
  136. std::vector<uint8_t> secret;
  137. absl::optional<CableEidArray> decrypted_eid;
  138. absl::optional<std::array<uint8_t, 32>> psk;
  139. absl::optional<std::vector<uint8_t>> handshake_message;
  140. base::OnceClosure pairing_is_invalid;
  141. };
  142. // EstablishedConnection represents a connection where the handshake has
  143. // completed.
  144. class EstablishedConnection : public base::RefCounted<EstablishedConnection> {
  145. public:
  146. EstablishedConnection(std::unique_ptr<WebSocketAdapter> websocket_client,
  147. std::string id_for_logging,
  148. int protocol_revision,
  149. std::unique_ptr<Crypter> crypter,
  150. const HandshakeHash& handshake_hash,
  151. QRInfo* maybe_qr_info);
  152. EstablishedConnection(const EstablishedConnection&) = delete;
  153. EstablishedConnection& operator=(const EstablishedConnection&) = delete;
  154. void Transact(std::vector<uint8_t> message, DeviceCallback callback);
  155. void Close();
  156. private:
  157. enum class State {
  158. kRunning,
  159. kLocallyShutdown,
  160. kRemoteShutdown,
  161. kClosed,
  162. };
  163. friend class base::RefCounted<EstablishedConnection>;
  164. ~EstablishedConnection();
  165. void OnTunnelData(absl::optional<base::span<const uint8_t>> data);
  166. void OnRemoteClose();
  167. void OnTimeout();
  168. bool ProcessUpdate(base::span<const uint8_t> plaintext);
  169. scoped_refptr<EstablishedConnection> self_reference_;
  170. State state_ = State::kRunning;
  171. std::unique_ptr<WebSocketAdapter> websocket_client_;
  172. const std::string id_for_logging_;
  173. const int protocol_revision_;
  174. const std::unique_ptr<Crypter> crypter_;
  175. const HandshakeHash handshake_hash_;
  176. // These three fields are either all present or all nullopt.
  177. absl::optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
  178. pairing_callback_;
  179. absl::optional<std::array<uint8_t, kQRSeedSize>> local_identity_seed_;
  180. absl::optional<tunnelserver::KnownDomainID> tunnel_server_domain_;
  181. base::OneShotTimer timer_;
  182. DeviceCallback callback_;
  183. SEQUENCE_CHECKER(sequence_checker_);
  184. };
  185. void OnTunnelReady(
  186. WebSocketAdapter::Result result,
  187. absl::optional<std::array<uint8_t, kRoutingIdSize>> routing_id);
  188. void OnTunnelData(absl::optional<base::span<const uint8_t>> data);
  189. void OnError();
  190. void DeviceTransactReady(std::vector<uint8_t> command,
  191. DeviceCallback callback);
  192. State state_ = State::kConnecting;
  193. absl::variant<QRInfo, PairedInfo> info_;
  194. const std::array<uint8_t, 8> id_;
  195. std::vector<uint8_t> pending_message_;
  196. DeviceCallback pending_callback_;
  197. absl::optional<HandshakeInitiator> handshake_;
  198. absl::optional<HandshakeHash> handshake_hash_;
  199. std::vector<uint8_t> getinfo_response_bytes_;
  200. // These fields are |nullptr| when in state |kReady|.
  201. std::unique_ptr<WebSocketAdapter> websocket_client_;
  202. std::unique_ptr<Crypter> crypter_;
  203. // This is only valid when in state |kReady|.
  204. scoped_refptr<EstablishedConnection> established_connection_;
  205. SEQUENCE_CHECKER(sequence_checker_);
  206. base::WeakPtrFactory<FidoTunnelDevice> weak_factory_{this};
  207. };
  208. } // namespace cablev2
  209. } // namespace device
  210. #endif // DEVICE_FIDO_CABLE_FIDO_TUNNEL_DEVICE_H_