Commit 5b4891f3 authored by Balazs Engedy's avatar Balazs Engedy Committed by Commit Bot

Fix two bugs affecting starting caBLE discovery.

The first bug is that the WebAuthn dialog is never shown if caBLE is
enabled but the |cable_extension| is not provided in the GetAssertion
request.

It's because GetAssertionRequestHandler's constructor will not actually
create and start a FidoCableDiscovery if the request is missing the
|cable_extension| data, while FidoRequestHandlerBase's barrier closure
will still wait for the discovery to start the transport protocol is
marked available in |available_transports|.

The second bug is that caBLE will not be used for a GetAssertion request
if the same web page already issued a MakeCredential request before.

This is because AuthenticatorImpl::MakeCredential will remove caBLE
from |protocols_|. However, the same AuthenticatorImpl instance will be
used to service the GetAssertionRequest, which will already see a
trimmed list of |protocols_| without caBLE, and pass it to
GetAssertionRequestHandler.

Bug: 878877
Change-Id: I6b7c915fc0de63e6da29399825071734405e424c
Reviewed-on: https://chromium-review.googlesource.com/1194040Reviewed-by: default avatarChris Palmer <palmer@chromium.org>
Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Commit-Queue: Balazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587355}
parent b4f1a520
...@@ -219,8 +219,7 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest( ...@@ -219,8 +219,7 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
if (!options->cable_authentication_data.empty()) { if (!options->cable_authentication_data.empty()) {
request_parameter.SetCableExtension( request_parameter.SetCableExtension(
mojo::ConvertTo< mojo::ConvertTo<std::vector<device::CableDiscoveryData>>(
std::vector<device::FidoCableDiscovery::CableDiscoveryData>>(
options->cable_authentication_data)); options->cable_authentication_data));
} }
return request_parameter; return request_parameter;
...@@ -311,6 +310,26 @@ std::string Base64UrlEncode(const base::span<const uint8_t> input) { ...@@ -311,6 +310,26 @@ std::string Base64UrlEncode(const base::span<const uint8_t> input) {
return ret; return ret;
} }
base::flat_set<device::FidoTransportProtocol> GetTransportsEnabledByFlags() {
base::flat_set<device::FidoTransportProtocol> transports;
transports.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
transports.insert(device::FidoTransportProtocol::kInternal);
if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
transports.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
}
#if defined(OS_WIN)
if (base::FeatureList::IsEnabled(features::kWebAuthCable) &&
base::FeatureList::IsEnabled(features::kWebAuthCableWin)) {
#else
if (base::FeatureList::IsEnabled(features::kWebAuthCable)) {
#endif // defined(OS_WIN)
transports.insert(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
}
return transports;
}
} // namespace } // namespace
AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host) AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host)
...@@ -324,27 +343,12 @@ AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host, ...@@ -324,27 +343,12 @@ AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host,
: WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)), : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
render_frame_host_(render_frame_host), render_frame_host_(render_frame_host),
connector_(connector), connector_(connector),
transports_(GetTransportsEnabledByFlags()),
timer_(std::move(timer)), timer_(std::move(timer)),
binding_(this), binding_(this),
weak_factory_(this) { weak_factory_(this) {
DCHECK(render_frame_host_); DCHECK(render_frame_host_);
DCHECK(timer_); DCHECK(timer_);
protocols_.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
protocols_.insert(device::FidoTransportProtocol::kInternal);
if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
protocols_.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
}
#if defined(OS_WIN)
if (base::FeatureList::IsEnabled(features::kWebAuthCable) &&
base::FeatureList::IsEnabled(features::kWebAuthCableWin)) {
#else
if (base::FeatureList::IsEnabled(features::kWebAuthCable)) {
#endif // defined(OS_WIN)
protocols_.insert(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
}
} }
AuthenticatorImpl::~AuthenticatorImpl() { AuthenticatorImpl::~AuthenticatorImpl() {
...@@ -371,11 +375,6 @@ void AuthenticatorImpl::UpdateRequestDelegate() { ...@@ -371,11 +375,6 @@ void AuthenticatorImpl::UpdateRequestDelegate() {
render_frame_host_); render_frame_host_);
} }
void AuthenticatorImpl::AddTransportProtocolForTesting(
device::FidoTransportProtocol protocol) {
protocols_.insert(protocol);
}
bool AuthenticatorImpl::IsFocused() const { bool AuthenticatorImpl::IsFocused() const {
return render_frame_host_->IsCurrent() && request_delegate_->IsFocused(); return render_frame_host_->IsCurrent() && request_delegate_->IsFocused();
} }
...@@ -477,11 +476,6 @@ void AuthenticatorImpl::MakeCredential( ...@@ -477,11 +476,6 @@ void AuthenticatorImpl::MakeCredential(
attestation_preference_ = options->attestation; attestation_preference_ = options->attestation;
// Communication using Cable protocol is only supported for GetAssertion
// request on CTAP2 devices.
protocols_.erase(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
auto authenticator_selection_criteria = auto authenticator_selection_criteria =
options->authenticator_selection options->authenticator_selection
? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>( ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
...@@ -489,7 +483,7 @@ void AuthenticatorImpl::MakeCredential( ...@@ -489,7 +483,7 @@ void AuthenticatorImpl::MakeCredential(
: device::AuthenticatorSelectionCriteria(); : device::AuthenticatorSelectionCriteria();
request_ = std::make_unique<device::MakeCredentialRequestHandler>( request_ = std::make_unique<device::MakeCredentialRequestHandler>(
connector_, protocols_, connector_, transports_,
CreateCtapMakeCredentialRequest( CreateCtapMakeCredentialRequest(
ConstructClientDataHash(client_data_json_), options, ConstructClientDataHash(client_data_json_), options,
individual_attestation), individual_attestation),
...@@ -580,7 +574,7 @@ void AuthenticatorImpl::GetAssertion( ...@@ -580,7 +574,7 @@ void AuthenticatorImpl::GetAssertion(
CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists( CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
ctap_request); ctap_request);
request_ = std::make_unique<device::GetAssertionRequestHandler>( request_ = std::make_unique<device::GetAssertionRequestHandler>(
connector_, protocols_, std::move(ctap_request), connector_, transports_, std::move(ctap_request),
base::BindOnce(&AuthenticatorImpl::OnSignResponse, base::BindOnce(&AuthenticatorImpl::OnSignResponse,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
......
...@@ -82,9 +82,13 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator, ...@@ -82,9 +82,13 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
// to a new active document. // to a new active document.
void Bind(blink::mojom::AuthenticatorRequest request); void Bind(blink::mojom::AuthenticatorRequest request);
base::flat_set<device::FidoTransportProtocol> enabled_transports_for_testing()
const {
return transports_;
}
protected: protected:
virtual void UpdateRequestDelegate(); virtual void UpdateRequestDelegate();
void AddTransportProtocolForTesting(device::FidoTransportProtocol protocol);
std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_; std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
...@@ -168,7 +172,7 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator, ...@@ -168,7 +172,7 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
RenderFrameHost* const render_frame_host_; RenderFrameHost* const render_frame_host_;
service_manager::Connector* connector_ = nullptr; service_manager::Connector* connector_ = nullptr;
base::flat_set<device::FidoTransportProtocol> protocols_; const base::flat_set<device::FidoTransportProtocol> transports_;
std::unique_ptr<device::FidoRequestHandlerBase> request_; std::unique_ptr<device::FidoRequestHandlerBase> request_;
MakeCredentialCallback make_credential_response_callback_; MakeCredentialCallback make_credential_response_callback_;
......
...@@ -388,7 +388,8 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness { ...@@ -388,7 +388,8 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
} }
bool SupportsTransportProtocol(::device::FidoTransportProtocol protocol) { bool SupportsTransportProtocol(::device::FidoTransportProtocol protocol) {
return base::ContainsKey(authenticator_impl_->protocols_, protocol); return base::ContainsKey(
authenticator_impl_->enabled_transports_for_testing(), protocol);
} }
void EnableFeature(const base::Feature& feature) { void EnableFeature(const base::Feature& feature) {
...@@ -826,24 +827,7 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) { ...@@ -826,24 +827,7 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
} }
TEST_F(AuthenticatorImplTest, TestCableDiscoveryByDefault) { TEST_F(AuthenticatorImplTest, TestCableDiscoveryByDefault) {
TestServiceManagerContext service_manager_context; auto authenticator = ConnectToAuthenticator();
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
// On Windows caBLE should be disabled by default. // On Windows caBLE should be disabled by default.
#if defined(OS_WIN) #if defined(OS_WIN)
EXPECT_FALSE(SupportsTransportProtocol( EXPECT_FALSE(SupportsTransportProtocol(
...@@ -854,26 +838,11 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryByDefault) { ...@@ -854,26 +838,11 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryByDefault) {
#endif #endif
} }
TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutFlag) { TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithFlag) {
scoped_feature_list_.emplace(); scoped_feature_list_.emplace();
scoped_feature_list_->InitAndDisableFeature(features::kWebAuthCable); scoped_feature_list_->InitAndDisableFeature(features::kWebAuthCable);
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>( auto authenticator = ConnectToAuthenticator();
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
EXPECT_FALSE(SupportsTransportProtocol( EXPECT_FALSE(SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy)); device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
} }
...@@ -881,23 +850,8 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutFlag) { ...@@ -881,23 +850,8 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutFlag) {
#if defined(OS_WIN) #if defined(OS_WIN)
TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithWinFlag) { TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithWinFlag) {
EnableFeature(features::kWebAuthCableWin); EnableFeature(features::kWebAuthCableWin);
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status()); auto authenticator = ConnectToAuthenticator();
EXPECT_TRUE(SupportsTransportProtocol( EXPECT_TRUE(SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy)); device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
} }
...@@ -913,53 +867,14 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutFlagWin) { ...@@ -913,53 +867,14 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutFlagWin) {
scoped_feature_list_.emplace(); scoped_feature_list_.emplace();
scoped_feature_list_->InitWithFeatures(enabled_features, disabled_features); scoped_feature_list_->InitWithFeatures(enabled_features, disabled_features);
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>( auto authenticator = ConnectToAuthenticator();
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options),
callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
EXPECT_FALSE(SupportsTransportProtocol( EXPECT_FALSE(SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy)); device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
} }
} }
#endif #endif
TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledForMakeCredential) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
TestMakeCredentialCallback callback_receiver;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
EXPECT_FALSE(SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
}
TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) { TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
SimulateNavigation(GURL(kTestOrigin1)); SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options = PublicKeyCredentialRequestOptionsPtr options =
...@@ -1923,16 +1838,14 @@ class AuthenticatorImplRequestDelegateTest : public AuthenticatorImplTest { ...@@ -1923,16 +1838,14 @@ class AuthenticatorImplRequestDelegateTest : public AuthenticatorImplTest {
std::move(timer)); std::move(timer));
} }
void AddTransport(device::FidoTransportProtocol protocol) {
authenticator_impl_->AddTransportProtocolForTesting(protocol);
}
protected: protected:
std::unique_ptr<FakeAuthenticatorImpl> authenticator_impl_; std::unique_ptr<FakeAuthenticatorImpl> authenticator_impl_;
}; };
TEST_F(AuthenticatorImplRequestDelegateTest, TEST_F(AuthenticatorImplRequestDelegateTest,
TestRequestDelegateObservesFidoRequestHandler) { TestRequestDelegateObservesFidoRequestHandler) {
EnableFeature(features::kWebAuthBle);
device::test::ScopedFakeFidoDiscoveryFactory discovery_factory; device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
auto* fake_ble_discovery = discovery_factory.ForgeNextBleDiscovery(); auto* fake_ble_discovery = discovery_factory.ForgeNextBleDiscovery();
...@@ -1948,7 +1861,6 @@ TEST_F(AuthenticatorImplRequestDelegateTest, ...@@ -1948,7 +1861,6 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
auto* const mock_delegate_ptr = mock_delegate.get(); auto* const mock_delegate_ptr = mock_delegate.get();
auto authenticator = ConstructFakeAuthenticatorWithTimer( auto authenticator = ConstructFakeAuthenticatorWithTimer(
std::move(mock_delegate), task_runner); std::move(mock_delegate), task_runner);
AddTransport(device::FidoTransportProtocol::kBluetoothLowEnergy);
auto mock_ble_device = device::MockFidoDevice::MakeCtap(); auto mock_ble_device = device::MockFidoDevice::MakeCtap();
mock_ble_device->StubGetId(); mock_ble_device->StubGetId();
......
...@@ -174,30 +174,30 @@ TypeConverter<::device::PublicKeyCredentialUserEntity, ...@@ -174,30 +174,30 @@ TypeConverter<::device::PublicKeyCredentialUserEntity,
} }
// static // static
std::vector<::device::FidoCableDiscovery::CableDiscoveryData> std::vector<::device::CableDiscoveryData>
TypeConverter<std::vector<::device::FidoCableDiscovery::CableDiscoveryData>, TypeConverter<std::vector<::device::CableDiscoveryData>,
std::vector<CableAuthenticationPtr>>:: std::vector<CableAuthenticationPtr>>::
Convert(const std::vector<CableAuthenticationPtr>& input) { Convert(const std::vector<CableAuthenticationPtr>& input) {
std::vector<::device::FidoCableDiscovery::CableDiscoveryData> discovery_data; std::vector<::device::CableDiscoveryData> discovery_data;
discovery_data.reserve(input.size()); discovery_data.reserve(input.size());
for (const auto& data : input) { for (const auto& data : input) {
::device::FidoCableDiscovery::EidArray client_eid; ::device::EidArray client_eid;
DCHECK_EQ(client_eid.size(), data->client_eid.size()); DCHECK_EQ(client_eid.size(), data->client_eid.size());
std::copy(data->client_eid.begin(), data->client_eid.end(), std::copy(data->client_eid.begin(), data->client_eid.end(),
client_eid.begin()); client_eid.begin());
::device::FidoCableDiscovery::EidArray authenticator_eid; ::device::EidArray authenticator_eid;
DCHECK_EQ(authenticator_eid.size(), data->authenticator_eid.size()); DCHECK_EQ(authenticator_eid.size(), data->authenticator_eid.size());
std::copy(data->authenticator_eid.begin(), data->authenticator_eid.end(), std::copy(data->authenticator_eid.begin(), data->authenticator_eid.end(),
authenticator_eid.begin()); authenticator_eid.begin());
::device::FidoCableDiscovery::SessionPreKeyArray session_pre_key; ::device::SessionPreKeyArray session_pre_key;
DCHECK_EQ(session_pre_key.size(), data->session_pre_key.size()); DCHECK_EQ(session_pre_key.size(), data->session_pre_key.size());
std::copy(data->session_pre_key.begin(), data->session_pre_key.end(), std::copy(data->session_pre_key.begin(), data->session_pre_key.end(),
session_pre_key.begin()); session_pre_key.begin());
discovery_data.push_back(::device::FidoCableDiscovery::CableDiscoveryData{ discovery_data.push_back(::device::CableDiscoveryData{
data->version, client_eid, authenticator_eid, session_pre_key}); data->version, client_eid, authenticator_eid, session_pre_key});
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <vector> #include <vector>
#include "device/fido/authenticator_selection_criteria.h" #include "device/fido/authenticator_selection_criteria.h"
#include "device/fido/cable/fido_cable_discovery.h" #include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/fido_transport_protocol.h" #include "device/fido/fido_transport_protocol.h"
#include "device/fido/public_key_credential_descriptor.h" #include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h" #include "device/fido/public_key_credential_params.h"
...@@ -91,10 +91,9 @@ struct TypeConverter<::device::PublicKeyCredentialUserEntity, ...@@ -91,10 +91,9 @@ struct TypeConverter<::device::PublicKeyCredentialUserEntity,
}; };
template <> template <>
struct TypeConverter< struct TypeConverter<std::vector<::device::CableDiscoveryData>,
std::vector<::device::FidoCableDiscovery::CableDiscoveryData>, std::vector<::blink::mojom::CableAuthenticationPtr>> {
std::vector<::blink::mojom::CableAuthenticationPtr>> { static std::vector<::device::CableDiscoveryData> Convert(
static std::vector<::device::FidoCableDiscovery::CableDiscoveryData> Convert(
const std::vector<::blink::mojom::CableAuthenticationPtr>& input); const std::vector<::blink::mojom::CableAuthenticationPtr>& input);
}; };
......
...@@ -41,6 +41,7 @@ component("fido") { ...@@ -41,6 +41,7 @@ component("fido") {
"ble/fido_ble_transaction.h", "ble/fido_ble_transaction.h",
"ble/fido_ble_uuids.cc", "ble/fido_ble_uuids.cc",
"ble/fido_ble_uuids.h", "ble/fido_ble_uuids.h",
"cable/cable_discovery_data.h",
"cable/fido_cable_device.cc", "cable/fido_cable_device.cc",
"cable/fido_cable_device.h", "cable/fido_cable_device.h",
"cable/fido_cable_discovery.cc", "cable/fido_cable_discovery.cc",
......
// Copyright 2018 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_CABLE_DISCOVERY_DATA_H_
#define DEVICE_FIDO_CABLE_CABLE_DISCOVERY_DATA_H_
#include <stdint.h>
#include <array>
#include "base/component_export.h"
namespace device {
constexpr size_t kEphemeralIdSize = 16;
constexpr size_t kSessionPreKeySize = 32;
using EidArray = std::array<uint8_t, kEphemeralIdSize>;
using SessionPreKeyArray = std::array<uint8_t, kSessionPreKeySize>;
// Encapsulates information required to discover Cable device per single
// credential. When multiple credentials are enrolled to a single account
// (i.e. more than one phone has been enrolled to an user account as a
// security key), then FidoCableDiscovery must advertise for all of the client
// EID received from the relying party.
// TODO(hongjunchoi): Add discovery data required for MakeCredential request.
// See: https://crbug.com/837088
struct COMPONENT_EXPORT(DEVICE_FIDO) CableDiscoveryData {
CableDiscoveryData(uint8_t version,
const EidArray& client_eid,
const EidArray& authenticator_eid,
const SessionPreKeyArray& session_pre_key);
CableDiscoveryData(const CableDiscoveryData& data);
CableDiscoveryData& operator=(const CableDiscoveryData& other);
~CableDiscoveryData();
uint8_t version;
EidArray client_eid;
EidArray authenticator_eid;
SessionPreKeyArray session_pre_key;
};
} // namespace device
#endif // DEVICE_FIDO_CABLE_CABLE_DISCOVERY_DATA_H_
...@@ -50,8 +50,7 @@ bool IsCableDevice(const BluetoothDevice* device) { ...@@ -50,8 +50,7 @@ bool IsCableDevice(const BluetoothDevice* device) {
// with the EID as its UUID. // with the EID as its UUID.
std::unique_ptr<BluetoothAdvertisement::Data> ConstructAdvertisementData( std::unique_ptr<BluetoothAdvertisement::Data> ConstructAdvertisementData(
uint8_t version_number, uint8_t version_number,
base::span<const uint8_t, FidoCableDiscovery::kEphemeralIdSize> base::span<const uint8_t, kEphemeralIdSize> client_eid) {
client_eid) {
auto advertisement_data = std::make_unique<BluetoothAdvertisement::Data>( auto advertisement_data = std::make_unique<BluetoothAdvertisement::Data>(
BluetoothAdvertisement::AdvertisementType::ADVERTISEMENT_TYPE_BROADCAST); BluetoothAdvertisement::AdvertisementType::ADVERTISEMENT_TYPE_BROADCAST);
...@@ -97,9 +96,9 @@ std::unique_ptr<BluetoothAdvertisement::Data> ConstructAdvertisementData( ...@@ -97,9 +96,9 @@ std::unique_ptr<BluetoothAdvertisement::Data> ConstructAdvertisementData(
} // namespace } // namespace
// FidoCableDiscovery::CableDiscoveryData ------------------------------------- // CableDiscoveryData -------------------------------------
FidoCableDiscovery::CableDiscoveryData::CableDiscoveryData( CableDiscoveryData::CableDiscoveryData(
uint8_t version, uint8_t version,
const EidArray& client_eid, const EidArray& client_eid,
const EidArray& authenticator_eid, const EidArray& authenticator_eid,
...@@ -109,13 +108,13 @@ FidoCableDiscovery::CableDiscoveryData::CableDiscoveryData( ...@@ -109,13 +108,13 @@ FidoCableDiscovery::CableDiscoveryData::CableDiscoveryData(
authenticator_eid(authenticator_eid), authenticator_eid(authenticator_eid),
session_pre_key(session_pre_key) {} session_pre_key(session_pre_key) {}
FidoCableDiscovery::CableDiscoveryData::CableDiscoveryData( CableDiscoveryData::CableDiscoveryData(const CableDiscoveryData& data) =
const CableDiscoveryData& data) = default; default;
FidoCableDiscovery::CableDiscoveryData& FidoCableDiscovery::CableDiscoveryData:: CableDiscoveryData& CableDiscoveryData::operator=(
operator=(const CableDiscoveryData& other) = default; const CableDiscoveryData& other) = default;
FidoCableDiscovery::CableDiscoveryData::~CableDiscoveryData() = default; CableDiscoveryData::~CableDiscoveryData() = default;
// FidoCableDiscovery --------------------------------------------------------- // FidoCableDiscovery ---------------------------------------------------------
...@@ -322,8 +321,7 @@ void FidoCableDiscovery::ValidateAuthenticatorHandshakeMessage( ...@@ -322,8 +321,7 @@ void FidoCableDiscovery::ValidateAuthenticatorHandshakeMessage(
} }
} }
const FidoCableDiscovery::CableDiscoveryData* const CableDiscoveryData* FidoCableDiscovery::GetFoundCableDiscoveryData(
FidoCableDiscovery::GetFoundCableDiscoveryData(
const BluetoothDevice* device) const { const BluetoothDevice* device) const {
const auto* discovery_data = const auto* discovery_data =
GetFoundCableDiscoveryDataFromServiceData(device); GetFoundCableDiscoveryDataFromServiceData(device);
...@@ -334,7 +332,7 @@ FidoCableDiscovery::GetFoundCableDiscoveryData( ...@@ -334,7 +332,7 @@ FidoCableDiscovery::GetFoundCableDiscoveryData(
return GetFoundCableDiscoveryDataFromServiceUUIDs(device); return GetFoundCableDiscoveryDataFromServiceUUIDs(device);
} }
const FidoCableDiscovery::CableDiscoveryData* const CableDiscoveryData*
FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceData( FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceData(
const BluetoothDevice* device) const { const BluetoothDevice* device) const {
const auto* service_data = const auto* service_data =
...@@ -366,7 +364,7 @@ FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceData( ...@@ -366,7 +364,7 @@ FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceData(
: nullptr; : nullptr;
} }
const FidoCableDiscovery::CableDiscoveryData* const CableDiscoveryData*
FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceUUIDs( FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceUUIDs(
const BluetoothDevice* device) const { const BluetoothDevice* device) const {
const auto service_uuids = device->GetUUIDs(); const auto service_uuids = device->GetUUIDs();
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "device/fido/ble/fido_ble_discovery_base.h" #include "device/fido/ble/fido_ble_discovery_base.h"
#include "device/fido/cable/cable_discovery_data.h"
namespace device { namespace device {
...@@ -30,33 +31,6 @@ class FidoCableHandshakeHandler; ...@@ -30,33 +31,6 @@ class FidoCableHandshakeHandler;
class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDiscovery
: public FidoBleDiscoveryBase { : public FidoBleDiscoveryBase {
public: public:
static constexpr size_t kEphemeralIdSize = 16;
static constexpr size_t kSessionPreKeySize = 32;
using EidArray = std::array<uint8_t, kEphemeralIdSize>;
using SessionPreKeyArray = std::array<uint8_t, kSessionPreKeySize>;
// Encapsulates information required to discover Cable device per single
// credential. When multiple credentials are enrolled to a single account
// (i.e. more than one phone has been enrolled to an user account as a
// security key), then FidoCableDiscovery must advertise for all of the client
// EID received from the relying party.
// TODO(hongjunchoi): Add discovery data required for MakeCredential request.
// See: https://crbug.com/837088
struct COMPONENT_EXPORT(DEVICE_FIDO) CableDiscoveryData {
CableDiscoveryData(uint8_t version,
const EidArray& client_eid,
const EidArray& authenticator_eid,
const SessionPreKeyArray& session_pre_key);
CableDiscoveryData(const CableDiscoveryData& data);
CableDiscoveryData& operator=(const CableDiscoveryData& other);
~CableDiscoveryData();
uint8_t version;
EidArray client_eid;
EidArray authenticator_eid;
SessionPreKeyArray session_pre_key;
};
FidoCableDiscovery(std::vector<CableDiscoveryData> discovery_data); FidoCableDiscovery(std::vector<CableDiscoveryData> discovery_data);
~FidoCableDiscovery() override; ~FidoCableDiscovery() override;
......
...@@ -36,38 +36,38 @@ constexpr uint8_t kTestCableVersionNumber = 0x01; ...@@ -36,38 +36,38 @@ constexpr uint8_t kTestCableVersionNumber = 0x01;
// Constants required for discovering and constructing a Cable device that // Constants required for discovering and constructing a Cable device that
// are given by the relying party via an extension. // are given by the relying party via an extension.
constexpr FidoCableDiscovery::EidArray kClientEid = { constexpr EidArray kClientEid = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13,
0x12, 0x13, 0x14, 0x15}}; 0x14, 0x15}};
constexpr char kUuidFormattedClientEid[] = constexpr char kUuidFormattedClientEid[] =
"00010203-0405-0607-0809-101112131415"; "00010203-0405-0607-0809-101112131415";
constexpr FidoCableDiscovery::EidArray kAuthenticatorEid = { constexpr EidArray kAuthenticatorEid = {{0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01}}; 0x01, 0x01, 0x01, 0x01}};
constexpr FidoCableDiscovery::EidArray kInvalidAuthenticatorEid = { constexpr EidArray kInvalidAuthenticatorEid = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}}; 0x00, 0x00, 0x00, 0x00}};
constexpr FidoCableDiscovery::SessionPreKeyArray kTestSessionPreKey = { constexpr SessionPreKeyArray kTestSessionPreKey = {
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
constexpr FidoCableDiscovery::EidArray kSecondaryClientEid = { constexpr EidArray kSecondaryClientEid = {{0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
{0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x00}}; 0x03, 0x02, 0x01, 0x00}};
constexpr char kUuidFormattedSecondaryClientEid[] = constexpr char kUuidFormattedSecondaryClientEid[] =
"15141312-1110-0908-0706-050403020100"; "15141312-1110-0908-0706-050403020100";
constexpr FidoCableDiscovery::EidArray kSecondaryAuthenticatorEid = { constexpr EidArray kSecondaryAuthenticatorEid = {
{0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, {0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xee}}; 0xee, 0xee, 0xee, 0xee}};
constexpr FidoCableDiscovery::SessionPreKeyArray kSecondarySessionPreKey = { constexpr SessionPreKeyArray kSecondarySessionPreKey = {
{0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}}; 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}};
...@@ -150,8 +150,7 @@ class CableMockAdapter : public MockBluetoothAdapter { ...@@ -150,8 +150,7 @@ class CableMockAdapter : public MockBluetoothAdapter {
const AdvertisementErrorCallback&)); const AdvertisementErrorCallback&));
void AddNewTestBluetoothDevice( void AddNewTestBluetoothDevice(
base::span<const uint8_t, FidoCableDiscovery::kEphemeralIdSize> base::span<const uint8_t, kEphemeralIdSize> authenticator_eid) {
authenticator_eid) {
auto mock_device = CreateTestBluetoothDevice(); auto mock_device = CreateTestBluetoothDevice();
std::vector<uint8_t> service_data(18); std::vector<uint8_t> service_data(18);
...@@ -175,8 +174,7 @@ class CableMockAdapter : public MockBluetoothAdapter { ...@@ -175,8 +174,7 @@ class CableMockAdapter : public MockBluetoothAdapter {
} }
void AddNewTestAppleBluetoothDevice( void AddNewTestAppleBluetoothDevice(
base::span<const uint8_t, FidoCableDiscovery::kEphemeralIdSize> base::span<const uint8_t, kEphemeralIdSize> authenticator_eid) {
authenticator_eid) {
auto mock_device = CreateTestBluetoothDevice(); auto mock_device = CreateTestBluetoothDevice();
// Apple doesn't allow advertising service data, so we advertise a 16 bit // Apple doesn't allow advertising service data, so we advertise a 16 bit
// UUID plus the EID converted into 128 bit UUID. // UUID plus the EID converted into 128 bit UUID.
...@@ -234,7 +232,7 @@ class CableMockAdapter : public MockBluetoothAdapter { ...@@ -234,7 +232,7 @@ class CableMockAdapter : public MockBluetoothAdapter {
} }
void ExpectDiscoveryWithScanCallback( void ExpectDiscoveryWithScanCallback(
base::span<const uint8_t, FidoCableDiscovery::kEphemeralIdSize> eid, base::span<const uint8_t, kEphemeralIdSize> eid,
bool is_apple_device = false) { bool is_apple_device = false) {
EXPECT_CALL(*this, StartDiscoverySessionWithFilterRaw(_, _, _)) EXPECT_CALL(*this, StartDiscoverySessionWithFilterRaw(_, _, _))
.WillOnce(::testing::WithArg<1>( .WillOnce(::testing::WithArg<1>(
...@@ -295,7 +293,7 @@ class FakeFidoCableDiscovery : public FidoCableDiscovery { ...@@ -295,7 +293,7 @@ class FakeFidoCableDiscovery : public FidoCableDiscovery {
class FidoCableDiscoveryTest : public ::testing::Test { class FidoCableDiscoveryTest : public ::testing::Test {
public: public:
std::unique_ptr<FidoCableDiscovery> CreateDiscovery() { std::unique_ptr<FidoCableDiscovery> CreateDiscovery() {
std::vector<FidoCableDiscovery::CableDiscoveryData> discovery_data; std::vector<CableDiscoveryData> discovery_data;
discovery_data.emplace_back(kTestCableVersionNumber, kClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kClientEid,
kAuthenticatorEid, kTestSessionPreKey); kAuthenticatorEid, kTestSessionPreKey);
return std::make_unique<FakeFidoCableDiscovery>(std::move(discovery_data)); return std::make_unique<FakeFidoCableDiscovery>(std::move(discovery_data));
...@@ -367,7 +365,7 @@ TEST_F(FidoCableDiscoveryTest, TestDiscoveryFindsIncorrectDevice) { ...@@ -367,7 +365,7 @@ TEST_F(FidoCableDiscoveryTest, TestDiscoveryFindsIncorrectDevice) {
// are passed on from the relying party. We should expect 2 invocations of // are passed on from the relying party. We should expect 2 invocations of
// BluetoothAdapter::RegisterAdvertisement(). // BluetoothAdapter::RegisterAdvertisement().
TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithMultipleEids) { TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithMultipleEids) {
std::vector<FidoCableDiscovery::CableDiscoveryData> discovery_data; std::vector<CableDiscoveryData> discovery_data;
discovery_data.emplace_back(kTestCableVersionNumber, kClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kClientEid,
kAuthenticatorEid, kTestSessionPreKey); kAuthenticatorEid, kTestSessionPreKey);
discovery_data.emplace_back(kTestCableVersionNumber, kSecondaryClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kSecondaryClientEid,
...@@ -401,7 +399,7 @@ TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithMultipleEids) { ...@@ -401,7 +399,7 @@ TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithMultipleEids) {
// successfully. Since at least one advertisement are successfully processed, // successfully. Since at least one advertisement are successfully processed,
// scanning process should be invoked. // scanning process should be invoked.
TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithPartialAdvertisementSuccess) { TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithPartialAdvertisementSuccess) {
std::vector<FidoCableDiscovery::CableDiscoveryData> discovery_data; std::vector<CableDiscoveryData> discovery_data;
discovery_data.emplace_back(kTestCableVersionNumber, kClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kClientEid,
kAuthenticatorEid, kTestSessionPreKey); kAuthenticatorEid, kTestSessionPreKey);
discovery_data.emplace_back(kTestCableVersionNumber, kSecondaryClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kSecondaryClientEid,
...@@ -432,7 +430,7 @@ TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithPartialAdvertisementSuccess) { ...@@ -432,7 +430,7 @@ TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithPartialAdvertisementSuccess) {
// Test the scenario when all advertisement for client EID's fails. // Test the scenario when all advertisement for client EID's fails.
TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithAdvertisementFailures) { TEST_F(FidoCableDiscoveryTest, TestDiscoveryWithAdvertisementFailures) {
std::vector<FidoCableDiscovery::CableDiscoveryData> discovery_data; std::vector<CableDiscoveryData> discovery_data;
discovery_data.emplace_back(kTestCableVersionNumber, kClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kClientEid,
kAuthenticatorEid, kTestSessionPreKey); kAuthenticatorEid, kTestSessionPreKey);
discovery_data.emplace_back(kTestCableVersionNumber, kSecondaryClientEid, discovery_data.emplace_back(kTestCableVersionNumber, kSecondaryClientEid,
......
...@@ -146,7 +146,7 @@ CtapGetAssertionRequest& CtapGetAssertionRequest::SetPinProtocol( ...@@ -146,7 +146,7 @@ CtapGetAssertionRequest& CtapGetAssertionRequest::SetPinProtocol(
} }
CtapGetAssertionRequest& CtapGetAssertionRequest::SetCableExtension( CtapGetAssertionRequest& CtapGetAssertionRequest::SetCableExtension(
std::vector<FidoCableDiscovery::CableDiscoveryData> cable_extension) { std::vector<CableDiscoveryData> cable_extension) {
cable_extension_ = std::move(cable_extension); cable_extension_ = std::move(cable_extension);
return *this; return *this;
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include "base/containers/span.h" #include "base/containers/span.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h" #include "base/optional.h"
#include "device/fido/cable/fido_cable_discovery.h" #include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/fido_constants.h" #include "device/fido/fido_constants.h"
#include "device/fido/public_key_credential_descriptor.h" #include "device/fido/public_key_credential_descriptor.h"
...@@ -47,7 +47,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest { ...@@ -47,7 +47,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
CtapGetAssertionRequest& SetPinAuth(std::vector<uint8_t> pin_auth); CtapGetAssertionRequest& SetPinAuth(std::vector<uint8_t> pin_auth);
CtapGetAssertionRequest& SetPinProtocol(uint8_t pin_protocol); CtapGetAssertionRequest& SetPinProtocol(uint8_t pin_protocol);
CtapGetAssertionRequest& SetCableExtension( CtapGetAssertionRequest& SetCableExtension(
std::vector<FidoCableDiscovery::CableDiscoveryData> cable_extension); std::vector<CableDiscoveryData> cable_extension);
CtapGetAssertionRequest& SetAlternativeApplicationParameter( CtapGetAssertionRequest& SetAlternativeApplicationParameter(
base::span<const uint8_t, kRpIdHashLength> base::span<const uint8_t, kRpIdHashLength>
alternative_application_parameter); alternative_application_parameter);
...@@ -77,8 +77,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest { ...@@ -77,8 +77,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
} }
const base::Optional<uint8_t>& pin_protocol() const { return pin_protocol_; } const base::Optional<uint8_t>& pin_protocol() const { return pin_protocol_; }
const base::Optional<std::vector<FidoCableDiscovery::CableDiscoveryData>>& const base::Optional<std::vector<CableDiscoveryData>>& cable_extension()
cable_extension() const { const {
return cable_extension_; return cable_extension_;
} }
const base::Optional<std::array<uint8_t, kRpIdHashLength>>& const base::Optional<std::array<uint8_t, kRpIdHashLength>>&
...@@ -96,8 +96,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest { ...@@ -96,8 +96,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
base::Optional<std::vector<PublicKeyCredentialDescriptor>> allow_list_; base::Optional<std::vector<PublicKeyCredentialDescriptor>> allow_list_;
base::Optional<std::vector<uint8_t>> pin_auth_; base::Optional<std::vector<uint8_t>> pin_auth_;
base::Optional<uint8_t> pin_protocol_; base::Optional<uint8_t> pin_protocol_;
base::Optional<std::vector<FidoCableDiscovery::CableDiscoveryData>> base::Optional<std::vector<CableDiscoveryData>> cable_extension_;
cable_extension_;
base::Optional<std::array<uint8_t, kRpIdHashLength>> base::Optional<std::array<uint8_t, kRpIdHashLength>>
alternative_application_parameter_; alternative_application_parameter_;
}; };
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "device/fido/ble/fido_ble_discovery.h" #include "device/fido/ble/fido_ble_discovery.h"
#include "device/fido/cable/fido_cable_discovery.h"
#include "device/fido/fido_device.h" #include "device/fido/fido_device.h"
// HID is not supported on Android. // HID is not supported on Android.
...@@ -34,12 +35,9 @@ std::unique_ptr<FidoDiscovery> CreateFidoDiscoveryImpl( ...@@ -34,12 +35,9 @@ std::unique_ptr<FidoDiscovery> CreateFidoDiscoveryImpl(
#endif // !defined(OS_ANDROID) #endif // !defined(OS_ANDROID)
case FidoTransportProtocol::kBluetoothLowEnergy: case FidoTransportProtocol::kBluetoothLowEnergy:
return std::make_unique<FidoBleDiscovery>(); return std::make_unique<FidoBleDiscovery>();
// FidoCaBleDiscovery is not constructed using FidoDiscovery factory
// function and instead constructed in FidoGetAssertionRequestHandler as it
// requires extensions passed on from the relying party.
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy: case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
NOTREACHED() NOTREACHED() << "Cable discovery is constructed using the dedicated "
<< "Cable discovery is not constructed using factory method."; "factory method.";
return nullptr; return nullptr;
case FidoTransportProtocol::kNearFieldCommunication: case FidoTransportProtocol::kNearFieldCommunication:
// TODO(https://crbug.com/825949): Add NFC support. // TODO(https://crbug.com/825949): Add NFC support.
...@@ -52,6 +50,11 @@ std::unique_ptr<FidoDiscovery> CreateFidoDiscoveryImpl( ...@@ -52,6 +50,11 @@ std::unique_ptr<FidoDiscovery> CreateFidoDiscoveryImpl(
return nullptr; return nullptr;
} }
std::unique_ptr<FidoDiscovery> CreateCableDiscoveryImpl(
std::vector<CableDiscoveryData> cable_data) {
return std::make_unique<FidoCableDiscovery>(std::move(cable_data));
}
} // namespace } // namespace
FidoDiscovery::Observer::~Observer() = default; FidoDiscovery::Observer::~Observer() = default;
...@@ -60,6 +63,10 @@ FidoDiscovery::Observer::~Observer() = default; ...@@ -60,6 +63,10 @@ FidoDiscovery::Observer::~Observer() = default;
FidoDiscovery::FactoryFuncPtr FidoDiscovery::g_factory_func_ = FidoDiscovery::FactoryFuncPtr FidoDiscovery::g_factory_func_ =
&CreateFidoDiscoveryImpl; &CreateFidoDiscoveryImpl;
// static
FidoDiscovery::CableFactoryFuncPtr FidoDiscovery::g_cable_factory_func_ =
&CreateCableDiscoveryImpl;
// static // static
std::unique_ptr<FidoDiscovery> FidoDiscovery::Create( std::unique_ptr<FidoDiscovery> FidoDiscovery::Create(
FidoTransportProtocol transport, FidoTransportProtocol transport,
...@@ -67,6 +74,12 @@ std::unique_ptr<FidoDiscovery> FidoDiscovery::Create( ...@@ -67,6 +74,12 @@ std::unique_ptr<FidoDiscovery> FidoDiscovery::Create(
return (*g_factory_func_)(transport, connector); return (*g_factory_func_)(transport, connector);
} }
// static
std::unique_ptr<FidoDiscovery> FidoDiscovery::CreateCable(
std::vector<CableDiscoveryData> cable_data) {
return (*g_cable_factory_func_)(std::move(cable_data));
}
FidoDiscovery::FidoDiscovery(FidoTransportProtocol transport) FidoDiscovery::FidoDiscovery(FidoTransportProtocol transport)
: transport_(transport), weak_factory_(this) {} : transport_(transport), weak_factory_(this) {}
...@@ -168,11 +181,15 @@ ScopedFidoDiscoveryFactory::ScopedFidoDiscoveryFactory() { ...@@ -168,11 +181,15 @@ ScopedFidoDiscoveryFactory::ScopedFidoDiscoveryFactory() {
original_factory_func_ = original_factory_func_ =
std::exchange(FidoDiscovery::g_factory_func_, std::exchange(FidoDiscovery::g_factory_func_,
&ForwardCreateFidoDiscoveryToCurrentFactory); &ForwardCreateFidoDiscoveryToCurrentFactory);
original_cable_factory_func_ =
std::exchange(FidoDiscovery::g_cable_factory_func_,
&ForwardCreateCableDiscoveryToCurrentFactory);
} }
ScopedFidoDiscoveryFactory::~ScopedFidoDiscoveryFactory() { ScopedFidoDiscoveryFactory::~ScopedFidoDiscoveryFactory() {
g_current_factory = nullptr; g_current_factory = nullptr;
FidoDiscovery::g_factory_func_ = original_factory_func_; FidoDiscovery::g_factory_func_ = original_factory_func_;
FidoDiscovery::g_cable_factory_func_ = original_cable_factory_func_;
} }
// static // static
...@@ -184,6 +201,17 @@ ScopedFidoDiscoveryFactory::ForwardCreateFidoDiscoveryToCurrentFactory( ...@@ -184,6 +201,17 @@ ScopedFidoDiscoveryFactory::ForwardCreateFidoDiscoveryToCurrentFactory(
return g_current_factory->CreateFidoDiscovery(transport, connector); return g_current_factory->CreateFidoDiscovery(transport, connector);
} }
// static
std::unique_ptr<FidoDiscovery>
ScopedFidoDiscoveryFactory::ForwardCreateCableDiscoveryToCurrentFactory(
std::vector<CableDiscoveryData> cable_data) {
DCHECK(g_current_factory);
g_current_factory->set_last_cable_data(std::move(cable_data));
return g_current_factory->CreateFidoDiscovery(
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
nullptr /* connector */);
}
// static // static
ScopedFidoDiscoveryFactory* ScopedFidoDiscoveryFactory::g_current_factory = ScopedFidoDiscoveryFactory* ScopedFidoDiscoveryFactory::g_current_factory =
nullptr; nullptr;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/fido_transport_protocol.h" #include "device/fido/fido_transport_protocol.h"
namespace service_manager { namespace service_manager {
...@@ -62,14 +63,17 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscovery { ...@@ -62,14 +63,17 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscovery {
virtual void BluetoothAdapterPowerChanged(bool is_powered_on) {} virtual void BluetoothAdapterPowerChanged(bool is_powered_on) {}
}; };
// Factory function to construct an instance that discovers authenticators on // Factory functions to construct an instance that discovers authenticators on
// the given |transport| protocol. // the given |transport| protocol. The first variant is for everything except
// for cloud-assisted BLE which is handled by the second variant.
// //
// FidoTransportProtocol::kUsbHumanInterfaceDevice requires specifying a valid // FidoTransportProtocol::kUsbHumanInterfaceDevice requires specifying a valid
// |connector| on Desktop, and is not valid on Android. // |connector| on Desktop, and is not valid on Android.
static std::unique_ptr<FidoDiscovery> Create( static std::unique_ptr<FidoDiscovery> Create(
FidoTransportProtocol transport, FidoTransportProtocol transport,
::service_manager::Connector* connector); ::service_manager::Connector* connector);
static std::unique_ptr<FidoDiscovery> CreateCable(
std::vector<CableDiscoveryData> cable_data);
virtual ~FidoDiscovery(); virtual ~FidoDiscovery();
...@@ -117,7 +121,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscovery { ...@@ -117,7 +121,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscovery {
// Factory function can be overridden by tests to construct fakes. // Factory function can be overridden by tests to construct fakes.
using FactoryFuncPtr = decltype(&Create); using FactoryFuncPtr = decltype(&Create);
using CableFactoryFuncPtr = decltype(&CreateCable);
static FactoryFuncPtr g_factory_func_; static FactoryFuncPtr g_factory_func_;
static CableFactoryFuncPtr g_cable_factory_func_;
const FidoTransportProtocol transport_; const FidoTransportProtocol transport_;
State state_ = State::kIdle; State state_ = State::kIdle;
...@@ -140,7 +146,15 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ScopedFidoDiscoveryFactory { ...@@ -140,7 +146,15 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ScopedFidoDiscoveryFactory {
ScopedFidoDiscoveryFactory(); ScopedFidoDiscoveryFactory();
virtual ~ScopedFidoDiscoveryFactory(); virtual ~ScopedFidoDiscoveryFactory();
const std::vector<CableDiscoveryData>& last_cable_data() const {
return last_cable_data_;
}
protected: protected:
void set_last_cable_data(std::vector<CableDiscoveryData> cable_data) {
last_cable_data_ = std::move(cable_data);
}
virtual std::unique_ptr<FidoDiscovery> CreateFidoDiscovery( virtual std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
FidoTransportProtocol transport, FidoTransportProtocol transport,
::service_manager::Connector* connector) = 0; ::service_manager::Connector* connector) = 0;
...@@ -151,8 +165,15 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ScopedFidoDiscoveryFactory { ...@@ -151,8 +165,15 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ScopedFidoDiscoveryFactory {
FidoTransportProtocol transport, FidoTransportProtocol transport,
::service_manager::Connector* connector); ::service_manager::Connector* connector);
static std::unique_ptr<FidoDiscovery>
ForwardCreateCableDiscoveryToCurrentFactory(
std::vector<CableDiscoveryData> cable_data);
static ScopedFidoDiscoveryFactory* g_current_factory; static ScopedFidoDiscoveryFactory* g_current_factory;
FidoDiscovery::FactoryFuncPtr original_factory_func_; FidoDiscovery::FactoryFuncPtr original_factory_func_;
FidoDiscovery::CableFactoryFuncPtr original_cable_factory_func_;
std::vector<CableDiscoveryData> last_cable_data_;
DISALLOW_COPY_AND_ASSIGN(ScopedFidoDiscoveryFactory); DISALLOW_COPY_AND_ASSIGN(ScopedFidoDiscoveryFactory);
}; };
......
...@@ -144,6 +144,14 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP( ...@@ -144,6 +144,14 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP(
return transports; return transports;
} }
base::flat_set<FidoTransportProtocol> GetTransportsAllowedAndConfiguredByRP(
const CtapGetAssertionRequest& request) {
auto transports = GetTransportsAllowedByRP(request);
if (!request.cable_extension())
transports.erase(FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
return transports;
}
} // namespace } // namespace
GetAssertionRequestHandler::GetAssertionRequestHandler( GetAssertionRequestHandler::GetAssertionRequestHandler(
...@@ -155,7 +163,7 @@ GetAssertionRequestHandler::GetAssertionRequestHandler( ...@@ -155,7 +163,7 @@ GetAssertionRequestHandler::GetAssertionRequestHandler(
connector, connector,
base::STLSetIntersection<base::flat_set<FidoTransportProtocol>>( base::STLSetIntersection<base::flat_set<FidoTransportProtocol>>(
supported_transports, supported_transports,
GetTransportsAllowedByRP(request)), GetTransportsAllowedAndConfiguredByRP(request)),
std::move(completion_callback)), std::move(completion_callback)),
request_(std::move(request)), request_(std::move(request)),
weak_factory_(this) { weak_factory_(this) {
...@@ -165,10 +173,9 @@ GetAssertionRequestHandler::GetAssertionRequestHandler( ...@@ -165,10 +173,9 @@ GetAssertionRequestHandler::GetAssertionRequestHandler(
if (base::ContainsKey( if (base::ContainsKey(
transport_availability_info().available_transports, transport_availability_info().available_transports,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy) && FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy)) {
request_.cable_extension()) { DCHECK(request_.cable_extension());
auto discovery = auto discovery = FidoDiscovery::CreateCable(*request_.cable_extension());
std::make_unique<FidoCableDiscovery>(*request_.cable_extension());
discovery->set_observer(this); discovery->set_observer(this);
discoveries().push_back(std::move(discovery)); discoveries().push_back(std::move(discovery));
} }
......
...@@ -39,15 +39,6 @@ using TestMakeCredentialRequestCallback = test::StatusAndValuesCallbackReceiver< ...@@ -39,15 +39,6 @@ using TestMakeCredentialRequestCallback = test::StatusAndValuesCallbackReceiver<
base::Optional<AuthenticatorMakeCredentialResponse>, base::Optional<AuthenticatorMakeCredentialResponse>,
FidoTransportProtocol>; FidoTransportProtocol>;
// Returns the set of transport protocols that are safe to test with. Because
// FidoCableDiscovery cannot be faked out, and attempting to start the real
// thing would flakily work/fail depending on the environment, avoid testing.
base::flat_set<FidoTransportProtocol> GetTestableTransportProtocols() {
auto transports = GetAllTransportProtocols();
transports.erase(FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
return transports;
}
} // namespace } // namespace
class FidoMakeCredentialHandlerTest : public ::testing::Test { class FidoMakeCredentialHandlerTest : public ::testing::Test {
...@@ -111,12 +102,6 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test { ...@@ -111,12 +102,6 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
::testing::UnorderedElementsAreArray(transports)); ::testing::UnorderedElementsAreArray(transports));
} }
void ExpectAllTransportsAreAllowedForRequest(
MakeCredentialRequestHandler* request_handler) {
ExpectAllowedTransportsForRequestAre(request_handler,
GetTestableTransportProtocols());
}
void InitFeatureListAndDisableCtapFlag() { void InitFeatureListAndDisableCtapFlag() {
scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device); scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device);
} }
...@@ -154,7 +139,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test { ...@@ -154,7 +139,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
std::unique_ptr<MockFidoDevice> mock_platform_device_; std::unique_ptr<MockFidoDevice> mock_platform_device_;
TestMakeCredentialRequestCallback cb_; TestMakeCredentialRequestCallback cb_;
base::flat_set<FidoTransportProtocol> supported_transports_ = base::flat_set<FidoTransportProtocol> supported_transports_ =
GetTestableTransportProtocols(); GetAllTransportProtocols();
}; };
TEST_F(FidoMakeCredentialHandlerTest, TransportAvailabilityInfo) { TEST_F(FidoMakeCredentialHandlerTest, TransportAvailabilityInfo) {
...@@ -287,6 +272,7 @@ TEST_F(FidoMakeCredentialHandlerTest, AnyAttachment) { ...@@ -287,6 +272,7 @@ TEST_F(FidoMakeCredentialHandlerTest, AnyAttachment) {
scoped_task_environment_.FastForwardUntilNoTasksRemain(); scoped_task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_FALSE(callback().was_called()); EXPECT_FALSE(callback().was_called());
// kCloudAssistedBluetoothLowEnergy not yet supported for MakeCredential.
ExpectAllowedTransportsForRequestAre( ExpectAllowedTransportsForRequestAre(
request_handler.get(), {FidoTransportProtocol::kBluetoothLowEnergy, request_handler.get(), {FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication, FidoTransportProtocol::kNearFieldCommunication,
...@@ -302,6 +288,7 @@ TEST_F(FidoMakeCredentialHandlerTest, CrossPlatformAttachment) { ...@@ -302,6 +288,7 @@ TEST_F(FidoMakeCredentialHandlerTest, CrossPlatformAttachment) {
false /* require_resident_key */, false /* require_resident_key */,
UserVerificationRequirement::kPreferred)); UserVerificationRequirement::kPreferred));
// kCloudAssistedBluetoothLowEnergy not yet supported for MakeCredential.
ExpectAllowedTransportsForRequestAre( ExpectAllowedTransportsForRequestAre(
request_handler.get(), {FidoTransportProtocol::kBluetoothLowEnergy, request_handler.get(), {FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication, FidoTransportProtocol::kNearFieldCommunication,
......
...@@ -68,16 +68,16 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP( ...@@ -68,16 +68,16 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP(
case AttachmentType::kPlatform: case AttachmentType::kPlatform:
return {FidoTransportProtocol::kInternal}; return {FidoTransportProtocol::kInternal};
case AttachmentType::kCrossPlatform: case AttachmentType::kCrossPlatform:
// Cloud-assisted BLE is not yet supported for MakeCredential requests.
return {FidoTransportProtocol::kUsbHumanInterfaceDevice, return {FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy, FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication, FidoTransportProtocol::kNearFieldCommunication};
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy};
case AttachmentType::kAny: case AttachmentType::kAny:
// Cloud-assisted BLE is not yet supported for MakeCredential requests.
return {FidoTransportProtocol::kInternal, return {FidoTransportProtocol::kInternal,
FidoTransportProtocol::kNearFieldCommunication, FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kUsbHumanInterfaceDevice, FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy, FidoTransportProtocol::kBluetoothLowEnergy};
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy};
} }
NOTREACHED(); NOTREACHED();
......
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