#include "content/browser/webauth/authenticator_common_impl.h"
#include <array>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "base/base64url.h"
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "components/webauthn/json/value_conversions.h"
#include "content/browser/renderer_host/back_forward_cache_disable.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/webauth/authenticator_environment.h"
#include "content/browser/webauth/client_data_json.h"
#include "content/browser/webauth/virtual_authenticator_manager_impl.h"
#include "content/browser/webauth/virtual_fido_discovery_factory.h"
#include "content/browser/webauth/webauth_request_security_checker.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "crypto/sha2.h"
#include "device/fido/attestation_statement.h"
#include "device/fido/authenticator_data.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/ctap_make_credential_request.h"
#include "device/fido/features.h"
#include "device/fido/fido_authenticator.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.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/filter.h"
#include "device/fido/get_assertion_request_handler.h"
#include "device/fido/make_credential_request_handler.h"
#include "device/fido/public_key.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
#include "net/cert/asn1_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "third_party/boringssl/src/pki/input.h"
#include "third_party/boringssl/src/pki/parse_values.h"
#include "third_party/boringssl/src/pki/parser.h"
#if BUILDFLAG(IS_MAC)
#include "device/fido/mac/authenticator.h"
#include "device/fido/mac/credential_metadata.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "device/fido/cros/authenticator.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "device/fido/win/authenticator.h"
#include "device/fido/win/webauthn_api.h"
#endif
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
#include "content/browser/webauth/is_uvpaa.h"
#endif
namespace content {
enum class RequestExtension { … };
enum class AttestationErasureOption { … };
GetAssertionOutcome;
MakeCredentialOutcome;
RequestMode;
namespace {
WebAuthenticationDelegate* GetWebAuthenticationDelegate() { … }
std::string Base64UrlEncode(const base::span<const uint8_t> input) { … }
std::array<uint8_t, crypto::kSHA256Length> CreateApplicationParameter(
const std::string& relying_party_id) { … }
device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
const std::string& client_data_json,
const blink::mojom::PublicKeyCredentialRequestOptionsPtr& options,
std::optional<std::string> app_id) { … }
bool AddTransportsFromCertificate(
base::span<const uint8_t> der_cert,
base::flat_set<device::FidoTransportProtocol>* out_transports) { … }
base::TimeDelta AdjustTimeout(std::optional<base::TimeDelta> timeout,
RenderFrameHost* render_frame_host) { … }
bool UsesDiscoverableCreds(const device::MakeCredentialOptions& options) { … }
bool UsesDiscoverableCreds(const device::CtapGetAssertionRequest& request) { … }
base::flat_set<device::FidoTransportProtocol> GetWebAuthnTransports(
RenderFrameHost* render_frame_host,
device::FidoDiscoveryFactory* discovery_factory,
bool uses_discoverable_creds,
std::optional<bool> is_uvpaa_override) { … }
std::unique_ptr<device::FidoDiscoveryFactory> MakeDiscoveryFactory(
RenderFrameHost* render_frame_host) { … }
std::optional<device::CredProtectRequest> ProtectionPolicyToCredProtect(
blink::mojom::ProtectionPolicy protection_policy,
const device::MakeCredentialOptions& make_credential_options) { … }
std::array<uint8_t, 32> HashPRFValue(base::span<const uint8_t> value) { … }
std::optional<device::PRFInput> ParsePRFInputForMakeCredential(
const blink::mojom::PRFValuesPtr& prf_input_from_renderer) { … }
std::optional<std::vector<device::PRFInput>> ParsePRFInputsForGetAssertion(
base::span<const blink::mojom::PRFValuesPtr> inputs) { … }
blink::mojom::PRFValuesPtr PRFResultsToValues(
base::span<const uint8_t> results) { … }
void SetHints(AuthenticatorRequestClientDelegate* request_delegate,
const base::flat_set<blink::mojom::Hint> hints) { … }
bool IsPlatformAuthenticatorForInvalidStateError(
const device::FidoAuthenticator* authenticator) { … }
AuthenticatorCommonImpl::CredentialRequestResult
CredentialRequestResultFromCode(bool success, device::AuthenticatorType type) { … }
void RecordRegisterOutcomeMetric(std::optional<RequestMode> mode,
ukm::SourceId source_id,
MakeCredentialOutcome outcome) { … }
void RecordSignOutcomeMetric(std::optional<RequestMode> mode,
ukm::SourceId source_id,
GetAssertionOutcome outcome) { … }
}
struct AuthenticatorCommonImpl::RequestState { … };
std::unique_ptr<AuthenticatorCommon> AuthenticatorCommon::Create(
RenderFrameHost* render_frame_host) { … }
AuthenticatorCommonImpl::AuthenticatorCommonImpl(
RenderFrameHost* render_frame_host,
ServingRequestsFor serving_requests_for)
: … { … }
AuthenticatorCommonImpl::~AuthenticatorCommonImpl() = default;
std::unique_ptr<AuthenticatorRequestClientDelegate>
AuthenticatorCommonImpl::MaybeCreateRequestDelegate() { … }
void AuthenticatorCommonImpl::StartMakeCredentialRequest(
bool allow_skipping_pin_touch) { … }
void AuthenticatorCommonImpl::StartGetAssertionRequest(
bool allow_skipping_pin_touch) { … }
bool AuthenticatorCommonImpl::IsFocused() const { … }
void AuthenticatorCommonImpl::MakeCredential(
url::Origin caller_origin,
blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
blink::mojom::Authenticator::MakeCredentialCallback callback) { … }
void AuthenticatorCommonImpl::ContinueMakeCredentialAfterRpIdCheck(
RequestKey request_key,
url::Origin caller_origin,
blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
bool is_cross_origin_iframe,
blink::mojom::AuthenticatorStatus rp_id_validation_result) { … }
void AuthenticatorCommonImpl::
ContinueMakeCredentialAfterBrowserPasskeysAvailabilityCheck(
RequestKey request_key,
bool available) { … }
void AuthenticatorCommonImpl::ContinueMakeCredentialAfterIsUvpaaOverrideCheck(
RequestKey request_key,
std::optional<bool> is_uvpaa_override) { … }
void AuthenticatorCommonImpl::GetAssertion(
url::Origin caller_origin,
blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
blink::mojom::PaymentOptionsPtr payment_options,
blink::mojom::Authenticator::GetAssertionCallback callback) { … }
void AuthenticatorCommonImpl::ContinueGetAssertionAfterRpIdCheck(
RequestKey request_key,
url::Origin caller_origin,
blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
blink::mojom::PaymentOptionsPtr payment_options,
bool is_cross_origin_iframe,
blink::mojom::AuthenticatorStatus rp_id_validation_result) { … }
void AuthenticatorCommonImpl::
ContinueGetAssertionAfterBrowserPasskeysAvailabilityCheck(
RequestKey request_key,
bool available) { … }
void AuthenticatorCommonImpl::ContinueGetAssertionAfterIsUvpaaOverrideCheck(
RequestKey request_key,
std::optional<bool> is_uvpaa_override) { … }
void AuthenticatorCommonImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
url::Origin caller_origin,
blink::mojom::Authenticator::
IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) { … }
void AuthenticatorCommonImpl::ContinueIsUvpaaAfterOverrideCheck(
blink::mojom::Authenticator::
IsUserVerifyingPlatformAuthenticatorAvailableCallback callback,
std::optional<bool> is_uvpaa_override) { … }
void AuthenticatorCommonImpl::IsConditionalMediationAvailable(
url::Origin caller_origin,
blink::mojom::Authenticator::IsConditionalMediationAvailableCallback
callback) { … }
void AuthenticatorCommonImpl::
ContinueIsConditionalMediationAvailableAfterOverrideCheck(
url::Origin caller_origin,
blink::mojom::Authenticator::IsConditionalMediationAvailableCallback
callback,
std::optional<bool> is_uvpaa_override) { … }
void AuthenticatorCommonImpl::Report(
url::Origin caller_origin,
blink::mojom::PublicKeyCredentialReportOptionsPtr options,
blink::mojom::Authenticator::ReportCallback callback) { … }
void AuthenticatorCommonImpl::ContinueReportAfterRpIdCheck(
RequestKey request_key,
blink::mojom::PublicKeyCredentialReportOptionsPtr options,
blink::mojom::AuthenticatorStatus rp_id_validation_result) { … }
void AuthenticatorCommonImpl::Cancel() { … }
void AuthenticatorCommonImpl::OnRegisterResponse(
device::MakeCredentialStatus status_code,
std::optional<device::AuthenticatorMakeCredentialResponse> response_data,
const device::FidoAuthenticator* authenticator) { … }
void AuthenticatorCommonImpl::OnRegisterResponseAttestationDecided(
AttestationErasureOption attestation_erasure,
device::AuthenticatorMakeCredentialResponse response_data,
bool attestation_permitted) { … }
void AuthenticatorCommonImpl::OnSignResponse(
device::GetAssertionStatus status_code,
std::optional<std::vector<device::AuthenticatorGetAssertionResponse>>
response_data,
device::FidoAuthenticator* authenticator) { … }
void AuthenticatorCommonImpl::OnAccountSelected(
device::AuthenticatorGetAssertionResponse response) { … }
void AuthenticatorCommonImpl::SignalFailureToRequestDelegate(
AuthenticatorRequestClientDelegate::InterestingFailureReason reason,
blink::mojom::AuthenticatorStatus status) { … }
void AuthenticatorCommonImpl::BeginRequestTimeout(
std::optional<base::TimeDelta> timeout) { … }
void AuthenticatorCommonImpl::OnTimeout() { … }
void AuthenticatorCommonImpl::CancelWithStatus(
blink::mojom::AuthenticatorStatus status) { … }
void AuthenticatorCommonImpl::OnCancelFromUI() { … }
blink::mojom::MakeCredentialAuthenticatorResponsePtr
AuthenticatorCommonImpl::CreateMakeCredentialResponse(
device::AuthenticatorMakeCredentialResponse response_data,
AttestationErasureOption attestation_erasure) { … }
void AuthenticatorCommonImpl::CompleteMakeCredentialRequest(
blink::mojom::AuthenticatorStatus status,
blink::mojom::MakeCredentialAuthenticatorResponsePtr response,
blink::mojom::WebAuthnDOMExceptionDetailsPtr dom_exception_details,
Focus check_focus) { … }
blink::mojom::GetAssertionAuthenticatorResponsePtr
AuthenticatorCommonImpl::CreateGetAssertionResponse(
device::AuthenticatorGetAssertionResponse response_data) { … }
void AuthenticatorCommonImpl::CompleteGetAssertionRequest(
blink::mojom::AuthenticatorStatus status,
blink::mojom::GetAssertionAuthenticatorResponsePtr response,
blink::mojom::WebAuthnDOMExceptionDetailsPtr dom_exception_details) { … }
void AuthenticatorCommonImpl::CompleteReportRequest(
blink::mojom::AuthenticatorStatus status,
blink::mojom::WebAuthnDOMExceptionDetailsPtr dom_exception_details) { … }
void AuthenticatorCommonImpl::Cleanup() { … }
void AuthenticatorCommonImpl::DisableUI() { … }
void AuthenticatorCommonImpl::DisableTLSCheck() { … }
RenderFrameHost* AuthenticatorCommonImpl::GetRenderFrameHost() const { … }
AuthenticatorRequestClientDelegate::RequestSource
AuthenticatorCommonImpl::RequestSource() const { … }
BrowserContext* AuthenticatorCommonImpl::GetBrowserContext() const { … }
device::FidoDiscoveryFactory* AuthenticatorCommonImpl::discovery_factory() { … }
void AuthenticatorCommonImpl::InitDiscoveryFactory() { … }
void AuthenticatorCommonImpl::EnableRequestProxyExtensionsAPISupport() { … }
WebAuthenticationRequestProxy*
AuthenticatorCommonImpl::GetWebAuthnRequestProxyIfActive(
const url::Origin& caller_origin) { … }
void AuthenticatorCommonImpl::OnMakeCredentialProxyResponse(
RequestKey request_key,
WebAuthenticationRequestProxy::RequestId request_id,
blink::mojom::WebAuthnDOMExceptionDetailsPtr error,
blink::mojom::MakeCredentialAuthenticatorResponsePtr response) { … }
void AuthenticatorCommonImpl::OnGetAssertionProxyResponse(
RequestKey request_key,
WebAuthenticationRequestProxy::RequestId request_id,
blink::mojom::WebAuthnDOMExceptionDetailsPtr error,
blink::mojom::GetAssertionAuthenticatorResponsePtr response) { … }
AuthenticatorCommonImpl::RequestKey AuthenticatorCommonImpl::GetRequestKey() { … }
bool AuthenticatorCommonImpl::CheckRequestKey(RequestKey request_key) { … }
}