123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- // Copyright 2020 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 DEVICE_FIDO_CABLE_FIDO_TUNNEL_DEVICE_H_
- #define DEVICE_FIDO_CABLE_FIDO_TUNNEL_DEVICE_H_
- #include <array>
- #include <vector>
- #include "base/callback_forward.h"
- #include "base/memory/ref_counted.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/sequence_checker.h"
- #include "base/timer/timer.h"
- #include "device/fido/cable/v2_constants.h"
- #include "device/fido/cable/websocket_adapter.h"
- #include "device/fido/fido_constants.h"
- #include "device/fido/fido_device.h"
- #include "third_party/abseil-cpp/absl/types/variant.h"
- namespace network {
- namespace mojom {
- class NetworkContext;
- }
- } // namespace network
- namespace device {
- namespace cablev2 {
- class Crypter;
- class WebSocketAdapter;
- struct Pairing;
- class COMPONENT_EXPORT(DEVICE_FIDO) FidoTunnelDevice : public FidoDevice {
- public:
- // This constructor is used for QR-initiated connections.
- FidoTunnelDevice(
- network::mojom::NetworkContext* network_context,
- absl::optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
- pairing_callback,
- base::span<const uint8_t> secret,
- base::span<const uint8_t, kQRSeedSize> local_identity_seed,
- const CableEidArray& decrypted_eid);
- // This constructor is used for pairing-initiated connections. If the given
- // |Pairing| is reported by the tunnel server to be invalid (which can happen
- // if the user opts to unlink all devices) then |pairing_is_invalid| is
- // run.
- FidoTunnelDevice(FidoRequestType request_type,
- network::mojom::NetworkContext* network_context,
- std::unique_ptr<Pairing> pairing,
- base::OnceClosure pairing_is_invalid);
- FidoTunnelDevice(const FidoTunnelDevice&) = delete;
- FidoTunnelDevice& operator=(const FidoTunnelDevice&) = delete;
- ~FidoTunnelDevice() override;
- // MatchAdvert is only valid for a pairing-initiated connection. It returns
- // true if the given |advert| matched this pending tunnel and thus this device
- // is now ready.
- bool MatchAdvert(const std::array<uint8_t, kAdvertSize>& advert);
- // FidoDevice:
- CancelToken DeviceTransact(std::vector<uint8_t> command,
- DeviceCallback callback) override;
- void Cancel(CancelToken token) override;
- std::string GetId() const override;
- FidoTransportProtocol DeviceTransport() const override;
- base::WeakPtr<FidoDevice> GetWeakPtr() override;
- // GetNumEstablishedConnectionInstancesForTesting returns the current number
- // of live |EstablishedConnection| objects. This is only for testing that
- // they aren't leaking.
- static int GetNumEstablishedConnectionInstancesForTesting();
- private:
- enum class State {
- // QR (or server-link) handshakes advance through the states like this:
- //
- // kConnecting
- // |
- // (Tunnel server connection completes and handshake is sent)
- // |
- // V
- // kHandshakeSent
- // |
- // (Handshake reply is received)
- // |
- // V
- // kWaitingForPostHandshakeMessage
- // |
- // (Post-handshake message is received)
- // |
- // V
- // kReady
- //
- //
- // Paired connections are similar, but there's a race between the tunnel
- // connection completing and the BLE advert being received.
- //
- // kConnecting -------------------------------------
- // | |
- // (Tunnel server connection completes) |
- // | (BLE advert is received _then_
- // V tunnel connection completes.)
- // kWaitingForEID |
- // | |
- // (BLE advert is received and handshake is sent) |
- // | |
- // V |
- // kHandshakeSent <------------------------------
- // |
- // (Handshake reply is received)
- // |
- // V
- // kWaitingForPostHandshakeMessage
- // |
- // (Post-handshake message is received)
- // |
- // V
- // kReady
- kConnecting,
- kHandshakeSent,
- kWaitingForEID,
- kWaitingForPostHandshakeMessage,
- kReady,
- kError,
- };
- struct QRInfo {
- QRInfo();
- ~QRInfo();
- QRInfo(const QRInfo&) = delete;
- QRInfo& operator=(const QRInfo&) = delete;
- CableEidArray decrypted_eid;
- std::array<uint8_t, 32> psk;
- absl::optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
- pairing_callback;
- std::array<uint8_t, kQRSeedSize> local_identity_seed;
- tunnelserver::KnownDomainID tunnel_server_domain;
- };
- struct PairedInfo {
- PairedInfo();
- ~PairedInfo();
- PairedInfo(const PairedInfo&) = delete;
- PairedInfo& operator=(const PairedInfo&) = delete;
- std::array<uint8_t, kEIDKeySize> eid_encryption_key;
- std::array<uint8_t, kP256X962Length> peer_identity;
- std::vector<uint8_t> secret;
- absl::optional<CableEidArray> decrypted_eid;
- absl::optional<std::array<uint8_t, 32>> psk;
- absl::optional<std::vector<uint8_t>> handshake_message;
- base::OnceClosure pairing_is_invalid;
- };
- // EstablishedConnection represents a connection where the handshake has
- // completed.
- class EstablishedConnection : public base::RefCounted<EstablishedConnection> {
- public:
- EstablishedConnection(std::unique_ptr<WebSocketAdapter> websocket_client,
- std::string id_for_logging,
- int protocol_revision,
- std::unique_ptr<Crypter> crypter,
- const HandshakeHash& handshake_hash,
- QRInfo* maybe_qr_info);
- EstablishedConnection(const EstablishedConnection&) = delete;
- EstablishedConnection& operator=(const EstablishedConnection&) = delete;
- void Transact(std::vector<uint8_t> message, DeviceCallback callback);
- void Close();
- private:
- enum class State {
- kRunning,
- kLocallyShutdown,
- kRemoteShutdown,
- kClosed,
- };
- friend class base::RefCounted<EstablishedConnection>;
- ~EstablishedConnection();
- void OnTunnelData(absl::optional<base::span<const uint8_t>> data);
- void OnRemoteClose();
- void OnTimeout();
- bool ProcessUpdate(base::span<const uint8_t> plaintext);
- scoped_refptr<EstablishedConnection> self_reference_;
- State state_ = State::kRunning;
- std::unique_ptr<WebSocketAdapter> websocket_client_;
- const std::string id_for_logging_;
- const int protocol_revision_;
- const std::unique_ptr<Crypter> crypter_;
- const HandshakeHash handshake_hash_;
- // These three fields are either all present or all nullopt.
- absl::optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
- pairing_callback_;
- absl::optional<std::array<uint8_t, kQRSeedSize>> local_identity_seed_;
- absl::optional<tunnelserver::KnownDomainID> tunnel_server_domain_;
- base::OneShotTimer timer_;
- DeviceCallback callback_;
- SEQUENCE_CHECKER(sequence_checker_);
- };
- void OnTunnelReady(
- WebSocketAdapter::Result result,
- absl::optional<std::array<uint8_t, kRoutingIdSize>> routing_id);
- void OnTunnelData(absl::optional<base::span<const uint8_t>> data);
- void OnError();
- void DeviceTransactReady(std::vector<uint8_t> command,
- DeviceCallback callback);
- State state_ = State::kConnecting;
- absl::variant<QRInfo, PairedInfo> info_;
- const std::array<uint8_t, 8> id_;
- std::vector<uint8_t> pending_message_;
- DeviceCallback pending_callback_;
- absl::optional<HandshakeInitiator> handshake_;
- absl::optional<HandshakeHash> handshake_hash_;
- std::vector<uint8_t> getinfo_response_bytes_;
- // These fields are |nullptr| when in state |kReady|.
- std::unique_ptr<WebSocketAdapter> websocket_client_;
- std::unique_ptr<Crypter> crypter_;
- // This is only valid when in state |kReady|.
- scoped_refptr<EstablishedConnection> established_connection_;
- SEQUENCE_CHECKER(sequence_checker_);
- base::WeakPtrFactory<FidoTunnelDevice> weak_factory_{this};
- };
- } // namespace cablev2
- } // namespace device
- #endif // DEVICE_FIDO_CABLE_FIDO_TUNNEL_DEVICE_H_
|