diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-13 16:23:34 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-14 10:37:21 +0000 |
commit | 38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch) | |
tree | c4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/device/fido | |
parent | e684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff) | |
download | qtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz |
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/device/fido')
38 files changed, 443 insertions, 395 deletions
diff --git a/chromium/device/fido/ble/fido_ble_connection.cc b/chromium/device/fido/ble/fido_ble_connection.cc index 32291b6bc05..bce6047d0ae 100644 --- a/chromium/device/fido/ble/fido_ble_connection.cc +++ b/chromium/device/fido/ble/fido_ble_connection.cc @@ -100,7 +100,10 @@ const BluetoothRemoteGattService* GetFidoService( } for (const auto* service : device->GetGattServices()) { - if (service->GetUUID() == BluetoothUUID(kFidoServiceUUID)) + // This assumes that no device is representing as both a FIDO BLE + // and a caBLE device. + if (service->GetUUID() == BluetoothUUID(kFidoServiceUUID) || + service->GetUUID() == BluetoothUUID(kCableAdvertisementUUID128)) return service; } diff --git a/chromium/device/fido/ble/fido_ble_discovery_base.cc b/chromium/device/fido/ble/fido_ble_discovery_base.cc index 19c24c12d08..ea15fc74eec 100644 --- a/chromium/device/fido/ble/fido_ble_discovery_base.cc +++ b/chromium/device/fido/ble/fido_ble_discovery_base.cc @@ -7,7 +7,6 @@ #include <utility> #include "base/bind.h" -#include "base/callback_helpers.h" #include "base/location.h" #include "base/no_destructor.h" #include "base/threading/thread_task_runner_handle.h" @@ -83,9 +82,8 @@ void FidoBleDiscoveryBase::OnGetAdapter( } void FidoBleDiscoveryBase::StartInternal() { - BluetoothAdapterFactory::Get().GetAdapter( - base::AdaptCallbackForRepeating(base::BindOnce( - &FidoBleDiscoveryBase::OnGetAdapter, weak_factory_.GetWeakPtr()))); + BluetoothAdapterFactory::Get().GetAdapter(base::BindOnce( + &FidoBleDiscoveryBase::OnGetAdapter, weak_factory_.GetWeakPtr())); } } // namespace device diff --git a/chromium/device/fido/ble_adapter_manager.cc b/chromium/device/fido/ble_adapter_manager.cc index 12f2aaf63b4..13b957660ee 100644 --- a/chromium/device/fido/ble_adapter_manager.cc +++ b/chromium/device/fido/ble_adapter_manager.cc @@ -15,8 +15,8 @@ namespace device { BleAdapterManager::BleAdapterManager(FidoRequestHandlerBase* request_handler) : request_handler_(request_handler), weak_factory_(this) { - BluetoothAdapterFactory::Get().GetAdapter(base::BindRepeating( - &BleAdapterManager::Start, weak_factory_.GetWeakPtr())); + BluetoothAdapterFactory::Get().GetAdapter( + base::BindOnce(&BleAdapterManager::Start, weak_factory_.GetWeakPtr())); } BleAdapterManager::~BleAdapterManager() { diff --git a/chromium/device/fido/ctap_make_credential_request.cc b/chromium/device/fido/ctap_make_credential_request.cc index 256aa28ccaf..b01aff6f625 100644 --- a/chromium/device/fido/ctap_make_credential_request.cc +++ b/chromium/device/fido/ctap_make_credential_request.cc @@ -133,13 +133,6 @@ CtapMakeCredentialRequest& CtapMakeCredentialRequest::SetPinProtocol( return *this; } -CtapMakeCredentialRequest& -CtapMakeCredentialRequest::SetIsIndividualAttestation( - bool is_individual_attestation) { - is_individual_attestation_ = is_individual_attestation; - return *this; -} - CtapMakeCredentialRequest& CtapMakeCredentialRequest::SetHmacSecret( bool hmac_secret) { hmac_secret_ = hmac_secret; diff --git a/chromium/device/fido/ctap_make_credential_request.h b/chromium/device/fido/ctap_make_credential_request.h index d639b0ada8f..80500544a9d 100644 --- a/chromium/device/fido/ctap_make_credential_request.h +++ b/chromium/device/fido/ctap_make_credential_request.h @@ -55,8 +55,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest { std::vector<PublicKeyCredentialDescriptor> exclude_list); CtapMakeCredentialRequest& SetPinAuth(std::vector<uint8_t> pin_auth); CtapMakeCredentialRequest& SetPinProtocol(uint8_t pin_protocol); - CtapMakeCredentialRequest& SetIsIndividualAttestation( - bool is_individual_attestation); CtapMakeCredentialRequest& SetHmacSecret(bool hmac_secret); const std::string& client_data_json() const { return client_data_json_; } @@ -75,7 +73,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest { return authenticator_attachment_; } bool resident_key_required() const { return resident_key_required_; } - bool is_individual_attestation() const { return is_individual_attestation_; } bool hmac_secret() const { return hmac_secret_; } const base::Optional<std::vector<PublicKeyCredentialDescriptor>>& exclude_list() const { @@ -93,6 +90,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest { is_incognito_mode_ = is_incognito_mode; } + AttestationConveyancePreference attestation_preference() const { + return attestation_preference_; + } + void set_attestation_preference( + AttestationConveyancePreference attestation_preference) { + attestation_preference_ = attestation_preference; + } + private: std::string client_data_json_; std::array<uint8_t, kClientDataHashLength> client_data_hash_; @@ -104,7 +109,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest { AuthenticatorAttachment authenticator_attachment_ = AuthenticatorAttachment::kAny; bool resident_key_required_ = false; - bool is_individual_attestation_ = false; // hmac_secret_ indicates whether the "hmac-secret" extension should be // asserted to CTAP2 authenticators. bool hmac_secret_ = false; @@ -117,6 +121,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest { base::Optional<std::vector<PublicKeyCredentialDescriptor>> exclude_list_; base::Optional<std::vector<uint8_t>> pin_auth_; base::Optional<uint8_t> pin_protocol_; + AttestationConveyancePreference attestation_preference_ = + AttestationConveyancePreference::NONE; }; } // namespace device diff --git a/chromium/device/fido/ctap_response_unittest.cc b/chromium/device/fido/ctap_response_unittest.cc index 609965c945e..aa5a4031864 100644 --- a/chromium/device/fido/ctap_response_unittest.cc +++ b/chromium/device/fido/ctap_response_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/stl_util.h" #include "components/cbor/reader.h" #include "components/cbor/values.h" #include "components/cbor/writer.h" @@ -298,7 +299,7 @@ std::vector<uint8_t> GetTestSignResponse() { // Get a subset of the response for testing error handling. std::vector<uint8_t> GetTestCorruptedSignResponse(size_t length) { - DCHECK_LE(length, arraysize(test_data::kTestU2fSignResponse)); + DCHECK_LE(length, base::size(test_data::kTestU2fSignResponse)); return fido_parsing_utils::Materialize(fido_parsing_utils::ExtractSpan( test_data::kTestU2fSignResponse, 0, length)); } diff --git a/chromium/device/fido/features.cc b/chromium/device/fido/features.cc index dad7f0d1335..ea36b7b66fb 100644 --- a/chromium/device/fido/features.cc +++ b/chromium/device/fido/features.cc @@ -13,18 +13,10 @@ namespace device { // Controls whether on Windows, U2F/CTAP2 requests are forwarded to the // native WebAuthentication API, where available. const base::Feature kWebAuthUseNativeWinApi{"WebAuthenticationUseNativeWinApi", - base::FEATURE_DISABLED_BY_DEFAULT}; - -// If true, the minimum API version check for integration with the native -// Windows WebAuthentication API is disabled. This is an interim solution for -// for manual testing while we await the release of a DLL that implements the -// version check. -const base::Feature kWebAuthDisableWinApiVersionCheckForTesting{ - "WebAuthenticationDisableWinApiVersionCheckForTesting", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #endif // defined(OS_WIN) extern const base::Feature kWebAuthProxyCryptotoken{ - "WebAuthenticationProxyCryptotoken", base::FEATURE_DISABLED_BY_DEFAULT}; + "WebAuthenticationProxyCryptotoken", base::FEATURE_ENABLED_BY_DEFAULT}; } // namespace device diff --git a/chromium/device/fido/features.h b/chromium/device/fido/features.h index dbcb880d0c6..1ed614c7a6e 100644 --- a/chromium/device/fido/features.h +++ b/chromium/device/fido/features.h @@ -14,9 +14,6 @@ namespace device { #if defined(OS_WIN) COMPONENT_EXPORT(DEVICE_FIDO) extern const base::Feature kWebAuthUseNativeWinApi; - -COMPONENT_EXPORT(DEVICE_FIDO) -extern const base::Feature kWebAuthDisableWinApiVersionCheckForTesting; #endif // defined(OS_WIN) // Controls the proxying of Cryptotoken requests through WebAuthn. diff --git a/chromium/device/fido/fido_constants.cc b/chromium/device/fido/fido_constants.cc index 8d477d2091a..91f8e344664 100644 --- a/chromium/device/fido/fido_constants.cc +++ b/chromium/device/fido/fido_constants.cc @@ -28,26 +28,6 @@ const char kIconUrlMapKey[] = "icon"; const char kCredentialTypeMapKey[] = "type"; const char kCredentialAlgorithmMapKey[] = "alg"; -const size_t kHidPacketSize = 64; -const uint32_t kHidBroadcastChannel = 0xffffffff; -const size_t kHidInitPacketHeaderSize = 7; -const size_t kHidContinuationPacketHeader = 5; -const size_t kHidMaxPacketSize = 64; -const size_t kHidInitPacketDataSize = - kHidMaxPacketSize - kHidInitPacketHeaderSize; -const size_t kHidContinuationPacketDataSize = - kHidMaxPacketSize - kHidContinuationPacketHeader; -const uint8_t kHidMaxLockSeconds = 10; -const size_t kHidMaxMessageSize = 7609; - -const size_t kU2fMaxResponseSize = 65536; -const uint8_t kP1TupRequired = 0x01; -const uint8_t kP1TupConsumed = 0x02; -const uint8_t kP1TupRequiredConsumed = kP1TupRequired | kP1TupConsumed; -const uint8_t kP1CheckOnly = 0x07; -const uint8_t kP1IndividualAttestation = 0x80; -const size_t kMaxKeyHandleLength = 255; - const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(3); const base::TimeDelta kU2fRetryDelay = base::TimeDelta::FromMilliseconds(200); const base::TimeDelta kHidKeepAliveDelay = diff --git a/chromium/device/fido/fido_constants.h b/chromium/device/fido/fido_constants.h index e8723a7dd51..02cc5b4d8b9 100644 --- a/chromium/device/fido/fido_constants.h +++ b/chromium/device/fido/fido_constants.h @@ -308,38 +308,34 @@ COMPONENT_EXPORT(DEVICE_FIDO) extern const char kCredentialTypeMapKey[]; COMPONENT_EXPORT(DEVICE_FIDO) extern const char kCredentialAlgorithmMapKey[]; // HID transport specific constants. -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidPacketSize; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint32_t kHidBroadcastChannel; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidInitPacketHeaderSize; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidContinuationPacketHeader; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidMaxPacketSize; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidInitPacketDataSize; -COMPONENT_EXPORT(DEVICE_FIDO) -extern const size_t kHidContinuationPacketDataSize; +constexpr uint32_t kHidBroadcastChannel = 0xffffffff; +constexpr size_t kHidInitPacketHeaderSize = 7; +constexpr size_t kHidContinuationPacketHeaderSize = 5; +constexpr size_t kHidMaxPacketSize = 64; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kHidMaxLockSeconds; +constexpr uint8_t kHidMaxLockSeconds = 10; // Messages are limited to an initiation packet and 128 continuation packets. -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidMaxMessageSize; +constexpr size_t kHidMaxMessageSize = 7609; // U2F APDU encoding constants, as specified in // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#bib-U2FHeader -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kU2fMaxResponseSize; +constexpr size_t kU2fMaxResponseSize = 65536; // P1 instructions. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1TupRequired; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1TupConsumed; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1TupRequiredConsumed; +constexpr uint8_t kP1TupRequired = 0x01; +constexpr uint8_t kP1TupConsumed = 0x02; +constexpr uint8_t kP1TupRequiredConsumed = kP1TupRequired | kP1TupConsumed; // Control byte used for check-only setting. The check-only command is used to // determine if the provided key handle was originally created by this token // and whether it was created for the provided application parameter. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1CheckOnly; +constexpr uint8_t kP1CheckOnly = 0x07; // Indicates that an individual attestation certificate is acceptable to // return with this registration. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1IndividualAttestation; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kMaxKeyHandleLength; +constexpr uint8_t kP1IndividualAttestation = 0x80; +constexpr size_t kMaxKeyHandleLength = 255; // Maximum wait time before client error outs on device. COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kDeviceTimeout; @@ -390,6 +386,16 @@ COMPONENT_EXPORT(DEVICE_FIDO) extern const char kExtensionHmacSecret[]; COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kBleDevicePairingModeWaitingInterval; +// https://w3c.github.io/webauthn/#attestation-convey +enum class AttestationConveyancePreference : uint8_t { + NONE, + INDIRECT, + DIRECT, + // Non-standard value for individual attestation that we hope to end up in + // the standard eventually. + ENTERPRISE, +}; + } // namespace device #endif // DEVICE_FIDO_FIDO_CONSTANTS_H_ diff --git a/chromium/device/fido/fido_device.cc b/chromium/device/fido/fido_device.cc index b27a1e1bea9..58a4151b0cf 100644 --- a/chromium/device/fido/fido_device.cc +++ b/chromium/device/fido/fido_device.cc @@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/stl_util.h" -#include "device/base/features.h" #include "device/fido/ctap_empty_authenticator_request.h" #include "device/fido/device_response_converter.h" #include "device/fido/fido_constants.h" @@ -33,18 +32,13 @@ bool FidoDevice::IsPaired() const { void FidoDevice::DiscoverSupportedProtocolAndDeviceInfo( base::OnceClosure done) { - if (base::FeatureList::IsEnabled(kNewCtap2Device)) { - // Set the protocol version to CTAP2 for the purpose of sending the GetInfo - // request. The correct value will be set in the callback based on the - // device response. - supported_protocol_ = ProtocolVersion::kCtap; - DeviceTransact(AuthenticatorGetInfoRequest().Serialize(), - base::BindOnce(&FidoDevice::OnDeviceInfoReceived, - GetWeakPtr(), std::move(done))); - } else { - supported_protocol_ = ProtocolVersion::kU2f; - std::move(done).Run(); - } + // Set the protocol version to CTAP2 for the purpose of sending the GetInfo + // request. The correct value will be set in the callback based on the + // device response. + supported_protocol_ = ProtocolVersion::kCtap; + DeviceTransact(AuthenticatorGetInfoRequest().Serialize(), + base::BindOnce(&FidoDevice::OnDeviceInfoReceived, GetWeakPtr(), + std::move(done))); } bool FidoDevice::SupportedProtocolIsInitialized() { diff --git a/chromium/device/fido/fido_device.h b/chromium/device/fido/fido_device.h index e9ecfa77060..eee3d3fb6d0 100644 --- a/chromium/device/fido/fido_device.h +++ b/chromium/device/fido/fido_device.h @@ -68,8 +68,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDevice { // Sends a speculative AuthenticatorGetInfo request to determine whether the // device supports the CTAP2 protocol, and initializes supported_protocol_ - // and device_info_ according to the result (unless the - // device::kNewCtap2Device feature is off, in which case U2F is assumed). + // and device_info_ according to the result. void DiscoverSupportedProtocolAndDeviceInfo(base::OnceClosure done); // Returns whether supported_protocol has been correctly initialized (usually // by calling DiscoverSupportedProtocolAndDeviceInfo). diff --git a/chromium/device/fido/get_assertion_handler_unittest.cc b/chromium/device/fido/get_assertion_handler_unittest.cc index 30391c3d161..bf1cda064cd 100644 --- a/chromium/device/fido/get_assertion_handler_unittest.cc +++ b/chromium/device/fido/get_assertion_handler_unittest.cc @@ -8,17 +8,14 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/stl_util.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "build/build_config.h" -#include "device/base/features.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/fido/authenticator_get_assertion_response.h" #include "device/fido/ctap_get_assertion_request.h" #include "device/fido/device_response_converter.h" #include "device/fido/fake_fido_discovery.h" -#include "device/fido/features.h" #include "device/fido/fido_constants.h" #include "device/fido/fido_parsing_utils.h" #include "device/fido/fido_test_data.h" @@ -143,10 +140,6 @@ class FidoGetAssertionHandlerTest : public ::testing::Test { GetAllTransportProtocols()); } - void InitFeatureListAndDisableCtapFlag() { - scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device); - } - test::FakeFidoDiscovery* discovery() const { return discovery_; } test::FakeFidoDiscovery* ble_discovery() const { return ble_discovery_; } test::FakeFidoDiscovery* cable_discovery() const { return cable_discovery_; } @@ -176,7 +169,6 @@ class FidoGetAssertionHandlerTest : public ::testing::Test { base::test::ScopedTaskEnvironment scoped_task_environment_{ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME}; - base::test::ScopedFeatureList scoped_feature_list_; test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_; test::FakeFidoDiscovery* discovery_; test::FakeFidoDiscovery* ble_discovery_; @@ -236,29 +228,6 @@ TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) { EXPECT_TRUE(request_handler->is_complete()); } -// Test a scenario where the connected authenticator is a U2F device and -// "WebAuthenticationCtap2" flag is not enabled. -TEST_F(FidoGetAssertionHandlerTest, TestU2fSignWithoutCtapFlag) { - InitFeatureListAndDisableCtapFlag(); - auto request_handler = CreateGetAssertionHandlerU2f(); - discovery()->WaitForCallToStartAndSimulateSuccess(); - - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectRequestAndRespondWith( - test_data::kU2fCheckOnlySignCommandApdu, - test_data::kApduEncodedNoErrorSignResponse); - device->ExpectRequestAndRespondWith( - test_data::kU2fSignCommandApdu, - test_data::kApduEncodedNoErrorSignResponse); - - discovery()->AddDevice(std::move(device)); - scoped_task_environment_.FastForwardUntilNoTasksRemain(); - EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status()); - EXPECT_TRUE(get_assertion_callback().value<0>()); - EXPECT_TRUE(request_handler->is_complete()); -} - TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) { auto request = CtapGetAssertionRequest(test_data::kRelyingPartyId, test_data::kClientDataJson); @@ -721,38 +690,15 @@ TEST_F(FidoGetAssertionHandlerTest, } #if defined(OS_WIN) -class GetAssertionRequestHandlerWinTest : public ::testing::Test { - protected: - base::test::ScopedTaskEnvironment scoped_task_environment_; - ScopedFakeWinWebAuthnApi scoped_fake_win_webauthn_api_; -}; - // Verify that the request handler instantiates a HID device backed // FidoDeviceAuthenticator or a WinNativeCrossPlatformAuthenticator, depending -// on feature flag and API availability. -TEST_F(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) { - enum class DeviceType { - kHid, - kWinNative, - }; - const struct TestCase { - bool enable_win_webauthn_api; - bool enable_feature_flag; - DeviceType expect_device_type; - } test_cases[] = { - {false, false, DeviceType::kHid}, - {false, true, DeviceType::kHid}, - {true, false, DeviceType::kHid}, - {true, true, DeviceType::kWinNative}, - }; - size_t i = 0; - for (const auto& test : test_cases) { - SCOPED_TRACE(i++); - scoped_fake_win_webauthn_api_.set_available(test.enable_win_webauthn_api); - base::test::ScopedFeatureList scoped_feature_list; - // Feature is default off (even with API present). - if (test.enable_feature_flag) - scoped_feature_list.InitAndEnableFeature(kWebAuthUseNativeWinApi); +// on API availability. +TEST(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) { + base::test::ScopedTaskEnvironment scoped_task_environment; + ScopedFakeWinWebAuthnApi scoped_fake_win_webauthn_api; + for (const bool enable_api : {false, true}) { + SCOPED_TRACE(::testing::Message() << "enable_api=" << enable_api); + scoped_fake_win_webauthn_api.set_available(enable_api); // Simulate a connected HID device. ScopedFakeHidManager fake_hid_manager; @@ -767,14 +713,13 @@ TEST_F(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) { test_data::kClientDataJson), cb.callback()); - scoped_task_environment_.RunUntilIdle(); + scoped_task_environment.RunUntilIdle(); EXPECT_EQ(1u, handler->AuthenticatorsForTesting().size()); // Crudely distinguish authenticator type by FidoAuthenticator::GetId. - EXPECT_EQ(test.expect_device_type == DeviceType::kHid - ? "hid:guid" - : WinWebAuthnApiAuthenticator::kAuthenticatorId, - handler->AuthenticatorsForTesting().begin()->second->GetId()); + EXPECT_EQ( + enable_api ? WinWebAuthnApiAuthenticator::kAuthenticatorId : "hid:guid", + handler->AuthenticatorsForTesting().begin()->second->GetId()); } } #endif // defined(OS_WIN) diff --git a/chromium/device/fido/get_assertion_task.cc b/chromium/device/fido/get_assertion_task.cc index 8fb08533bcb..3ec9a9f1eae 100644 --- a/chromium/device/fido/get_assertion_task.cc +++ b/chromium/device/fido/get_assertion_task.cc @@ -40,8 +40,7 @@ GetAssertionTask::GetAssertionTask(FidoDevice* device, GetAssertionTask::~GetAssertionTask() = default; void GetAssertionTask::StartTask() { - if (base::FeatureList::IsEnabled(kNewCtap2Device) && - device()->supported_protocol() == ProtocolVersion::kCtap) { + if (device()->supported_protocol() == ProtocolVersion::kCtap) { GetAssertion(); } else { U2fSign(); diff --git a/chromium/device/fido/get_assertion_task_unittest.cc b/chromium/device/fido/get_assertion_task_unittest.cc index 5227452a1d2..2ee535d7b2e 100644 --- a/chromium/device/fido/get_assertion_task_unittest.cc +++ b/chromium/device/fido/get_assertion_task_unittest.cc @@ -11,7 +11,6 @@ #include <vector> #include "base/bind.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "crypto/ec_private_key.h" #include "device/base/features.h" @@ -39,20 +38,14 @@ using TestGetAssertionTaskCallbackReceiver = class FidoGetAssertionTaskTest : public testing::Test { public: - FidoGetAssertionTaskTest() { scoped_feature_list_.emplace(); } + FidoGetAssertionTaskTest() {} TestGetAssertionTaskCallbackReceiver& get_assertion_callback_receiver() { return cb_; } - void RemoveCtapFlag() { - scoped_feature_list_.emplace(); - scoped_feature_list_->InitAndDisableFeature(kNewCtap2Device); - } - private: base::test::ScopedTaskEnvironment scoped_task_environment_; - base::Optional<base::test::ScopedFeatureList> scoped_feature_list_; TestGetAssertionTaskCallbackReceiver cb_; }; @@ -151,32 +144,6 @@ TEST_F(FidoGetAssertionTaskTest, TestSignSuccessWithFake) { .SerializeToByteArray()[36]); // counter } -TEST_F(FidoGetAssertionTaskTest, TestU2fSignWithoutFlag) { - RemoveCtapFlag(); - auto device = MockFidoDevice::MakeU2f(); - device->ExpectRequestAndRespondWith( - test_data::kU2fCheckOnlySignCommandApdu, - test_data::kApduEncodedNoErrorSignResponse); - device->ExpectRequestAndRespondWith( - test_data::kU2fSignCommandApdu, - test_data::kApduEncodedNoErrorSignResponse); - - CtapGetAssertionRequest request_param(test_data::kRelyingPartyId, - test_data::kClientDataJson); - request_param.SetAllowList( - {{CredentialType::kPublicKey, - fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}}); - - auto task = std::make_unique<GetAssertionTask>( - device.get(), std::move(request_param), - get_assertion_callback_receiver().callback()); - - get_assertion_callback_receiver().WaitForCallback(); - EXPECT_EQ(CtapDeviceResponseCode::kSuccess, - get_assertion_callback_receiver().status()); - EXPECT_TRUE(get_assertion_callback_receiver().value()); -} - TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) { auto device = MockFidoDevice::MakeCtap(); device->ExpectCtap2CommandAndRespondWith( diff --git a/chromium/device/fido/hid/fake_hid_impl_for_testing.cc b/chromium/device/fido/hid/fake_hid_impl_for_testing.cc index 7170324c560..d16cbce54bd 100644 --- a/chromium/device/fido/hid/fake_hid_impl_for_testing.cc +++ b/chromium/device/fido/hid/fake_hid_impl_for_testing.cc @@ -23,7 +23,7 @@ MATCHER_P(IsCtapHidCommand, expected_command, "") { } // namespace -MockHidConnection::MockHidConnection( +MockFidoHidConnection::MockFidoHidConnection( device::mojom::HidDeviceInfoPtr device, device::mojom::HidConnectionRequest request, std::vector<uint8_t> connection_channel_id) @@ -31,34 +31,36 @@ MockHidConnection::MockHidConnection( device_(std::move(device)), connection_channel_id_(connection_channel_id) {} -MockHidConnection::~MockHidConnection() {} +MockFidoHidConnection::~MockFidoHidConnection() {} -void MockHidConnection::Read(ReadCallback callback) { +void MockFidoHidConnection::Read(ReadCallback callback) { return ReadPtr(&callback); } -void MockHidConnection::Write(uint8_t report_id, - const std::vector<uint8_t>& buffer, - WriteCallback callback) { +void MockFidoHidConnection::Write(uint8_t report_id, + const std::vector<uint8_t>& buffer, + WriteCallback callback) { return WritePtr(report_id, buffer, &callback); } -void MockHidConnection::GetFeatureReport(uint8_t report_id, - GetFeatureReportCallback callback) { +void MockFidoHidConnection::GetFeatureReport( + uint8_t report_id, + GetFeatureReportCallback callback) { NOTREACHED(); } -void MockHidConnection::SendFeatureReport(uint8_t report_id, - const std::vector<uint8_t>& buffer, - SendFeatureReportCallback callback) { +void MockFidoHidConnection::SendFeatureReport( + uint8_t report_id, + const std::vector<uint8_t>& buffer, + SendFeatureReportCallback callback) { NOTREACHED(); } -void MockHidConnection::SetNonce(base::span<uint8_t const> nonce) { +void MockFidoHidConnection::SetNonce(base::span<uint8_t const> nonce) { nonce_ = std::vector<uint8_t>(nonce.begin(), nonce.end()); } -void MockHidConnection::ExpectWriteHidInit() { +void MockFidoHidConnection::ExpectWriteHidInit() { EXPECT_CALL(*this, WritePtr(::testing::_, IsCtapHidCommand(FidoHidDeviceCommand::kInit), ::testing::_)) @@ -73,7 +75,8 @@ void MockHidConnection::ExpectWriteHidInit() { })); } -void MockHidConnection::ExpectHidWriteWithCommand(FidoHidDeviceCommand cmd) { +void MockFidoHidConnection::ExpectHidWriteWithCommand( + FidoHidDeviceCommand cmd) { EXPECT_CALL(*this, WritePtr(::testing::_, IsCtapHidCommand(cmd), ::testing::_)) .WillOnce(::testing::Invoke( diff --git a/chromium/device/fido/hid/fake_hid_impl_for_testing.h b/chromium/device/fido/hid/fake_hid_impl_for_testing.h index 022775c0709..c49e461ef07 100644 --- a/chromium/device/fido/hid/fake_hid_impl_for_testing.h +++ b/chromium/device/fido/hid/fake_hid_impl_for_testing.h @@ -26,13 +26,13 @@ class Connector; namespace device { -class MockHidConnection : public device::mojom::HidConnection { +class MockFidoHidConnection : public device::mojom::HidConnection { public: - explicit MockHidConnection(device::mojom::HidDeviceInfoPtr device, - device::mojom::HidConnectionRequest request, - std::vector<uint8_t> connection_channel_id); + explicit MockFidoHidConnection(device::mojom::HidDeviceInfoPtr device, + device::mojom::HidConnectionRequest request, + std::vector<uint8_t> connection_channel_id); - ~MockHidConnection() override; + ~MockFidoHidConnection() override; MOCK_METHOD1(ReadPtr, void(ReadCallback* callback)); MOCK_METHOD3(WritePtr, void(uint8_t report_id, @@ -66,7 +66,7 @@ class MockHidConnection : public device::mojom::HidConnection { std::vector<uint8_t> nonce_; std::vector<uint8_t> connection_channel_id_; - DISALLOW_COPY_AND_ASSIGN(MockHidConnection); + DISALLOW_COPY_AND_ASSIGN(MockFidoHidConnection); }; class FakeHidConnection : public device::mojom::HidConnection { diff --git a/chromium/device/fido/hid/fido_hid_device.cc b/chromium/device/fido/hid/fido_hid_device.cc index db134be7e04..80ad4ae2b8c 100644 --- a/chromium/device/fido/hid/fido_hid_device.cc +++ b/chromium/device/fido/hid/fido_hid_device.cc @@ -4,6 +4,8 @@ #include "device/fido/hid/fido_hid_device.h" +#include <limits> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" @@ -23,9 +25,16 @@ static constexpr uint8_t kReportId = 0x00; FidoHidDevice::FidoHidDevice(device::mojom::HidDeviceInfoPtr device_info, device::mojom::HidManager* hid_manager) : FidoDevice(), + output_report_size_(device_info->max_output_report_size), hid_manager_(hid_manager), device_info_(std::move(device_info)), - weak_factory_(this) {} + weak_factory_(this) { + DCHECK_GE(std::numeric_limits<decltype(output_report_size_)>::max(), + device_info_->max_output_report_size); + // These limits on the report size are enforced in fido_hid_discovery.cc. + DCHECK_LT(kHidInitPacketHeaderSize, output_report_size_); + DCHECK_GE(kHidMaxPacketSize, output_report_size_); +} FidoHidDevice::~FidoHidDevice() = default; @@ -43,7 +52,7 @@ void FidoHidDevice::Cancel() { pending_transactions_ = {}; WriteMessage( FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kCancel, - std::vector<uint8_t>()), + output_report_size_, std::vector<uint8_t>()), false /* response_expected */, base::DoNothing()); } @@ -75,7 +84,8 @@ void FidoHidDevice::Transition(std::vector<uint8_t> command, ? FidoHidDeviceCommand::kCbor : FidoHidDeviceCommand::kMsg; WriteMessage( - FidoHidMessage::Create(channel_id_, command_type, std::move(command)), + FidoHidMessage::Create(channel_id_, command_type, output_report_size_, + std::move(command)), true, base::BindOnce(&FidoHidDevice::MessageReceived, weak_factory_.GetWeakPtr(), repeating_callback)); @@ -126,12 +136,12 @@ void FidoHidDevice::AllocateChannel(std::vector<uint8_t> command, // Send random nonce to device to verify received message. std::vector<uint8_t> nonce(8); crypto::RandBytes(nonce.data(), nonce.size()); - WriteMessage( - FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kInit, nonce), - true, - base::BindOnce(&FidoHidDevice::OnAllocateChannel, - weak_factory_.GetWeakPtr(), nonce, std::move(command), - std::move(callback))); + WriteMessage(FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kInit, + output_report_size_, nonce), + true, + base::BindOnce(&FidoHidDevice::OnAllocateChannel, + weak_factory_.GetWeakPtr(), nonce, + std::move(command), std::move(callback))); } void FidoHidDevice::OnAllocateChannel(std::vector<uint8_t> nonce, @@ -195,7 +205,9 @@ void FidoHidDevice::WriteMessage(base::Optional<FidoHidMessage> message, std::move(callback).Run(base::nullopt); return; } - const auto& packet = message->PopNextPacket(); + auto packet = message->PopNextPacket(); + DCHECK_LE(packet.size(), output_report_size_); + packet.resize(output_report_size_, 0); connection_->Write( kReportId, packet, base::BindOnce(&FidoHidDevice::PacketWritten, weak_factory_.GetWeakPtr(), @@ -340,11 +352,12 @@ void FidoHidDevice::TryWink(WinkCallback callback) { return; } - WriteMessage(FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kWink, - std::vector<uint8_t>()), - true, - base::BindOnce(&FidoHidDevice::OnWink, - weak_factory_.GetWeakPtr(), std::move(callback))); + WriteMessage( + FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kWink, + output_report_size_, std::vector<uint8_t>()), + true, + base::BindOnce(&FidoHidDevice::OnWink, weak_factory_.GetWeakPtr(), + std::move(callback))); } void FidoHidDevice::OnKeepAlive(DeviceCallback callback) { diff --git a/chromium/device/fido/hid/fido_hid_device.h b/chromium/device/fido/hid/fido_hid_device.h index 64a2ac9bee7..4022b3b5af0 100644 --- a/chromium/device/fido/hid/fido_hid_device.h +++ b/chromium/device/fido/hid/fido_hid_device.h @@ -120,6 +120,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoHidDevice : public FidoDevice { uint32_t channel_id_ = kBroadcastChannel; uint8_t capabilities_ = 0; + // |output_report_size_| is the size of the packets that will be sent to the + // device. (For HID devices, these are called reports.) + const uint8_t output_report_size_; base::CancelableOnceClosure timeout_callback_; base::queue<std::pair<std::vector<uint8_t>, DeviceCallback>> diff --git a/chromium/device/fido/hid/fido_hid_device_unittest.cc b/chromium/device/fido/hid/fido_hid_device_unittest.cc index 0942bf14226..c958c2868cd 100644 --- a/chromium/device/fido/hid/fido_hid_device_unittest.cc +++ b/chromium/device/fido/hid/fido_hid_device_unittest.cc @@ -108,16 +108,16 @@ device::mojom::HidDeviceInfoPtr TestHidDevice() { return hid_device; } -std::unique_ptr<MockHidConnection> CreateHidConnectionWithHidInitExpectations( - base::span<const uint8_t> channel_id, - FakeHidManager* fake_hid_manager, - ::testing::Sequence sequence) { +std::unique_ptr<MockFidoHidConnection> +CreateHidConnectionWithHidInitExpectations(base::span<const uint8_t> channel_id, + FakeHidManager* fake_hid_manager, + ::testing::Sequence sequence) { auto hid_device = TestHidDevice(); device::mojom::HidConnectionPtr connection_client; // Replace device HID connection with custom client connection bound to mock // server-side mojo connection. - auto mock_connection = std::make_unique<MockHidConnection>( + auto mock_connection = std::make_unique<MockFidoHidConnection>( hid_device.Clone(), mojo::MakeRequest(&connection_client), fido_parsing_utils::Materialize(channel_id)); @@ -276,7 +276,7 @@ TEST_F(FidoHidDeviceTest, TestRetryChannelAllocation) { // Replace device HID connection with custom client connection bound to mock // server-side mojo connection. device::mojom::HidConnectionPtr connection_client; - MockHidConnection mock_connection( + MockFidoHidConnection mock_connection( hid_device.Clone(), mojo::MakeRequest(&connection_client), fido_parsing_utils::Materialize(kChannelId)); diff --git a/chromium/device/fido/hid/fido_hid_discovery.cc b/chromium/device/fido/hid/fido_hid_discovery.cc index 92b908ecf5f..5c288c990bd 100644 --- a/chromium/device/fido/hid/fido_hid_discovery.cc +++ b/chromium/device/fido/hid/fido_hid_discovery.cc @@ -38,8 +38,21 @@ void FidoHidDiscovery::StartInternal() { void FidoHidDiscovery::DeviceAdded( device::mojom::HidDeviceInfoPtr device_info) { + // The init packet header is the larger of the headers so we only compare + // against it below. + static_assert( + kHidInitPacketHeaderSize >= kHidContinuationPacketHeaderSize, + "init header is expected to be larger than continuation header"); + // Ignore non-U2F devices. - if (filter_.Matches(*device_info)) { + if (filter_.Matches(*device_info) && + // Check that the supported report sizes are sufficient for at least one + // byte of non-header data per report and not larger than our maximum + // size. + device_info->max_input_report_size > kHidInitPacketHeaderSize && + device_info->max_input_report_size <= kHidMaxPacketSize && + device_info->max_output_report_size > kHidInitPacketHeaderSize && + device_info->max_output_report_size <= kHidMaxPacketSize) { AddDevice(std::make_unique<FidoHidDevice>(std::move(device_info), hid_manager_.get())); } diff --git a/chromium/device/fido/hid/fido_hid_message.cc b/chromium/device/fido/hid/fido_hid_message.cc index 3040696c26d..52aa4929dee 100644 --- a/chromium/device/fido/hid/fido_hid_message.cc +++ b/chromium/device/fido/hid/fido_hid_message.cc @@ -18,10 +18,17 @@ namespace device { base::Optional<FidoHidMessage> FidoHidMessage::Create( uint32_t channel_id, FidoHidDeviceCommand type, + size_t max_report_size, base::span<const uint8_t> data) { if (data.size() > kHidMaxMessageSize) return base::nullopt; + if (max_report_size <= kHidInitPacketHeaderSize || + max_report_size > kHidMaxPacketSize) { + NOTREACHED(); + return base::nullopt; + } + switch (type) { case FidoHidDeviceCommand::kPing: break; @@ -54,14 +61,14 @@ base::Optional<FidoHidMessage> FidoHidMessage::Create( return base::nullopt; } - return FidoHidMessage(channel_id, type, data); + return FidoHidMessage(channel_id, type, max_report_size, data); } // static base::Optional<FidoHidMessage> FidoHidMessage::CreateFromSerializedData( base::span<const uint8_t> serialized_data) { size_t remaining_size = 0; - if (serialized_data.size() > kHidPacketSize || + if (serialized_data.size() > kHidMaxPacketSize || serialized_data.size() < kHidInitPacketHeaderSize) return base::nullopt; @@ -129,18 +136,28 @@ size_t FidoHidMessage::NumPackets() const { FidoHidMessage::FidoHidMessage(uint32_t channel_id, FidoHidDeviceCommand type, + size_t max_report_size, base::span<const uint8_t> data) : channel_id_(channel_id) { + static_assert( + kHidInitPacketHeaderSize >= kHidContinuationPacketHeaderSize, + "init header is expected to be larger than continuation header"); + DCHECK_GT(max_report_size, kHidInitPacketHeaderSize); + + const size_t init_packet_data_size = + max_report_size - kHidInitPacketHeaderSize; + const size_t continuation_packet_data_size = + max_report_size - kHidContinuationPacketHeaderSize; uint8_t sequence = 0; - auto init_data = data.first(std::min(kHidInitPacketDataSize, data.size())); + auto init_data = data.first(std::min(init_packet_data_size, data.size())); packets_.push_back(std::make_unique<FidoHidInitPacket>( channel_id, type, std::vector<uint8_t>(init_data.begin(), init_data.end()), data.size())); data = data.subspan(init_data.size()); for (auto cont_data : - fido_parsing_utils::SplitSpan(data, kHidContinuationPacketDataSize)) { + fido_parsing_utils::SplitSpan(data, continuation_packet_data_size)) { packets_.push_back(std::make_unique<FidoHidContinuationPacket>( channel_id, sequence++, fido_parsing_utils::Materialize(cont_data))); } diff --git a/chromium/device/fido/hid/fido_hid_message.h b/chromium/device/fido/hid/fido_hid_message.h index 715c68e800e..cc8a3781a80 100644 --- a/chromium/device/fido/hid/fido_hid_message.h +++ b/chromium/device/fido/hid/fido_hid_message.h @@ -30,6 +30,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoHidMessage { // Static functions to create CTAP/U2F HID commands. static base::Optional<FidoHidMessage> Create(uint32_t channel_id, FidoHidDeviceCommand cmd, + size_t max_report_size, base::span<const uint8_t> data); // Reconstruct a message from serialized message data. @@ -59,6 +60,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoHidMessage { private: FidoHidMessage(uint32_t channel_id, FidoHidDeviceCommand type, + size_t max_report_size, base::span<const uint8_t> data); FidoHidMessage(std::unique_ptr<FidoHidInitPacket> init_packet, size_t remaining_size); diff --git a/chromium/device/fido/hid/fido_hid_message_unittest.cc b/chromium/device/fido/hid/fido_hid_message_unittest.cc index 610af543756..11f43b5e2f2 100644 --- a/chromium/device/fido/hid/fido_hid_message_unittest.cc +++ b/chromium/device/fido/hid/fido_hid_message_unittest.cc @@ -13,19 +13,10 @@ namespace device { -// Packets should be 64 bytes + 1 report ID byte. -TEST(FidoHidMessageTest, TestPacketSize) { - uint32_t channel_id = 0x05060708; - std::vector<uint8_t> data; - - auto init_packet = std::make_unique<FidoHidInitPacket>( - channel_id, FidoHidDeviceCommand::kInit, data, data.size()); - EXPECT_EQ(64u, init_packet->GetSerializedData().size()); - - auto continuation_packet = - std::make_unique<FidoHidContinuationPacket>(channel_id, 0, data); - EXPECT_EQ(64u, continuation_packet->GetSerializedData().size()); -} +static const size_t kDefaultInitDataSize = + kHidMaxPacketSize - kHidInitPacketHeaderSize; +static const size_t kDefaultContinuationDataSize = + kHidMaxPacketSize - kHidContinuationPacketHeaderSize; /* * U2f Init Packets are of the format: @@ -96,78 +87,117 @@ TEST(FidoHidMessageTest, TestMaxLengthPacketConstructors) { for (size_t i = 0; i < kHidMaxMessageSize; ++i) data.push_back(static_cast<uint8_t>(i % 0xff)); - auto orig_msg = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kMsg, data); - ASSERT_TRUE(orig_msg); + for (size_t report_size = kHidInitPacketHeaderSize + 1; + report_size <= kHidMaxPacketSize; report_size++) { + auto orig_msg = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kMsg, report_size, data); + ASSERT_TRUE(orig_msg); + + const auto& original_msg_packets = orig_msg->GetPacketsForTesting(); + auto it = original_msg_packets.begin(); + auto msg_data = (*it)->GetSerializedData(); + auto new_msg = FidoHidMessage::CreateFromSerializedData(msg_data); + it++; + + for (; it != original_msg_packets.end(); ++it) { + msg_data = (*it)->GetSerializedData(); + new_msg->AddContinuationPacket(msg_data); + } - const auto& original_msg_packets = orig_msg->GetPacketsForTesting(); - auto it = original_msg_packets.begin(); - auto msg_data = (*it)->GetSerializedData(); - auto new_msg = FidoHidMessage::CreateFromSerializedData(msg_data); - it++; + EXPECT_EQ(new_msg->NumPackets(), orig_msg->NumPackets()); - for (; it != original_msg_packets.end(); ++it) { - msg_data = (*it)->GetSerializedData(); - new_msg->AddContinuationPacket(msg_data); - } + auto orig_it = original_msg_packets.begin(); + const auto& new_msg_packets = new_msg->GetPacketsForTesting(); + auto new_msg_it = new_msg_packets.begin(); + + for (; orig_it != original_msg_packets.end() && + new_msg_it != new_msg_packets.end(); + ++orig_it, ++new_msg_it) { + EXPECT_THAT((*orig_it)->GetPacketPayload(), + ::testing::ContainerEq((*new_msg_it)->GetPacketPayload())); + + EXPECT_EQ((*orig_it)->channel_id(), (*new_msg_it)->channel_id()); - auto orig_it = original_msg_packets.begin(); - const auto& new_msg_packets = new_msg->GetPacketsForTesting(); - auto new_msg_it = new_msg_packets.begin(); - - for (; orig_it != original_msg_packets.end() && - new_msg_it != new_msg_packets.end(); - ++orig_it, ++new_msg_it) { - EXPECT_THAT((*orig_it)->GetPacketPayload(), - ::testing::ContainerEq((*new_msg_it)->GetPacketPayload())); - - EXPECT_EQ((*orig_it)->channel_id(), (*new_msg_it)->channel_id()); - - ASSERT_EQ((*orig_it)->GetSerializedData().size(), - (*new_msg_it)->GetSerializedData().size()); - for (size_t index = 0; index < (*orig_it)->GetSerializedData().size(); - ++index) { - EXPECT_EQ((*orig_it)->GetSerializedData()[index], - (*new_msg_it)->GetSerializedData()[index]) - << "mismatch at index " << index; + ASSERT_EQ((*orig_it)->GetSerializedData().size(), + (*new_msg_it)->GetSerializedData().size()); + for (size_t index = 0; index < (*orig_it)->GetSerializedData().size(); + ++index) { + EXPECT_EQ((*orig_it)->GetSerializedData()[index], + (*new_msg_it)->GetSerializedData()[index]) + << "mismatch at index " << index; + } } + + EXPECT_TRUE(orig_it == original_msg_packets.end()); + EXPECT_TRUE(new_msg_it == new_msg_packets.end()); } } TEST(FidoHidMessageTest, TestMessagePartitoning) { uint32_t channel_id = 0x01010203; - std::vector<uint8_t> data(kHidInitPacketDataSize + 1); - auto two_packet_message = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, data); + std::vector<uint8_t> data(kDefaultInitDataSize + 1); + auto two_packet_message = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kPing, kHidMaxPacketSize, data); ASSERT_TRUE(two_packet_message); EXPECT_EQ(2U, two_packet_message->NumPackets()); - data.resize(kHidInitPacketDataSize); - auto one_packet_message = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, data); + data.resize(kDefaultInitDataSize); + auto one_packet_message = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kPing, kHidMaxPacketSize, data); ASSERT_TRUE(one_packet_message); EXPECT_EQ(1U, one_packet_message->NumPackets()); - data.resize(kHidInitPacketDataSize + kHidContinuationPacketDataSize + 1); - auto three_packet_message = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, data); + data.resize(kDefaultInitDataSize + kDefaultContinuationDataSize + 1); + auto three_packet_message = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kPing, kHidMaxPacketSize, data); ASSERT_TRUE(three_packet_message); EXPECT_EQ(3U, three_packet_message->NumPackets()); + + // With the minimal report size, only a single byte of data will fit in an + // init message, followed by three bytes in each continuation message. + data.resize(1 + 3 + 3); + auto three_small_messages = + FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, + kHidInitPacketHeaderSize + 1, data); + ASSERT_TRUE(three_small_messages); + EXPECT_EQ(3U, three_small_messages->NumPackets()); +} + +TEST(FidoHidMessageTest, TooLarge) { + std::vector<uint8_t> data; + +#if DCHECK_IS_ON() +#define EXPECT_SIZE_FAILURE(x) EXPECT_DEATH_IF_SUPPORTED(x, "") +#else +#define EXPECT_SIZE_FAILURE(x) EXPECT_FALSE(x.has_value()) +#endif + + // kHidInitPacketHeaderSize is too small a report size to be valid. + EXPECT_SIZE_FAILURE(FidoHidMessage::Create(kHidBroadcastChannel, + FidoHidDeviceCommand::kPing, + kHidInitPacketHeaderSize, data)); + + // kHidMaxPacketSize + 1 is too large a report size. + EXPECT_SIZE_FAILURE(FidoHidMessage::Create(kHidBroadcastChannel, + FidoHidDeviceCommand::kPing, + kHidMaxPacketSize + 1, data)); + +#undef EXPECT_SIZE_FAILURE } TEST(FidoHidMessageTest, TestMaxSize) { uint32_t channel_id = 0x00010203; std::vector<uint8_t> data(kHidMaxMessageSize + 1); - auto oversize_message = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, data); + auto oversize_message = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kPing, kHidMaxPacketSize, data); EXPECT_FALSE(oversize_message); } TEST(FidoHidMessageTest, TestDeconstruct) { uint32_t channel_id = 0x0A0B0C0D; std::vector<uint8_t> data(kHidMaxMessageSize, 0x7F); - auto filled_message = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, data); + auto filled_message = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kPing, kHidMaxPacketSize, data); ASSERT_TRUE(filled_message); EXPECT_THAT(data, ::testing::ContainerEq(filled_message->GetMessagePayload())); @@ -177,8 +207,8 @@ TEST(FidoHidMessageTest, TestDeserialize) { uint32_t channel_id = 0x0A0B0C0D; std::vector<uint8_t> data(kHidMaxMessageSize); - auto orig_message = - FidoHidMessage::Create(channel_id, FidoHidDeviceCommand::kPing, data); + auto orig_message = FidoHidMessage::Create( + channel_id, FidoHidDeviceCommand::kPing, kHidMaxPacketSize, data); ASSERT_TRUE(orig_message); base::circular_deque<std::vector<uint8_t>> orig_list; diff --git a/chromium/device/fido/hid/fido_hid_packet.cc b/chromium/device/fido/hid/fido_hid_packet.cc index 0024cddc91e..58994e31b11 100644 --- a/chromium/device/fido/hid/fido_hid_packet.cc +++ b/chromium/device/fido/hid/fido_hid_packet.cc @@ -24,7 +24,7 @@ FidoHidPacket::~FidoHidPacket() = default; std::unique_ptr<FidoHidInitPacket> FidoHidInitPacket::CreateFromSerializedData( base::span<const uint8_t> serialized, size_t* remaining_size) { - if (!remaining_size || serialized.size() != kHidPacketSize) + if (serialized.size() <= kHidInitPacketHeaderSize) return nullptr; size_t index = 0; @@ -39,10 +39,11 @@ std::unique_ptr<FidoHidInitPacket> FidoHidInitPacket::CreateFromSerializedData( uint16_t payload_size = serialized[index++] << 8; payload_size |= serialized[index++]; + DCHECK_EQ(index, kHidInitPacketHeaderSize); // Check to see if payload is less than maximum size and padded with 0s. uint16_t data_size = - std::min(payload_size, static_cast<uint16_t>(kHidPacketSize - index)); + std::min(payload_size, static_cast<uint16_t>(serialized.size() - index)); // Update remaining size to determine the payload size of follow on packets. *remaining_size = payload_size - data_size; @@ -73,7 +74,7 @@ FidoHidInitPacket::~FidoHidInitPacket() = default; std::vector<uint8_t> FidoHidInitPacket::GetSerializedData() const { std::vector<uint8_t> serialized; - serialized.reserve(kHidPacketSize); + serialized.reserve(kHidMaxPacketSize); serialized.push_back((channel_id_ >> 24) & 0xff); serialized.push_back((channel_id_ >> 16) & 0xff); serialized.push_back((channel_id_ >> 8) & 0xff); @@ -82,7 +83,6 @@ std::vector<uint8_t> FidoHidInitPacket::GetSerializedData() const { serialized.push_back((payload_length_ >> 8) & 0xff); serialized.push_back(payload_length_ & 0xff); serialized.insert(serialized.end(), data_.begin(), data_.end()); - serialized.resize(kHidPacketSize, 0); return serialized; } @@ -92,7 +92,7 @@ std::unique_ptr<FidoHidContinuationPacket> FidoHidContinuationPacket::CreateFromSerializedData( base::span<const uint8_t> serialized, size_t* remaining_size) { - if (!remaining_size || serialized.size() != kHidPacketSize) + if (serialized.size() <= kHidContinuationPacketHeaderSize) return nullptr; size_t index = 0; @@ -101,10 +101,11 @@ FidoHidContinuationPacket::CreateFromSerializedData( channel_id |= (serialized[index++] & 0xff) << 8; channel_id |= serialized[index++] & 0xff; auto sequence = serialized[index++]; + DCHECK_EQ(index, kHidContinuationPacketHeaderSize); // Check to see if packet payload is less than maximum size and padded with // 0s. - size_t data_size = std::min(*remaining_size, kHidPacketSize - index); + size_t data_size = std::min(*remaining_size, serialized.size() - index); *remaining_size -= data_size; auto data = std::vector<uint8_t>(serialized.begin() + index, serialized.begin() + index + data_size); @@ -127,14 +128,13 @@ FidoHidContinuationPacket::~FidoHidContinuationPacket() = default; std::vector<uint8_t> FidoHidContinuationPacket::GetSerializedData() const { std::vector<uint8_t> serialized; - serialized.reserve(kHidPacketSize); + serialized.reserve(kHidMaxPacketSize); serialized.push_back((channel_id_ >> 24) & 0xff); serialized.push_back((channel_id_ >> 16) & 0xff); serialized.push_back((channel_id_ >> 8) & 0xff); serialized.push_back(channel_id_ & 0xff); serialized.push_back(sequence_); serialized.insert(serialized.end(), data_.begin(), data_.end()); - serialized.resize(kHidPacketSize, 0); return serialized; } diff --git a/chromium/device/fido/mac/authenticator.mm b/chromium/device/fido/mac/authenticator.mm index edcea5b6988..cc697d6d2b5 100644 --- a/chromium/device/fido/mac/authenticator.mm +++ b/chromium/device/fido/mac/authenticator.mm @@ -31,10 +31,8 @@ namespace mac { // static bool TouchIdAuthenticator::IsAvailable() { - if (base::FeatureList::IsEnabled(device::kWebAuthTouchId)) { - if (__builtin_available(macOS 10.12.2, *)) { - return TouchIdContext::TouchIdAvailable(); - } + if (__builtin_available(macOS 10.12.2, *)) { + return TouchIdContext::TouchIdAvailable(); } return false; } diff --git a/chromium/device/fido/mac/browsing_data_deletion_unittest.mm b/chromium/device/fido/mac/browsing_data_deletion_unittest.mm index 4ba0c955672..67fc80be6a5 100644 --- a/chromium/device/fido/mac/browsing_data_deletion_unittest.mm +++ b/chromium/device/fido/mac/browsing_data_deletion_unittest.mm @@ -11,7 +11,6 @@ #include "base/mac/mac_logging.h" #include "base/mac/scoped_cftyperef.h" #include "base/strings/sys_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "device/base/features.h" #include "device/fido/ctap_make_credential_request.h" @@ -112,7 +111,6 @@ bool ResetKeychain() { class BrowsingDataDeletionTest : public testing::Test { public: void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(device::kWebAuthTouchId); authenticator_ = MakeAuthenticator(kMetadataSecret); CHECK(authenticator_); CHECK(ResetKeychain()); @@ -162,7 +160,6 @@ class BrowsingDataDeletionTest : public testing::Test { .CountCredentials(base::Time(), base::Time::Max()); } - base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<TouchIdAuthenticator> authenticator_; }; @@ -198,20 +195,6 @@ TEST_F(BrowsingDataDeletionTest, DISABLED_DifferentProfiles) { EXPECT_EQ(0, KeychainItemCount()); } -TEST_F(BrowsingDataDeletionTest, DISABLED_FeatureFlag) { - // Remove the feature flag override provided by the fixture. - base::FeatureList::ClearInstanceForTesting(); - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(device::kWebAuthTouchId); - - ASSERT_EQ(0, KeychainItemCount()); - ASSERT_TRUE(MakeCredential()); - - // DeleteCredentials() has no effect with the feature flag flipped off. - EXPECT_TRUE(DeleteCredentials()); - EXPECT_EQ(1, KeychainItemCount()); -} - TEST_F(BrowsingDataDeletionTest, DISABLED_Count) { EXPECT_EQ(0u, CountCredentials()); EXPECT_EQ(0u, CountCredentials(kOtherMetadataSecret)); diff --git a/chromium/device/fido/mac/credential_store.mm b/chromium/device/fido/mac/credential_store.mm index 19f5749419d..c16fa96a6b4 100644 --- a/chromium/device/fido/mac/credential_store.mm +++ b/chromium/device/fido/mac/credential_store.mm @@ -198,26 +198,22 @@ TouchIdCredentialStore::~TouchIdCredentialStore() = default; bool TouchIdCredentialStore::DeleteCredentials(base::Time created_not_before, base::Time created_not_after) { - if (base::FeatureList::IsEnabled(device::kWebAuthTouchId)) { - // Touch ID uses macOS APIs available in 10.12.2 or newer. No need to check - // for credentials in lower OS versions. - if (__builtin_available(macos 10.12.2, *)) { - return DoDeleteWebAuthnCredentials(config_.keychain_access_group, - config_.metadata_secret, - created_not_before, created_not_after); - } + // Touch ID uses macOS APIs available in 10.12.2 or newer. No need to check + // for credentials in lower OS versions. + if (__builtin_available(macos 10.12.2, *)) { + return DoDeleteWebAuthnCredentials(config_.keychain_access_group, + config_.metadata_secret, + created_not_before, created_not_after); } return true; } size_t TouchIdCredentialStore::CountCredentials(base::Time created_not_before, base::Time created_not_after) { - if (base::FeatureList::IsEnabled(device::kWebAuthTouchId)) { - if (__builtin_available(macos 10.12.2, *)) { - return DoCountWebAuthnCredentials(config_.keychain_access_group, - config_.metadata_secret, - created_not_before, created_not_after); - } + if (__builtin_available(macos 10.12.2, *)) { + return DoCountWebAuthnCredentials(config_.keychain_access_group, + config_.metadata_secret, + created_not_before, created_not_after); } return 0; } diff --git a/chromium/device/fido/make_credential_handler_unittest.cc b/chromium/device/fido/make_credential_handler_unittest.cc index dd3b3188916..c51893c4c3d 100644 --- a/chromium/device/fido/make_credential_handler_unittest.cc +++ b/chromium/device/fido/make_credential_handler_unittest.cc @@ -7,9 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" -#include "device/base/features.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/fido/authenticator_make_credential_response.h" @@ -110,10 +108,6 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test { ::testing::UnorderedElementsAreArray(transports)); } - void InitFeatureListAndDisableCtapFlag() { - scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device); - } - test::FakeFidoDiscovery* discovery() const { return discovery_; } test::FakeFidoDiscovery* ble_discovery() const { return ble_discovery_; } test::FakeFidoDiscovery* nfc_discovery() const { return nfc_discovery_; } @@ -138,7 +132,6 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test { false /* has_recognized_mac_touch_id_credential_available */); } - base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedTaskEnvironment scoped_task_environment_{ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME}; test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_; @@ -161,7 +154,7 @@ TEST_F(FidoMakeCredentialHandlerTest, TransportAvailabilityInfo) { request_handler->transport_availability_info().rp_id); } -TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredentialWithFlagEnabled) { +TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredential) { auto request_handler = CreateMakeCredentialHandler(); discovery()->WaitForCallToStartAndSimulateSuccess(); @@ -177,7 +170,7 @@ TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredentialWithFlagEnabled) { } // Test a scenario where the connected authenticator is a U2F device. -TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithFlagEnabled) { +TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegister) { auto request_handler = CreateMakeCredentialHandler(); discovery()->WaitForCallToStartAndSimulateSuccess(); @@ -192,25 +185,6 @@ TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithFlagEnabled) { EXPECT_TRUE(request_handler->is_complete()); } -// Test a scenario where the connected authenticator is a U2F device using a -// logic that defaults to handling U2F devices. -TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithoutFlagEnabled) { - InitFeatureListAndDisableCtapFlag(); - auto request_handler = CreateMakeCredentialHandler(); - discovery()->WaitForCallToStartAndSimulateSuccess(); - - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectRequestAndRespondWith( - test_data::kU2fRegisterCommandApdu, - test_data::kApduEncodedNoErrorRegisterResponse); - - discovery()->AddDevice(std::move(device)); - callback().WaitForCallback(); - EXPECT_EQ(FidoReturnCode::kSuccess, callback().status()); - EXPECT_TRUE(request_handler->is_complete()); -} - TEST_F(FidoMakeCredentialHandlerTest, U2fRegisterWithUserVerificationRequired) { auto request_handler = CreateMakeCredentialHandlerWithAuthenticatorSelectionCriteria( diff --git a/chromium/device/fido/make_credential_task.cc b/chromium/device/fido/make_credential_task.cc index 1206da092cb..401b8ea878e 100644 --- a/chromium/device/fido/make_credential_task.cc +++ b/chromium/device/fido/make_credential_task.cc @@ -54,8 +54,7 @@ MakeCredentialTask::MakeCredentialTask( MakeCredentialTask::~MakeCredentialTask() = default; void MakeCredentialTask::StartTask() { - if (base::FeatureList::IsEnabled(kNewCtap2Device) && - device()->supported_protocol() == ProtocolVersion::kCtap && + if (device()->supported_protocol() == ProtocolVersion::kCtap && !request_parameter_.is_u2f_only() && !ShouldUseU2fBecauseCtapRequiresClientPin(device(), request_parameter_)) { MakeCredential(); diff --git a/chromium/device/fido/make_credential_task_unittest.cc b/chromium/device/fido/make_credential_task_unittest.cc index a63a27275f1..af609703a46 100644 --- a/chromium/device/fido/make_credential_task_unittest.cc +++ b/chromium/device/fido/make_credential_task_unittest.cc @@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/numerics/safe_conversions.h" #include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "device/base/features.h" #include "device/fido/authenticator_make_credential_response.h" @@ -42,7 +41,7 @@ using TestMakeCredentialTaskCallback = class FidoMakeCredentialTaskTest : public testing::Test { public: - FidoMakeCredentialTaskTest() { scoped_feature_list_.emplace(); } + FidoMakeCredentialTaskTest() {} std::unique_ptr<MakeCredentialTask> CreateMakeCredentialTask( FidoDevice* device) { @@ -58,17 +57,11 @@ class FidoMakeCredentialTaskTest : public testing::Test { callback_receiver_.callback()); } - void RemoveCtapFlag() { - scoped_feature_list_.emplace(); - scoped_feature_list_->InitAndDisableFeature(kNewCtap2Device); - } - TestMakeCredentialTaskCallback& make_credential_callback_receiver() { return callback_receiver_; } protected: - base::Optional<base::test::ScopedFeatureList> scoped_feature_list_; base::test::ScopedTaskEnvironment scoped_task_environment_; TestMakeCredentialTaskCallback callback_receiver_; }; @@ -121,20 +114,6 @@ TEST_F(FidoMakeCredentialTaskTest, FallbackToU2fRegisterSuccess) { make_credential_callback_receiver().status()); } -TEST_F(FidoMakeCredentialTaskTest, TestDefaultU2fRegisterOperationWithoutFlag) { - RemoveCtapFlag(); - auto device = MockFidoDevice::MakeU2f(); - device->ExpectRequestAndRespondWith( - test_data::kU2fRegisterCommandApdu, - test_data::kApduEncodedNoErrorRegisterResponse); - - const auto task = CreateMakeCredentialTask(device.get()); - make_credential_callback_receiver().WaitForCallback(); - - EXPECT_EQ(CtapDeviceResponseCode::kSuccess, - make_credential_callback_receiver().status()); -} - TEST_F(FidoMakeCredentialTaskTest, DefaultToU2fWhenClientPinSet) { AuthenticatorGetInfoResponse device_info( {ProtocolVersion::kCtap, ProtocolVersion::kU2f}, kTestDeviceAaguid); diff --git a/chromium/device/fido/u2f_command_constructor.cc b/chromium/device/fido/u2f_command_constructor.cc index 733d99cfeb8..22311068bf3 100644 --- a/chromium/device/fido/u2f_command_constructor.cc +++ b/chromium/device/fido/u2f_command_constructor.cc @@ -41,9 +41,12 @@ base::Optional<std::vector<uint8_t>> ConvertToU2fRegisterCommand( if (!IsConvertibleToU2fRegisterCommand(request)) return base::nullopt; + const bool is_invidual_attestation = + request.attestation_preference() == + AttestationConveyancePreference::ENTERPRISE; return ConstructU2fRegisterCommand( fido_parsing_utils::CreateSHA256Hash(request.rp().rp_id()), - request.client_data_hash(), request.is_individual_attestation()); + request.client_data_hash(), is_invidual_attestation); } base::Optional<std::vector<uint8_t>> ConvertToU2fCheckOnlySignCommand( diff --git a/chromium/device/fido/u2f_register_operation_unittest.cc b/chromium/device/fido/u2f_register_operation_unittest.cc index dacdfd3ff14..567ce6186f4 100644 --- a/chromium/device/fido/u2f_register_operation_unittest.cc +++ b/chromium/device/fido/u2f_register_operation_unittest.cc @@ -39,7 +39,10 @@ CtapMakeCredentialRequest CreateRegisterRequestWithRegisteredKeys( PublicKeyCredentialParams( std::vector<PublicKeyCredentialParams::CredentialInfo>(1))); request.SetExcludeList(std::move(registered_keys)); - request.SetIsIndividualAttestation(is_individual_attestation); + if (is_individual_attestation) + request.set_attestation_preference( + AttestationConveyancePreference::ENTERPRISE); + return request; } diff --git a/chromium/device/fido/win/authenticator.cc b/chromium/device/fido/win/authenticator.cc index eca65dabf8f..c26df0723da 100644 --- a/chromium/device/fido/win/authenticator.cc +++ b/chromium/device/fido/win/authenticator.cc @@ -122,7 +122,9 @@ void WinWebAuthnApiAuthenticator::MakeCredential( WEBAUTHN_EXTENSIONS{0, nullptr}, // will be set later authenticator_attachment, request.resident_key_required(), ToWinUserVerificationRequirement(request.user_verification()), - WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT, 0 /* flags */, + ToWinAttestationConveyancePreference( + request.attestation_preference()), + 0 /* flags */, nullptr, // pCancellationId -- will be set later nullptr, // pExcludeCredentialList -- will be set later }, diff --git a/chromium/device/fido/win/type_conversions.cc b/chromium/device/fido/win/type_conversions.cc index e7db7760090..20b94a763c6 100644 --- a/chromium/device/fido/win/type_conversions.cc +++ b/chromium/device/fido/win/type_conversions.cc @@ -35,7 +35,7 @@ ToAuthenticatorMakeCredentialResponse( base::Optional<cbor::Value> cbor_attestation_statement = cbor::Reader::Read( base::span<const uint8_t>(credential_attestation.pbAttestation, credential_attestation.cbAttestation)); - if (!cbor_attestation_statement) { + if (!cbor_attestation_statement || !cbor_attestation_statement->is_map()) { DLOG(ERROR) << "CBOR decoding attestation statement failed: " << base::HexEncode(credential_attestation.pbAttestation, credential_attestation.cbAttestation); @@ -67,7 +67,7 @@ ToAuthenticatorMakeCredentialResponse( } return AuthenticatorMakeCredentialResponse( - base::nullopt /* transport_used */, + transport_used, AttestationObject( std::move(*authenticator_data), std::make_unique<OpaqueAttestationStatement>( @@ -226,4 +226,21 @@ CtapDeviceResponseCode WinErrorNameToCtapDeviceResponseCode( : CtapDeviceResponseCode::kCtap2ErrOther; } +uint32_t ToWinAttestationConveyancePreference( + const AttestationConveyancePreference& value) { + switch (value) { + case AttestationConveyancePreference::NONE: + return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE; + case AttestationConveyancePreference::INDIRECT: + return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT; + case AttestationConveyancePreference::DIRECT: + return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT; + case AttestationConveyancePreference::ENTERPRISE: + // Windows does not support enterprise attestation. + return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT; + } + NOTREACHED(); + return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE; +} + } // namespace device diff --git a/chromium/device/fido/win/type_conversions.h b/chromium/device/fido/win/type_conversions.h index b0656aea91f..740979bc8ef 100644 --- a/chromium/device/fido/win/type_conversions.h +++ b/chromium/device/fido/win/type_conversions.h @@ -49,6 +49,10 @@ COMPONENT_EXPORT(DEVICE_FIDO) CtapDeviceResponseCode WinErrorNameToCtapDeviceResponseCode( const base::string16& error_name); +COMPONENT_EXPORT(DEVICE_FIDO) +uint32_t ToWinAttestationConveyancePreference( + const AttestationConveyancePreference&); + } // namespace device #endif // DEVICE_FIDO_WIN_TYPE_CONVERSIONS_H_ diff --git a/chromium/device/fido/win/type_conversions_unittest.cc b/chromium/device/fido/win/type_conversions_unittest.cc new file mode 100644 index 00000000000..ab02c1c5c6a --- /dev/null +++ b/chromium/device/fido/win/type_conversions_unittest.cc @@ -0,0 +1,132 @@ +// Copyright 2019 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/win/type_conversions.h" + +#include "base/strings/utf_string_conversions.h" +#include "components/cbor/values.h" +#include "components/cbor/writer.h" +#include "device/fido/attestation_object.h" +#include "device/fido/attestation_statement.h" +#include "device/fido/fido_parsing_utils.h" +#include "device/fido/fido_test_data.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { +namespace { + +TEST(TypeConversionsTest, ToAuthenticatorMakeCredentialResponse) { + struct TestCase { + const wchar_t* format; + std::vector<uint8_t> authenticator_data; + std::vector<uint8_t> cbor_attestation_statement; + uint8_t used_transport; // WEBAUTHN_CTAP_TRANSPORT_* from <webauthn.h> + bool success; + base::Optional<FidoTransportProtocol> expected_transport; + } test_cases[] = { + {L"packed", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + fido_parsing_utils::Materialize( + test_data::kPackedAttestationStatementCBOR), + WEBAUTHN_CTAP_TRANSPORT_USB, true, + FidoTransportProtocol::kUsbHumanInterfaceDevice}, + {L"packed", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + fido_parsing_utils::Materialize( + test_data::kPackedAttestationStatementCBOR), + WEBAUTHN_CTAP_TRANSPORT_NFC, true, + FidoTransportProtocol::kNearFieldCommunication}, + {L"packed", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + fido_parsing_utils::Materialize( + test_data::kPackedAttestationStatementCBOR), + WEBAUTHN_CTAP_TRANSPORT_INTERNAL, true, + FidoTransportProtocol::kInternal}, + {L"packed", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + fido_parsing_utils::Materialize( + test_data::kPackedAttestationStatementCBOR), + WEBAUTHN_CTAP_TRANSPORT_TEST, true, base::nullopt}, + // Unknown attestation formats + {L"weird-unknown-format", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + {0xa0}, // Empty CBOR map. + WEBAUTHN_CTAP_TRANSPORT_USB, + true, + FidoTransportProtocol::kUsbHumanInterfaceDevice}, + {L"weird-unknown-format", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + {0x60}, // Empty string. Not a valid attStmt. + WEBAUTHN_CTAP_TRANSPORT_USB, + false}, + // Invalid authenticator data + {L"packed", + {}, + fido_parsing_utils::Materialize( + test_data::kPackedAttestationStatementCBOR), + WEBAUTHN_CTAP_TRANSPORT_USB, + false}, + {L"packed", + {1, 2, 3}, + fido_parsing_utils::Materialize( + test_data::kPackedAttestationStatementCBOR), + WEBAUTHN_CTAP_TRANSPORT_USB, + false}, + // Invalid attestation statement + {L"packed", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + {}, + WEBAUTHN_CTAP_TRANSPORT_USB, + false}, + {L"packed", + fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData), + {1, 2, 3}, + WEBAUTHN_CTAP_TRANSPORT_USB, + false}, + }; + size_t i = 0; + for (const auto test : test_cases) { + SCOPED_TRACE(::testing::Message() << "Test case " << i++); + auto response = + ToAuthenticatorMakeCredentialResponse(WEBAUTHN_CREDENTIAL_ATTESTATION{ + WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3, + test.format, + test.authenticator_data.size(), + const_cast<unsigned char*>(test.authenticator_data.data()), + test.cbor_attestation_statement.size(), + const_cast<unsigned char*>(test.cbor_attestation_statement.data()), + // dwAttestationDecodeType and pvAttestationDecode are ignored. + WEBAUTHN_ATTESTATION_DECODE_NONE, + nullptr, + // cbAttestationObject and pbAttestationObject are ignored. + 0, + nullptr, + // cbCredentialId and pbCredentialId are ignored. + 0, + nullptr, + WEBAUTHN_EXTENSIONS{}, + test.used_transport, + }); + EXPECT_EQ(response.has_value(), test.success); + if (!response) + return; + + EXPECT_EQ(response->attestation_object() + .authenticator_data() + .SerializeToByteArray(), + test.authenticator_data); + EXPECT_EQ( + response->attestation_object().attestation_statement().format_name(), + base::UTF16ToUTF8(test.format)); + EXPECT_EQ(cbor::Writer::Write(cbor::Value(response->attestation_object() + .attestation_statement() + .GetAsCBORMap())), + test.cbor_attestation_statement); + EXPECT_EQ(response->transport_used(), test.expected_transport); + } +}; + +} // namespace +} // namespace device diff --git a/chromium/device/fido/win/webauthn_api.cc b/chromium/device/fido/win/webauthn_api.cc index 22765b41685..7e88a472802 100644 --- a/chromium/device/fido/win/webauthn_api.cc +++ b/chromium/device/fido/win/webauthn_api.cc @@ -18,7 +18,6 @@ #include "base/task_runner_util.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread.h" -#include "device/fido/features.h" #include "device/fido/win/type_conversions.h" namespace device { @@ -88,9 +87,7 @@ class WinWebAuthnApiImpl : public WinWebAuthnApi { // WinWebAuthnApi: bool IsAvailable() const override { - return is_bound_ && (api_version_ >= kMinWinWebAuthnApiVersion || - base::FeatureList::IsEnabled( - kWebAuthDisableWinApiVersionCheckForTesting)); + return is_bound_ && (api_version_ >= kMinWinWebAuthnApiVersion); } HRESULT IsUserVerifyingPlatformAuthenticatorAvailable(BOOL* result) override { |