cable_discovery_data.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. #include "device/fido/cable/cable_discovery_data.h"
  5. #include <cstring>
  6. #include "base/check_op.h"
  7. #include "base/i18n/string_compare.h"
  8. #include "base/strings/utf_string_conversions.h"
  9. #include "base/time/time.h"
  10. #include "components/cbor/values.h"
  11. #include "crypto/random.h"
  12. #include "device/fido/cable/v2_handshake.h"
  13. #include "device/fido/fido_parsing_utils.h"
  14. #include "third_party/boringssl/src/include/openssl/aes.h"
  15. #include "third_party/boringssl/src/include/openssl/digest.h"
  16. #include "third_party/boringssl/src/include/openssl/ec.h"
  17. #include "third_party/boringssl/src/include/openssl/hkdf.h"
  18. #include "third_party/boringssl/src/include/openssl/mem.h"
  19. #include "third_party/boringssl/src/include/openssl/obj.h"
  20. #include "third_party/icu/source/common/unicode/locid.h"
  21. #include "third_party/icu/source/i18n/unicode/coll.h"
  22. namespace device {
  23. CableDiscoveryData::CableDiscoveryData() = default;
  24. CableDiscoveryData::CableDiscoveryData(
  25. CableDiscoveryData::Version version,
  26. const CableEidArray& client_eid,
  27. const CableEidArray& authenticator_eid,
  28. const CableSessionPreKeyArray& session_pre_key)
  29. : version(version) {
  30. CHECK_EQ(Version::V1, version);
  31. v1.emplace();
  32. v1->client_eid = client_eid;
  33. v1->authenticator_eid = authenticator_eid;
  34. v1->session_pre_key = session_pre_key;
  35. }
  36. CableDiscoveryData::CableDiscoveryData(const CableDiscoveryData& data) =
  37. default;
  38. CableDiscoveryData& CableDiscoveryData::operator=(
  39. const CableDiscoveryData& other) = default;
  40. CableDiscoveryData::~CableDiscoveryData() = default;
  41. bool CableDiscoveryData::operator==(const CableDiscoveryData& other) const {
  42. if (version != other.version) {
  43. return false;
  44. }
  45. switch (version) {
  46. case CableDiscoveryData::Version::V1:
  47. return v1->client_eid == other.v1->client_eid &&
  48. v1->authenticator_eid == other.v1->authenticator_eid &&
  49. v1->session_pre_key == other.v1->session_pre_key;
  50. case CableDiscoveryData::Version::V2:
  51. return v2.value() == other.v2.value();
  52. case CableDiscoveryData::Version::INVALID:
  53. CHECK(false);
  54. return false;
  55. }
  56. }
  57. bool CableDiscoveryData::MatchV1(const CableEidArray& eid) const {
  58. DCHECK_EQ(version, Version::V1);
  59. return eid == v1->authenticator_eid;
  60. }
  61. CableDiscoveryData::V2Data::V2Data(std::vector<uint8_t> server_link_data_in,
  62. std::vector<uint8_t> experiments_in)
  63. : server_link_data(std::move(server_link_data_in)),
  64. experiments(std::move(experiments_in)) {}
  65. CableDiscoveryData::V2Data::V2Data(const V2Data&) = default;
  66. CableDiscoveryData::V2Data::~V2Data() = default;
  67. bool CableDiscoveryData::V2Data::operator==(const V2Data& other) const {
  68. return server_link_data == other.server_link_data &&
  69. experiments == other.experiments;
  70. }
  71. namespace cablev2 {
  72. Pairing::NameComparator::NameComparator(const icu::Locale* locale) {
  73. UErrorCode error = U_ZERO_ERROR;
  74. collator_.reset(icu::Collator::createInstance(*locale, error));
  75. }
  76. Pairing::NameComparator::NameComparator(NameComparator&&) = default;
  77. Pairing::NameComparator::~NameComparator() = default;
  78. bool Pairing::NameComparator::operator()(const std::unique_ptr<Pairing>& a,
  79. const std::unique_ptr<Pairing>& b) {
  80. return base::i18n::CompareString16WithCollator(
  81. *collator_, base::UTF8ToUTF16(a->name),
  82. base::UTF8ToUTF16(b->name)) == UCOL_LESS;
  83. }
  84. Pairing::Pairing() = default;
  85. Pairing::~Pairing() = default;
  86. // static
  87. absl::optional<std::unique_ptr<Pairing>> Pairing::Parse(
  88. const cbor::Value& cbor,
  89. tunnelserver::KnownDomainID domain,
  90. base::span<const uint8_t, kQRSeedSize> local_identity_seed,
  91. base::span<const uint8_t, 32> handshake_hash) {
  92. if (!cbor.is_map()) {
  93. return absl::nullopt;
  94. }
  95. const cbor::Value::MapValue& map = cbor.GetMap();
  96. auto pairing = std::make_unique<Pairing>();
  97. const std::array<cbor::Value::MapValue::const_iterator, 5> its = {
  98. map.find(cbor::Value(1)), map.find(cbor::Value(2)),
  99. map.find(cbor::Value(3)), map.find(cbor::Value(4)),
  100. map.find(cbor::Value(6))};
  101. const cbor::Value::MapValue::const_iterator name_it =
  102. map.find(cbor::Value(5));
  103. if (name_it == map.end() || !name_it->second.is_string() ||
  104. std::any_of(
  105. its.begin(), its.end(),
  106. [&map](const cbor::Value::MapValue::const_iterator& it) -> bool {
  107. return it == map.end() || !it->second.is_bytestring();
  108. }) ||
  109. its[3]->second.GetBytestring().size() !=
  110. std::tuple_size<decltype(pairing->peer_public_key_x962)>::value) {
  111. return absl::nullopt;
  112. }
  113. pairing->tunnel_server_domain = tunnelserver::DecodeDomain(domain);
  114. pairing->contact_id = its[0]->second.GetBytestring();
  115. pairing->id = its[1]->second.GetBytestring();
  116. pairing->secret = its[2]->second.GetBytestring();
  117. const std::vector<uint8_t>& peer_public_key = its[3]->second.GetBytestring();
  118. std::copy(peer_public_key.begin(), peer_public_key.end(),
  119. pairing->peer_public_key_x962.begin());
  120. pairing->name = name_it->second.GetString();
  121. if (!VerifyPairingSignature(local_identity_seed,
  122. pairing->peer_public_key_x962, handshake_hash,
  123. its[4]->second.GetBytestring())) {
  124. return absl::nullopt;
  125. }
  126. return pairing;
  127. }
  128. // static
  129. bool Pairing::CompareByMostRecentFirst(const std::unique_ptr<Pairing>& a,
  130. const std::unique_ptr<Pairing>& b) {
  131. return a->last_updated > b->last_updated;
  132. }
  133. // static
  134. bool Pairing::CompareByLeastStableChannelFirst(
  135. const std::unique_ptr<Pairing>& a,
  136. const std::unique_ptr<Pairing>& b) {
  137. return a->channel_priority > b->channel_priority;
  138. }
  139. // static
  140. bool Pairing::CompareByPublicKey(const std::unique_ptr<Pairing>& a,
  141. const std::unique_ptr<Pairing>& b) {
  142. return memcmp(a->peer_public_key_x962.data(), b->peer_public_key_x962.data(),
  143. sizeof(a->peer_public_key_x962)) < 0;
  144. }
  145. // static
  146. Pairing::NameComparator Pairing::CompareByName(const icu::Locale* locale) {
  147. return NameComparator(locale);
  148. }
  149. // static
  150. bool Pairing::EqualPublicKeys(const std::unique_ptr<Pairing>& a,
  151. const std::unique_ptr<Pairing>& b) {
  152. return a->peer_public_key_x962 == b->peer_public_key_x962;
  153. }
  154. } // namespace cablev2
  155. } // namespace device