#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/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/make_credential_task.h"
#include "device/fido/mock_fido_device.h"
#include "device/fido/public_key_credential_descriptor.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
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/u2f/u2f_client.h"
#endif
namespace device {
namespace {
constexpr uint8_t kBogusCredentialId[] = …;
constexpr char kRequestTransportHistogram[] = …;
constexpr char kResponseTransportHistogram[] = …;
TestGetAssertionRequestFuture;
}
_;
class FidoGetAssertionHandlerTest : public ::testing::Test { … };
TEST_F(FidoGetAssertionHandlerTest, TransportAvailabilityInfo) { … }
TEST_F(FidoGetAssertionHandlerTest, CtapRequestOnSingleDevice) { … }
TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) { … }
TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) { … }
TEST_F(FidoGetAssertionHandlerTest,
TestU2fSignRequestWithUserVerificationRequired) { … }
TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) { … }
TEST_F(FidoGetAssertionHandlerTest, InvalidCredential) { … }
TEST_F(FidoGetAssertionHandlerTest, ValidEmptyCredential) { … }
TEST_F(FidoGetAssertionHandlerTest, TruncatedUTF8) { … }
TEST_F(FidoGetAssertionHandlerTest, TruncatedAndInvalidUTF8) { … }
TEST_F(FidoGetAssertionHandlerTest, IncorrectUserEntity) { … }
TEST_F(FidoGetAssertionHandlerTest,
AllTransportsAllowedIfAllowCredentialsListUndefined) { … }
TEST_F(FidoGetAssertionHandlerTest,
AllTransportsAllowedIfAllowCredentialsListIsEmpty) { … }
TEST_F(FidoGetAssertionHandlerTest,
AllTransportsAllowedIfHasAllowedCredentialWithEmptyTransportsList) { … }
TEST_F(FidoGetAssertionHandlerTest,
AllowedTransportsAreUnionOfTransportsLists) { … }
TEST_F(FidoGetAssertionHandlerTest, SupportedTransportsAreOnlyNfc) { … }
TEST_F(FidoGetAssertionHandlerTest,
SupportedTransportsAreOnlyCableAndInternal) { … }
TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyUsbTransportAllowed) { … }
TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyNfcTransportAllowed) { … }
TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyInternalTransportAllowed) { … }
TEST_F(FidoGetAssertionHandlerTest,
TestRequestWithOperationDeniedErrorPlatform) { … }
TEST_F(FidoGetAssertionHandlerTest,
TestRequestWithOperationDeniedErrorCrossPlatform) { … }
TEST_F(FidoGetAssertionHandlerTest, TestRequestWithPinAuthInvalid) { … }
MATCHER_P(IsCtap2Command, expected_command, "") { … }
TEST_F(FidoGetAssertionHandlerTest, DeviceFailsImmediately) { … }
TEST_F(FidoGetAssertionHandlerTest, PinUvAuthTokenPreTouchFailure) { … }
TEST(GetAssertionRequestHandlerTest, IncorrectTransportType) { … }
TEST_F(FidoGetAssertionHandlerTest, ReportTransportMetric) { … }
#if BUILDFLAG(IS_WIN)
TEST(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) {
base::test::TaskEnvironment task_environment;
for (const bool enable_api : {false, true}) {
SCOPED_TRACE(::testing::Message() << "enable_api=" << enable_api);
FakeWinWebAuthnApi api;
api.set_available(enable_api);
api.InjectNonDiscoverableCredential(
test_data::kTestGetAssertionCredentialId, test_data::kRelyingPartyId);
WinWebAuthnApi::ScopedOverride win_webauthn_api_override(&api);
ScopedFakeFidoHidManager fake_hid_manager;
fake_hid_manager.AddFidoHidDevice("guid");
TestGetAssertionRequestFuture future;
FidoDiscoveryFactory fido_discovery_factory;
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataJson);
request.allow_list = {PublicKeyCredentialDescriptor(
CredentialType::kPublicKey,
fido_parsing_utils::Materialize(
test_data::kTestGetAssertionCredentialId))};
auto handler = std::make_unique<GetAssertionRequestHandler>(
&fido_discovery_factory,
std::vector<std::unique_ptr<FidoDiscoveryBase>>(),
base::flat_set<FidoTransportProtocol>(
{FidoTransportProtocol::kUsbHumanInterfaceDevice}),
std::move(request), CtapGetAssertionOptions(),
true, future.GetCallback());
task_environment.RunUntilIdle();
EXPECT_EQ(handler->AuthenticatorsForTesting().size(), 1u);
EXPECT_EQ(handler->AuthenticatorsForTesting().begin()->second->GetType() ==
AuthenticatorType::kWinNative,
enable_api);
}
}
#endif
}