blob: 0ae7ce6fa70ea149153c3bd455a80c9730a1e48e [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_FIDO_ENCLAVE_ENCLAVE_AUTHENTICATOR_H_
#define DEVICE_FIDO_ENCLAVE_ENCLAVE_AUTHENTICATOR_H_
#include <array>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/types/expected.h"
#include "components/sync/protocol/webauthn_credential_specifics.pb.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/authenticator_make_credential_response.h"
#include "device/fido/cable/v2_constants.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
#include "device/fido/enclave/enclave_protocol_utils.h"
#include "device/fido/enclave/enclave_websocket_client.h"
#include "device/fido/enclave/transact.h"
#include "device/fido/fido_authenticator.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_types.h"
#include "device/fido/network_context_factory.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace device::enclave {
struct CredentialRequest;
// This feature holds parameters that control the cert.xml & cert.sig.xml file
// locations, allowing us to roll out a new Vault cohort progressively.
// If URL parsing fails, the default is used instead.
COMPONENT_EXPORT(DEVICE_FIDO) BASE_DECLARE_FEATURE(kEnclaveTrustedVaultCohort);
COMPONENT_EXPORT(DEVICE_FIDO)
const extern base::FeatureParam<std::string> kCertXmlUrlFeature;
COMPONENT_EXPORT(DEVICE_FIDO)
const extern base::FeatureParam<std::string> kSigXmlUrlFeature;
class COMPONENT_EXPORT(DEVICE_FIDO) EnclaveAuthenticator
: public FidoAuthenticator {
public:
EnclaveAuthenticator(
std::unique_ptr<CredentialRequest> ui_request,
NetworkContextFactory network_context_factory);
~EnclaveAuthenticator() override;
EnclaveAuthenticator(const EnclaveAuthenticator&) = delete;
EnclaveAuthenticator& operator=(const EnclaveAuthenticator&) = delete;
void SetOauthToken(std::optional<std::string_view> token);
// FidoAuthenticator:
void GetAssertion(CtapGetAssertionRequest request,
CtapGetAssertionOptions options,
GetAssertionCallback callback) override;
void MakeCredential(CtapMakeCredentialRequest request,
MakeCredentialOptions options,
MakeCredentialCallback callback) override;
void InitializeAuthenticator(base::OnceClosure callback) override;
void Cancel() override;
AuthenticatorType GetType() const override;
std::string GetId() const override;
const AuthenticatorSupportedOptions& Options() const override;
std::optional<FidoTransportProtocol> AuthenticatorTransport() const override;
base::WeakPtr<FidoAuthenticator> GetWeakPtr() override;
private:
struct PendingGetAssertionRequest {
PendingGetAssertionRequest(CtapGetAssertionRequest,
CtapGetAssertionOptions,
GetAssertionCallback);
~PendingGetAssertionRequest();
PendingGetAssertionRequest(const PendingGetAssertionRequest&) = delete;
PendingGetAssertionRequest& operator=(const PendingGetAssertionRequest&) =
delete;
CtapGetAssertionRequest request;
CtapGetAssertionOptions options;
GetAssertionCallback callback;
};
struct PendingMakeCredentialRequest {
PendingMakeCredentialRequest(CtapMakeCredentialRequest,
MakeCredentialOptions,
MakeCredentialCallback);
~PendingMakeCredentialRequest();
PendingMakeCredentialRequest(const PendingMakeCredentialRequest&) = delete;
PendingMakeCredentialRequest& operator=(
const PendingMakeCredentialRequest&) = delete;
CtapMakeCredentialRequest request;
MakeCredentialOptions options;
MakeCredentialCallback callback;
};
void DispatchGetAssertion();
void OnHaveReencodedLargeBlob(
size_t original_size,
base::expected<mojo_base::BigBuffer, std::string> maybe_deflated);
void OnHaveInflatedLargeBlobForGetAssertion(
AuthenticatorGetAssertionResponse,
base::expected<mojo_base::BigBuffer, std::string>);
void ReturnGetAssertionSuccess(AuthenticatorGetAssertionResponse);
void DispatchMakeCredentialWithNewUVKey(
base::span<const uint8_t> uv_public_key);
void DispatchGetAssertionWithNewUVKey(
base::span<const uint8_t> uv_public_key);
void ProcessMakeCredentialResponse(
base::expected<cbor::Value, TransactError> maybe_response);
void ProcessGetAssertionResponse(
base::expected<cbor::Value, TransactError> maybe_response);
void ProcessErrorResponse(const ErrorResponse& error);
// `Complete*` methods invoke callbacks that can result in `this` being
// destroyed, and so should only be called immediately before a return.
void CompleteRequestWithError(
std::variant<GetAssertionStatus, MakeCredentialStatus> error);
void CompleteMakeCredentialRequest(
MakeCredentialStatus status,
std::optional<AuthenticatorMakeCredentialResponse> response);
void CompleteGetAssertionRequest(
GetAssertionStatus status,
std::vector<AuthenticatorGetAssertionResponse> responses);
data_decoder::DataDecoder* data_decoder();
const std::array<uint8_t, 8> id_;
const NetworkContextFactory network_context_factory_;
const std::unique_ptr<CredentialRequest> ui_request_;
// Caches the request while waiting for the connection to be established.
// At most one of these can be non-null at any given time.
std::unique_ptr<PendingGetAssertionRequest> pending_get_assertion_request_;
std::unique_ptr<PendingMakeCredentialRequest>
pending_make_credential_request_;
// Set to true when the request included a deferred UV key creation.
bool includes_new_uv_key_ = false;
std::unique_ptr<data_decoder::DataDecoder> data_decoder_;
base::WeakPtrFactory<EnclaveAuthenticator> weak_factory_{this};
};
} // namespace device::enclave
#endif // DEVICE_FIDO_ENCLAVE_ENCLAVE_AUTHENTICATOR_H_