// Copyright 2017 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_CTAP_MAKE_CREDENTIAL_REQUEST_H_
#define DEVICE_FIDO_CTAP_MAKE_CREDENTIAL_REQUEST_H_
#include <stdint.h>
#include <array>
#include <optional>
#include <string>
#include <vector>
#include "base/component_export.h"
#include "device/fido/authenticator_selection_criteria.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/json_request.h"
#include "device/fido/pin.h"
#include "device/fido/prf_input.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
#include "device/fido/public_key_credential_rp_entity.h"
#include "device/fido/public_key_credential_user_entity.h"
#if BUILDFLAG(ARKWEB_FIDO)
#include "device/fido/ctap_make_credential_request_extra.h"
#endif // BUILDFLAG(ARKWEB_FIDO)
namespace cbor {
class Value;
}
namespace device {
// Object containing request parameters for AuthenticatorMakeCredential command
// as specified in
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
struct COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest {
public:
using ClientDataHash = std::array<uint8_t, kClientDataHashLength>;
// ParseOpts are optional parameters passed to Parse().
struct ParseOpts {
// reject_all_extensions makes parsing fail if any extensions are present.
bool reject_all_extensions = false;
};
// Decodes a CTAP2 authenticatorMakeCredential request message. The request's
// |client_data_json| will be empty and |client_data_hash| will be set.
static std::optional<CtapMakeCredentialRequest> Parse(
const cbor::Value::MapValue& request_map) {
return Parse(request_map, ParseOpts());
}
static std::optional<CtapMakeCredentialRequest> Parse(
const cbor::Value::MapValue& request_map,
const ParseOpts& opts);
CtapMakeCredentialRequest(
std::string client_data_json,
PublicKeyCredentialRpEntity rp,
PublicKeyCredentialUserEntity user,
PublicKeyCredentialParams public_key_credential_params);
CtapMakeCredentialRequest(const CtapMakeCredentialRequest& that);
CtapMakeCredentialRequest(CtapMakeCredentialRequest&& that);
CtapMakeCredentialRequest& operator=(const CtapMakeCredentialRequest& that);
CtapMakeCredentialRequest& operator=(CtapMakeCredentialRequest&& that);
~CtapMakeCredentialRequest();
std::string client_data_json;
ClientDataHash client_data_hash;
PublicKeyCredentialRpEntity rp;
PublicKeyCredentialUserEntity user;
PublicKeyCredentialParams public_key_credential_params;
UserVerificationRequirement user_verification =
UserVerificationRequirement::kDiscouraged;
AuthenticatorAttachment authenticator_attachment =
AuthenticatorAttachment::kAny;
bool resident_key_required = false;
// hmac_secret indicates whether the "hmac-secret" extension should be
// asserted to CTAP2 authenticators.
bool hmac_secret = false;
// prf indicates that the "prf" extension should be asserted to request that
// the authenticator associate a PRF with the credential.
bool prf = false;
// prf_input contains the hashed salts for doing a PRF evaluation at
// credential creation time. This is only possible when the authenticator
// supports the "prf" extension, i.e. over hybrid CTAP.
std::optional<PRFInput> prf_input;
// large_blob_support indicates whether support for largeBlobs should be
// requested using the `largeBlob` extension. This should be mutually
// exclusive with `large_blob_key`.
LargeBlobSupport large_blob_support = LargeBlobSupport::kNotRequested;
// large_blob_key indicates whether a large blob key should be associated to
// the new credential through the "largeBlobKey" extension. This should be
// mutually exclusive with `large_blob_support`.
bool large_blob_key = false;
std::vector<PublicKeyCredentialDescriptor> exclude_list;
// The pinUvAuthParam field. This is the result of calling
// |pin::TokenResponse::PinAuth(client_data_hash)| with the PIN/UV Auth Token
// response obtained from the authenticator.
std::optional<std::vector<uint8_t>> pin_auth;
// The pinUvAuthProtocol field. It is the version of the PIN/UV Auth Token
// response obtained from the authenticator.
std::optional<PINUVAuthProtocol> pin_protocol;
// The PIN/UV Auth Token response obtained from the authenticator. This field
// is only used for computing a fresh pinUvAuthParam for getAssertion requests
// during silent probing of |exclude_list| credentials. It is ignored when
// encoding this request to CBOR (|pin_auth| and |pin_protocol| are used for
// that).
std::optional<pin::TokenResponse> pin_token_for_exclude_list_probing;
AttestationConveyancePreference attestation_preference =
AttestationConveyancePreference::kNone;
// U2F AppID for excluding credentials.
std::optional<std::string> app_id_exclude;
// cred_protect indicates the level of protection afforded to a credential.
// This depends on a CTAP2 extension that not all authenticators will support.
// This is filled out by |MakeCredentialRequestHandler|.
std::optional<CredProtect> cred_protect;
// If |cred_protect| is not |nullopt|, this is true if the credProtect level
// must be provided by the target authenticator for the MakeCredential request
// to be sent. This only makes sense when there is a collection of
// authenticators to consider, i.e. for the Windows API.
bool cred_protect_enforce = false;
// min_pin_length_requested indicates that the minPinLength extension[1]
// should be sent to request that the authenticator report the minimum allowed
// PIN length configured.
//
// [1]
// https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-minpinlength-extension
bool min_pin_length_requested = false;
// cred_blob contains an optional credBlob extension.
// https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html#sctn-credBlob-extension
std::optional<std::vector<uint8_t>> cred_blob;
#if BUILDFLAG(ARKWEB_FIDO)
std::optional<CtapMakeCredentialRequestExtra> extra;
#endif // BUILDFLAG(ARKWEB_FIDO)
};
// MakeCredentialOptions contains higher-level request parameters that aren't
// part of the makeCredential request itself, or that need to be combined with
// knowledge of the specific authenticator, thus don't live in
// |CtapMakeCredentialRequest|.
struct COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialOptions {
MakeCredentialOptions();
explicit MakeCredentialOptions(
const AuthenticatorSelectionCriteria& authenticator_selection_criteria);
~MakeCredentialOptions();
MakeCredentialOptions(const MakeCredentialOptions&);
MakeCredentialOptions(MakeCredentialOptions&&);
MakeCredentialOptions& operator=(const MakeCredentialOptions&);
MakeCredentialOptions& operator=(MakeCredentialOptions&&);
// The JSON form of the request. (May be nullptr.)
scoped_refptr<JSONRequest> json;
// authenticator_attachment is a constraint on the type of authenticator
// that a credential should be created on.
AuthenticatorAttachment authenticator_attachment =
AuthenticatorAttachment::kAny;
// resident_key indicates whether the request should result in the creation
// of a client-side discoverable credential (aka resident key).
ResidentKeyRequirement resident_key = ResidentKeyRequirement::kDiscouraged;
// user_verification indicates whether the authenticator should (or must)
// perform user verficiation before creating the credential.
UserVerificationRequirement user_verification =
UserVerificationRequirement::kPreferred;
// cred_protect_request extends |CredProtect| to include information that
// applies at request-routing time. The second element is true if the
// indicated protection level must be provided by the target authenticator
// for the MakeCredential request to be sent.
std::optional<std::pair<CredProtectRequest, bool>> cred_protect_request;
// allow_skipping_pin_touch causes the handler to forego the first
// "touch-only" step to collect a PIN if exactly one authenticator is
// discovered.
bool allow_skipping_pin_touch = false;
// large_blob_support indicates whether the request should select for
// authenticators supporting the largeBlobs extension (kRequired), merely
// indicate support on the response (kPreferred), or ignore it
// (kNotRequested).
// Values other than kNotRequested will attempt to initialize the large blob
// on the authenticator.
LargeBlobSupport large_blob_support = LargeBlobSupport::kNotRequested;
// Indicates whether the request was created in an off-the-record
// BrowserContext (e.g. Chrome Incognito mode).
bool is_off_the_record_context = false;
// Indicates if this is a passkey upgrade request, i.e. whether
// mediation=conditional.
bool is_passkey_upgrade_request = false;
// The set of hints passed by the relying party.
// https://w3c.github.io/webauthn/#enum-hints.
std::vector<FidoTransportProtocol> hints;
};
// Serializes MakeCredential request parameter into CBOR encoded map with
// integer keys and CBOR encoded values as defined by the CTAP spec.
// https://drafts.fidoalliance.org/fido-2/latest/fido-client-to-authenticator-protocol-v2.0-wd-20180305.html#authenticatorMakeCredential
COMPONENT_EXPORT(DEVICE_FIDO)
std::pair<CtapRequestCommand, std::optional<cbor::Value>>
AsCTAPRequestValuePair(const CtapMakeCredentialRequest& request);
} // namespace device
#endif // DEVICE_FIDO_CTAP_MAKE_CREDENTIAL_REQUEST_H_