Commit 02daf76f authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

webauthn: add support for caBLE over USB.

This change adds desktop-side, disabled-by-default, preliminary support
for communicating with phones over USB so that they can act as a
security key. This requires phone-side changes too that are forthcoming.

Android supports an “accessory” mode[1] that allows USB communication with
apps on the phone. This involves sending vendor commands to the device
to request that it switch into this mode and then watching the USB bus
for the device to reappear in the new configuration. Once that's
complete, data can be exchanged.

There's no good way, however, of knowing which USB devices are phones.
And it seems unwise to blast vendor commands at every attached USB
device each time we start a WebAuthn transaction. Therefore this is only
attempted for devices that are connected during the transaction. We do,
however, remember which accessory devices we previously configured and
can use them immediately if still connected.

In the future, the UI could plausibly allow the user to select the
device from a list rather than connect it. Although I'm unsure whether
that's actually useful.

[1] https://source.android.com/devices/accessories/aoa

BUG=1002262

Change-Id: Ia58632d89c83a60559b59146d69bd2638a597f59
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2310193
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#795034}
parent 03fc8301
......@@ -28,6 +28,8 @@ int GetMessageIdForTransportOnTransportSelectionSheet(
return IDS_WEBAUTHN_TRANSPORT_INTERNAL;
case AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy:
return IDS_WEBAUTHN_TRANSPORT_CABLE;
case AuthenticatorTransport::kAndroidAccessory:
return IDS_WEBAUTHN_TRANSPORT_USB;
}
NOTREACHED();
return 0;
......@@ -48,6 +50,8 @@ int GetMessageIdForTransportOnOtherTransportsPopup(
return IDS_WEBAUTHN_TRANSPORT_POPUP_INTERNAL;
case AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy:
return IDS_WEBAUTHN_TRANSPORT_POPUP_CABLE;
case AuthenticatorTransport::kAndroidAccessory:
return IDS_WEBAUTHN_TRANSPORT_POPUP_USB;
}
NOTREACHED();
return 0;
......@@ -81,6 +85,8 @@ const gfx::VectorIcon* GetTransportVectorIcon(
return &kFingerprintIcon;
case AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy:
return &kSmartphoneIcon;
case AuthenticatorTransport::kAndroidAccessory:
return &kSmartphoneIcon;
}
NOTREACHED();
return &kFingerprintIcon;
......
......@@ -28,6 +28,7 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "device/fido/features.h"
......@@ -323,6 +324,11 @@ void ChromeAuthenticatorRequestDelegate::ConfigureCable(
auto paired_phones = GetCablePairings();
have_paired_phones = !paired_phones.empty();
pairings.insert(pairings.end(), paired_phones.begin(), paired_phones.end());
mojo::Remote<device::mojom::UsbDeviceManager> usb_device_manager;
content::GetDeviceService().BindUsbDeviceManager(
usb_device_manager.BindNewPipeAndPassReceiver());
discovery_factory()->set_usb_device_manager(std::move(usb_device_manager));
}
if (pairings.empty() && !qr_generator_key) {
......
......@@ -26,6 +26,7 @@
#include "content/browser/webauth/webauth_request_security_checker.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/is_uvpaa.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
......@@ -520,6 +521,10 @@ base::flat_set<device::FidoTransportProtocol> GetAvailableTransports(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
}
if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
transports.insert(device::FidoTransportProtocol::kAndroidAccessory);
}
return transports;
}
......
......@@ -24,6 +24,8 @@ EnumTraits<blink::mojom::AuthenticatorTransport,
return blink::mojom::AuthenticatorTransport::CABLE;
case ::device::FidoTransportProtocol::kInternal:
return blink::mojom::AuthenticatorTransport::INTERNAL;
case ::device::FidoTransportProtocol::kAndroidAccessory:
return blink::mojom::AuthenticatorTransport::CABLE;
}
NOTREACHED();
return blink::mojom::AuthenticatorTransport::USB;
......
......@@ -69,6 +69,10 @@ component("fido") {
# Android implementation of FIDO is delegated to GMSCore.
if (!is_android) {
sources += [
"aoa/android_accessory_device.cc",
"aoa/android_accessory_device.h",
"aoa/android_accessory_discovery.cc",
"aoa/android_accessory_discovery.h",
"attestation_object.cc",
"attestation_object.h",
"attestation_statement.cc",
......@@ -183,7 +187,9 @@ component("fido") {
deps += [
"//services/device/public/cpp/hid",
"//services/device/public/cpp/usb",
"//services/device/public/mojom",
"//services/device/public/mojom:usb",
]
}
......
// 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/aoa/android_accessory_device.h"
#include <limits>
#include <utility>
#include "base/bind.h"
#include "base/notreached.h"
#include "base/optional.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "components/device_event_log/device_event_log.h"
namespace device {
static constexpr unsigned kTimeoutMilliseconds = 1000;
static constexpr unsigned kLongTimeoutMilliseconds = 90 * 1000;
AndroidAccessoryDevice::AndroidAccessoryDevice(
mojo::Remote<mojom::UsbDevice> device,
uint8_t in_endpoint,
uint8_t out_endpoint)
: device_(std::move(device)),
in_endpoint_(in_endpoint),
out_endpoint_(out_endpoint) {
base::RandBytes(id_, sizeof(id_));
}
AndroidAccessoryDevice::~AndroidAccessoryDevice() = default;
FidoDevice::CancelToken AndroidAccessoryDevice::DeviceTransact(
std::vector<uint8_t> command,
DeviceCallback callback) {
if (static_cast<uint64_t>(command.size()) >
std::numeric_limits<uint32_t>::max()) {
NOTREACHED();
std::move(callback).Run(base::nullopt);
return 0;
}
uint8_t prefix[1 + sizeof(uint32_t)];
prefix[0] = kCoaoaMsg;
const uint32_t size32 = static_cast<uint32_t>(command.size());
memcpy(&prefix[1], &size32, sizeof(size32));
command.insert(command.begin(), prefix, &prefix[sizeof(prefix)]);
device_->GenericTransferOut(
out_endpoint_, std::move(command), kTimeoutMilliseconds,
base::BindOnce(&AndroidAccessoryDevice::OnWriteComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
return 0;
}
void AndroidAccessoryDevice::OnWriteComplete(DeviceCallback callback,
mojom::UsbTransferStatus result) {
if (result != mojom::UsbTransferStatus::COMPLETED) {
FIDO_LOG(ERROR) << "Failed to write to USB device ("
<< static_cast<int>(result) << ").";
std::move(callback).Run(base::nullopt);
return;
}
device_->GenericTransferIn(
in_endpoint_, 1 + sizeof(uint32_t), kLongTimeoutMilliseconds,
base::BindOnce(&AndroidAccessoryDevice::OnReadLengthComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void AndroidAccessoryDevice::OnReadLengthComplete(
DeviceCallback callback,
mojom::UsbTransferStatus result,
const std::vector<uint8_t>& payload) {
if (result != mojom::UsbTransferStatus::COMPLETED ||
payload.size() != 1 + sizeof(uint32_t)) {
FIDO_LOG(ERROR) << "Failed to read reply from USB device ("
<< static_cast<int>(result) << ")";
std::move(callback).Run(base::nullopt);
return;
}
if (payload[0] != kCoaoaMsg) {
FIDO_LOG(ERROR) << "Reply from USB device with wrong type ("
<< static_cast<int>(payload[0]) << ")";
std::move(callback).Run(base::nullopt);
return;
}
uint32_t length;
memcpy(&length, &payload[1], sizeof(length));
if (length > (1 << 20)) {
FIDO_LOG(ERROR) << "USB device sent excessive reply containing " << length
<< " bytes";
std::move(callback).Run(base::nullopt);
return;
}
buffer_.clear();
buffer_.reserve(length);
if (length == 0) {
std::move(callback).Run(std::move(buffer_));
return;
}
device_->GenericTransferIn(
in_endpoint_, length, kTimeoutMilliseconds,
base::BindOnce(&AndroidAccessoryDevice::OnReadComplete,
weak_factory_.GetWeakPtr(), std::move(callback), length));
}
void AndroidAccessoryDevice::OnReadComplete(
DeviceCallback callback,
const uint32_t length,
mojom::UsbTransferStatus result,
const std::vector<uint8_t>& payload) {
if (result != mojom::UsbTransferStatus::COMPLETED ||
payload.size() + buffer_.size() > length) {
FIDO_LOG(ERROR) << "Failed to read from USB device ("
<< static_cast<int>(result) << ")";
std::move(callback).Run(base::nullopt);
return;
}
buffer_.insert(buffer_.end(), payload.begin(), payload.end());
if (buffer_.size() == length) {
std::move(callback).Run(std::move(buffer_));
return;
}
device_->GenericTransferIn(
in_endpoint_, length - buffer_.size(), kTimeoutMilliseconds,
base::BindOnce(&AndroidAccessoryDevice::OnReadComplete,
weak_factory_.GetWeakPtr(), std::move(callback), length));
}
void AndroidAccessoryDevice::Cancel(CancelToken token) {}
std::string AndroidAccessoryDevice::GetId() const {
return "aoa-" + base::HexEncode(id_);
}
FidoTransportProtocol AndroidAccessoryDevice::DeviceTransport() const {
return FidoTransportProtocol::kAndroidAccessory;
}
base::WeakPtr<FidoDevice> AndroidAccessoryDevice::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
} // 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_AOA_ANDROID_ACCESSORY_DEVICE_H_
#define DEVICE_FIDO_AOA_ANDROID_ACCESSORY_DEVICE_H_
#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "device/fido/fido_device.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/usb_device.mojom.h"
namespace device {
// AndroidAccessoryDevice sends CTAP messages over USB to a given device.
class COMPONENT_EXPORT(DEVICE_FIDO) AndroidAccessoryDevice : public FidoDevice {
public:
// These enum values are magic values on the wire that indicate a
// synchronisation message and a CTAP2 message, respectively.
enum {
kCoaoaSync = 119,
kCoaoaMsg = 33,
};
AndroidAccessoryDevice(mojo::Remote<device::mojom::UsbDevice> device,
uint8_t in_endpoint,
uint8_t out_endpoint);
~AndroidAccessoryDevice() override;
// FidoDevice:
CancelToken DeviceTransact(std::vector<uint8_t> command,
DeviceCallback callback) override;
void Cancel(CancelToken token) override;
std::string GetId() const override;
FidoTransportProtocol DeviceTransport() const override;
base::WeakPtr<FidoDevice> GetWeakPtr() override;
private:
void OnWriteComplete(DeviceCallback callback,
device::mojom::UsbTransferStatus result);
void OnReadLengthComplete(DeviceCallback callback,
device::mojom::UsbTransferStatus result,
const std::vector<uint8_t>& payload);
void OnReadComplete(DeviceCallback callback,
const uint32_t length,
device::mojom::UsbTransferStatus result,
const std::vector<uint8_t>& payload);
mojo::Remote<device::mojom::UsbDevice> device_;
const uint8_t in_endpoint_;
const uint8_t out_endpoint_;
uint8_t id_[8];
std::vector<uint8_t> buffer_;
base::WeakPtrFactory<AndroidAccessoryDevice> weak_factory_{this};
};
} // namespace device
#endif // DEVICE_FIDO_AOA_ANDROID_ACCESSORY_DEVICE_H_
This diff is collapsed.
// 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_AOA_ANDROID_ACCESSORY_DISCOVERY_H_
#define DEVICE_FIDO_AOA_ANDROID_ACCESSORY_DISCOVERY_H_
#include <array>
#include <memory>
#include <tuple>
#include <vector>
#include "base/callback.h"
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "device/fido/fido_device_discovery.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
#include "services/device/public/mojom/usb_manager_client.mojom.h"
namespace device {
// AndroidAccessoryDiscovery watches for USB devices that are inserted during
// its lifetime and tries sending AOA[1] commands to them in case they are a
// phone that can speak CTAP over the accessory protocol.
//
// [1] https://source.android.com/devices/accessories/aoa
class COMPONENT_EXPORT(DEVICE_FIDO) AndroidAccessoryDiscovery
: public FidoDeviceDiscovery,
device::mojom::UsbDeviceManagerClient {
public:
// InterfaceInfo contains the results of evaluating the USB metadata from an
// accessory device.
struct InterfaceInfo {
// configuration is the USB configuration number that contains the AOA
// interface.
uint8_t configuration;
// interface is the interface number of the AOA interface.
uint8_t interface;
// in_endpoint and out_endpoint are the endpoint numbers for AOA.
uint8_t in_endpoint;
uint8_t out_endpoint;
// guid is the identifier assigned by Chromium's USB layer to this specific
// USB connection.
std::string guid;
};
explicit AndroidAccessoryDiscovery(
mojo::Remote<device::mojom::UsbDeviceManager>);
~AndroidAccessoryDiscovery() override;
private:
static constexpr size_t kSyncNonceLength = 16;
static constexpr size_t kSyncMessageLength =
sizeof(uint8_t) + AndroidAccessoryDiscovery::kSyncNonceLength;
// FidoDeviceDiscovery:
void StartInternal() override;
// device::mojom::UsbDeviceManagerClient:
void OnDeviceAdded(device::mojom::UsbDeviceInfoPtr device_info) override;
void OnDeviceRemoved(device::mojom::UsbDeviceInfoPtr device_info) override;
void OnGetDevices(std::vector<device::mojom::UsbDeviceInfoPtr> devices);
void OnOpen(mojo::Remote<device::mojom::UsbDevice> device,
device::mojom::UsbOpenDeviceError error);
void OnVersionReply(mojo::Remote<device::mojom::UsbDevice> device,
device::mojom::UsbTransferStatus status,
const std::vector<uint8_t>& payload);
void OnConfigurationStepComplete(
mojo::Remote<device::mojom::UsbDevice> device,
unsigned step,
device::mojom::UsbTransferStatus status);
void HandleAccessoryDevice(mojo::Remote<device::mojom::UsbDevice> device,
device::mojom::UsbDeviceInfoPtr device_info);
void OnAccessoryConfigured(mojo::Remote<device::mojom::UsbDevice> device,
InterfaceInfo interface_info,
bool success);
void OnOpenAccessory(mojo::Remote<device::mojom::UsbDevice> device,
device::mojom::UsbDeviceInfoPtr device_info,
InterfaceInfo interface_info,
device::mojom::UsbOpenDeviceError error);
void OnSyncWritten(mojo::Remote<device::mojom::UsbDevice> device,
InterfaceInfo interface_info,
std::array<uint8_t, kSyncNonceLength> nonce,
mojom::UsbTransferStatus result);
void OnReadComplete(mojo::Remote<device::mojom::UsbDevice> device,
InterfaceInfo interface_info,
std::array<uint8_t, kSyncNonceLength> nonce,
mojom::UsbTransferStatus result,
const std::vector<uint8_t>& payload);
void OnAccessoryInterfaceClaimed(
mojo::Remote<device::mojom::UsbDevice> device,
InterfaceInfo interface_info,
bool success);
mojo::Remote<device::mojom::UsbDeviceManager> device_manager_;
mojo::AssociatedReceiver<device::mojom::UsbDeviceManagerClient> receiver_{
this};
base::WeakPtrFactory<AndroidAccessoryDiscovery> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AndroidAccessoryDiscovery);
};
} // namespace device
#endif // DEVICE_FIDO_AOA_ANDROID_ACCESSORY_DISCOVERY_H_
......@@ -88,6 +88,7 @@ std::unique_ptr<FidoDiscoveryBase> FakeFidoDiscoveryFactory::Create(
case FidoTransportProtocol::kNearFieldCommunication:
return std::move(next_nfc_discovery_);
case FidoTransportProtocol::kBluetoothLowEnergy:
case FidoTransportProtocol::kAndroidAccessory:
return nullptr;
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
return std::move(next_cable_discovery_);
......
......@@ -356,6 +356,12 @@ constexpr uint8_t kP1CheckOnly = 0x07;
constexpr uint8_t kP1IndividualAttestation = 0x80;
constexpr size_t kMaxKeyHandleLength = 255;
// kCableOverAOAVersion is a magic value that is sent as the "version" in an
// Android AOA[1] configuration to identity a security-key request.
//
// [1] https://source.android.com/devices/accessories/aoa
constexpr char kCableOverAOAVersion[] = "12eba9f901039b36";
// Maximum wait time before client error outs on device.
COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kDeviceTimeout;
......
......@@ -6,6 +6,7 @@
#include "base/notreached.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/fido/aoa/android_accessory_discovery.h"
#include "device/fido/cable/fido_cable_discovery.h"
#include "device/fido/features.h"
#include "device/fido/fido_discovery_base.h"
......@@ -71,6 +72,12 @@ std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
#else
return nullptr;
#endif
case FidoTransportProtocol::kAndroidAccessory:
if (usb_device_manager_) {
return std::make_unique<AndroidAccessoryDiscovery>(
std::move(usb_device_manager_.value()));
}
return nullptr;
}
NOTREACHED() << "Unhandled transport type";
return nullptr;
......@@ -83,6 +90,11 @@ void FidoDiscoveryFactory::set_cable_data(
qr_generator_key_ = std::move(qr_generator_key);
}
void FidoDiscoveryFactory::set_usb_device_manager(
mojo::Remote<device::mojom::UsbDeviceManager> usb_device_manager) {
usb_device_manager_.emplace(std::move(usb_device_manager));
}
void FidoDiscoveryFactory::set_cable_pairing_callback(
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>
pairing_callback) {
......
......@@ -16,6 +16,8 @@
#include "device/fido/fido_discovery_base.h"
#include "device/fido/fido_request_handler_base.h"
#include "device/fido/fido_transport_protocol.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
#if defined(OS_MAC)
#include "device/fido/mac/authenticator_config.h"
......@@ -44,6 +46,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
void set_cable_data(std::vector<CableDiscoveryData> cable_data,
base::Optional<QRGeneratorKey> qr_generator_key);
void set_usb_device_manager(mojo::Remote<device::mojom::UsbDeviceManager>);
// set_cable_pairing_callback installs a repeating callback that will be
// called when a QR handshake results in a phone wishing to pair with this
// browser.
......@@ -78,6 +82,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
#if defined(OS_MAC)
base::Optional<fido::mac::AuthenticatorConfig> mac_touch_id_config_;
#endif // defined(OS_MAC)
base::Optional<mojo::Remote<device::mojom::UsbDeviceManager>>
usb_device_manager_;
base::Optional<std::vector<CableDiscoveryData>> cable_data_;
base::Optional<QRGeneratorKey> qr_generator_key_;
base::Optional<
......
......@@ -14,14 +14,6 @@ const char kBluetoothLowEnergy[] = "ble";
const char kCloudAssistedBluetoothLowEnergy[] = "cable";
const char kInternal[] = "internal";
base::flat_set<FidoTransportProtocol> GetAllTransportProtocols() {
return {FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kInternal};
}
base::Optional<FidoTransportProtocol> ConvertToFidoTransportProtocol(
base::StringPiece protocol) {
if (protocol == kUsbHumanInterfaceDevice)
......@@ -51,6 +43,10 @@ std::string ToString(FidoTransportProtocol protocol) {
return kCloudAssistedBluetoothLowEnergy;
case FidoTransportProtocol::kInternal:
return kInternal;
case FidoTransportProtocol::kAndroidAccessory:
// The Android accessory transport is not exposed to the outside world and
// is considered a flavour of caBLE.
return kCloudAssistedBluetoothLowEnergy;
}
NOTREACHED();
return "";
......
......@@ -25,7 +25,8 @@ enum class FidoTransportProtocol : uint8_t {
kBluetoothLowEnergy = 2,
kCloudAssistedBluetoothLowEnergy = 3,
kInternal = 4,
kMaxValue = kInternal,
kAndroidAccessory = 5,
kMaxValue = kAndroidAccessory,
};
// String representation of above FidoTransportProtocol enum.
......@@ -35,9 +36,6 @@ extern const char kBluetoothLowEnergy[];
extern const char kCloudAssistedBluetoothLowEnergy[];
extern const char kInternal[];
COMPONENT_EXPORT(DEVICE_FIDO)
base::flat_set<FidoTransportProtocol> GetAllTransportProtocols();
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<FidoTransportProtocol> ConvertToFidoTransportProtocol(
base::StringPiece protocol);
......
......@@ -17,6 +17,7 @@
#include "components/cbor/diagnostic_writer.h"
#include "components/device_event_log/device_event_log.h"
#include "device/fido/cable/fido_cable_discovery.h"
#include "device/fido/features.h"
#include "device/fido/fido_authenticator.h"
#include "device/fido/fido_discovery_factory.h"
#include "device/fido/fido_parsing_utils.h"
......@@ -189,7 +190,9 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP(
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy};
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
FidoTransportProtocol::kAndroidAccessory,
};
const auto& allowed_list = request.allow_list;
if (allowed_list.empty()) {
......@@ -198,12 +201,17 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP(
base::flat_set<FidoTransportProtocol> transports;
for (const auto& credential : allowed_list) {
if (credential.transports().empty())
if (credential.transports().empty()) {
return kAllTransports;
}
transports.insert(credential.transports().begin(),
credential.transports().end());
}
if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
transports.insert(device::FidoTransportProtocol::kAndroidAccessory);
}
return transports;
}
......
......@@ -143,8 +143,12 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
scoped_refptr<::testing::NiceMock<MockBluetoothAdapter>> mock_adapter_;
std::unique_ptr<MockFidoDevice> pending_mock_platform_device_;
TestMakeCredentialRequestCallback cb_;
base::flat_set<FidoTransportProtocol> supported_transports_ =
GetAllTransportProtocols();
base::flat_set<FidoTransportProtocol> supported_transports_ = {
FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kInternal,
};
};
TEST_F(FidoMakeCredentialHandlerTest, TransportAvailabilityInfo) {
......
......@@ -167,16 +167,22 @@ base::flat_set<FidoTransportProtocol> GetTransportsAllowedByRP(
case AuthenticatorAttachment::kPlatform:
return {FidoTransportProtocol::kInternal};
case AuthenticatorAttachment::kCrossPlatform:
return {FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy};
return {
FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
FidoTransportProtocol::kAndroidAccessory,
};
case AuthenticatorAttachment::kAny:
return {FidoTransportProtocol::kInternal,
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy};
return {
FidoTransportProtocol::kInternal,
FidoTransportProtocol::kNearFieldCommunication,
FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy,
FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
FidoTransportProtocol::kAndroidAccessory,
};
}
NOTREACHED();
......
......@@ -470,6 +470,9 @@ VirtualFidoDevice::GenerateAttestationCertificate(
case FidoTransportProtocol::kInternal:
transport_bit = 4;
break;
case FidoTransportProtocol::kAndroidAccessory:
transport_bit = 1;
break;
}
const uint8_t kTransportTypesContents[] = {
3, // BIT STRING
......
......@@ -151,6 +151,7 @@ static uint32_t ToWinTransportsMask(
result |= WEBAUTHN_CTAP_TRANSPORT_BLE;
break;
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
case FidoTransportProtocol::kAndroidAccessory:
// caBLE is unsupported by the Windows API.
break;
case FidoTransportProtocol::kInternal:
......
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