WebAuthn: Use TestFuture in tests pt. 2
Getting rid of the TestCallbackReceiver duplication Bug: 347047628, 40275628 Change-Id: Ia638ece50aa2a0ed2b9ce9316e38d802daf74aa4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5644906 Reviewed-by: Adam Langley <agl@chromium.org> Commit-Queue: Adem Derinel <derinel@google.com> Cr-Commit-Position: refs/heads/main@{#1319576}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
685c84eef1
commit
7f954eebef
chrome/browser/webauthn
authenticator_request_dialog_model_unittest.ccchrome_authenticator_request_delegate_unittest.cclocal_credential_management_win_unittest.cc
content/browser/webauth
device/fido
@ -4,18 +4,32 @@
|
||||
|
||||
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/containers/to_vector.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/scoped_observation.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/test/bind.h"
|
||||
@ -25,6 +39,7 @@
|
||||
#include "base/types/strong_alias.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/app/vector_icons/vector_icons.h"
|
||||
#include "chrome/browser/password_manager/chrome_webauthn_credentials_delegate.h"
|
||||
#include "chrome/browser/password_manager/chrome_webauthn_credentials_delegate_factory.h"
|
||||
#include "chrome/browser/webauthn/authenticator_reference.h"
|
||||
#include "chrome/browser/webauthn/authenticator_transport.h"
|
||||
@ -37,7 +52,9 @@
|
||||
#include "components/sync/base/features.h"
|
||||
#include "components/vector_icons/vector_icons.h"
|
||||
#include "components/webauthn/core/browser/passkey_model.h"
|
||||
#include "content/public/browser/authenticator_request_client_delegate.h"
|
||||
#include "device/fido/cable/cable_discovery_data.h"
|
||||
#include "device/fido/cable/v2_constants.h"
|
||||
#include "device/fido/discoverable_credential_metadata.h"
|
||||
#include "device/fido/features.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
@ -45,14 +62,12 @@
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/platform_user_verification_policy.h"
|
||||
#include "device/fido/public_key_credential_descriptor.h"
|
||||
#include "device/fido/public_key_credential_user_entity.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/abseil-cpp/absl/types/variant.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/gfx/vector_icon_types.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "device/fido/win/fake_webauthn_api.h"
|
||||
|
@ -5,12 +5,23 @@
|
||||
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/test/scoped_command_line.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "base/values.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/password_manager/chrome_webauthn_credentials_delegate_factory.h"
|
||||
#include "chrome/browser/signin/identity_manager_factory.h"
|
||||
@ -21,15 +32,14 @@
|
||||
#include "chrome/browser/webauthn/webauthn_switches.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
|
||||
#include "chrome/test/base/testing_profile.h"
|
||||
#include "components/keyed_service/core/keyed_service.h"
|
||||
#include "components/network_session_configurator/common/network_switches.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/signin/public/base/consent_level.h"
|
||||
#include "components/signin/public/identity_manager/identity_test_utils.h"
|
||||
#include "components/sync/base/features.h"
|
||||
#include "components/sync/base/user_selectable_type.h"
|
||||
#include "components/sync/test/test_sync_service.h"
|
||||
#include "components/sync_preferences/testing_pref_service_syncable.h"
|
||||
#include "components/webauthn/core/browser/passkey_model.h"
|
||||
#include "components/webauthn/core/browser/test_passkey_model.h"
|
||||
#include "content/public/browser/authenticator_request_client_delegate.h"
|
||||
@ -37,14 +47,13 @@
|
||||
#include "content/public/test/web_contents_tester.h"
|
||||
#include "crypto/scoped_mock_unexportable_key_provider.h"
|
||||
#include "device/fido/cable/cable_discovery_data.h"
|
||||
#include "device/fido/cable/v2_constants.h"
|
||||
#include "device/fido/discoverable_credential_metadata.h"
|
||||
#include "device/fido/features.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_discovery_factory.h"
|
||||
#include "device/fido/fido_request_handler_base.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
#include "device/fido/virtual_fido_device_authenticator.h"
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
@ -63,6 +72,7 @@
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "chrome/test/base/testing_profile.h"
|
||||
#include "device/fido/mac/authenticator_config.h"
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
@ -712,11 +722,11 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest, VirtualEnvironmentAttestation) {
|
||||
delegate.SetVirtualEnvironment(true);
|
||||
device::VirtualFidoDeviceAuthenticator authenticator(
|
||||
std::make_unique<device::VirtualCtap2Device>());
|
||||
device::test::ValueCallbackReceiver<bool> cb;
|
||||
base::test::TestFuture<bool> future;
|
||||
delegate.ShouldReturnAttestation(kRelyingPartyID, &authenticator,
|
||||
/*is_enterprise_attestation=*/false,
|
||||
cb.callback());
|
||||
EXPECT_TRUE(cb.value());
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Get());
|
||||
}
|
||||
|
||||
// Tests that synced GPM passkeys are injected in the transport availability
|
||||
@ -1063,10 +1073,11 @@ TEST_F(EnclaveAuthenticatorRequestDelegateTest,
|
||||
.emplace<crypto::ScopedMockUnexportableKeyProvider>();
|
||||
}
|
||||
|
||||
device::test::ValueCallbackReceiver<bool> cb;
|
||||
delegate.BrowserProvidedPasskeysAvailable(browser_context(), cb.callback());
|
||||
cb.WaitForCallback();
|
||||
EXPECT_EQ(cb.value(), test.expected_passkeys_available);
|
||||
base::test::TestFuture<bool> future;
|
||||
delegate.BrowserProvidedPasskeysAvailable(browser_context(),
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
EXPECT_EQ(future.Get(), test.expected_passkeys_available);
|
||||
signin::ClearPrimaryAccount(identity_manager);
|
||||
}
|
||||
}
|
||||
@ -1128,13 +1139,13 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest, ShouldPromptForAttestationWin) {
|
||||
::device::WinWebAuthnApiAuthenticator authenticator(
|
||||
/*current_window=*/nullptr, &win_webauthn_api);
|
||||
|
||||
::device::test::ValueCallbackReceiver<bool> cb;
|
||||
base::test::TestFuture<bool> future;
|
||||
ChromeAuthenticatorRequestDelegate delegate(main_rfh());
|
||||
delegate.ShouldReturnAttestation(kRelyingPartyID, &authenticator,
|
||||
/*is_enterprise_attestation=*/false,
|
||||
cb.callback());
|
||||
cb.WaitForCallback();
|
||||
EXPECT_EQ(cb.value(), true);
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
EXPECT_EQ(future.Get(), true);
|
||||
}
|
||||
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
@ -2,17 +2,18 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "chrome/browser/webauthn/local_credential_management_win.h"
|
||||
|
||||
#include "base/run_loop.h"
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "base/test/test_future.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/test/base/testing_profile.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/sync_preferences/testing_pref_service_syncable.h"
|
||||
#include "content/public/test/browser_task_environment.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/discoverable_credential_metadata.h"
|
||||
#include "device/fido/win/fake_webauthn_api.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -30,22 +31,22 @@ class LocalCredentialManagementTest : public testing::Test {
|
||||
void SetUp() override { api_.set_supports_silent_discovery(true); }
|
||||
|
||||
bool HasCredentials() {
|
||||
device::test::TestCallbackReceiver<bool> callback;
|
||||
local_cred_man_.HasCredentials(callback.callback());
|
||||
base::test::TestFuture<bool> future;
|
||||
local_cred_man_.HasCredentials(future.GetCallback());
|
||||
|
||||
callback.WaitForCallback();
|
||||
return std::get<0>(callback.TakeResult());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
return future.Get();
|
||||
}
|
||||
|
||||
std::optional<std::vector<device::DiscoverableCredentialMetadata>>
|
||||
Enumerate() {
|
||||
device::test::TestCallbackReceiver<
|
||||
base::test::TestFuture<
|
||||
std::optional<std::vector<device::DiscoverableCredentialMetadata>>>
|
||||
callback;
|
||||
local_cred_man_.Enumerate(callback.callback());
|
||||
future;
|
||||
local_cred_man_.Enumerate(future.GetCallback());
|
||||
|
||||
callback.WaitForCallback();
|
||||
return std::get<0>(callback.TakeResult());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
return future.Get();
|
||||
}
|
||||
|
||||
// A `BrowserTaskEnvironment` needs to be in-scope in order to create a
|
||||
|
@ -4,26 +4,31 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/base64.h"
|
||||
#include "base/check.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/test/bind.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "base/values.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "base/time/time.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/cbor/reader.h"
|
||||
#include "content/browser/payments/stub_payment_credential.h"
|
||||
#include "content/browser/renderer_host/back_forward_cache_disable.h"
|
||||
#include "content/browser/renderer_host/render_frame_host_impl.h"
|
||||
@ -50,23 +55,22 @@
|
||||
#include "content/shell/browser/shell.h"
|
||||
#include "content/test/did_commit_navigation_interceptor.h"
|
||||
#include "content/test/fake_network_url_loader_factory.h"
|
||||
#include "crypto/sha2.h"
|
||||
#include "crypto/signature_verifier.h"
|
||||
#include "device/base/features.h"
|
||||
#include "device/fido/fake_fido_discovery.h"
|
||||
#include "device/fido/features.h"
|
||||
#include "device/fido/fido_discovery_factory.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/hid/fake_hid_impl_for_testing.h"
|
||||
#include "device/fido/mock_fido_device.h"
|
||||
#include "device/fido/p256_public_key.h"
|
||||
#include "device/fido/public_key.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/public_key_credential_params.h"
|
||||
#include "device/fido/virtual_fido_device.h"
|
||||
#include "device/fido/virtual_fido_device_factory.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "net/dns/mock_host_resolver.h"
|
||||
#include "net/test/embedded_test_server/embedded_test_server.h"
|
||||
#include "services/network/public/cpp/resource_request.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "services/network/public/mojom/url_loader.mojom.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
|
||||
@ -87,16 +91,15 @@ using blink::mojom::GetAssertionAuthenticatorResponsePtr;
|
||||
using blink::mojom::MakeCredentialAuthenticatorResponsePtr;
|
||||
using blink::mojom::WebAuthnDOMExceptionDetailsPtr;
|
||||
|
||||
using TestCreateCallbackReceiver =
|
||||
device::test::StatusAndValuesCallbackReceiver<
|
||||
AuthenticatorStatus,
|
||||
MakeCredentialAuthenticatorResponsePtr,
|
||||
WebAuthnDOMExceptionDetailsPtr>;
|
||||
using TestCreateFuture =
|
||||
base::test::TestFuture<AuthenticatorStatus,
|
||||
MakeCredentialAuthenticatorResponsePtr,
|
||||
WebAuthnDOMExceptionDetailsPtr>;
|
||||
|
||||
using TestGetCallbackReceiver = device::test::StatusAndValuesCallbackReceiver<
|
||||
AuthenticatorStatus,
|
||||
GetAssertionAuthenticatorResponsePtr,
|
||||
WebAuthnDOMExceptionDetailsPtr>;
|
||||
using TestGetFuture =
|
||||
base::test::TestFuture<AuthenticatorStatus,
|
||||
GetAssertionAuthenticatorResponsePtr,
|
||||
WebAuthnDOMExceptionDetailsPtr>;
|
||||
|
||||
constexpr char kOkMessage[] = "OK";
|
||||
|
||||
@ -767,10 +770,10 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
base::BindLambdaForTesting(
|
||||
[&](device::VirtualFidoDevice* device) { return false; });
|
||||
|
||||
TestCreateCallbackReceiver create_callback_receiver;
|
||||
TestCreateFuture create_future;
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
create_callback_receiver.callback());
|
||||
ASSERT_FALSE(create_callback_receiver.was_called());
|
||||
create_future.GetCallback());
|
||||
ASSERT_FALSE(create_future.IsReady());
|
||||
EXPECT_TRUE(
|
||||
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html")));
|
||||
WaitForConnectionError();
|
||||
@ -779,11 +782,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
// navigator.credentials.create({publicKey: ...}) again.
|
||||
ConnectToAuthenticator();
|
||||
InjectVirtualFidoDeviceFactory();
|
||||
TestCreateCallbackReceiver create_callback_receiver2;
|
||||
TestCreateFuture create_future2;
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
create_callback_receiver2.callback());
|
||||
create_callback_receiver2.WaitForCallback();
|
||||
EXPECT_EQ(create_callback_receiver2.status(), AuthenticatorStatus::SUCCESS);
|
||||
create_future2.GetCallback());
|
||||
EXPECT_TRUE(create_future2.Wait());
|
||||
EXPECT_EQ(std::get<0>(create_future2.Get()), AuthenticatorStatus::SUCCESS);
|
||||
}
|
||||
|
||||
// Tests that no crash occurs when the implementation is destroyed with a
|
||||
@ -796,10 +799,10 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
base::BindLambdaForTesting(
|
||||
[&](device::VirtualFidoDevice* device) { return false; });
|
||||
|
||||
TestGetCallbackReceiver get_callback_receiver;
|
||||
TestGetFuture get_future;
|
||||
authenticator()->GetAssertion(BuildBasicGetOptions(),
|
||||
get_callback_receiver.callback());
|
||||
ASSERT_FALSE(get_callback_receiver.was_called());
|
||||
get_future.GetCallback());
|
||||
ASSERT_FALSE(get_future.IsReady());
|
||||
EXPECT_TRUE(
|
||||
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html")));
|
||||
WaitForConnectionError();
|
||||
@ -808,11 +811,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
// navigator.credentials.get({publicKey: ...}) again.
|
||||
ConnectToAuthenticator();
|
||||
InjectVirtualFidoDeviceFactory();
|
||||
TestGetCallbackReceiver get_callback_receiver2;
|
||||
TestGetFuture get_future2;
|
||||
authenticator()->GetAssertion(BuildBasicGetOptions(),
|
||||
get_callback_receiver2.callback());
|
||||
get_callback_receiver2.WaitForCallback();
|
||||
EXPECT_EQ(get_callback_receiver2.status(),
|
||||
get_future2.GetCallback());
|
||||
EXPECT_TRUE(get_future2.Wait());
|
||||
EXPECT_EQ(std::get<0>(get_future2.Get()),
|
||||
AuthenticatorStatus::NOT_ALLOWED_ERROR);
|
||||
}
|
||||
|
||||
@ -847,11 +850,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
SCOPED_TRACE(AttestationCallbackBehaviorToString(behavior));
|
||||
|
||||
InjectVirtualFidoDeviceFactory();
|
||||
TestCreateCallbackReceiver create_callback_receiver;
|
||||
TestCreateFuture create_future;
|
||||
auto options = BuildBasicCreateOptions();
|
||||
options->attestation = device::AttestationConveyancePreference::kDirect;
|
||||
authenticator()->MakeCredential(std::move(options),
|
||||
create_callback_receiver.callback());
|
||||
create_future.GetCallback());
|
||||
bool attestation_callback_was_invoked = false;
|
||||
test_state()->attestation_prompt_callback_ = base::BindLambdaForTesting(
|
||||
[&](base::OnceCallback<void(bool)> callback) {
|
||||
@ -887,11 +890,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html")));
|
||||
|
||||
InjectVirtualFidoDeviceFactory();
|
||||
TestCreateCallbackReceiver create_callback_receiver;
|
||||
TestCreateFuture create_future;
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
create_callback_receiver.callback());
|
||||
create_callback_receiver.WaitForCallback();
|
||||
EXPECT_EQ(create_callback_receiver.status(), AuthenticatorStatus::SUCCESS);
|
||||
create_future.GetCallback());
|
||||
EXPECT_TRUE(create_future.Wait());
|
||||
EXPECT_EQ(std::get<0>(create_future.Get()), AuthenticatorStatus::SUCCESS);
|
||||
}
|
||||
|
||||
// Tests that a navigator.credentials.create({publicKey: ...}) issued at the
|
||||
@ -900,13 +903,13 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
CreatePublicKeyCredentialRacingWithNavigation) {
|
||||
InjectVirtualFidoDeviceFactory();
|
||||
|
||||
TestCreateCallbackReceiver create_callback_receiver;
|
||||
TestCreateFuture create_future;
|
||||
auto request_options = BuildBasicCreateOptions();
|
||||
|
||||
ClosureExecutorBeforeNavigationCommit executor(
|
||||
shell()->web_contents(), base::BindLambdaForTesting([&]() {
|
||||
authenticator()->MakeCredential(std::move(request_options),
|
||||
create_callback_receiver.callback());
|
||||
create_future.GetCallback());
|
||||
}));
|
||||
|
||||
EXPECT_TRUE(
|
||||
@ -916,11 +919,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
// The next active document should be able to successfully call
|
||||
// navigator.credentials.create({publicKey: ...}) again.
|
||||
ConnectToAuthenticator();
|
||||
TestCreateCallbackReceiver create_callback_receiver2;
|
||||
TestCreateFuture create_future2;
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
create_callback_receiver2.callback());
|
||||
create_callback_receiver2.WaitForCallback();
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, create_callback_receiver2.status());
|
||||
create_future2.GetCallback());
|
||||
EXPECT_TRUE(create_future2.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, std::get<0>(create_future2.Get()));
|
||||
}
|
||||
|
||||
// Regression test for https://crbug.com/818219.
|
||||
@ -932,16 +935,16 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
base::BindLambdaForTesting(
|
||||
[&](device::VirtualFidoDevice* device) { return false; });
|
||||
|
||||
TestCreateCallbackReceiver callback_receiver_1;
|
||||
TestCreateCallbackReceiver callback_receiver_2;
|
||||
TestCreateFuture future_1;
|
||||
TestCreateFuture future_2;
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
callback_receiver_1.callback());
|
||||
future_1.GetCallback());
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
callback_receiver_2.callback());
|
||||
callback_receiver_2.WaitForCallback();
|
||||
future_2.GetCallback());
|
||||
EXPECT_TRUE(future_2.Wait());
|
||||
|
||||
EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver_2.status());
|
||||
EXPECT_FALSE(callback_receiver_1.was_called());
|
||||
EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, std::get<0>(future_2.Get()));
|
||||
EXPECT_FALSE(future_1.IsReady());
|
||||
}
|
||||
|
||||
// Regression test for https://crbug.com/818219.
|
||||
@ -953,16 +956,14 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
|
||||
base::BindLambdaForTesting(
|
||||
[&](device::VirtualFidoDevice* device) { return false; });
|
||||
|
||||
TestGetCallbackReceiver callback_receiver_1;
|
||||
TestGetCallbackReceiver callback_receiver_2;
|
||||
authenticator()->GetAssertion(BuildBasicGetOptions(),
|
||||
callback_receiver_1.callback());
|
||||
authenticator()->GetAssertion(BuildBasicGetOptions(),
|
||||
callback_receiver_2.callback());
|
||||
callback_receiver_2.WaitForCallback();
|
||||
TestGetFuture future_1;
|
||||
TestGetFuture future_2;
|
||||
authenticator()->GetAssertion(BuildBasicGetOptions(), future_1.GetCallback());
|
||||
authenticator()->GetAssertion(BuildBasicGetOptions(), future_2.GetCallback());
|
||||
EXPECT_TRUE(future_2.Wait());
|
||||
|
||||
EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver_2.status());
|
||||
EXPECT_FALSE(callback_receiver_1.was_called());
|
||||
EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, std::get<0>(future_2.Get()));
|
||||
EXPECT_FALSE(future_1.IsReady());
|
||||
}
|
||||
|
||||
// WebAuthJavascriptClientBrowserTest -----------------------------------------
|
||||
@ -1954,12 +1955,12 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestMakeCredential) {
|
||||
auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
|
||||
virtual_device_factory->SetSupportedProtocol(protocol);
|
||||
|
||||
TestCreateCallbackReceiver create_callback_receiver;
|
||||
TestCreateFuture create_future;
|
||||
authenticator()->MakeCredential(BuildBasicCreateOptions(),
|
||||
create_callback_receiver.callback());
|
||||
create_future.GetCallback());
|
||||
|
||||
create_callback_receiver.WaitForCallback();
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, create_callback_receiver.status());
|
||||
EXPECT_TRUE(create_future.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, std::get<0>(create_future.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1982,13 +1983,13 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
|
||||
device::test_data::kCtap2MakeCredentialCredentialId),
|
||||
make_credential_request->relying_party.id));
|
||||
|
||||
TestCreateCallbackReceiver create_callback_receiver;
|
||||
TestCreateFuture create_future;
|
||||
authenticator()->MakeCredential(std::move(make_credential_request),
|
||||
create_callback_receiver.callback());
|
||||
create_future.GetCallback());
|
||||
|
||||
create_callback_receiver.WaitForCallback();
|
||||
EXPECT_TRUE(create_future.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_EXCLUDED,
|
||||
create_callback_receiver.status());
|
||||
std::get<0>(create_future.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2002,11 +2003,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestGetAssertion) {
|
||||
device::test_data::kTestGetAssertionCredentialId),
|
||||
get_assertion_request_params->relying_party_id));
|
||||
|
||||
TestGetCallbackReceiver get_callback_receiver;
|
||||
TestGetFuture get_future;
|
||||
authenticator()->GetAssertion(std::move(get_assertion_request_params),
|
||||
get_callback_receiver.callback());
|
||||
get_callback_receiver.WaitForCallback();
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, get_callback_receiver.status());
|
||||
get_future.GetCallback());
|
||||
EXPECT_TRUE(get_future.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, std::get<0>(get_future.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2017,12 +2018,12 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
|
||||
virtual_device_factory->SetSupportedProtocol(protocol);
|
||||
auto get_assertion_request_params = BuildBasicGetOptions();
|
||||
|
||||
TestGetCallbackReceiver get_callback_receiver;
|
||||
TestGetFuture get_future;
|
||||
authenticator()->GetAssertion(std::move(get_assertion_request_params),
|
||||
get_callback_receiver.callback());
|
||||
get_callback_receiver.WaitForCallback();
|
||||
get_future.GetCallback());
|
||||
EXPECT_TRUE(get_future.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
|
||||
get_callback_receiver.status());
|
||||
std::get<0>(get_future.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2073,11 +2074,11 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
|
||||
device::test_data::kTestGetAssertionCredentialId),
|
||||
get_assertion_request_params->relying_party_id));
|
||||
|
||||
TestGetCallbackReceiver get_callback_receiver;
|
||||
TestGetFuture get_future;
|
||||
authenticator()->GetAssertion(std::move(get_assertion_request_params),
|
||||
get_callback_receiver.callback());
|
||||
get_callback_receiver.WaitForCallback();
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, get_callback_receiver.status());
|
||||
get_future.GetCallback());
|
||||
EXPECT_TRUE(get_future.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::SUCCESS, std::get<0>(get_future.Get()));
|
||||
|
||||
EXPECT_THAT(logger->log(), testing::ElementsAre("www.acme.com"));
|
||||
}
|
||||
@ -2093,12 +2094,12 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
|
||||
blink::mojom::PublicKeyCredentialRequestOptionsPtr
|
||||
get_assertion_request_params = BuildBasicGetOptions();
|
||||
|
||||
TestGetCallbackReceiver get_callback_receiver;
|
||||
TestGetFuture get_future;
|
||||
authenticator()->GetAssertion(std::move(get_assertion_request_params),
|
||||
get_callback_receiver.callback());
|
||||
get_callback_receiver.WaitForCallback();
|
||||
get_future.GetCallback());
|
||||
EXPECT_TRUE(get_future.Wait());
|
||||
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
|
||||
get_callback_receiver.status());
|
||||
std::get<0>(get_future.Get()));
|
||||
|
||||
EXPECT_TRUE(logger->log().empty());
|
||||
}
|
||||
|
@ -4,15 +4,17 @@
|
||||
|
||||
#include "device/fido/ble_adapter_manager.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/test/gmock_callback_support.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "device/bluetooth/bluetooth_adapter.h"
|
||||
#include "device/bluetooth/bluetooth_adapter_factory.h"
|
||||
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
|
||||
@ -21,7 +23,6 @@
|
||||
#include "device/fido/fido_authenticator.h"
|
||||
#include "device/fido/fido_request_handler_base.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -238,10 +239,10 @@ TEST_F(FidoBleAdapterManagerTest, RequestBluetoothPermissionAllowed) {
|
||||
SetAdapterPermissions(BluetoothAdapter::PermissionStatus::kAllowed);
|
||||
EXPECT_CALL(*adapter(), IsPowered).WillOnce(::testing::Return(true));
|
||||
|
||||
test::ValueCallbackReceiver<BleStatus> callback;
|
||||
fake_request_handler_->RequestBluetoothPermission(callback.callback());
|
||||
callback.WaitForCallback();
|
||||
EXPECT_EQ(callback.value(), BleStatus::kOn);
|
||||
base::test::TestFuture<BleStatus> future;
|
||||
fake_request_handler_->RequestBluetoothPermission(future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
EXPECT_EQ(future.Get(), BleStatus::kOn);
|
||||
}
|
||||
|
||||
TEST_F(FidoBleAdapterManagerTest, RequestBluetoothPermissionDenied) {
|
||||
@ -249,10 +250,10 @@ TEST_F(FidoBleAdapterManagerTest, RequestBluetoothPermissionDenied) {
|
||||
SetAdapterPermissions(BluetoothAdapter::PermissionStatus::kDenied);
|
||||
EXPECT_CALL(*adapter(), IsPowered).Times(0);
|
||||
|
||||
test::ValueCallbackReceiver<BleStatus> callback;
|
||||
fake_request_handler_->RequestBluetoothPermission(callback.callback());
|
||||
callback.WaitForCallback();
|
||||
EXPECT_EQ(callback.value(), BleStatus::kPermissionDenied);
|
||||
base::test::TestFuture<BleStatus> future;
|
||||
fake_request_handler_->RequestBluetoothPermission(future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
EXPECT_EQ(future.Get(), BleStatus::kPermissionDenied);
|
||||
}
|
||||
|
||||
// Tests that if the Bluetooth API happens to report the OS permission status as
|
||||
@ -264,10 +265,10 @@ TEST_F(FidoBleAdapterManagerTest,
|
||||
SetAdapterPermissions(BluetoothAdapter::PermissionStatus::kUndetermined);
|
||||
EXPECT_CALL(*adapter(), IsPowered).WillOnce(::testing::Return(true));
|
||||
|
||||
test::ValueCallbackReceiver<BleStatus> callback;
|
||||
fake_request_handler_->RequestBluetoothPermission(callback.callback());
|
||||
callback.WaitForCallback();
|
||||
EXPECT_EQ(callback.value(), BleStatus::kOn);
|
||||
base::test::TestFuture<BleStatus> future;
|
||||
fake_request_handler_->RequestBluetoothPermission(future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
EXPECT_EQ(future.Get(), BleStatus::kOn);
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
|
@ -5,23 +5,28 @@
|
||||
#include "device/fido/cable/fido_cable_device.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/check.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/location.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "crypto/aead.h"
|
||||
#include "device/bluetooth/test/bluetooth_test.h"
|
||||
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
|
||||
#include "device/fido/cable/mock_fido_ble_connection.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -32,8 +37,8 @@ namespace {
|
||||
using ::testing::_;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::Test;
|
||||
using TestDeviceCallbackReceiver =
|
||||
test::ValueCallbackReceiver<std::optional<std::vector<uint8_t>>>;
|
||||
using TestDeviceFuture =
|
||||
base::test::TestFuture<std::optional<std::vector<uint8_t>>>;
|
||||
using NiceMockBluetoothAdapter = ::testing::NiceMock<MockBluetoothAdapter>;
|
||||
|
||||
// Sufficiently large test control point length as we are not interested
|
||||
@ -192,13 +197,13 @@ TEST_F(FidoCableDeviceTest, GetIdTest) {
|
||||
|
||||
TEST_F(FidoCableDeviceTest, Timeout) {
|
||||
EXPECT_CALL(*connection(), ConnectPtr);
|
||||
TestDeviceCallbackReceiver callback_receiver;
|
||||
device()->SendPing(std::vector<uint8_t>(), callback_receiver.callback());
|
||||
TestDeviceFuture future;
|
||||
device()->SendPing(std::vector<uint8_t>(), future.GetCallback());
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(FidoDevice::State::kDeviceError, device()->state_for_testing());
|
||||
EXPECT_TRUE(callback_receiver.was_called());
|
||||
EXPECT_FALSE(callback_receiver.value());
|
||||
EXPECT_TRUE(future.IsReady());
|
||||
EXPECT_FALSE(future.Get());
|
||||
}
|
||||
|
||||
TEST_F(FidoCableDeviceTest, TestCaBleDeviceSendData) {
|
||||
@ -220,12 +225,12 @@ TEST_F(FidoCableDeviceTest, TestCaBleDeviceSendData) {
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
SCOPED_TRACE(i);
|
||||
|
||||
TestDeviceCallbackReceiver callback_receiver;
|
||||
TestDeviceFuture future;
|
||||
device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
|
||||
callback_receiver.callback());
|
||||
future.GetCallback());
|
||||
|
||||
callback_receiver.WaitForCallback();
|
||||
const auto& value = callback_receiver.value();
|
||||
EXPECT_TRUE(future.Wait());
|
||||
const auto& value = future.Get();
|
||||
ASSERT_TRUE(value);
|
||||
EXPECT_THAT(*value, ::testing::ElementsAreArray(kTestData));
|
||||
}
|
||||
@ -251,12 +256,12 @@ TEST_F(FidoCableDeviceTest, TestCableDeviceFailOnIncorrectSessionKey) {
|
||||
authenticator_reply)));
|
||||
}));
|
||||
|
||||
TestDeviceCallbackReceiver callback_receiver;
|
||||
TestDeviceFuture future;
|
||||
device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
|
||||
callback_receiver.callback());
|
||||
future.GetCallback());
|
||||
|
||||
callback_receiver.WaitForCallback();
|
||||
const auto& value = callback_receiver.value();
|
||||
EXPECT_TRUE(future.Wait());
|
||||
const auto& value = future.Get();
|
||||
EXPECT_FALSE(value);
|
||||
}
|
||||
|
||||
@ -280,12 +285,12 @@ TEST_F(FidoCableDeviceTest, TestCableDeviceFailOnUnexpectedCounter) {
|
||||
authenticator_reply)));
|
||||
}));
|
||||
|
||||
TestDeviceCallbackReceiver callback_receiver;
|
||||
TestDeviceFuture future;
|
||||
device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
|
||||
callback_receiver.callback());
|
||||
future.GetCallback());
|
||||
|
||||
callback_receiver.WaitForCallback();
|
||||
const auto& value = callback_receiver.value();
|
||||
EXPECT_TRUE(future.Wait());
|
||||
const auto& value = future.Get();
|
||||
EXPECT_FALSE(value);
|
||||
}
|
||||
|
||||
@ -312,13 +317,13 @@ TEST_F(FidoCableDeviceTest, TestCableDeviceErrorOnMaxCounter) {
|
||||
authenticator_reply)));
|
||||
}));
|
||||
|
||||
TestDeviceCallbackReceiver callback_receiver;
|
||||
TestDeviceFuture future;
|
||||
device()->SetSequenceNumbersForTesting(kInvalidCounter, 0);
|
||||
device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
|
||||
callback_receiver.callback());
|
||||
future.GetCallback());
|
||||
|
||||
callback_receiver.WaitForCallback();
|
||||
const auto& value = callback_receiver.value();
|
||||
EXPECT_TRUE(future.Wait());
|
||||
const auto& value = future.Get();
|
||||
EXPECT_FALSE(value);
|
||||
}
|
||||
|
||||
|
@ -4,20 +4,35 @@
|
||||
|
||||
#include "device/fido/credential_management_handler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "device/fido/credential_management.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/large_blob.h"
|
||||
#include "device/fido/public_key_credential_descriptor.h"
|
||||
#include "device/fido/public_key_credential_rp_entity.h"
|
||||
#include "device/fido/public_key_credential_user_entity.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
#include "device/fido/virtual_fido_device.h"
|
||||
#include "device/fido/virtual_fido_device_factory.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@ -44,7 +59,7 @@ class CredentialManagementHandlerTest : public ::testing::Test {
|
||||
&virtual_device_factory_,
|
||||
base::flat_set<FidoTransportProtocol>{
|
||||
FidoTransportProtocol::kUsbHumanInterfaceDevice},
|
||||
ready_callback_.callback(),
|
||||
ready_future_.GetCallback(),
|
||||
base::BindRepeating(&CredentialManagementHandlerTest::GetPIN,
|
||||
base::Unretained(this)),
|
||||
finished_callback_.callback());
|
||||
@ -59,7 +74,7 @@ class CredentialManagementHandlerTest : public ::testing::Test {
|
||||
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
|
||||
test::TestCallbackReceiver<> ready_callback_;
|
||||
base::test::TestFuture<void> ready_future_;
|
||||
test::StatusAndValuesCallbackReceiver<
|
||||
CtapDeviceResponseCode,
|
||||
std::optional<std::vector<AggregatedEnumerateCredentialsResponse>>,
|
||||
@ -91,7 +106,7 @@ TEST_F(CredentialManagementHandlerTest, TestDeleteCredentials) {
|
||||
kCredentialID, rp, user));
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
ASSERT_TRUE(ready_future_.Wait());
|
||||
|
||||
handler->GetCredentials(get_credentials_callback_.callback());
|
||||
get_credentials_callback_.WaitForCallback();
|
||||
@ -155,7 +170,7 @@ TEST_F(CredentialManagementHandlerTest, TestGarbageCollectLargeBlob_Startup) {
|
||||
virtual_device_factory_.mutable_state()->registrations.clear();
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
EXPECT_TRUE(ready_future_.Wait());
|
||||
EXPECT_EQ(virtual_device_factory_.mutable_state()->large_blob,
|
||||
empty_large_blob);
|
||||
}
|
||||
@ -178,7 +193,7 @@ TEST_F(CredentialManagementHandlerTest, TestGarbageCollectLargeBlob_Delete) {
|
||||
virtual_device_factory_.mutable_state()->large_blob;
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
EXPECT_TRUE(ready_future_.Wait());
|
||||
|
||||
PublicKeyCredentialRpEntity rp(kRPID, kRPName);
|
||||
PublicKeyCredentialUserEntity user(fido_parsing_utils::Materialize(kUserID),
|
||||
@ -224,7 +239,7 @@ TEST_F(CredentialManagementHandlerTest,
|
||||
virtual_device_factory_.mutable_state()->large_blob;
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
EXPECT_TRUE(ready_future_.Wait());
|
||||
|
||||
PublicKeyCredentialRpEntity rp(kRPID, kRPName);
|
||||
PublicKeyCredentialUserEntity user(fido_parsing_utils::Materialize(kUserID),
|
||||
@ -277,7 +292,7 @@ TEST_F(CredentialManagementHandlerTest, TestUpdateUserInformation) {
|
||||
kCredentialID, rp, user));
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
EXPECT_TRUE(ready_future_.Wait());
|
||||
|
||||
PublicKeyCredentialUserEntity updated_user(
|
||||
fido_parsing_utils::Materialize(kUserID), "bobbyr@example.com",
|
||||
@ -358,7 +373,7 @@ TEST_F(CredentialManagementHandlerTest,
|
||||
base::StrCat({display_name, kTruncatedUTF8}))));
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
EXPECT_TRUE(ready_future_.Wait());
|
||||
handler->GetCredentials(get_credentials_callback_.callback());
|
||||
get_credentials_callback_.WaitForCallback();
|
||||
|
||||
@ -407,7 +422,7 @@ TEST_F(CredentialManagementHandlerTest, EnumerateCredentialsMultipleRPs) {
|
||||
}
|
||||
|
||||
auto handler = MakeHandler();
|
||||
ready_callback_.WaitForCallback();
|
||||
EXPECT_TRUE(ready_future_.Wait());
|
||||
|
||||
handler->GetCredentials(get_credentials_callback_.callback());
|
||||
get_credentials_callback_.WaitForCallback();
|
||||
|
@ -2,42 +2,54 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/location.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "base/time/time.h"
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.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/ctap_make_credential_request.h"
|
||||
#include "device/fido/device_response_converter.h"
|
||||
#include "device/fido/fake_fido_discovery.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_device_authenticator.h"
|
||||
#include "device/fido/fido_discovery_base.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_request_handler_base.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/get_assertion_request_handler.h"
|
||||
#include "device/fido/hid/fake_hid_impl_for_testing.h"
|
||||
#include "device/fido/make_credential_task.h"
|
||||
#include "device/fido/mock_fido_device.h"
|
||||
#include "device/fido/public_key_credential_descriptor.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/u2f_command_constructor.h"
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
#include "device/fido/virtual_fido_device.h"
|
||||
#include "device/fido/virtual_fido_device_factory.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "device/fido/hid/fake_hid_impl_for_testing.h"
|
||||
#include "device/fido/win/fake_webauthn_api.h"
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
@ -55,7 +67,7 @@ constexpr char kRequestTransportHistogram[] =
|
||||
constexpr char kResponseTransportHistogram[] =
|
||||
"WebAuthentication.GetAssertionResponseTransport";
|
||||
|
||||
using TestGetAssertionRequestCallback = test::StatusAndValuesCallbackReceiver<
|
||||
using TestGetAssertionRequestFuture = base::test::TestFuture<
|
||||
GetAssertionStatus,
|
||||
std::optional<std::vector<AuthenticatorGetAssertionResponse>>,
|
||||
FidoAuthenticator*>;
|
||||
@ -125,7 +137,7 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
|
||||
fake_discovery_factory_.get(),
|
||||
std::vector<std::unique_ptr<FidoDiscoveryBase>>(),
|
||||
supported_transports_, std::move(request), CtapGetAssertionOptions(),
|
||||
/*allow_skipping_pin_touch=*/true, get_assertion_cb_.callback());
|
||||
/*allow_skipping_pin_touch=*/true, get_assertion_future_.GetCallback());
|
||||
return handler;
|
||||
}
|
||||
|
||||
@ -156,7 +168,7 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
|
||||
platform_discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(get_assertion_callback().was_called());
|
||||
EXPECT_FALSE(get_assertion_future().IsReady());
|
||||
|
||||
if (!base::Contains(transports, Transport::kUsbHumanInterfaceDevice))
|
||||
EXPECT_FALSE(discovery()->is_start_requested());
|
||||
@ -187,8 +199,8 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
|
||||
test::FakeFidoDiscovery* platform_discovery() const {
|
||||
return platform_discovery_;
|
||||
}
|
||||
TestGetAssertionRequestCallback& get_assertion_callback() {
|
||||
return get_assertion_cb_;
|
||||
TestGetAssertionRequestFuture& get_assertion_future() {
|
||||
return get_assertion_future_;
|
||||
}
|
||||
|
||||
void set_supported_transports(
|
||||
@ -207,7 +219,7 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
|
||||
raw_ptr<test::FakeFidoDiscovery, DanglingUntriaged> platform_discovery_;
|
||||
scoped_refptr<::testing::NiceMock<MockBluetoothAdapter>> mock_adapter_ =
|
||||
base::MakeRefCounted<::testing::NiceMock<MockBluetoothAdapter>>();
|
||||
TestGetAssertionRequestCallback get_assertion_cb_;
|
||||
TestGetAssertionRequestFuture get_assertion_future_;
|
||||
base::flat_set<FidoTransportProtocol> supported_transports_ = {
|
||||
FidoTransportProtocol::kUsbHumanInterfaceDevice,
|
||||
FidoTransportProtocol::kInternal,
|
||||
@ -348,10 +360,11 @@ TEST_F(FidoGetAssertionHandlerTest, CtapRequestOnSingleDevice) {
|
||||
test_data::kTestGetAssertionResponse);
|
||||
|
||||
discovery()->AddDevice(std::move(device));
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_callback().value<0>());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
// Test a scenario where the connected authenticator is a U2F device.
|
||||
@ -366,8 +379,9 @@ TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) {
|
||||
|
||||
discovery()->AddDevice(std::move(device));
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_callback().value<0>());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) {
|
||||
@ -389,7 +403,7 @@ TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) {
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(GetAssertionStatus::kAuthenticatorMissingUserVerification,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionHandlerTest,
|
||||
@ -412,7 +426,7 @@ TEST_F(FidoGetAssertionHandlerTest,
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(GetAssertionStatus::kAuthenticatorMissingUserVerification,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) {
|
||||
@ -427,9 +441,9 @@ TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) {
|
||||
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(GetAssertionStatus::kAuthenticatorResponseInvalid,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
// Tests a scenario where the authenticator responds with credential ID that
|
||||
@ -455,7 +469,7 @@ TEST_F(FidoGetAssertionHandlerTest, InvalidCredential) {
|
||||
// The response with the invalid credential ID is considered to be an error at
|
||||
// the task level and the request handler will drop the authenticator.
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(get_assertion_callback().was_called());
|
||||
EXPECT_FALSE(get_assertion_future().IsReady());
|
||||
}
|
||||
|
||||
// Tests a scenario where the authenticator responds with an empty credential.
|
||||
@ -473,9 +487,10 @@ TEST_F(FidoGetAssertionHandlerTest, ValidEmptyCredential) {
|
||||
test_data::kTestGetAssertionResponseWithEmptyCredential);
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
const auto& response = get_assertion_callback().value<0>();
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
const auto& response = std::get<1>(get_assertion_future().Get());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
ASSERT_TRUE(response);
|
||||
ASSERT_EQ(1u, response->size());
|
||||
EXPECT_TRUE(response.value()[0].credential);
|
||||
@ -500,9 +515,10 @@ TEST_F(FidoGetAssertionHandlerTest, TruncatedUTF8) {
|
||||
test_data::kTestGetAssertionResponseWithTruncatedUTF8);
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
const auto& response = get_assertion_callback().value<0>();
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
const auto& response = std::get<1>(get_assertion_future().Get());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
ASSERT_TRUE(response);
|
||||
ASSERT_EQ(1u, response->size());
|
||||
ASSERT_TRUE(response.value()[0].user_entity);
|
||||
@ -523,7 +539,7 @@ TEST_F(FidoGetAssertionHandlerTest, TruncatedAndInvalidUTF8) {
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(get_assertion_callback().was_called());
|
||||
EXPECT_FALSE(get_assertion_future().IsReady());
|
||||
}
|
||||
|
||||
// Tests a scenario where authenticator responds without user entity in its
|
||||
@ -541,9 +557,9 @@ TEST_F(FidoGetAssertionHandlerTest, IncorrectUserEntity) {
|
||||
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(GetAssertionStatus::kAuthenticatorResponseInvalid,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionHandlerTest,
|
||||
@ -656,10 +672,11 @@ TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyUsbTransportAllowed) {
|
||||
discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_callback().value<0>());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()));
|
||||
EXPECT_THAT(
|
||||
request_handler->transport_availability_info().available_transports,
|
||||
::testing::UnorderedElementsAre(
|
||||
@ -689,10 +706,11 @@ TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyNfcTransportAllowed) {
|
||||
nfc_discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
nfc_discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_callback().value<0>());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()));
|
||||
EXPECT_THAT(
|
||||
request_handler->transport_availability_info().available_transports,
|
||||
::testing::UnorderedElementsAre(
|
||||
@ -727,10 +745,11 @@ TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyInternalTransportAllowed) {
|
||||
platform_discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
platform_discovery()->AddDevice(std::move(device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_callback().value<0>());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()));
|
||||
EXPECT_THAT(
|
||||
request_handler->transport_availability_info().available_transports,
|
||||
::testing::UnorderedElementsAre(FidoTransportProtocol::kInternal));
|
||||
@ -762,9 +781,9 @@ TEST_F(FidoGetAssertionHandlerTest,
|
||||
discovery()->AddDevice(std::move(other_device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_TRUE(get_assertion_callback().was_called());
|
||||
EXPECT_TRUE(get_assertion_future().IsReady());
|
||||
EXPECT_EQ(GetAssertionStatus::kUserConsentDenied,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
// Like |TestRequestWithOperationDeniedErrorPlatform|, but with a
|
||||
@ -781,9 +800,9 @@ TEST_F(FidoGetAssertionHandlerTest,
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_TRUE(get_assertion_callback().was_called());
|
||||
EXPECT_TRUE(get_assertion_future().IsReady());
|
||||
EXPECT_EQ(GetAssertionStatus::kUserConsentDenied,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
// If a device returns CTAP2_ERR_PIN_AUTH_INVALID, the request should complete
|
||||
@ -799,9 +818,9 @@ TEST_F(FidoGetAssertionHandlerTest, TestRequestWithPinAuthInvalid) {
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_TRUE(get_assertion_callback().was_called());
|
||||
EXPECT_TRUE(get_assertion_future().IsReady());
|
||||
EXPECT_EQ(GetAssertionStatus::kUserConsentDenied,
|
||||
get_assertion_callback().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
MATCHER_P(IsCtap2Command, expected_command, "") {
|
||||
@ -839,8 +858,9 @@ TEST_F(FidoGetAssertionHandlerTest, DeviceFailsImmediately) {
|
||||
discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
discovery()->AddDevice(std::move(broken_device));
|
||||
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionHandlerTest, PinUvAuthTokenPreTouchFailure) {
|
||||
@ -867,7 +887,7 @@ TEST_F(FidoGetAssertionHandlerTest, PinUvAuthTokenPreTouchFailure) {
|
||||
std::move(state), std::move(config)));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(get_assertion_callback().was_called());
|
||||
EXPECT_FALSE(get_assertion_future().IsReady());
|
||||
}
|
||||
|
||||
// Tests a scenario where authenticator of incorrect transport type was used to
|
||||
@ -897,17 +917,17 @@ TEST(GetAssertionRequestHandlerTest, IncorrectTransportType) {
|
||||
{FidoTransportProtocol::kBluetoothLowEnergy}),
|
||||
};
|
||||
|
||||
TestGetAssertionRequestCallback cb;
|
||||
TestGetAssertionRequestFuture future;
|
||||
auto request_handler = std::make_unique<GetAssertionRequestHandler>(
|
||||
&virtual_device_factory,
|
||||
std::vector<std::unique_ptr<FidoDiscoveryBase>>(),
|
||||
base::flat_set<FidoTransportProtocol>(
|
||||
{FidoTransportProtocol::kUsbHumanInterfaceDevice}),
|
||||
std::move(request), CtapGetAssertionOptions(),
|
||||
/*allow_skipping_pin_touch=*/true, cb.callback());
|
||||
/*allow_skipping_pin_touch=*/true, future.GetCallback());
|
||||
|
||||
task_environment.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(cb.was_called());
|
||||
EXPECT_FALSE(future.IsReady());
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionHandlerTest, ReportTransportMetric) {
|
||||
@ -930,9 +950,10 @@ TEST_F(FidoGetAssertionHandlerTest, ReportTransportMetric) {
|
||||
|
||||
nfc_discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
get_assertion_callback().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess, get_assertion_callback().status());
|
||||
EXPECT_EQ(GetAssertionStatus::kSuccess,
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
histograms.ExpectBucketCount(kRequestTransportHistogram,
|
||||
FidoTransportProtocol::kUsbHumanInterfaceDevice,
|
||||
1);
|
||||
@ -963,7 +984,7 @@ TEST(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) {
|
||||
ScopedFakeFidoHidManager fake_hid_manager;
|
||||
fake_hid_manager.AddFidoHidDevice("guid");
|
||||
|
||||
TestGetAssertionRequestCallback cb;
|
||||
TestGetAssertionRequestFuture future;
|
||||
FidoDiscoveryFactory fido_discovery_factory;
|
||||
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
|
||||
test_data::kClientDataJson);
|
||||
@ -977,7 +998,7 @@ TEST(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) {
|
||||
base::flat_set<FidoTransportProtocol>(
|
||||
{FidoTransportProtocol::kUsbHumanInterfaceDevice}),
|
||||
std::move(request), CtapGetAssertionOptions(),
|
||||
/*allow_skipping_pin_touch=*/true, cb.callback());
|
||||
/*allow_skipping_pin_touch=*/true, future.GetCallback());
|
||||
task_environment.RunUntilIdle();
|
||||
|
||||
EXPECT_EQ(handler->AuthenticatorsForTesting().size(), 1u);
|
||||
|
@ -4,24 +4,28 @@
|
||||
|
||||
#include "device/fido/get_assertion_task.h"
|
||||
|
||||
#include <iterator>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "crypto/ec_private_key.h"
|
||||
#include "device/base/features.h"
|
||||
#include "base/test/test_future.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/fido_constants.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/mock_fido_device.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/public_key_credential_descriptor.h"
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@ -31,22 +35,19 @@ using ::testing::_;
|
||||
namespace device {
|
||||
namespace {
|
||||
|
||||
using TestGetAssertionTaskCallbackReceiver =
|
||||
::device::test::StatusAndValueCallbackReceiver<
|
||||
CtapDeviceResponseCode,
|
||||
std::vector<AuthenticatorGetAssertionResponse>>;
|
||||
using TestGetAssertionTaskFuture =
|
||||
base::test::TestFuture<CtapDeviceResponseCode,
|
||||
std::vector<AuthenticatorGetAssertionResponse>>;
|
||||
|
||||
class FidoGetAssertionTaskTest : public testing::Test {
|
||||
public:
|
||||
FidoGetAssertionTaskTest() = default;
|
||||
|
||||
TestGetAssertionTaskCallbackReceiver& get_assertion_callback_receiver() {
|
||||
return cb_;
|
||||
}
|
||||
TestGetAssertionTaskFuture& get_assertion_future() { return future_; }
|
||||
|
||||
private:
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
TestGetAssertionTaskCallbackReceiver cb_;
|
||||
TestGetAssertionTaskFuture future_;
|
||||
};
|
||||
|
||||
TEST_F(FidoGetAssertionTaskTest, TestGetAssertionSuccess) {
|
||||
@ -57,19 +58,19 @@ TEST_F(FidoGetAssertionTaskTest, TestGetAssertionSuccess) {
|
||||
|
||||
CtapGetAssertionRequest request_param(test_data::kRelyingPartyId,
|
||||
test_data::kClientDataJson);
|
||||
request_param.allow_list.emplace_back(PublicKeyCredentialDescriptor(
|
||||
request_param.allow_list.emplace_back(
|
||||
CredentialType::kPublicKey,
|
||||
fido_parsing_utils::Materialize(
|
||||
test_data::kTestGetAssertionCredentialId)));
|
||||
test_data::kTestGetAssertionCredentialId));
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request_param), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_future().GetCallback());
|
||||
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
get_assertion_callback_receiver().status());
|
||||
EXPECT_EQ(get_assertion_callback_receiver().value().size(), 1u);
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_EQ(std::get<1>(get_assertion_future().Get()).size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionTaskTest, TestU2fSignSuccess) {
|
||||
@ -81,18 +82,18 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fSignSuccess) {
|
||||
|
||||
CtapGetAssertionRequest request_param(test_data::kRelyingPartyId,
|
||||
test_data::kClientDataJson);
|
||||
request_param.allow_list.emplace_back(PublicKeyCredentialDescriptor(
|
||||
request_param.allow_list.emplace_back(
|
||||
CredentialType::kPublicKey,
|
||||
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)));
|
||||
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle));
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request_param), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_future().GetCallback());
|
||||
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
get_assertion_callback_receiver().status());
|
||||
EXPECT_EQ(get_assertion_callback_receiver().value().size(), 1u);
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_EQ(std::get<1>(get_assertion_future().Get()).size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionTaskTest, TestSignSuccessWithFake) {
|
||||
@ -106,33 +107,30 @@ TEST_F(FidoGetAssertionTaskTest, TestSignSuccessWithFake) {
|
||||
auto device = std::make_unique<VirtualCtap2Device>();
|
||||
ASSERT_TRUE(device->mutable_state()->InjectRegistration(
|
||||
kCredentialId, test_data::kRelyingPartyId));
|
||||
test::TestCallbackReceiver<> done;
|
||||
device->DiscoverSupportedProtocolAndDeviceInfo(done.callback());
|
||||
done.WaitForCallback();
|
||||
base::test::TestFuture<void> done;
|
||||
device->DiscoverSupportedProtocolAndDeviceInfo(done.GetCallback());
|
||||
EXPECT_TRUE(done.Wait());
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request_param), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_future().GetCallback());
|
||||
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
get_assertion_callback_receiver().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
|
||||
// Just a sanity check, we don't verify the actual signature.
|
||||
ASSERT_GE(32u + 1u + 4u + 8u, // Minimal ECDSA signature is 8 bytes
|
||||
get_assertion_callback_receiver()
|
||||
.value()
|
||||
std::get<1>(get_assertion_future().Get())
|
||||
.at(0)
|
||||
.authenticator_data.SerializeToByteArray()
|
||||
.size());
|
||||
EXPECT_EQ(0x01,
|
||||
get_assertion_callback_receiver()
|
||||
.value()
|
||||
std::get<1>(get_assertion_future().Get())
|
||||
.at(0)
|
||||
.authenticator_data.SerializeToByteArray()[32]); // UP flag
|
||||
// Counter starts at zero and is incremented for every sign request.
|
||||
EXPECT_EQ(1, get_assertion_callback_receiver()
|
||||
.value()
|
||||
EXPECT_EQ(1, std::get<1>(get_assertion_future().Get())
|
||||
.at(0)
|
||||
.authenticator_data.SerializeToByteArray()[36]); // counter
|
||||
}
|
||||
@ -146,12 +144,12 @@ TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) {
|
||||
device.get(),
|
||||
CtapGetAssertionRequest(test_data::kRelyingPartyId,
|
||||
test_data::kClientDataJson),
|
||||
CtapGetAssertionOptions(), get_assertion_callback_receiver().callback());
|
||||
CtapGetAssertionOptions(), get_assertion_future().GetCallback());
|
||||
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
|
||||
get_assertion_callback_receiver().status());
|
||||
EXPECT_TRUE(get_assertion_callback_receiver().value().empty());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()).empty());
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionTaskTest, TestU2fSignRequestWithEmptyAllowedList) {
|
||||
@ -166,12 +164,12 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fSignRequestWithEmptyAllowedList) {
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_future().GetCallback());
|
||||
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrNoCredentials,
|
||||
get_assertion_callback_receiver().status());
|
||||
EXPECT_TRUE(get_assertion_callback_receiver().value().empty());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(get_assertion_future().Get()).empty());
|
||||
}
|
||||
|
||||
// Checks that when device supports both CTAP2 and U2F protocol and when
|
||||
@ -199,11 +197,11 @@ TEST_F(FidoGetAssertionTaskTest, TestSilentSignInWhenAppIdExtensionPresent) {
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_future().GetCallback());
|
||||
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
get_assertion_callback_receiver().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionTaskTest, TestU2fFallbackForAppIdExtension) {
|
||||
@ -243,10 +241,10 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fFallbackForAppIdExtension) {
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
get_assertion_future().GetCallback());
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
get_assertion_callback_receiver().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoGetAssertionTaskTest, TestAvoidSilentSignInForCtapOnlyDevice) {
|
||||
@ -273,10 +271,10 @@ TEST_F(FidoGetAssertionTaskTest, TestAvoidSilentSignInForCtapOnlyDevice) {
|
||||
|
||||
auto task = std::make_unique<GetAssertionTask>(
|
||||
device.get(), std::move(request), CtapGetAssertionOptions(),
|
||||
get_assertion_callback_receiver().callback());
|
||||
get_assertion_callback_receiver().WaitForCallback();
|
||||
get_assertion_future().GetCallback());
|
||||
EXPECT_TRUE(get_assertion_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
|
||||
get_assertion_callback_receiver().status());
|
||||
std::get<0>(get_assertion_future().Get()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -2,16 +2,29 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/location.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "base/time/time.h"
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.h"
|
||||
#include "components/cbor/reader.h"
|
||||
@ -21,12 +34,14 @@
|
||||
#include "device/fido/authenticator_get_info_response.h"
|
||||
#include "device/fido/authenticator_make_credential_response.h"
|
||||
#include "device/fido/authenticator_selection_criteria.h"
|
||||
#include "device/fido/authenticator_supported_options.h"
|
||||
#include "device/fido/ctap_make_credential_request.h"
|
||||
#include "device/fido/device_response_converter.h"
|
||||
#include "device/fido/fake_fido_discovery.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_device.h"
|
||||
#include "device/fido/fido_device_authenticator.h"
|
||||
#include "device/fido/fido_discovery_base.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
@ -34,8 +49,11 @@
|
||||
#include "device/fido/make_credential_request_handler.h"
|
||||
#include "device/fido/make_credential_task.h"
|
||||
#include "device/fido/mock_fido_device.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/public_key_credential_params.h"
|
||||
#include "device/fido/public_key_credential_rp_entity.h"
|
||||
#include "device/fido/public_key_credential_user_entity.h"
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
#include "device/fido/virtual_fido_device.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -53,10 +71,10 @@ namespace device {
|
||||
|
||||
namespace {
|
||||
|
||||
using TestMakeCredentialRequestCallback = test::StatusAndValuesCallbackReceiver<
|
||||
MakeCredentialStatus,
|
||||
std::optional<AuthenticatorMakeCredentialResponse>,
|
||||
const FidoAuthenticator*>;
|
||||
using TestMakeCredentialRequestFuture =
|
||||
base::test::TestFuture<MakeCredentialStatus,
|
||||
std::optional<AuthenticatorMakeCredentialResponse>,
|
||||
const FidoAuthenticator*>;
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -98,7 +116,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
|
||||
fake_discovery_factory_.get(),
|
||||
std::vector<std::unique_ptr<FidoDiscoveryBase>>(),
|
||||
supported_transports_, std::move(request_parameter), std::move(options),
|
||||
cb_.callback());
|
||||
future_.GetCallback());
|
||||
if (pending_mock_platform_device_) {
|
||||
platform_discovery_->AddDevice(std::move(pending_mock_platform_device_));
|
||||
platform_discovery_->WaitForCallToStartAndSimulateSuccess();
|
||||
@ -116,7 +134,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
|
||||
nfc_discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(callback().was_called());
|
||||
EXPECT_FALSE(future().IsReady());
|
||||
|
||||
if (!base::Contains(transports, Transport::kUsbHumanInterfaceDevice))
|
||||
EXPECT_FALSE(discovery()->is_start_requested());
|
||||
@ -130,7 +148,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
|
||||
|
||||
test::FakeFidoDiscovery* discovery() const { return discovery_; }
|
||||
test::FakeFidoDiscovery* nfc_discovery() const { return nfc_discovery_; }
|
||||
TestMakeCredentialRequestCallback& callback() { return cb_; }
|
||||
TestMakeCredentialRequestFuture& future() { return future_; }
|
||||
|
||||
void set_mock_platform_device(std::unique_ptr<MockFidoDevice> device) {
|
||||
pending_mock_platform_device_ = std::move(device);
|
||||
@ -152,7 +170,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
|
||||
platform_discovery_;
|
||||
scoped_refptr<::testing::NiceMock<MockBluetoothAdapter>> mock_adapter_;
|
||||
std::unique_ptr<MockFidoDevice> pending_mock_platform_device_;
|
||||
TestMakeCredentialRequestCallback cb_;
|
||||
TestMakeCredentialRequestFuture future_;
|
||||
base::flat_set<FidoTransportProtocol> supported_transports_ = {
|
||||
FidoTransportProtocol::kUsbHumanInterfaceDevice,
|
||||
FidoTransportProtocol::kHybrid,
|
||||
@ -221,8 +239,8 @@ TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredential) {
|
||||
test_data::kTestMakeCredentialResponse);
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
// Test a scenario where the connected authenticator is a U2F device.
|
||||
@ -236,8 +254,8 @@ TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegister) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, U2fRegisterWithUserVerificationRequired) {
|
||||
@ -255,7 +273,7 @@ TEST_F(FidoMakeCredentialHandlerTest, U2fRegisterWithUserVerificationRequired) {
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(MakeCredentialStatus::kAuthenticatorMissingUserVerification,
|
||||
callback().status());
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, U2fRegisterWithResidentKeyRequirement) {
|
||||
@ -273,7 +291,7 @@ TEST_F(FidoMakeCredentialHandlerTest, U2fRegisterWithResidentKeyRequirement) {
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(MakeCredentialStatus::kAuthenticatorMissingResidentKeys,
|
||||
callback().status());
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, UserVerificationRequirementNotMet) {
|
||||
@ -293,7 +311,7 @@ TEST_F(FidoMakeCredentialHandlerTest, UserVerificationRequirementNotMet) {
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(MakeCredentialStatus::kAuthenticatorMissingUserVerification,
|
||||
callback().status());
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, CrossPlatformAttachment) {
|
||||
@ -353,7 +371,7 @@ TEST_F(FidoMakeCredentialHandlerTest, ResidentKeyRequirementNotMet) {
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(MakeCredentialStatus::kAuthenticatorMissingResidentKeys,
|
||||
callback().status());
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
MATCHER(IsResidentKeyRequest, "") {
|
||||
@ -474,8 +492,8 @@ TEST_F(FidoMakeCredentialHandlerTest, ResidentKeyCancelOtherAuthenticator) {
|
||||
discovery()->AddDevice(std::move(device1));
|
||||
discovery()->AddDevice(std::move(device2));
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, ResidentKeyCancel) {
|
||||
@ -526,8 +544,8 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
test_data::kTestMakeCredentialResponse);
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
|
||||
EXPECT_THAT(
|
||||
request_handler->transport_availability_info().available_transports,
|
||||
@ -556,8 +574,8 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
AuthenticatorAttachment::kPlatform, ResidentKeyRequirement::kRequired,
|
||||
UserVerificationRequirement::kRequired));
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
|
||||
EXPECT_THAT(
|
||||
request_handler->transport_availability_info().available_transports,
|
||||
@ -586,9 +604,9 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
EXPECT_TRUE(callback().was_called());
|
||||
EXPECT_TRUE(future().IsReady());
|
||||
#else
|
||||
EXPECT_FALSE(callback().was_called());
|
||||
EXPECT_FALSE(future().IsReady());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -612,7 +630,7 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
UserVerificationRequirement::kRequired));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(callback().was_called());
|
||||
EXPECT_FALSE(future().IsReady());
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, SupportedTransportsAreOnlyNfc) {
|
||||
@ -643,7 +661,7 @@ TEST_F(FidoMakeCredentialHandlerTest, IncorrectRpIdHash) {
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(callback().was_called());
|
||||
EXPECT_FALSE(future().IsReady());
|
||||
}
|
||||
|
||||
// Tests that only authenticators with resident key support will successfully
|
||||
@ -667,8 +685,8 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
std::move(state), std::move(config)));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
// Tests that MakeCredential request fails when asking to use resident keys with
|
||||
@ -686,7 +704,7 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_EQ(MakeCredentialStatus::kAuthenticatorMissingResidentKeys,
|
||||
callback().status());
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
// If a device with transport type kInternal returns a
|
||||
@ -708,8 +726,9 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
UserVerificationRequirement::kPreferred));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_TRUE(callback().was_called());
|
||||
EXPECT_EQ(MakeCredentialStatus::kUserConsentDenied, callback().status());
|
||||
EXPECT_TRUE(future().IsReady());
|
||||
EXPECT_EQ(MakeCredentialStatus::kUserConsentDenied,
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
// Like |TestRequestWithOperationDeniedErrorPlatform|, but with a
|
||||
@ -730,8 +749,9 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_TRUE(callback().was_called());
|
||||
EXPECT_EQ(MakeCredentialStatus::kUserConsentDenied, callback().status());
|
||||
EXPECT_TRUE(future().IsReady());
|
||||
EXPECT_EQ(MakeCredentialStatus::kUserConsentDenied,
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest,
|
||||
@ -757,8 +777,8 @@ TEST_F(FidoMakeCredentialHandlerTest,
|
||||
discovery()->AddDevice(std::move(device));
|
||||
discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
// If a device returns CTAP2_ERR_PIN_AUTH_INVALID, the request should complete
|
||||
@ -778,8 +798,9 @@ TEST_F(FidoMakeCredentialHandlerTest, TestRequestWithPinAuthInvalid) {
|
||||
discovery()->AddDevice(std::move(device));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_TRUE(callback().was_called());
|
||||
EXPECT_EQ(MakeCredentialStatus::kUserConsentDenied, callback().status());
|
||||
EXPECT_TRUE(future().IsReady());
|
||||
EXPECT_EQ(MakeCredentialStatus::kUserConsentDenied,
|
||||
std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
MATCHER_P(IsCtap2Command, expected_command, "") {
|
||||
@ -817,8 +838,8 @@ TEST_F(FidoMakeCredentialHandlerTest, DeviceFailsImmediately) {
|
||||
discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
discovery()->AddDevice(std::move(broken_device));
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, PinUvAuthTokenPreTouchFailure) {
|
||||
@ -837,7 +858,7 @@ TEST_F(FidoMakeCredentialHandlerTest, PinUvAuthTokenPreTouchFailure) {
|
||||
std::move(state), std::move(config)));
|
||||
|
||||
task_environment_.FastForwardUntilNoTasksRemain();
|
||||
EXPECT_FALSE(callback().was_called());
|
||||
EXPECT_FALSE(future().IsReady());
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialHandlerTest, ReportTransportMetric) {
|
||||
@ -859,8 +880,8 @@ TEST_F(FidoMakeCredentialHandlerTest, ReportTransportMetric) {
|
||||
nfc_discovery()->AddDevice(std::move(nfc_device));
|
||||
nfc_discovery()->WaitForCallToStartAndSimulateSuccess();
|
||||
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
histograms.ExpectUniqueSample(kResponseTransportHistogram,
|
||||
FidoTransportProtocol::kUsbHumanInterfaceDevice,
|
||||
1);
|
||||
@ -875,8 +896,8 @@ TEST_F(FidoMakeCredentialHandlerTest, ReportTransportMetricWin) {
|
||||
base::HistogramTester histograms;
|
||||
fake_discovery_factory_->set_discover_win_webauthn_api_authenticator(true);
|
||||
auto request_handler = CreateMakeCredentialHandler();
|
||||
callback().WaitForCallback();
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, callback().status());
|
||||
EXPECT_TRUE(future().Wait());
|
||||
EXPECT_EQ(MakeCredentialStatus::kSuccess, std::get<0>(future().Get()));
|
||||
histograms.ExpectUniqueSample(kResponseTransportHistogram,
|
||||
FidoTransportProtocol::kBluetoothLowEnergy, 1);
|
||||
}
|
||||
|
@ -2,24 +2,32 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "device/fido/make_credential_task.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "device/base/features.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "device/fido/authenticator_get_info_response.h"
|
||||
#include "device/fido/authenticator_make_credential_response.h"
|
||||
#include "device/fido/authenticator_supported_options.h"
|
||||
#include "device/fido/ctap_make_credential_request.h"
|
||||
#include "device/fido/device_response_converter.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_device.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/make_credential_task.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/mock_fido_device.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/public_key_credential_params.h"
|
||||
#include "device/fido/public_key_credential_rp_entity.h"
|
||||
#include "device/fido/public_key_credential_user_entity.h"
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@ -34,10 +42,9 @@ constexpr std::array<uint8_t, kAaguidLength> kTestDeviceAaguid = {
|
||||
{0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06, 0x17, 0x11,
|
||||
0x1F, 0x9E, 0xDC, 0x7D}};
|
||||
|
||||
using TestMakeCredentialTaskCallback =
|
||||
::device::test::StatusAndValueCallbackReceiver<
|
||||
CtapDeviceResponseCode,
|
||||
std::optional<AuthenticatorMakeCredentialResponse>>;
|
||||
using TestMakeCredentialTaskFuture = ::base::test::TestFuture<
|
||||
CtapDeviceResponseCode,
|
||||
std::optional<AuthenticatorMakeCredentialResponse>>;
|
||||
|
||||
class FidoMakeCredentialTaskTest : public testing::Test {
|
||||
public:
|
||||
@ -54,16 +61,14 @@ class FidoMakeCredentialTaskTest : public testing::Test {
|
||||
test_data::kClientDataJson, std::move(rp), std::move(user),
|
||||
PublicKeyCredentialParams(
|
||||
std::vector<PublicKeyCredentialParams::CredentialInfo>(1))),
|
||||
MakeCredentialOptions(), callback_receiver_.callback());
|
||||
MakeCredentialOptions(), future_.GetCallback());
|
||||
}
|
||||
|
||||
TestMakeCredentialTaskCallback& make_credential_callback_receiver() {
|
||||
return callback_receiver_;
|
||||
}
|
||||
TestMakeCredentialTaskFuture& make_credential_future() { return future_; }
|
||||
|
||||
protected:
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
TestMakeCredentialTaskCallback callback_receiver_;
|
||||
TestMakeCredentialTaskFuture future_;
|
||||
};
|
||||
|
||||
TEST_F(FidoMakeCredentialTaskTest, MakeCredentialSuccess) {
|
||||
@ -73,30 +78,29 @@ TEST_F(FidoMakeCredentialTaskTest, MakeCredentialSuccess) {
|
||||
test_data::kTestMakeCredentialResponse);
|
||||
|
||||
const auto task = CreateMakeCredentialTask(device.get());
|
||||
make_credential_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(make_credential_future().Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
make_credential_callback_receiver().status());
|
||||
EXPECT_TRUE(make_credential_callback_receiver().value());
|
||||
std::get<0>(make_credential_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(make_credential_future().Get()));
|
||||
EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kCtap2);
|
||||
EXPECT_TRUE(device->device_info());
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialTaskTest, TestRegisterSuccessWithFake) {
|
||||
auto device = std::make_unique<VirtualCtap2Device>();
|
||||
test::TestCallbackReceiver<> done_init;
|
||||
device->DiscoverSupportedProtocolAndDeviceInfo(done_init.callback());
|
||||
done_init.WaitForCallback();
|
||||
base::test::TestFuture<void> done_init;
|
||||
device->DiscoverSupportedProtocolAndDeviceInfo(done_init.GetCallback());
|
||||
EXPECT_TRUE(done_init.Wait());
|
||||
const auto task = CreateMakeCredentialTask(device.get());
|
||||
make_credential_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(make_credential_future().Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
make_credential_callback_receiver().status());
|
||||
std::get<0>(make_credential_future().Get()));
|
||||
|
||||
// We don't verify the response from the fake, but do a quick sanity check.
|
||||
ASSERT_TRUE(make_credential_callback_receiver().value());
|
||||
EXPECT_EQ(32u, make_credential_callback_receiver()
|
||||
.value()
|
||||
ASSERT_TRUE(std::get<1>(make_credential_future().Get()));
|
||||
EXPECT_EQ(32u, std::get<1>(make_credential_future().Get())
|
||||
->attestation_object.GetCredentialId()
|
||||
.size());
|
||||
}
|
||||
@ -109,11 +113,11 @@ TEST_F(FidoMakeCredentialTaskTest, FallbackToU2fRegisterSuccess) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
|
||||
const auto task = CreateMakeCredentialTask(device.get());
|
||||
make_credential_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(make_credential_future().Wait());
|
||||
|
||||
EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
make_credential_callback_receiver().status());
|
||||
std::get<0>(make_credential_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialTaskTest, DefaultToU2fWhenClientPinSet) {
|
||||
@ -132,10 +136,10 @@ TEST_F(FidoMakeCredentialTaskTest, DefaultToU2fWhenClientPinSet) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
|
||||
const auto task = CreateMakeCredentialTask(device.get());
|
||||
make_credential_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(make_credential_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
make_credential_callback_receiver().status());
|
||||
EXPECT_TRUE(make_credential_callback_receiver().value());
|
||||
std::get<0>(make_credential_future().Get()));
|
||||
EXPECT_TRUE(std::get<1>(make_credential_future().Get()));
|
||||
}
|
||||
|
||||
TEST_F(FidoMakeCredentialTaskTest, EnforceClientPinWhenUserVerificationSet) {
|
||||
@ -161,12 +165,12 @@ TEST_F(FidoMakeCredentialTaskTest, EnforceClientPinWhenUserVerificationSet) {
|
||||
request.user_verification = UserVerificationRequirement::kRequired;
|
||||
const auto task = std::make_unique<MakeCredentialTask>(
|
||||
device.get(), std::move(request), MakeCredentialOptions(),
|
||||
callback_receiver_.callback());
|
||||
make_credential_future().GetCallback());
|
||||
|
||||
make_credential_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(make_credential_future().Wait());
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
|
||||
make_credential_callback_receiver().status());
|
||||
EXPECT_FALSE(make_credential_callback_receiver().value());
|
||||
std::get<0>(make_credential_future().Get()));
|
||||
EXPECT_FALSE(std::get<1>(make_credential_future().Get()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -5,16 +5,23 @@
|
||||
#include "device/fido/u2f_register_operation.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "device/fido/authenticator_make_credential_response.h"
|
||||
#include "device/fido/ctap_make_credential_request.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/mock_fido_device.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/public_key_credential_params.h"
|
||||
#include "device/fido/public_key_credential_rp_entity.h"
|
||||
#include "device/fido/public_key_credential_user_entity.h"
|
||||
#include "device/fido/virtual_u2f_device.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@ -54,21 +61,19 @@ CtapMakeCredentialRequest CreateRegisterRequest(
|
||||
std::vector<PublicKeyCredentialDescriptor>(), is_individual_attestation);
|
||||
}
|
||||
|
||||
using TestRegisterCallback = ::device::test::StatusAndValueCallbackReceiver<
|
||||
CtapDeviceResponseCode,
|
||||
std::optional<AuthenticatorMakeCredentialResponse>>;
|
||||
using TestRegisterFuture =
|
||||
base::test::TestFuture<CtapDeviceResponseCode,
|
||||
std::optional<AuthenticatorMakeCredentialResponse>>;
|
||||
|
||||
} // namespace
|
||||
|
||||
class U2fRegisterOperationTest : public ::testing::Test {
|
||||
public:
|
||||
TestRegisterCallback& register_callback_receiver() {
|
||||
return register_callback_receiver_;
|
||||
}
|
||||
TestRegisterFuture& register_future() { return register_future_; }
|
||||
|
||||
private:
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
TestRegisterCallback register_callback_receiver_;
|
||||
TestRegisterFuture register_future_;
|
||||
};
|
||||
|
||||
TEST_F(U2fRegisterOperationTest, TestRegisterSuccess) {
|
||||
@ -81,16 +86,14 @@ TEST_F(U2fRegisterOperationTest, TestRegisterSuccess) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
|
||||
auto u2f_register = std::make_unique<U2fRegisterOperation>(
|
||||
device.get(), std::move(request),
|
||||
register_callback_receiver().callback());
|
||||
device.get(), std::move(request), register_future().GetCallback());
|
||||
u2f_register->Start();
|
||||
register_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(register_future().Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
register_callback_receiver().status());
|
||||
ASSERT_TRUE(register_callback_receiver().value());
|
||||
EXPECT_THAT(register_callback_receiver()
|
||||
.value()
|
||||
std::get<0>(register_future().Get()));
|
||||
ASSERT_TRUE(std::get<1>(register_future().Get()));
|
||||
EXPECT_THAT(std::get<1>(register_future().Get())
|
||||
->attestation_object.GetCredentialId(),
|
||||
::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
|
||||
}
|
||||
@ -100,17 +103,15 @@ TEST_F(U2fRegisterOperationTest, TestRegisterSuccessWithFake) {
|
||||
|
||||
auto device = std::make_unique<VirtualU2fDevice>();
|
||||
auto u2f_register = std::make_unique<U2fRegisterOperation>(
|
||||
device.get(), std::move(request),
|
||||
register_callback_receiver().callback());
|
||||
device.get(), std::move(request), register_future().GetCallback());
|
||||
u2f_register->Start();
|
||||
register_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(register_future().Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
register_callback_receiver().status());
|
||||
std::get<0>(register_future().Get()));
|
||||
// We don't verify the response from the fake, but do a quick sanity check.
|
||||
ASSERT_TRUE(register_callback_receiver().value());
|
||||
EXPECT_EQ(32ul, register_callback_receiver()
|
||||
.value()
|
||||
ASSERT_TRUE(std::get<1>(register_future().Get()));
|
||||
EXPECT_EQ(32ul, std::get<1>(register_future().Get())
|
||||
->attestation_object.GetCredentialId()
|
||||
.size());
|
||||
}
|
||||
@ -133,16 +134,14 @@ TEST_F(U2fRegisterOperationTest, TestDelayedSuccess) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
|
||||
auto u2f_register = std::make_unique<U2fRegisterOperation>(
|
||||
device.get(), std::move(request),
|
||||
register_callback_receiver().callback());
|
||||
device.get(), std::move(request), register_future().GetCallback());
|
||||
u2f_register->Start();
|
||||
register_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(register_future().Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
register_callback_receiver().status());
|
||||
ASSERT_TRUE(register_callback_receiver().value());
|
||||
EXPECT_THAT(register_callback_receiver()
|
||||
.value()
|
||||
std::get<0>(register_future().Get()));
|
||||
ASSERT_TRUE(std::get<1>(register_future().Get()));
|
||||
EXPECT_THAT(std::get<1>(register_future().Get())
|
||||
->attestation_object.GetCredentialId(),
|
||||
::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
|
||||
}
|
||||
@ -180,16 +179,14 @@ TEST_F(U2fRegisterOperationTest, TestRegistrationWithExclusionList) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
|
||||
auto u2f_register = std::make_unique<U2fRegisterOperation>(
|
||||
device.get(), std::move(request),
|
||||
register_callback_receiver().callback());
|
||||
device.get(), std::move(request), register_future().GetCallback());
|
||||
u2f_register->Start();
|
||||
register_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(register_future().Wait());
|
||||
|
||||
ASSERT_TRUE(register_callback_receiver().value());
|
||||
ASSERT_TRUE(std::get<1>(register_future().Get()));
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
|
||||
register_callback_receiver().status());
|
||||
EXPECT_THAT(register_callback_receiver()
|
||||
.value()
|
||||
std::get<0>(register_future().Get()));
|
||||
EXPECT_THAT(std::get<1>(register_future().Get())
|
||||
->attestation_object.GetCredentialId(),
|
||||
::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
|
||||
}
|
||||
@ -233,14 +230,13 @@ TEST_F(U2fRegisterOperationTest, TestRegistrationWithDuplicateHandle) {
|
||||
test_data::kApduEncodedNoErrorSignResponse);
|
||||
|
||||
auto u2f_register = std::make_unique<U2fRegisterOperation>(
|
||||
device.get(), std::move(request),
|
||||
register_callback_receiver().callback());
|
||||
device.get(), std::move(request), register_future().GetCallback());
|
||||
u2f_register->Start();
|
||||
register_callback_receiver().WaitForCallback();
|
||||
EXPECT_TRUE(register_future().Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrCredentialExcluded,
|
||||
register_callback_receiver().status());
|
||||
EXPECT_FALSE(register_callback_receiver().value());
|
||||
std::get<0>(register_future().Get()));
|
||||
EXPECT_FALSE(std::get<1>(register_future().Get()));
|
||||
}
|
||||
|
||||
MATCHER_P(IndicatesIndividualAttestation, expected, "") {
|
||||
@ -252,7 +248,7 @@ TEST_F(U2fRegisterOperationTest, TestIndividualAttestation) {
|
||||
// resulting registration APDU.
|
||||
for (const auto& individual_attestation : {false, true}) {
|
||||
SCOPED_TRACE(individual_attestation);
|
||||
TestRegisterCallback cb;
|
||||
TestRegisterFuture future;
|
||||
auto request = CreateRegisterRequest(individual_attestation);
|
||||
|
||||
auto device = std::make_unique<MockFidoDevice>();
|
||||
@ -266,13 +262,13 @@ TEST_F(U2fRegisterOperationTest, TestIndividualAttestation) {
|
||||
test_data::kApduEncodedNoErrorRegisterResponse);
|
||||
|
||||
auto u2f_register = std::make_unique<U2fRegisterOperation>(
|
||||
device.get(), std::move(request), cb.callback());
|
||||
device.get(), std::move(request), future.GetCallback());
|
||||
u2f_register->Start();
|
||||
cb.WaitForCallback();
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess, cb.status());
|
||||
ASSERT_TRUE(cb.value());
|
||||
EXPECT_THAT(cb.value()->attestation_object.GetCredentialId(),
|
||||
EXPECT_EQ(CtapDeviceResponseCode::kSuccess, std::get<0>(future.Get()));
|
||||
ASSERT_TRUE(std::get<1>(future.Get()));
|
||||
EXPECT_THAT(std::get<1>(future.Get())->attestation_object.GetCredentialId(),
|
||||
::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
|
||||
}
|
||||
}
|
||||
|
@ -4,24 +4,40 @@
|
||||
|
||||
#include "device/fido/virtual_ctap2_device.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/check.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/test/bind.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/cbor/reader.h"
|
||||
#include "components/cbor/values.h"
|
||||
#include "components/cbor/writer.h"
|
||||
#include "device/fido/attestation_statement.h"
|
||||
#include "device/fido/authenticator_get_assertion_response.h"
|
||||
#include "device/fido/authenticator_make_credential_response.h"
|
||||
#include "device/fido/ctap_get_assertion_request.h"
|
||||
#include "device/fido/ctap_make_credential_request.h"
|
||||
#include "device/fido/device_response_converter.h"
|
||||
#include "device/fido/fido_constants.h"
|
||||
#include "device/fido/fido_device.h"
|
||||
#include "device/fido/fido_parsing_utils.h"
|
||||
#include "device/fido/fido_test_data.h"
|
||||
#include "device/fido/fido_transport_protocol.h"
|
||||
#include "device/fido/fido_types.h"
|
||||
#include "device/fido/large_blob.h"
|
||||
#include "device/fido/test_callback_receiver.h"
|
||||
#include "device/fido/public_key_credential_descriptor.h"
|
||||
#include "device/fido/virtual_fido_device.h"
|
||||
#include "net/cert/asn1_util.h"
|
||||
#include "net/cert/x509_certificate.h"
|
||||
#include "net/cert/x509_util.h"
|
||||
@ -32,8 +48,7 @@ namespace device {
|
||||
|
||||
namespace {
|
||||
|
||||
using TestCallbackReceiver =
|
||||
test::ValueCallbackReceiver<std::optional<std::vector<uint8_t>>>;
|
||||
using TestFuture = base::test::TestFuture<std::optional<std::vector<uint8_t>>>;
|
||||
|
||||
void SendCommand(VirtualCtap2Device* device,
|
||||
base::span<const uint8_t> command,
|
||||
@ -175,12 +190,12 @@ TEST_F(VirtualCtap2DeviceTest, DestroyInsideSimulatePressCallback) {
|
||||
// https://w3c.github.io/webauthn/#sctn-packed-attestation-cert-requirements
|
||||
TEST_F(VirtualCtap2DeviceTest, AttestationCertificateIsValid) {
|
||||
MakeDevice();
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
SendCommand(device_.get(), test_data::kCtapSimpleMakeCredentialRequest,
|
||||
callback_receiver.callback());
|
||||
callback_receiver.WaitForCallback();
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
std::optional<AuthenticatorMakeCredentialResponse> response =
|
||||
ReadCTAPMakeCredentialResponse(
|
||||
@ -253,12 +268,12 @@ TEST_F(VirtualCtap2DeviceTest, RejectsCredentialsWithExtraKeys) {
|
||||
static_cast<uint8_t>(CtapRequestCommand::kAuthenticatorGetAssertion));
|
||||
|
||||
MakeDevice();
|
||||
TestCallbackReceiver callback_receiver;
|
||||
SendCommand(device_.get(), *bytes, callback_receiver.callback());
|
||||
callback_receiver.WaitForCallback();
|
||||
TestFuture future;
|
||||
SendCommand(device_.get(), *bytes, future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
ASSERT_TRUE(callback_receiver.value().has_value());
|
||||
base::span<const uint8_t> result = *callback_receiver.value();
|
||||
ASSERT_TRUE(future.Get().has_value());
|
||||
base::span<const uint8_t> result = future.Get().value();
|
||||
ASSERT_EQ(result.size(), 1u);
|
||||
EXPECT_EQ(result[0],
|
||||
static_cast<uint8_t>(
|
||||
@ -277,7 +292,7 @@ TEST_F(VirtualCtap2DeviceTest, OnGetAssertionBogusSignature) {
|
||||
device_->mutable_state()->InjectRegistration(kCredentialId,
|
||||
test_data::kRelyingPartyId);
|
||||
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
device::CtapGetAssertionRequest request = CtapGetAssertionRequest(
|
||||
test_data::kRelyingPartyId, test_data::kClientDataJson);
|
||||
std::vector<uint8_t> credential_id =
|
||||
@ -289,10 +304,10 @@ TEST_F(VirtualCtap2DeviceTest, OnGetAssertionBogusSignature) {
|
||||
request.allow_list.push_back(std::move(descriptor));
|
||||
device_->DeviceTransact(
|
||||
ToCTAP2Command(AsCTAPRequestValuePair(std::move(request))),
|
||||
base::BindOnce(callback_receiver.callback()));
|
||||
callback_receiver.WaitForCallback();
|
||||
base::BindOnce(future.GetCallback()));
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
|
||||
std::optional<AuthenticatorGetAssertionResponse> response =
|
||||
@ -307,11 +322,11 @@ TEST_F(VirtualCtap2DeviceTest, OnMakeCredentialBogusSignature) {
|
||||
device_->mutable_state()->ctap2_invalid_signature = true;
|
||||
|
||||
constexpr uint8_t bogus_sig[] = {0x00};
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
SendCommand(device_.get(), test_data::kCtapSimpleMakeCredentialRequest,
|
||||
callback_receiver.callback());
|
||||
callback_receiver.WaitForCallback();
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
std::optional<AuthenticatorMakeCredentialResponse> response =
|
||||
ReadCTAPMakeCredentialResponse(
|
||||
@ -333,7 +348,7 @@ TEST_F(VirtualCtap2DeviceTest, OnGetAssertionUnsetUPBit) {
|
||||
device_->mutable_state()->InjectRegistration(kCredentialId,
|
||||
test_data::kRelyingPartyId);
|
||||
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
device::CtapGetAssertionRequest request = CtapGetAssertionRequest(
|
||||
test_data::kRelyingPartyId, test_data::kClientDataJson);
|
||||
std::vector<uint8_t> credential_id =
|
||||
@ -345,10 +360,10 @@ TEST_F(VirtualCtap2DeviceTest, OnGetAssertionUnsetUPBit) {
|
||||
request.allow_list.push_back(std::move(descriptor));
|
||||
device_->DeviceTransact(
|
||||
ToCTAP2Command(AsCTAPRequestValuePair(std::move(request))),
|
||||
base::BindOnce(callback_receiver.callback()));
|
||||
callback_receiver.WaitForCallback();
|
||||
base::BindOnce(future.GetCallback()));
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
|
||||
std::optional<AuthenticatorGetAssertionResponse> response =
|
||||
@ -370,7 +385,7 @@ TEST_F(VirtualCtap2DeviceTest, OnGetAssertionUnsetUVBit) {
|
||||
state->InjectRegistration(kCredentialId, test_data::kRelyingPartyId);
|
||||
MakeDevice(state, config);
|
||||
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
device::CtapGetAssertionRequest request = CtapGetAssertionRequest(
|
||||
test_data::kRelyingPartyId, test_data::kClientDataJson);
|
||||
std::vector<uint8_t> credential_id =
|
||||
@ -383,10 +398,10 @@ TEST_F(VirtualCtap2DeviceTest, OnGetAssertionUnsetUVBit) {
|
||||
request.user_verification = UserVerificationRequirement::kRequired;
|
||||
device_->DeviceTransact(
|
||||
ToCTAP2Command(AsCTAPRequestValuePair(std::move(request))),
|
||||
base::BindOnce(callback_receiver.callback()));
|
||||
callback_receiver.WaitForCallback();
|
||||
base::BindOnce(future.GetCallback()));
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
|
||||
std::optional<AuthenticatorGetAssertionResponse> response =
|
||||
@ -400,11 +415,11 @@ TEST_F(VirtualCtap2DeviceTest, OnMakeCredentialUnsetUPBit) {
|
||||
MakeDevice();
|
||||
device_->mutable_state()->unset_up_bit = true;
|
||||
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
SendCommand(device_.get(), test_data::kCtapSimpleMakeCredentialRequest,
|
||||
callback_receiver.callback());
|
||||
callback_receiver.WaitForCallback();
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
std::optional<AuthenticatorMakeCredentialResponse> response =
|
||||
ReadCTAPMakeCredentialResponse(
|
||||
@ -424,12 +439,12 @@ TEST_F(VirtualCtap2DeviceTest, OnMakeCredentialUnsetUVBit) {
|
||||
state->unset_uv_bit = true;
|
||||
MakeDevice(state, config);
|
||||
|
||||
TestCallbackReceiver callback_receiver;
|
||||
TestFuture future;
|
||||
SendCommand(device_.get(), test_data::kCtapMakeCredentialRequest,
|
||||
callback_receiver.callback());
|
||||
callback_receiver.WaitForCallback();
|
||||
future.GetCallback());
|
||||
EXPECT_TRUE(future.Wait());
|
||||
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(*callback_receiver.value());
|
||||
std::optional<cbor::Value> cbor = DecodeCBOR(future.Take().value());
|
||||
ASSERT_TRUE(cbor);
|
||||
std::optional<AuthenticatorMakeCredentialResponse> response =
|
||||
ReadCTAPMakeCredentialResponse(
|
||||
|
Reference in New Issue
Block a user