diff --git a/chromeos/dbus/u2f/fake_u2f_client.cc b/chromeos/dbus/u2f/fake_u2f_client.cc index 8a76975cf3c6f6..1d748a05652e9b 100644 --- a/chromeos/dbus/u2f/fake_u2f_client.cc +++ b/chromeos/dbus/u2f/fake_u2f_client.cc @@ -80,4 +80,10 @@ void FakeU2FClient::CancelWebAuthnFlow( NOTREACHED(); } +void FakeU2FClient::GetAlgorithms( + const u2f::GetAlgorithmsRequest& request, + DBusMethodCallback callback) { + NOTREACHED(); +} + } // namespace chromeos diff --git a/chromeos/dbus/u2f/fake_u2f_client.h b/chromeos/dbus/u2f/fake_u2f_client.h index fe36b72bcd9457..949e6e72f5267b 100644 --- a/chromeos/dbus/u2f/fake_u2f_client.h +++ b/chromeos/dbus/u2f/fake_u2f_client.h @@ -46,6 +46,9 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_U2F) FakeU2FClient : public U2FClient { void CancelWebAuthnFlow( const u2f::CancelWebAuthnFlowRequest& request, DBusMethodCallback callback) override; + void GetAlgorithms( + const u2f::GetAlgorithmsRequest& request, + DBusMethodCallback callback) override; }; } // namespace chromeos diff --git a/chromeos/dbus/u2f/u2f_client.cc b/chromeos/dbus/u2f/u2f_client.cc index e15398878a8375..7538d9715125b7 100644 --- a/chromeos/dbus/u2f/u2f_client.cc +++ b/chromeos/dbus/u2f/u2f_client.cc @@ -116,6 +116,9 @@ class U2FClientImpl : public U2FClient { void CancelWebAuthnFlow( const u2f::CancelWebAuthnFlowRequest& request, DBusMethodCallback callback) override; + void GetAlgorithms( + const u2f::GetAlgorithmsRequest& request, + DBusMethodCallback callback) override; private: dbus::ObjectProxy* proxy_ = nullptr; @@ -303,6 +306,18 @@ void U2FClientImpl::CancelWebAuthnFlow( weak_factory_.GetWeakPtr(), std::move(callback))); } +void U2FClientImpl::GetAlgorithms( + const u2f::GetAlgorithmsRequest& request, + DBusMethodCallback callback) { + dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FGetAlgorithms); + dbus::MessageWriter writer(&method_call); + writer.AppendProtoAsArrayOfBytes(request); + proxy_->CallMethod( + &method_call, kU2FShortTimeout, + base::BindOnce(&U2FClientImpl::HandleResponse, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + } // namespace U2FClient::U2FClient() { diff --git a/chromeos/dbus/u2f/u2f_client.h b/chromeos/dbus/u2f/u2f_client.h index eceddeb2b0dfc3..f999e8b225af62 100644 --- a/chromeos/dbus/u2f/u2f_client.h +++ b/chromeos/dbus/u2f/u2f_client.h @@ -102,6 +102,10 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_U2F) U2FClient { const u2f::CancelWebAuthnFlowRequest& request, DBusMethodCallback callback) = 0; + virtual void GetAlgorithms( + const u2f::GetAlgorithmsRequest& request, + DBusMethodCallback callback) = 0; + protected: U2FClient(); virtual ~U2FClient(); diff --git a/device/fido/cros/authenticator.cc b/device/fido/cros/authenticator.cc index abefdac6da9139..19ca55d7ec9bdf 100644 --- a/device/fido/cros/authenticator.cc +++ b/device/fido/cros/authenticator.cc @@ -9,6 +9,7 @@ #include "device/fido/cros/authenticator.h" #include "base/bind.h" +#include "base/containers/span.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/dbus/u2f/u2f_client.h" @@ -68,9 +69,39 @@ ChromeOSAuthenticator::AuthenticatorTransport() const { void ChromeOSAuthenticator::InitializeAuthenticator( base::OnceClosure callback) { + u2f::GetAlgorithmsRequest request; + chromeos::U2FClient::Get()->GetAlgorithms( + request, base::BindOnce(&ChromeOSAuthenticator::OnGetAlgorithmsResponse, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void ChromeOSAuthenticator::OnGetAlgorithmsResponse( + base::OnceClosure callback, + absl::optional response) { + if (response && response->status() == + u2f::GetAlgorithmsResponse_GetAlgorithmsStatus_SUCCESS) { + supported_algorithms_ = std::vector(); + for (int i = 0; i < response->algorithm_size(); i++) { + supported_algorithms_->push_back(response->algorithm(i)); + } + } else { + // Keep `supported_algorithms_` as nullopt if fetching supported algorithms + // from u2fd failed, since the caller of `GetAlgorithms` method might want + // to provide defaults. + supported_algorithms_ = absl::nullopt; + } + std::move(callback).Run(); } +absl::optional> +ChromeOSAuthenticator::GetAlgorithms() { + if (supported_algorithms_) { + return base::span(*supported_algorithms_); + } + return absl::nullopt; +} + void ChromeOSAuthenticator::MakeCredential( CtapMakeCredentialRequest request, MakeCredentialOptions request_options, diff --git a/device/fido/cros/authenticator.h b/device/fido/cros/authenticator.h index 2798583b8cd6bf..1f553bde831b95 100644 --- a/device/fido/cros/authenticator.h +++ b/device/fido/cros/authenticator.h @@ -8,6 +8,7 @@ #include #include "base/component_export.h" +#include "base/containers/span.h" #include "base/memory/weak_ptr.h" #include "chromeos/dbus/u2f/u2f_interface.pb.h" #include "dbus/bus.h" @@ -60,7 +61,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator base::OnceCallback callback); // FidoAuthenticator + + // Calls the u2fd API `GetAlgorithms` and cache the result. void InitializeAuthenticator(base::OnceClosure callback) override; + + // Since this method is synchronous, it will simply return the GetAlgorithms + // result obtained during `InitializeAuthenticator`. + absl::optional> GetAlgorithms() override; + void MakeCredential(CtapMakeCredentialRequest request, MakeCredentialOptions request_options, MakeCredentialCallback callback) override; @@ -84,6 +92,11 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator base::WeakPtr GetWeakPtr() override; private: + // Cache the supported algorithms in response, and run the completion callback + // of `InitializeAuthenticator`. + void OnGetAlgorithmsResponse( + base::OnceClosure callback, + absl::optional response); void OnMakeCredentialResponse( CtapMakeCredentialRequest request, MakeCredentialCallback callback, @@ -104,6 +117,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator // Callback to set request_id in the window property. base::RepeatingCallback generate_request_id_callback_; const Config config_; + absl::optional> supported_algorithms_; base::WeakPtrFactory weak_factory_; };