Commit 7789a086 authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

device/fido: split caBLEv2 into its own discovery.

This change extracts all caBLEv2 bits from the caBLEv1 discovery and
puts them in a separate class. This class is not an active discovery: it
depends on BLE adverts getting fed to it from the caBLEv1 discovery. But
this style permits the caBLEv2 discovery to be used in unittests because
the BLE adverts can be fed from anywhere.

Since caBLE only has a single transport value, this means that the
discovery factory can now return a vector of discoveries for a given
transport. It might be the case that we should split the transport
value, but since the v2 discovery depends on the v1 discovery, that's
not as simple as it sounds.

BUG=1002262

Change-Id: Ia3c277e8f7211beb81d352a1cb31918dc643abbe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2415430
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#808709}
parent 06917154
...@@ -70,17 +70,24 @@ std::string Base64(base::span<const uint8_t> in) { ...@@ -70,17 +70,24 @@ std::string Base64(base::span<const uint8_t> in) {
return ret; return ret;
} }
template <size_t N> base::Optional<std::string> GetString(const base::Value& dict,
bool CopyBytestring(std::array<uint8_t, N>* out, const char* key) {
const base::Value& dict,
const char* key) {
const base::Value* v = dict.FindKey(key); const base::Value* v = dict.FindKey(key);
if (!v || !v->is_string()) { if (!v || !v->is_string()) {
return base::nullopt;
}
return v->GetString();
}
template <size_t N>
bool CopyBytestring(std::array<uint8_t, N>* out,
base::Optional<std::string> value) {
if (!value) {
return false; return false;
} }
std::string bytes; std::string bytes;
if (!base::Base64Decode(v->GetString(), &bytes) || bytes.size() != N) { if (!base::Base64Decode(*value, &bytes) || bytes.size() != N) {
return false; return false;
} }
...@@ -88,6 +95,30 @@ bool CopyBytestring(std::array<uint8_t, N>* out, ...@@ -88,6 +95,30 @@ bool CopyBytestring(std::array<uint8_t, N>* out,
return true; return true;
} }
bool CopyBytestring(std::vector<uint8_t>* out,
base::Optional<std::string> value) {
if (!value) {
return false;
}
std::string bytes;
if (!base::Base64Decode(*value, &bytes)) {
return false;
}
out->clear();
out->insert(out->begin(), bytes.begin(), bytes.end());
return true;
}
bool CopyString(std::string* out, base::Optional<std::string> value) {
if (!value) {
return false;
}
*out = *value;
return true;
}
#if defined(OS_MAC) #if defined(OS_MAC)
const char kWebAuthnTouchIdMetadataSecretPrefName[] = const char kWebAuthnTouchIdMetadataSecretPrefName[] =
"webauthn.touchid.metadata_secret"; "webauthn.touchid.metadata_secret";
...@@ -96,15 +127,17 @@ const char kWebAuthnTouchIdMetadataSecretPrefName[] = ...@@ -96,15 +127,17 @@ const char kWebAuthnTouchIdMetadataSecretPrefName[] =
const char kWebAuthnLastTransportUsedPrefName[] = const char kWebAuthnLastTransportUsedPrefName[] =
"webauthn.last_transport_used"; "webauthn.last_transport_used";
const char kWebAuthnCablePairingsPrefName[] = "webauthn.cable_pairings"; const char kWebAuthnCablePairingsPrefName[] = "webauthn.cablev2_pairings";
// The |kWebAuthnCablePairingsPrefName| preference contains a list of dicts, // The |kWebAuthnCablePairingsPrefName| preference contains a list of dicts,
// where each dict has these keys: // where each dict has these keys:
const char kPairingPrefIdentity[] = "identity";
const char kPairingPrefName[] = "name"; const char kPairingPrefName[] = "name";
const char kPairingPrefContactId[] = "contact_id";
const char kPairingPrefTunnelServer[] = "tunnel_server";
const char kPairingPrefId[] = "id";
const char kPairingPrefSecret[] = "secret";
const char kPairingPrefPublicKey[] = "pub_key";
const char kPairingPrefTime[] = "time"; const char kPairingPrefTime[] = "time";
const char kPairingPrefEIDGenKey[] = "eid_gen_key";
const char kPairingPrefPSKGenKey[] = "psk_gen_key";
} // namespace } // namespace
...@@ -322,11 +355,11 @@ void ChromeAuthenticatorRequestDelegate::ConfigureCable( ...@@ -322,11 +355,11 @@ void ChromeAuthenticatorRequestDelegate::ConfigureCable(
base::Optional<device::QRGeneratorKey> qr_generator_key; base::Optional<device::QRGeneratorKey> qr_generator_key;
bool have_paired_phones = false; bool have_paired_phones = false;
std::vector<std::unique_ptr<device::cablev2::Pairing>> paired_phones;
if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) { if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
qr_generator_key.emplace(device::CableDiscoveryData::NewQRKey()); qr_generator_key.emplace(device::CableDiscoveryData::NewQRKey());
auto paired_phones = GetCablePairings(); paired_phones = GetCablePairings();
have_paired_phones = !paired_phones.empty(); have_paired_phones = !paired_phones.empty();
pairings.insert(pairings.end(), paired_phones.begin(), paired_phones.end());
mojo::Remote<device::mojom::UsbDeviceManager> usb_device_manager; mojo::Remote<device::mojom::UsbDeviceManager> usb_device_manager;
content::GetDeviceService().BindUsbDeviceManager( content::GetDeviceService().BindUsbDeviceManager(
...@@ -342,7 +375,8 @@ void ChromeAuthenticatorRequestDelegate::ConfigureCable( ...@@ -342,7 +375,8 @@ void ChromeAuthenticatorRequestDelegate::ConfigureCable(
weak_dialog_model_->set_cable_transport_info( weak_dialog_model_->set_cable_transport_info(
cable_extension_provided, have_paired_phones, qr_generator_key); cable_extension_provided, have_paired_phones, qr_generator_key);
discovery_factory->set_cable_data(std::move(pairings), qr_generator_key); discovery_factory->set_cable_data(std::move(pairings), qr_generator_key,
std::move(paired_phones));
discovery_factory->set_cable_pairing_callback(base::BindRepeating( discovery_factory->set_cable_pairing_callback(base::BindRepeating(
&ChromeAuthenticatorRequestDelegate::StoreNewCablePairingInPrefs, &ChromeAuthenticatorRequestDelegate::StoreNewCablePairingInPrefs,
...@@ -595,9 +629,9 @@ bool ChromeAuthenticatorRequestDelegate::ShouldPermitCableExtension( ...@@ -595,9 +629,9 @@ bool ChromeAuthenticatorRequestDelegate::ShouldPermitCableExtension(
return origin.IsSameOriginWith(url::Origin::Create(test_site)); return origin.IsSameOriginWith(url::Origin::Create(test_site));
} }
std::vector<device::CableDiscoveryData> std::vector<std::unique_ptr<device::cablev2::Pairing>>
ChromeAuthenticatorRequestDelegate::GetCablePairings() { ChromeAuthenticatorRequestDelegate::GetCablePairings() {
std::vector<device::CableDiscoveryData> ret; std::vector<std::unique_ptr<device::cablev2::Pairing>> ret;
if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) { if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
NOTREACHED(); NOTREACHED();
return ret; return ret;
...@@ -613,34 +647,31 @@ ChromeAuthenticatorRequestDelegate::GetCablePairings() { ...@@ -613,34 +647,31 @@ ChromeAuthenticatorRequestDelegate::GetCablePairings() {
continue; continue;
} }
device::CableDiscoveryData discovery; auto out_pairing = std::make_unique<device::cablev2::Pairing>();
discovery.version = device::CableDiscoveryData::Version::V2; if (!CopyString(&out_pairing->name, GetString(pairing, kPairingPrefName)) ||
discovery.v2.emplace(); !CopyString(&out_pairing->tunnel_server_domain,
discovery.v2->peer_identity.emplace(); GetString(pairing, kPairingPrefTunnelServer)) ||
!CopyBytestring(&out_pairing->contact_id,
if (!CopyBytestring(&discovery.v2->peer_identity.value(), pairing, GetString(pairing, kPairingPrefContactId)) ||
kPairingPrefIdentity) || !CopyBytestring(&out_pairing->id, GetString(pairing, kPairingPrefId)) ||
!CopyBytestring(&discovery.v2->eid_gen_key, pairing, !CopyBytestring(&out_pairing->secret,
kPairingPrefEIDGenKey) || GetString(pairing, kPairingPrefSecret)) ||
!CopyBytestring(&discovery.v2->psk_gen_key, pairing, !CopyBytestring(&out_pairing->peer_public_key_x962,
kPairingPrefPSKGenKey)) { GetString(pairing, kPairingPrefPublicKey))) {
continue; continue;
} }
ret.push_back(discovery); ret.emplace_back(std::move(out_pairing));
} }
return ret; return ret;
} }
void ChromeAuthenticatorRequestDelegate::StoreNewCablePairingInPrefs( void ChromeAuthenticatorRequestDelegate::StoreNewCablePairingInPrefs(
std::unique_ptr<device::CableDiscoveryData> discovery_data) { std::unique_ptr<device::cablev2::Pairing> pairing) {
// This is called when doing a QR-code pairing with a phone and the phone // This is called when doing a QR-code pairing with a phone and the phone
// sends long-term pairing information during the handshake. The pairing // sends long-term pairing information during the handshake. The pairing
// information is saved in preferences for future operations. // information is saved in preferences for future operations.
DCHECK_EQ(device::CableDiscoveryData::Version::V2, discovery_data->version);
DCHECK(discovery_data->v2->peer_identity.has_value());
DCHECK(discovery_data->v2->peer_name.has_value());
if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) { if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
NOTREACHED(); NOTREACHED();
return; return;
...@@ -652,30 +683,29 @@ void ChromeAuthenticatorRequestDelegate::StoreNewCablePairingInPrefs( ...@@ -652,30 +683,29 @@ void ChromeAuthenticatorRequestDelegate::StoreNewCablePairingInPrefs(
ListPrefUpdate update( ListPrefUpdate update(
Profile::FromBrowserContext(browser_context())->GetPrefs(), Profile::FromBrowserContext(browser_context())->GetPrefs(),
kWebAuthnCablePairingsPrefName); kWebAuthnCablePairingsPrefName);
const std::string identity_base64 =
Base64(*discovery_data->v2->peer_identity); // Find any existing entries with the same public key and replace them. The
if (std::any_of(update->begin(), update->end(), // handshake protocol requires the phone to prove possession of the public key
[&identity_base64](const auto& value) { // so it's not possible for an evil phone to displace another's pairing.
if (!value.is_dict()) { const std::string public_key_base64 = Base64(pairing->peer_public_key_x962);
return false; update->EraseListValueIf([&public_key_base64](const auto& value) {
} if (!value.is_dict()) {
const base::Value* identity = return false;
value.FindKey(kPairingPrefIdentity); }
return identity && identity->is_string() && const base::Value* pref_public_key = value.FindKey(kPairingPrefPublicKey);
identity->GetString() == identity_base64; return pref_public_key && pref_public_key->is_string() &&
})) { pref_public_key->GetString() == public_key_base64;
// This phone is already known, don't add it again. });
return;
}
auto dict = std::make_unique<base::Value>(base::Value::Type::DICTIONARY); auto dict = std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
dict->SetKey(kPairingPrefIdentity, base::Value(std::move(identity_base64))); dict->SetKey(kPairingPrefPublicKey,
dict->SetKey(kPairingPrefName, base::Value(std::move(public_key_base64)));
base::Value(std::move(*discovery_data->v2->peer_name))); dict->SetKey(kPairingPrefTunnelServer,
dict->SetKey(kPairingPrefEIDGenKey, base::Value(pairing->tunnel_server_domain));
base::Value(Base64(discovery_data->v2->eid_gen_key))); dict->SetKey(kPairingPrefName, base::Value(std::move(pairing->name)));
dict->SetKey(kPairingPrefPSKGenKey, dict->SetKey(kPairingPrefContactId, base::Value(Base64(pairing->contact_id)));
base::Value(Base64(discovery_data->v2->psk_gen_key))); dict->SetKey(kPairingPrefId, base::Value(Base64(pairing->id)));
dict->SetKey(kPairingPrefSecret, base::Value(Base64(pairing->secret)));
base::Time::Exploded now; base::Time::Exploded now;
base::Time::Now().UTCExplode(&now); base::Time::Now().UTCExplode(&now);
......
...@@ -138,10 +138,11 @@ class ChromeAuthenticatorRequestDelegate ...@@ -138,10 +138,11 @@ class ChromeAuthenticatorRequestDelegate
bool ShouldPermitCableExtension(const url::Origin& origin); bool ShouldPermitCableExtension(const url::Origin& origin);
// GetCablePairings returns any known caBLE pairing data. // GetCablePairings returns any known caBLE pairing data.
virtual std::vector<device::CableDiscoveryData> GetCablePairings(); virtual std::vector<std::unique_ptr<device::cablev2::Pairing>>
GetCablePairings();
void StoreNewCablePairingInPrefs( void StoreNewCablePairingInPrefs(
std::unique_ptr<device::CableDiscoveryData> discovery_data); std::unique_ptr<device::cablev2::Pairing> pairing);
content::RenderFrameHost* const render_frame_host_; content::RenderFrameHost* const render_frame_host_;
// Holds ownership of AuthenticatorRequestDialogModel until // Holds ownership of AuthenticatorRequestDialogModel until
......
...@@ -27,7 +27,7 @@ VirtualFidoDiscoveryFactory::~VirtualFidoDiscoveryFactory() { ...@@ -27,7 +27,7 @@ VirtualFidoDiscoveryFactory::~VirtualFidoDiscoveryFactory() {
} }
} }
std::unique_ptr<::device::FidoDiscoveryBase> std::vector<std::unique_ptr<::device::FidoDiscoveryBase>>
VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) { VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) {
auto discovery = std::make_unique<VirtualFidoDiscovery>(transport); auto discovery = std::make_unique<VirtualFidoDiscovery>(transport);
...@@ -47,7 +47,7 @@ VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) { ...@@ -47,7 +47,7 @@ VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) {
} }
discoveries_.insert(discovery.get()); discoveries_.insert(discovery.get());
return discovery; return SingleDiscovery(std::move(discovery));
} }
void VirtualFidoDiscoveryFactory::AuthenticatorAdded( void VirtualFidoDiscoveryFactory::AuthenticatorAdded(
......
...@@ -46,7 +46,7 @@ class CONTENT_EXPORT VirtualFidoDiscoveryFactory ...@@ -46,7 +46,7 @@ class CONTENT_EXPORT VirtualFidoDiscoveryFactory
~VirtualFidoDiscoveryFactory() override; ~VirtualFidoDiscoveryFactory() override;
// device::FidoDiscoveryFactory: // device::FidoDiscoveryFactory:
std::unique_ptr<::device::FidoDiscoveryBase> Create( std::vector<std::unique_ptr<::device::FidoDiscoveryBase>> Create(
device::FidoTransportProtocol transport) override; device::FidoTransportProtocol transport) override;
bool IsTestOverride() override; bool IsTestOverride() override;
......
...@@ -711,9 +711,10 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest, ...@@ -711,9 +711,10 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// factory as one of the first steps. Here, the request should not have been // factory as one of the first steps. Here, the request should not have been
// serviced at all, so the fake request should still be pending on the fake // serviced at all, so the fake request should still be pending on the fake
// factory. // factory.
auto hid_discovery = discovery_factory_->Create( std::vector<std::unique_ptr<device::FidoDiscoveryBase>> discoveries =
::device::FidoTransportProtocol::kUsbHumanInterfaceDevice); discovery_factory_->Create(
ASSERT_TRUE(!!hid_discovery); ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
EXPECT_EQ(discoveries.size(), 1u);
// The next active document should be able to successfully call // The next active document should be able to successfully call
// navigator.credentials.create({publicKey: ...}) again. // navigator.credentials.create({publicKey: ...}) again.
......
...@@ -116,6 +116,8 @@ component("fido") { ...@@ -116,6 +116,8 @@ component("fido") {
"cable/fido_cable_handshake_handler.h", "cable/fido_cable_handshake_handler.h",
"cable/fido_tunnel_device.cc", "cable/fido_tunnel_device.cc",
"cable/fido_tunnel_device.h", "cable/fido_tunnel_device.h",
"cable/v2_discovery.cc",
"cable/v2_discovery.h",
"client_data.cc", "client_data.cc",
"client_data.h", "client_data.h",
"credential_management.cc", "credential_management.cc",
......
This diff is collapsed.
...@@ -23,12 +23,6 @@ ...@@ -23,12 +23,6 @@
#include "device/fido/cable/fido_cable_device.h" #include "device/fido/cable/fido_cable_device.h"
#include "device/fido/fido_device_discovery.h" #include "device/fido/fido_device_discovery.h"
namespace network {
namespace mojom {
class NetworkContext;
}
} // namespace network
namespace device { namespace device {
class BluetoothDevice; class BluetoothDevice;
...@@ -40,13 +34,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -40,13 +34,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
public BluetoothAdapter::Observer, public BluetoothAdapter::Observer,
public FidoCableDevice::Observer { public FidoCableDevice::Observer {
public: public:
FidoCableDiscovery( FidoCableDiscovery(std::vector<CableDiscoveryData> discovery_data,
std::vector<CableDiscoveryData> discovery_data, FidoDeviceDiscovery::BLEObserver* ble_observer);
base::Optional<QRGeneratorKey> qr_generator_key,
base::Optional<
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>>
pairing_callback,
network::mojom::NetworkContext* network_context);
~FidoCableDiscovery() override; ~FidoCableDiscovery() override;
// FidoDeviceDiscovery: // FidoDeviceDiscovery:
...@@ -66,26 +55,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -66,26 +55,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
private: private:
enum class CableV1DiscoveryEvent : int; enum class CableV1DiscoveryEvent : int;
// Result represents a successful match of a received EID against a specific // V1DiscoveryDataAndEID represents a match against caBLEv1 pairing data. It
// |FidoDiscoveryData|. // contains the CableDiscoveryData that matched and the BLE EID that triggered
struct Result { // the match.
Result(); using V1DiscoveryDataAndEID = std::pair<CableDiscoveryData, CableEidArray>;
Result(const CableDiscoveryData& in_discovery_data,
const CableEidArray& in_eid,
base::Optional<CableEidArray> decrypted_eid,
base::Optional<int> ticks_back);
Result(const Result&);
~Result();
CableDiscoveryData discovery_data;
CableEidArray eid;
base::Optional<CableEidArray> decrypted_eid;
// ticks_back is either |base::nullopt|, if the Result is from established
// discovery pairings, or else contains the number of QR ticks back in time
// against which the match was found.
base::Optional<int> ticks_back;
};
// ObservedDeviceData contains potential EIDs observed from a BLE device. This // ObservedDeviceData contains potential EIDs observed from a BLE device. This
// information is kept in order to de-duplicate device-log entries and make // information is kept in order to de-duplicate device-log entries and make
...@@ -103,8 +76,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -103,8 +76,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
// ResultDebugString returns a string containing a hex dump of |eid| and a // ResultDebugString returns a string containing a hex dump of |eid| and a
// description of |result|, if present. // description of |result|, if present.
static std::string ResultDebugString(const CableEidArray& eid, static std::string ResultDebugString(
const base::Optional<Result>& result); const CableEidArray& eid,
const base::Optional<V1DiscoveryDataAndEID>& result);
static base::Optional<CableEidArray> MaybeGetEidFromServiceData( static base::Optional<CableEidArray> MaybeGetEidFromServiceData(
const BluetoothDevice* device); const BluetoothDevice* device);
static std::vector<CableEidArray> GetUUIDs(const BluetoothDevice* device); static std::vector<CableEidArray> GetUUIDs(const BluetoothDevice* device);
...@@ -138,10 +112,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -138,10 +112,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
FidoCableHandshakeHandler* handshake_handler, FidoCableHandshakeHandler* handshake_handler,
base::Optional<std::vector<uint8_t>> handshake_response); base::Optional<std::vector<uint8_t>> handshake_response);
base::Optional<Result> GetCableDiscoveryData( base::Optional<V1DiscoveryDataAndEID> GetCableDiscoveryData(
const BluetoothDevice* device) const; const BluetoothDevice* device);
base::Optional<Result> GetCableDiscoveryDataFromAuthenticatorEid( base::Optional<V1DiscoveryDataAndEID>
CableEidArray authenticator_eid) const; GetCableDiscoveryDataFromAuthenticatorEid(CableEidArray authenticator_eid);
void RecordCableV1DiscoveryEventOnce(CableV1DiscoveryEvent event); void RecordCableV1DiscoveryEventOnce(CableV1DiscoveryEvent event);
// FidoDeviceDiscovery: // FidoDeviceDiscovery:
...@@ -165,16 +139,17 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -165,16 +139,17 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
std::unique_ptr<BluetoothDiscoverySession> discovery_session_; std::unique_ptr<BluetoothDiscoverySession> discovery_session_;
std::vector<CableDiscoveryData> discovery_data_; std::vector<CableDiscoveryData> discovery_data_;
FidoDeviceDiscovery::BLEObserver* const ble_observer_;
// active_authenticator_eids_ contains authenticator EIDs for which a // active_authenticator_eids_ contains authenticator EIDs for which a
// handshake is currently running. Further advertisements for the same EIDs // handshake is currently running. Further advertisements for the same EIDs
// will be ignored. // will be ignored.
std::set<CableEidArray> active_authenticator_eids_; std::set<CableEidArray> active_authenticator_eids_;
// active_devices_ contains the BLE addresses of devices for which a handshake // active_devices_ contains the BLE addresses of devices for which a
// is already running. Further advertisements from these devices will be // handshake is already running. Further advertisements from these devices
// ignored. However, devices may rotate their BLE address at will so this is // will be ignored. However, devices may rotate their BLE address at will so
// not completely effective. // this is not completely effective.
std::set<std::string> active_devices_; std::set<std::string> active_devices_;
base::Optional<QRGeneratorKey> qr_generator_key_; base::Optional<QRGeneratorKey> qr_generator_key_;
...@@ -186,20 +161,12 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -186,20 +161,12 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
std::vector<std::pair<std::unique_ptr<FidoCableDevice>, std::vector<std::pair<std::unique_ptr<FidoCableDevice>,
std::unique_ptr<FidoCableHandshakeHandler>>> std::unique_ptr<FidoCableHandshakeHandler>>>
active_handshakes_; active_handshakes_;
base::Optional<
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>>
pairing_callback_;
network::mojom::NetworkContext* const network_context_;
// observed_devices_ caches the information from observed caBLE devices so // observed_devices_ caches the information from observed caBLE devices so
// that the device-log isn't spammed. // that the device-log isn't spammed.
mutable base::flat_map<std::string, std::unique_ptr<ObservedDeviceData>> base::flat_map<std::string, std::unique_ptr<ObservedDeviceData>>
observed_devices_; observed_devices_;
// noted_obsolete_eids_ remembers QR-code EIDs that have been logged as
// valid-but-expired in order to avoid spamming the device-log.
mutable base::flat_set<CableEidArray> noted_obsolete_eids_;
bool has_v1_discovery_data_ = false; bool has_v1_discovery_data_ = false;
base::flat_set<CableV1DiscoveryEvent> recorded_events_; base::flat_set<CableV1DiscoveryEvent> recorded_events_;
......
...@@ -326,9 +326,7 @@ class FakeFidoCableDiscovery : public FidoCableDiscovery { ...@@ -326,9 +326,7 @@ class FakeFidoCableDiscovery : public FidoCableDiscovery {
explicit FakeFidoCableDiscovery( explicit FakeFidoCableDiscovery(
std::vector<CableDiscoveryData> discovery_data) std::vector<CableDiscoveryData> discovery_data)
: FidoCableDiscovery(std::move(discovery_data), : FidoCableDiscovery(std::move(discovery_data),
BogusQRGeneratorKey(), /*ble_observer=*/nullptr) {}
/*pairing_callback=*/base::nullopt,
/*network_context=*/nullptr) {}
~FakeFidoCableDiscovery() override = default; ~FakeFidoCableDiscovery() override = default;
private: private:
...@@ -342,12 +340,6 @@ class FakeFidoCableDiscovery : public FidoCableDiscovery { ...@@ -342,12 +340,6 @@ class FakeFidoCableDiscovery : public FidoCableDiscovery {
return std::make_unique<FakeHandshakeHandler>( return std::make_unique<FakeHandshakeHandler>(
device, nonce, discovery_data.v1->session_pre_key); device, nonce, discovery_data.v1->session_pre_key);
} }
static std::array<uint8_t, kCableQRDataSize> BogusQRGeneratorKey() {
std::array<uint8_t, kCableQRDataSize> ret;
memset(ret.data(), 0, ret.size());
return ret;
}
}; };
} // namespace } // namespace
......
// 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.
#include "device/fido/cable/v2_discovery.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/string_number_conversions.h"
#include "device/fido/cable/v2_handshake.h"
#include "device/fido/fido_parsing_utils.h"
#include "components/device_event_log/device_event_log.h"
#include "device/fido/cable/fido_tunnel_device.h"
#include "third_party/boringssl/src/include/openssl/aes.h"
namespace device {
namespace cablev2 {
Discovery::Discovery(
network::mojom::NetworkContext* network_context,
QRGeneratorKey qr_generator_key,
std::vector<std::unique_ptr<Pairing>> pairings,
base::Optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
pairing_callback)
: FidoDeviceDiscovery(
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy),
network_context_(network_context),
local_identity_seed_(fido_parsing_utils::Materialize(
base::span<const uint8_t, kCableIdentityKeySeedSize>(
qr_generator_key.data(),
kCableIdentityKeySeedSize))),
qr_secret_(fido_parsing_utils::Materialize(
base::span<const uint8_t, kCableQRSecretSize>(
qr_generator_key.data() + kCableIdentityKeySeedSize,
kCableQRSecretSize))),
eid_key_(Derive<EXTENT(eid_key_)>(qr_secret_,
base::span<const uint8_t>(),
DerivedValueType::kEIDKey)),
pairings_(std::move(pairings)),
pairing_callback_(std::move(pairing_callback)) {
// TODO(agl): disabled in order to separate out CLs. Re-enable.
// static_assert(EXTENT(qr_generator_key) ==
// kCableIdentityKeySeedSize + kCableQRSecretSize,
// "");
}
Discovery::~Discovery() = default;
void Discovery::StartInternal() {
DCHECK(!started_);
for (auto& pairing : pairings_) {
tunnels_pending_advert_.emplace_back(std::make_unique<FidoTunnelDevice>(
network_context_, std::move(pairing)));
}
pairings_.clear();
started_ = true;
NotifyDiscoveryStarted(true);
std::vector<CableEidArray> pending_eids(std::move(pending_eids_));
for (const auto& eid : pending_eids) {
OnBLEAdvertSeen("", eid);
}
}
void Discovery::OnBLEAdvertSeen(const std::string& address,
const CableEidArray& eid) {
if (!started_) {
pending_eids_.push_back(eid);
return;
}
if (base::Contains(observed_eids_, eid)) {
return;
}
observed_eids_.insert(eid);
// Check whether the EID satisfies any pending tunnels.
for (std::vector<std::unique_ptr<FidoTunnelDevice>>::iterator i =
tunnels_pending_advert_.begin();
i != tunnels_pending_advert_.end(); i++) {
if (!(*i)->MatchEID(eid)) {
continue;
}
FIDO_LOG(DEBUG) << " (" << base::HexEncode(eid)
<< " matches pending tunnel)";
std::unique_ptr<FidoTunnelDevice> device(std::move(*i));
tunnels_pending_advert_.erase(i);
AddDevice(std::move(device));
return;
}
// Check whether the EID matches a QR code.
AES_KEY aes_key;
CHECK(AES_set_decrypt_key(eid_key_.data(),
/*bits=*/8 * eid_key_.size(), &aes_key) == 0);
CableEidArray plaintext;
static_assert(EXTENT(plaintext) == AES_BLOCK_SIZE, "EIDs are not AES blocks");
AES_decrypt(/*in=*/eid.data(), /*out=*/plaintext.data(), &aes_key);
if (cablev2::eid::IsValid(plaintext)) {
FIDO_LOG(DEBUG) << " (" << base::HexEncode(eid) << " matches QR code)";
AddDevice(std::make_unique<cablev2::FidoTunnelDevice>(
network_context_,
base::BindOnce(&Discovery::AddPairing, weak_factory_.GetWeakPtr()),
qr_secret_, local_identity_seed_, eid, plaintext));
return;
}
FIDO_LOG(DEBUG) << " (" << base::HexEncode(eid) << ": no v2 match)";
}
void Discovery::AddPairing(std::unique_ptr<Pairing> pairing) {
if (!pairing_callback_) {
return;
}
pairing_callback_->Run(std::move(pairing));
}
} // namespace cablev2
} // namespace device
// 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_V2_DISCOVERY_H_
#define DEVICE_FIDO_CABLE_V2_DISCOVERY_H_
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/optional.h"
#include "base/memory/weak_ptr.h"
#include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/cable/v2_constants.h"
#include "device/fido/fido_device_discovery.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
namespace device {
namespace cablev2 {
struct Pairing;
class FidoTunnelDevice;
// Discovery creates caBLEv2 devices, either based on |pairings|, or when a BLE
// advert is seen that matches |qr_generator_key|. It does not actively scan for
// BLE adverts itself. Rather it depends on |OnBLEAdvertSeen| getting called.
class COMPONENT_EXPORT(DEVICE_FIDO) Discovery
: public FidoDeviceDiscovery,
public FidoDeviceDiscovery::BLEObserver {
public:
Discovery(
network::mojom::NetworkContext* network_context,
QRGeneratorKey qr_generator_key,
std::vector<std::unique_ptr<Pairing>> pairings,
// pairing_callback will be called when a QR-initiated connection receives
// pairing information from the peer.
base::Optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
pairing_callback);
~Discovery() override;
Discovery(const Discovery&) = delete;
Discovery& operator=(const Discovery&) = delete;
// FidoDeviceDiscovery:
void StartInternal() override;
// BLEObserver:
void OnBLEAdvertSeen(const std::string& address,
const CableEidArray& eid) override;
private:
void AddPairing(std::unique_ptr<Pairing> pairing);
network::mojom::NetworkContext* const network_context_;
const std::array<uint8_t, kCableIdentityKeySeedSize> local_identity_seed_;
const std::array<uint8_t, kCableQRSecretSize> qr_secret_;
const std::array<uint8_t, kEIDKeySize> eid_key_;
std::vector<std::unique_ptr<Pairing>> pairings_;
const base::Optional<base::RepeatingCallback<void(std::unique_ptr<Pairing>)>>
pairing_callback_;
std::vector<std::unique_ptr<FidoTunnelDevice>> tunnels_pending_advert_;
base::flat_set<CableEidArray> observed_eids_;
bool started_ = false;
std::vector<CableEidArray> pending_eids_;
base::WeakPtrFactory<Discovery> weak_factory_{this};
};
} // namespace cablev2
} // namespace device
#endif // DEVICE_FIDO_CABLE_V2_DISCOVERY_H_
...@@ -79,23 +79,23 @@ FakeFidoDiscovery* FakeFidoDiscoveryFactory::ForgeNextPlatformDiscovery( ...@@ -79,23 +79,23 @@ FakeFidoDiscovery* FakeFidoDiscoveryFactory::ForgeNextPlatformDiscovery(
return next_platform_discovery_.get(); return next_platform_discovery_.get();
} }
std::unique_ptr<FidoDiscoveryBase> FakeFidoDiscoveryFactory::Create( std::vector<std::unique_ptr<FidoDiscoveryBase>>
FidoTransportProtocol transport) { FakeFidoDiscoveryFactory::Create(FidoTransportProtocol transport) {
switch (transport) { switch (transport) {
case FidoTransportProtocol::kUsbHumanInterfaceDevice: case FidoTransportProtocol::kUsbHumanInterfaceDevice:
return std::move(next_hid_discovery_); return SingleDiscovery(std::move(next_hid_discovery_));
case FidoTransportProtocol::kNearFieldCommunication: case FidoTransportProtocol::kNearFieldCommunication:
return std::move(next_nfc_discovery_); return SingleDiscovery(std::move(next_nfc_discovery_));
case FidoTransportProtocol::kBluetoothLowEnergy: case FidoTransportProtocol::kBluetoothLowEnergy:
case FidoTransportProtocol::kAndroidAccessory: case FidoTransportProtocol::kAndroidAccessory:
return nullptr; return {};
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy: case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
return std::move(next_cable_discovery_); return SingleDiscovery(std::move(next_cable_discovery_));
case FidoTransportProtocol::kInternal: case FidoTransportProtocol::kInternal:
return std::move(next_platform_discovery_); return SingleDiscovery(std::move(next_platform_discovery_));
} }
NOTREACHED(); NOTREACHED();
return nullptr; return {};
} }
} // namespace test } // namespace test
......
...@@ -111,7 +111,7 @@ class FakeFidoDiscoveryFactory : public device::FidoDiscoveryFactory { ...@@ -111,7 +111,7 @@ class FakeFidoDiscoveryFactory : public device::FidoDiscoveryFactory {
StartMode mode = StartMode::kManual); StartMode mode = StartMode::kManual);
// device::FidoDiscoveryFactory: // device::FidoDiscoveryFactory:
std::unique_ptr<FidoDiscoveryBase> Create( std::vector<std::unique_ptr<FidoDiscoveryBase>> Create(
FidoTransportProtocol transport) override; FidoTransportProtocol transport) override;
private: private:
......
...@@ -147,10 +147,11 @@ TEST_F(FakeFidoDiscoveryFactoryTest, ForgesUsbFactoryFunction) { ...@@ -147,10 +147,11 @@ TEST_F(FakeFidoDiscoveryFactoryTest, ForgesUsbFactoryFunction) {
fake_fido_discovery_factory_.ForgeNextHidDiscovery(); fake_fido_discovery_factory_.ForgeNextHidDiscovery();
ASSERT_EQ(FidoTransportProtocol::kUsbHumanInterfaceDevice, ASSERT_EQ(FidoTransportProtocol::kUsbHumanInterfaceDevice,
injected_fake_discovery->transport()); injected_fake_discovery->transport());
auto produced_discovery = fake_fido_discovery_factory_.Create( std::vector<std::unique_ptr<FidoDiscoveryBase>> produced_discoveries =
FidoTransportProtocol::kUsbHumanInterfaceDevice); fake_fido_discovery_factory_.Create(
EXPECT_TRUE(produced_discovery); FidoTransportProtocol::kUsbHumanInterfaceDevice);
EXPECT_EQ(injected_fake_discovery, produced_discovery.get()); ASSERT_EQ(produced_discoveries.size(), 1u);
EXPECT_EQ(injected_fake_discovery, produced_discoveries[0].get());
} }
#endif #endif
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
namespace device { namespace device {
FidoDeviceDiscovery::BLEObserver::~BLEObserver() = default;
FidoDeviceDiscovery::Observer::~Observer() = default; FidoDeviceDiscovery::Observer::~Observer() = default;
FidoDeviceDiscovery::FidoDeviceDiscovery(FidoTransportProtocol transport) FidoDeviceDiscovery::FidoDeviceDiscovery(FidoTransportProtocol transport)
......
...@@ -27,6 +27,15 @@ class FidoDeviceAuthenticator; ...@@ -27,6 +27,15 @@ class FidoDeviceAuthenticator;
class COMPONENT_EXPORT(DEVICE_FIDO) FidoDeviceDiscovery class COMPONENT_EXPORT(DEVICE_FIDO) FidoDeviceDiscovery
: public FidoDiscoveryBase { : public FidoDiscoveryBase {
public: public:
// BLEObserver is an interface for discoveries that watch for BLE adverts.
class BLEObserver {
public:
virtual ~BLEObserver();
virtual void OnBLEAdvertSeen(const std::string& address,
const std::array<uint8_t, 16>& eid) = 0;
};
enum class State { enum class State {
kIdle, kIdle,
kStarting, kStarting,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/fido/aoa/android_accessory_discovery.h" #include "device/fido/aoa/android_accessory_discovery.h"
#include "device/fido/cable/fido_cable_discovery.h" #include "device/fido/cable/fido_cable_discovery.h"
#include "device/fido/cable/v2_discovery.h"
#include "device/fido/features.h" #include "device/fido/features.h"
#include "device/fido/fido_discovery_base.h" #include "device/fido/fido_discovery_base.h"
...@@ -35,39 +36,60 @@ namespace device { ...@@ -35,39 +36,60 @@ namespace device {
FidoDiscoveryFactory::FidoDiscoveryFactory() = default; FidoDiscoveryFactory::FidoDiscoveryFactory() = default;
FidoDiscoveryFactory::~FidoDiscoveryFactory() = default; FidoDiscoveryFactory::~FidoDiscoveryFactory() = default;
std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create( std::vector<std::unique_ptr<FidoDiscoveryBase>> FidoDiscoveryFactory::Create(
FidoTransportProtocol transport) { FidoTransportProtocol transport) {
switch (transport) { switch (transport) {
case FidoTransportProtocol::kUsbHumanInterfaceDevice: case FidoTransportProtocol::kUsbHumanInterfaceDevice:
return std::make_unique<FidoHidDiscovery>(hid_ignore_list_); return SingleDiscovery(
std::make_unique<FidoHidDiscovery>(hid_ignore_list_));
case FidoTransportProtocol::kBluetoothLowEnergy: case FidoTransportProtocol::kBluetoothLowEnergy:
return nullptr; return {};
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy: case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
if (device::BluetoothAdapterFactory::Get()->IsLowEnergySupported() && if (device::BluetoothAdapterFactory::Get()->IsLowEnergySupported() &&
(cable_data_.has_value() || qr_generator_key_.has_value())) { (cable_data_.has_value() || qr_generator_key_.has_value())) {
return std::make_unique<FidoCableDiscovery>( std::unique_ptr<cablev2::Discovery> v2_discovery;
cable_data_.value_or(std::vector<CableDiscoveryData>()), if (qr_generator_key_.has_value()) {
qr_generator_key_, cable_pairing_callback_, network_context_); v2_discovery = std::make_unique<cablev2::Discovery>(
network_context_, *qr_generator_key_, std::move(v2_pairings_),
std::move(cable_pairing_callback_));
}
std::unique_ptr<FidoDiscoveryBase> v1_discovery =
std::make_unique<FidoCableDiscovery>(
cable_data_.value_or(std::vector<CableDiscoveryData>()),
v2_discovery ? v2_discovery.get() : nullptr);
std::vector<std::unique_ptr<FidoDiscoveryBase>> ret;
if (v2_discovery) {
ret.emplace_back(std::move(v2_discovery));
}
ret.emplace_back(std::move(v1_discovery));
return ret;
} }
return nullptr; return {};
case FidoTransportProtocol::kNearFieldCommunication: case FidoTransportProtocol::kNearFieldCommunication:
// TODO(https://crbug.com/825949): Add NFC support. // TODO(https://crbug.com/825949): Add NFC support.
return nullptr; return {};
case FidoTransportProtocol::kInternal: case FidoTransportProtocol::kInternal: {
#if defined(OS_MAC) || defined(OS_CHROMEOS) #if defined(OS_MAC) || defined(OS_CHROMEOS)
return MaybeCreatePlatformDiscovery(); std::unique_ptr<FidoDiscoveryBase> discovery =
MaybeCreatePlatformDiscovery();
if (discovery) {
return SingleDiscovery(std::move(discovery));
}
return {};
#else #else
return nullptr; return {};
#endif #endif
}
case FidoTransportProtocol::kAndroidAccessory: case FidoTransportProtocol::kAndroidAccessory:
if (usb_device_manager_) { if (usb_device_manager_) {
return std::make_unique<AndroidAccessoryDiscovery>( return SingleDiscovery(std::make_unique<AndroidAccessoryDiscovery>(
std::move(usb_device_manager_.value())); std::move(usb_device_manager_.value())));
} }
return nullptr; return {};
} }
NOTREACHED() << "Unhandled transport type"; NOTREACHED() << "Unhandled transport type";
return nullptr; return {};
} }
bool FidoDiscoveryFactory::IsTestOverride() { bool FidoDiscoveryFactory::IsTestOverride() {
...@@ -76,9 +98,11 @@ bool FidoDiscoveryFactory::IsTestOverride() { ...@@ -76,9 +98,11 @@ bool FidoDiscoveryFactory::IsTestOverride() {
void FidoDiscoveryFactory::set_cable_data( void FidoDiscoveryFactory::set_cable_data(
std::vector<CableDiscoveryData> cable_data, std::vector<CableDiscoveryData> cable_data,
base::Optional<QRGeneratorKey> qr_generator_key) { base::Optional<QRGeneratorKey> qr_generator_key,
std::vector<std::unique_ptr<cablev2::Pairing>> v2_pairings) {
cable_data_ = std::move(cable_data); cable_data_ = std::move(cable_data);
qr_generator_key_ = std::move(qr_generator_key); qr_generator_key_ = std::move(qr_generator_key);
v2_pairings_ = std::move(v2_pairings);
} }
void FidoDiscoveryFactory::set_usb_device_manager( void FidoDiscoveryFactory::set_usb_device_manager(
...@@ -92,7 +116,7 @@ void FidoDiscoveryFactory::set_network_context( ...@@ -92,7 +116,7 @@ void FidoDiscoveryFactory::set_network_context(
} }
void FidoDiscoveryFactory::set_cable_pairing_callback( void FidoDiscoveryFactory::set_cable_pairing_callback(
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)> base::RepeatingCallback<void(std::unique_ptr<cablev2::Pairing>)>
pairing_callback) { pairing_callback) {
cable_pairing_callback_.emplace(std::move(pairing_callback)); cable_pairing_callback_.emplace(std::move(pairing_callback));
} }
...@@ -102,6 +126,19 @@ void FidoDiscoveryFactory::set_hid_ignore_list( ...@@ -102,6 +126,19 @@ void FidoDiscoveryFactory::set_hid_ignore_list(
hid_ignore_list_ = std::move(hid_ignore_list); hid_ignore_list_ = std::move(hid_ignore_list);
} }
// static
std::vector<std::unique_ptr<FidoDiscoveryBase>>
FidoDiscoveryFactory::SingleDiscovery(
std::unique_ptr<FidoDiscoveryBase> discovery) {
if (!discovery) {
return {};
}
std::vector<std::unique_ptr<FidoDiscoveryBase>> ret;
ret.emplace_back(std::move(discovery));
return ret;
}
#if defined(OS_WIN) #if defined(OS_WIN)
void FidoDiscoveryFactory::set_win_webauthn_api(WinWebAuthnApi* api) { void FidoDiscoveryFactory::set_win_webauthn_api(WinWebAuthnApi* api) {
win_webauthn_api_ = api; win_webauthn_api_ = api;
......
...@@ -38,10 +38,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -38,10 +38,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
FidoDiscoveryFactory(); FidoDiscoveryFactory();
virtual ~FidoDiscoveryFactory(); virtual ~FidoDiscoveryFactory();
// Instantiates a FidoDiscoveryBase for the given transport. // Instantiates one or more FidoDiscoveryBases for the given transport.
// //
// FidoTransportProtocol::kUsbHumanInterfaceDevice is not valid on Android. // FidoTransportProtocol::kUsbHumanInterfaceDevice is not valid on Android.
virtual std::unique_ptr<FidoDiscoveryBase> Create( virtual std::vector<std::unique_ptr<FidoDiscoveryBase>> Create(
FidoTransportProtocol transport); FidoTransportProtocol transport);
// Returns whether the current instance is an override injected by the // Returns whether the current instance is an override injected by the
...@@ -49,8 +49,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -49,8 +49,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
virtual bool IsTestOverride(); virtual bool IsTestOverride();
// set_cable_data configures caBLE obtained via a WebAuthn extension. // set_cable_data configures caBLE obtained via a WebAuthn extension.
void set_cable_data(std::vector<CableDiscoveryData> cable_data, void set_cable_data(
base::Optional<QRGeneratorKey> qr_generator_key); std::vector<CableDiscoveryData> cable_data,
base::Optional<QRGeneratorKey> qr_generator_key,
std::vector<std::unique_ptr<cablev2::Pairing>> v2_pairings);
void set_usb_device_manager(mojo::Remote<device::mojom::UsbDeviceManager>); void set_usb_device_manager(mojo::Remote<device::mojom::UsbDeviceManager>);
...@@ -60,7 +62,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -60,7 +62,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
// called when a QR handshake results in a phone wishing to pair with this // called when a QR handshake results in a phone wishing to pair with this
// browser. // browser.
void set_cable_pairing_callback( void set_cable_pairing_callback(
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>); base::RepeatingCallback<void(std::unique_ptr<cablev2::Pairing>)>);
void set_hid_ignore_list(base::flat_set<VidPid> hid_ignore_list); void set_hid_ignore_list(base::flat_set<VidPid> hid_ignore_list);
...@@ -84,6 +86,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -84,6 +86,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
WinWebAuthnApi* win_webauthn_api() const; WinWebAuthnApi* win_webauthn_api() const;
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
protected:
static std::vector<std::unique_ptr<FidoDiscoveryBase>> SingleDiscovery(
std::unique_ptr<FidoDiscoveryBase> discovery);
private: private:
#if defined(OS_MAC) || defined(OS_CHROMEOS) #if defined(OS_MAC) || defined(OS_CHROMEOS)
std::unique_ptr<FidoDiscoveryBase> MaybeCreatePlatformDiscovery() const; std::unique_ptr<FidoDiscoveryBase> MaybeCreatePlatformDiscovery() const;
...@@ -97,8 +103,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -97,8 +103,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
network::mojom::NetworkContext* network_context_ = nullptr; network::mojom::NetworkContext* network_context_ = nullptr;
base::Optional<std::vector<CableDiscoveryData>> cable_data_; base::Optional<std::vector<CableDiscoveryData>> cable_data_;
base::Optional<QRGeneratorKey> qr_generator_key_; base::Optional<QRGeneratorKey> qr_generator_key_;
std::vector<std::unique_ptr<cablev2::Pairing>> v2_pairings_;
base::Optional< base::Optional<
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>> base::RepeatingCallback<void(std::unique_ptr<cablev2::Pairing>)>>
cable_pairing_callback_; cable_pairing_callback_;
#if defined(OS_WIN) #if defined(OS_WIN)
WinWebAuthnApi* win_webauthn_api_ = nullptr; WinWebAuthnApi* win_webauthn_api_ = nullptr;
......
...@@ -62,9 +62,9 @@ void FidoRequestHandlerBase::InitDiscoveries( ...@@ -62,9 +62,9 @@ void FidoRequestHandlerBase::InitDiscoveries(
const base::flat_set<FidoTransportProtocol>& available_transports) { const base::flat_set<FidoTransportProtocol>& available_transports) {
transport_availability_info_.available_transports = available_transports; transport_availability_info_.available_transports = available_transports;
for (const auto transport : available_transports) { for (const auto transport : available_transports) {
std::unique_ptr<FidoDiscoveryBase> discovery = std::vector<std::unique_ptr<FidoDiscoveryBase>> discoveries =
fido_discovery_factory->Create(transport); fido_discovery_factory->Create(transport);
if (discovery == nullptr) { if (discoveries.empty()) {
// This can occur in tests when a ScopedVirtualU2fDevice is in effect and // This can occur in tests when a ScopedVirtualU2fDevice is in effect and
// HID transports are not configured or when caBLE discovery data isn't // HID transports are not configured or when caBLE discovery data isn't
// available. // available.
...@@ -72,8 +72,10 @@ void FidoRequestHandlerBase::InitDiscoveries( ...@@ -72,8 +72,10 @@ void FidoRequestHandlerBase::InitDiscoveries(
continue; continue;
} }
discovery->set_observer(this); for (auto& discovery : discoveries) {
discoveries_.push_back(std::move(discovery)); discovery->set_observer(this);
discoveries_.emplace_back(std::move(discovery));
}
} }
// Check if the platform supports BLE before trying to get a power manager. // Check if the platform supports BLE before trying to get a power manager.
......
...@@ -80,13 +80,13 @@ VirtualFidoDevice::State* VirtualFidoDeviceFactory::mutable_state() { ...@@ -80,13 +80,13 @@ VirtualFidoDevice::State* VirtualFidoDeviceFactory::mutable_state() {
return state_.get(); return state_.get();
} }
std::unique_ptr<FidoDiscoveryBase> VirtualFidoDeviceFactory::Create( std::vector<std::unique_ptr<FidoDiscoveryBase>>
FidoTransportProtocol transport) { VirtualFidoDeviceFactory::Create(FidoTransportProtocol transport) {
if (transport != transport_) { if (transport != transport_) {
return nullptr; return {};
} }
return std::make_unique<VirtualFidoDeviceDiscovery>( return SingleDiscovery(std::make_unique<VirtualFidoDeviceDiscovery>(
transport_, state_, supported_protocol_, ctap2_config_); transport_, state_, supported_protocol_, ctap2_config_));
} }
bool VirtualFidoDeviceFactory::IsTestOverride() { bool VirtualFidoDeviceFactory::IsTestOverride() {
......
...@@ -39,7 +39,7 @@ class VirtualFidoDeviceFactory : public device::FidoDiscoveryFactory { ...@@ -39,7 +39,7 @@ class VirtualFidoDeviceFactory : public device::FidoDiscoveryFactory {
protected: protected:
// device::FidoDiscoveryFactory: // device::FidoDiscoveryFactory:
std::unique_ptr<FidoDiscoveryBase> Create( std::vector<std::unique_ptr<FidoDiscoveryBase>> Create(
FidoTransportProtocol transport) override; FidoTransportProtocol transport) override;
bool IsTestOverride() override; bool IsTestOverride() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment