#ifndef DEVICE_FIDO_CABLE_CABLE_DISCOVERY_DATA_H_
#define DEVICE_FIDO_CABLE_CABLE_DISCOVERY_DATA_H_
#include <stdint.h>
#include <array>
#include <memory>
#include <string>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/time/time.h"
#include "device/fido/cable/v2_constants.h"
#include "device/fido/fido_constants.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/icu/source/common/unicode/uversion.h"
namespace cbor {
class Value;
}
namespace U_ICU_NAMESPACE {
class Collator;
class Locale;
}
namespace device {
constexpr size_t kCableEphemeralIdSize = 16;
constexpr size_t kCableSessionPreKeySize = 32;
constexpr size_t kCableNonceSize = 8;
using CableEidArray = std::array<uint8_t, kCableEphemeralIdSize>;
using CableSessionPreKeyArray = std::array<uint8_t, kCableSessionPreKeySize>;
using CableNonce = std::array<uint8_t, 8>;
using CableEidGeneratorKey = std::array<uint8_t, 32>;
using CablePskGeneratorKey = std::array<uint8_t, 32>;
using CableTunnelIDGeneratorKey = std::array<uint8_t, 32>;
using CableAuthenticatorIdentityKey = std::array<uint8_t, kP256X962Length>;
struct COMPONENT_EXPORT(DEVICE_FIDO) CableDiscoveryData {
enum class Version {
INVALID,
V1,
V2,
};
CableDiscoveryData(Version version,
const CableEidArray& client_eid,
const CableEidArray& authenticator_eid,
const CableSessionPreKeyArray& session_pre_key);
CableDiscoveryData();
CableDiscoveryData(const CableDiscoveryData& data);
~CableDiscoveryData();
CableDiscoveryData& operator=(const CableDiscoveryData& other);
bool operator==(const CableDiscoveryData& other) const;
bool MatchV1(const CableEidArray& candidate_eid) const;
Version version = Version::INVALID;
struct V1Data {
CableEidArray client_eid;
CableEidArray authenticator_eid;
CableSessionPreKeyArray session_pre_key;
};
absl::optional<V1Data> v1;
struct COMPONENT_EXPORT(DEVICE_FIDO) V2Data {
V2Data(std::vector<uint8_t> server_link_data,
std::vector<uint8_t> experiments);
V2Data(const V2Data&);
~V2Data();
bool operator==(const V2Data&) const;
std::vector<uint8_t> server_link_data;
std::vector<uint8_t> experiments;
};
absl::optional<V2Data> v2;
};
namespace cablev2 {
struct COMPONENT_EXPORT(DEVICE_FIDO) Pairing {
class COMPONENT_EXPORT(DEVICE_FIDO) NameComparator {
public:
explicit NameComparator(const icu::Locale* locale);
NameComparator(NameComparator&&);
NameComparator(const NameComparator&) = delete;
NameComparator& operator=(const NameComparator&) = delete;
~NameComparator();
bool operator()(const std::unique_ptr<Pairing>&,
const std::unique_ptr<Pairing>&);
private:
std::unique_ptr<icu::Collator> collator_;
};
Pairing();
~Pairing();
Pairing(const Pairing&) = delete;
Pairing& operator=(const Pairing&) = delete;
static absl::optional<std::unique_ptr<Pairing>> Parse(
const cbor::Value& cbor,
tunnelserver::KnownDomainID domain,
base::span<const uint8_t, kQRSeedSize> local_identity_seed,
base::span<const uint8_t, 32> handshake_hash);
static bool CompareByMostRecentFirst(const std::unique_ptr<Pairing>&,
const std::unique_ptr<Pairing>&);
static bool CompareByLeastStableChannelFirst(const std::unique_ptr<Pairing>&,
const std::unique_ptr<Pairing>&);
static bool CompareByPublicKey(const std::unique_ptr<Pairing>&,
const std::unique_ptr<Pairing>&);
static NameComparator CompareByName(const icu::Locale* locale);
static bool EqualPublicKeys(const std::unique_ptr<Pairing>&,
const std::unique_ptr<Pairing>&);
std::string tunnel_server_domain;
std::vector<uint8_t> contact_id;
std::vector<uint8_t> id;
std::vector<uint8_t> secret;
std::array<uint8_t, kP256X962Length> peer_public_key_x962;
std::string name;
base::Time last_updated;
bool from_sync_deviceinfo = false;
int channel_priority = 0;
};
}
}
#endif