chromium/content/browser/webauth/authenticator_common_impl.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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 {

// RequestExtension is a type of extension in a WebAuthn request that might
// yield an extension output in the response.
enum class RequestExtension {};

enum class AttestationErasureOption {};

GetAssertionOutcome;
MakeCredentialOutcome;
RequestMode;

namespace {

WebAuthenticationDelegate* GetWebAuthenticationDelegate() {}

std::string Base64UrlEncode(const base::span<const uint8_t> input) {}

// The application parameter is the SHA-256 hash of the UTF-8 encoding of
// the application identity (i.e. relying_party_id) of the application
// requesting the registration.
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) {}

// Parses the FIDO transport types extension from the DER-encoded, X.509
// certificate in |der_cert| and adds any transport types found to
// |out_transports|. Returns true if any transports were added.
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) {}

// GetWebAuthnTransports returns the set of transports that should be passed to
// a FidoRequestHandler for a WebAuthn request. This determines for which
// transports the request handler will attempt to obtain FidoDiscovery
// instances.
base::flat_set<device::FidoTransportProtocol> GetWebAuthnTransports(
    RenderFrameHost* render_frame_host,
    device::FidoDiscoveryFactory* discovery_factory,
    bool uses_discoverable_creds,
    std::optional<bool> is_uvpaa_override) {}

// Returns a new FidoDiscoveryFactory for the current request. This may be
// a factory for virtual authenticators if the testing API is enabled for the
// given frame.
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) {}

// HashPRFValue hashes a PRF evaluation point with a fixed prefix in order to
// separate the set of points that a website can evaluate. See
// https://w3c.github.io/webauthn/#prf-extension.
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) {}

}  // namespace

// RequestState contains all state that is specific to a single WebAuthn call.
// Since `AuthenticatorCommonImpl` can service multiple calls, it's important
// that this state be reset after processing each one and collecting it into
// this structure makes that easier to enforce.
struct AuthenticatorCommonImpl::RequestState {};

// static
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 {}

// mojom::Authenticator
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) {}

// TODO(crbug.com/41371792): Add web tests to verify timeouts are
// indistinguishable from NOT_ALLOWED_ERROR cases.
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) {}

}  // namespace content