Commit 23f2521d authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

device/fido: have caBLE discovery own the discovery data.

Previously, caBLE discovery dealt with a const pointer to a
|CableDiscoveryData| because the only possible |CableDiscoveryData|
objects were those given via the WebAuthn extension.

In the future, we'll need to be able to create |CableDiscoveryData|
objects from candidate EIDs because they could also match a QR code.
Thus, rejig the functions to return an optional |CableDiscoveryData|
rather than a const pointer.

The Bluetooth stack returns UUIDs as strings and the previous
implementation hex-encoded the expected UUID and matched the resulting
string. Since we now need to get the binary EID, the UUID needs to be
parsed instead. That leaves the binary-to-string encoding function as
something that's only used in a unittest, so the function moves into
that unit test in this change.

Change-Id: I3e675bcec66bf2416df4945ec1b2487962971729
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1753697
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#690810}
parent a50dfe61
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -356,7 +357,8 @@ void FidoCableDiscovery::RecordAdvertisementResult(bool is_success) { ...@@ -356,7 +357,8 @@ void FidoCableDiscovery::RecordAdvertisementResult(bool is_success) {
void FidoCableDiscovery::CableDeviceFound(BluetoothAdapter* adapter, void FidoCableDiscovery::CableDeviceFound(BluetoothAdapter* adapter,
BluetoothDevice* device) { BluetoothDevice* device) {
const auto* found_cable_device_data = GetCableDiscoveryData(device); base::Optional<CableDiscoveryData> found_cable_device_data =
GetCableDiscoveryData(device);
const std::string device_address = device->GetAddress(); const std::string device_address = device->GetAddress();
if (!found_cable_device_data || if (!found_cable_device_data ||
base::Contains(active_authenticator_eids_, base::Contains(active_authenticator_eids_,
...@@ -366,21 +368,15 @@ void FidoCableDiscovery::CableDeviceFound(BluetoothAdapter* adapter, ...@@ -366,21 +368,15 @@ void FidoCableDiscovery::CableDeviceFound(BluetoothAdapter* adapter,
} }
FIDO_LOG(EVENT) << "Found new caBLE device."; FIDO_LOG(EVENT) << "Found new caBLE device.";
// Nonce is embedded as first 8 bytes of client EID. active_authenticator_eids_.insert(found_cable_device_data->authenticator_eid);
std::array<uint8_t, 8> nonce; active_devices_.insert(device_address);
bool extract_success = fido_parsing_utils::ExtractArray(
found_cable_device_data->client_eid, 0, &nonce);
if (!extract_success)
return;
auto cable_device = auto cable_device =
std::make_unique<FidoCableDevice>(adapter, device->GetAddress()); std::make_unique<FidoCableDevice>(adapter, device->GetAddress());
active_authenticator_eids_.insert(found_cable_device_data->authenticator_eid);
active_devices_.insert(device_address);
StopAdvertisements( StopAdvertisements(
base::BindOnce(&FidoCableDiscovery::ConductEncryptionHandshake, base::BindOnce(&FidoCableDiscovery::ConductEncryptionHandshake,
weak_factory_.GetWeakPtr(), std::move(cable_device), weak_factory_.GetWeakPtr(), std::move(cable_device),
*found_cable_device_data)); std::move(*found_cable_device_data)));
} }
void FidoCableDiscovery::ConductEncryptionHandshake( void FidoCableDiscovery::ConductEncryptionHandshake(
...@@ -416,12 +412,12 @@ void FidoCableDiscovery::ValidateAuthenticatorHandshakeMessage( ...@@ -416,12 +412,12 @@ void FidoCableDiscovery::ValidateAuthenticatorHandshakeMessage(
} }
} }
const CableDiscoveryData* FidoCableDiscovery::GetCableDiscoveryData( base::Optional<CableDiscoveryData> FidoCableDiscovery::GetCableDiscoveryData(
const BluetoothDevice* device) const { const BluetoothDevice* device) const {
const auto* discovery_data = GetCableDiscoveryDataFromServiceData(device); auto maybe_discovery_data = GetCableDiscoveryDataFromServiceData(device);
if (discovery_data != nullptr) { if (maybe_discovery_data) {
FIDO_LOG(DEBUG) << "Found caBLE service data."; FIDO_LOG(DEBUG) << "Found caBLE service data.";
return discovery_data; return maybe_discovery_data;
} }
FIDO_LOG(DEBUG) FIDO_LOG(DEBUG)
...@@ -431,39 +427,31 @@ const CableDiscoveryData* FidoCableDiscovery::GetCableDiscoveryData( ...@@ -431,39 +427,31 @@ const CableDiscoveryData* FidoCableDiscovery::GetCableDiscoveryData(
return GetCableDiscoveryDataFromServiceUUIDs(device); return GetCableDiscoveryDataFromServiceUUIDs(device);
} }
const CableDiscoveryData* base::Optional<CableDiscoveryData>
FidoCableDiscovery::GetCableDiscoveryDataFromServiceData( FidoCableDiscovery::GetCableDiscoveryDataFromServiceData(
const BluetoothDevice* device) const { const BluetoothDevice* device) const {
const auto* service_data = const auto* service_data =
device->GetServiceDataForUUID(CableAdvertisementUUID()); device->GetServiceDataForUUID(CableAdvertisementUUID());
if (!service_data) { if (!service_data) {
return nullptr; return base::nullopt;
} }
DCHECK(service_data);
// Received service data from authenticator must have a flag that signals that // Received service data from authenticator must have a flag that signals that
// the service data includes Cable EID. // the service data includes Cable EID.
if (service_data->empty() || !(service_data->at(0) >> 5 & 1u)) if (service_data->empty() || !(service_data->at(0) >> 5 & 1u))
return nullptr; return base::nullopt;
CableEidArray received_authenticator_eid; CableEidArray received_authenticator_eid;
bool extract_success = fido_parsing_utils::ExtractArray( bool extract_success = fido_parsing_utils::ExtractArray(
*service_data, 2, &received_authenticator_eid); *service_data, 2, &received_authenticator_eid);
if (!extract_success) if (!extract_success)
return nullptr; return base::nullopt;
auto discovery_data_iterator = std::find_if(
discovery_data_.begin(), discovery_data_.end(),
[&received_authenticator_eid](const auto& data) {
return received_authenticator_eid == data.authenticator_eid;
});
return discovery_data_iterator != discovery_data_.end() return GetCableDiscoveryDataFromAuthenticatorEid(
? &(*discovery_data_iterator) std::move(received_authenticator_eid));
: nullptr;
} }
const CableDiscoveryData* base::Optional<CableDiscoveryData>
FidoCableDiscovery::GetCableDiscoveryDataFromServiceUUIDs( FidoCableDiscovery::GetCableDiscoveryDataFromServiceUUIDs(
const BluetoothDevice* device) const { const BluetoothDevice* device) const {
const auto service_uuids = device->GetUUIDs(); const auto service_uuids = device->GetUUIDs();
...@@ -471,18 +459,53 @@ FidoCableDiscovery::GetCableDiscoveryDataFromServiceUUIDs( ...@@ -471,18 +459,53 @@ FidoCableDiscovery::GetCableDiscoveryDataFromServiceUUIDs(
if (uuid == CableAdvertisementUUID()) if (uuid == CableAdvertisementUUID())
continue; continue;
auto discovery_data_iterator = std::find_if( // |uuid_hex| is a hex string with the format:
discovery_data_.begin(), discovery_data_.end(), // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
[&uuid](const auto& data) { const std::string& uuid_hex = uuid.canonical_value();
std::string received_eid_string = DCHECK_EQ(32u + 4u, uuid_hex.size());
fido_parsing_utils::ConvertBytesToUuid(data.authenticator_eid);
return uuid == BluetoothUUID(received_eid_string); // Copy substrings of |uuid_hex| to drop the hyphens.
std::string hex;
hex.reserve(32);
hex.append(uuid_hex, 0, 8);
hex.append(uuid_hex, 9, 4);
hex.append(uuid_hex, 14, 4);
hex.append(uuid_hex, 19, 4);
hex.append(uuid_hex, 24, 12);
DCHECK_EQ(32u, hex.size());
std::vector<uint8_t> uuid_binary;
const bool ok = base::HexStringToBytes(hex, &uuid_binary);
DCHECK(ok);
CableEidArray authenticator_eid;
DCHECK_EQ(authenticator_eid.size(), uuid_binary.size());
memcpy(authenticator_eid.data(), uuid_binary.data(),
authenticator_eid.size());
auto match = GetCableDiscoveryDataFromAuthenticatorEid(authenticator_eid);
if (match.has_value()) {
return match;
}
}
return base::nullopt;
}
base::Optional<CableDiscoveryData>
FidoCableDiscovery::GetCableDiscoveryDataFromAuthenticatorEid(
CableEidArray authenticator_eid) const {
auto discovery_data_iterator =
std::find_if(discovery_data_.begin(), discovery_data_.end(),
[&authenticator_eid](const auto& data) {
return authenticator_eid == data.authenticator_eid;
}); });
if (discovery_data_iterator != discovery_data_.end()) { if (discovery_data_iterator != discovery_data_.end()) {
return &(*discovery_data_iterator); return *discovery_data_iterator;
} }
}
return nullptr; return base::nullopt;
} }
} // namespace device } // namespace device
...@@ -82,12 +82,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery ...@@ -82,12 +82,14 @@ 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);
const CableDiscoveryData* GetCableDiscoveryData( base::Optional<CableDiscoveryData> GetCableDiscoveryData(
const BluetoothDevice* device) const; const BluetoothDevice* device) const;
const CableDiscoveryData* GetCableDiscoveryDataFromServiceData( base::Optional<CableDiscoveryData> GetCableDiscoveryDataFromServiceData(
const BluetoothDevice* device) const; const BluetoothDevice* device) const;
const CableDiscoveryData* GetCableDiscoveryDataFromServiceUUIDs( base::Optional<CableDiscoveryData> GetCableDiscoveryDataFromServiceUUIDs(
const BluetoothDevice* device) const; const BluetoothDevice* device) const;
base::Optional<CableDiscoveryData> GetCableDiscoveryDataFromAuthenticatorEid(
CableEidArray authenticator_eid) const;
std::vector<CableDiscoveryData> discovery_data_; std::vector<CableDiscoveryData> discovery_data_;
// active_authenticator_eids_ contains authenticator EIDs for which a // active_authenticator_eids_ contains authenticator EIDs for which a
......
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