1. Introduction
This section is not normative.
This protocol is intended to be used in scenarios where a user interacts with a Relying Party (a website or native app) on some platform (e.g., a PC) which prompts the user to interact with a roaming authenticator (e.g., a smartphone).
In order to provide evidence of user interaction, a roaming authenticator implementing this protocol may have a built-in mechanism to obtain a "user gesture", allowing the platform to collect a PIN on behalf of the authenticator.
1.1. Relationship to Other Specifications
This specification is part of the FIDO2 project, which includes this specification and is related to the W3C [WebAuthn] specification. This specification refers to two CTAP protocol versions:
-
The CTAP1/U2F protocol, which is defined by the U2F Raw Messages specification [U2FRawMsgs]. CTAP1/U2F messages are recognizable by their APDU-like binary structure. CTAP1/U2F may also be referred to as CTAP 1.2 or U2F 1.2. The latter was the U2F specification version used as the basis for several portions of this specification. Authenticators implementing CTAP1/U2F are typically referred to as U2F authenticators or CTAP1 authenticators.
-
The CTAP2 protocol, whose messages are encoded in the CTAP2 canonical CBOR encoding form. Authenticators implementing CTAP2 are referred to as CTAP2 authenticators, FIDO2 authenticators, or WebAuthn Authenticators.
Both CTAP1 and CTAP2 share the same underlying transports: USB Human Interface Device (USB HID), Near Field Communication (NFC), and Bluetooth Smart / Bluetooth Low Energy Technology (BLE).
Whole documents or specific features may be superseded by this document. A superseded document or feature MAY be implemented if optional, but it exists purely for backwards compatibility with older platforms or authenticators. Thus a superseded document or feature SHOULD NOT be used unless the replacement is not implemented by the counterparty. (Superseded features are not automatically optional, e.g. a CTAP 2.1 authenticator MUST still support authenticatorClientPIN's getPinToken subcommand if it supports clientPIN and CTAP 2.0.)
The [U2FUsbHid], [U2FNfc], [U2FBle], and [U2FRawMsgs] specifications, specifically, are superseded by this specification.
CTAP2 authenticators SHOULD also implement CTAP1/U2F. See § 10 Interoperating with CTAP1/U2F authenticators for details on how these protocols interoperate from the perspective of authenticators, platforms, and RPs.
Occasionally, the term "CTAP" may be used without clarifying whether it is referring to CTAP1 or CTAP2. In such cases, it should be understood to be referring to the entirety of this specification or portions of this specification that are not specific to either CTAP1 or CTAP2. For example, some error messages begin with the term "CTAP" without clarifying whether they are CTAP1- or CTAP2-specific because they are applicable to both CTAP protocol versions. CTAP protocol-specific error messages are prefixed with either "CTAP1" or "CTAP2" as appropriate.
Note: For certifications, other requirements than those specified in this specification may apply. Those seeking authenticator certifications can refer to the applicable certification documentation for additional information and requirements.
1.2. Data Elements Referenced by Other Specifications
The following data elements might be referenced by other specifications and hence should not be changed in their fundamental data type or high-level semantics without liaising with the other specifications:
-
aaguid, data type byte string and identifying the authenticator model, i.e. identical values mean that they refer to the same authenticator model and different values mean they refer to different authenticator models.
-
RP ID, data type string representing the Relying party identifier, i.e. identical values mean that they refer to the same Relying Party.
-
credentialID, data type byte string identifying a specific public key credential source, i.e. identical values mean that they refer to the same credential and different values mean they refer to different credentials. Note that there might be a very small probability that different credentials get assigned the same credentialID.
-
up and uv, data type boolean indicating whether user presence (up) or user verification (uv) was performed by the authenticator.
Note: Some of the data elements might have an internal structure that might change. Other specifications shall not rely on such internal structure.
2. Conformance
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this specification are to be interpreted as described in [RFC2119].
Authenticators and Platforms may implement additional constraints on these specifications to meet the certification requirements of programs like [CMVP], [CSPN], and [CommonCriteria].
3. Protocol Structure
This protocol is specified in three parts:
-
Authenticator API: At this level of abstraction, each authenticator operation is defined similarly to an API call - it accepts input parameters and returns either an output or error code. Note that this API level is conceptual and does not represent actual APIs. The actual APIs will be provided by each implementing platform.
-
Message Encoding: In order to invoke a method in the authenticator API, the host must construct and encode a request and send it to the authenticator over the chosen transport protocol. The authenticator will then process the request and return an encoded response.
-
Transport-specific Binding: Requests and responses are conveyed to roaming authenticators over specific transports (e.g., USB, NFC, Bluetooth). For each transport technology, message bindings are specified for this protocol.
This document specifies all three of the above pieces for roaming FIDO2 authenticators.
4. Protocol Overview
The general protocol between a Relying Party application, a client platform, and an authenticator is as follows:
-
In Relying Party-oriented use cases involving credential registration or user authentication, a Relying Party application calls
navigator.credentials.create()
ornavigator.credentials.get()
if it is a website, or the client platform’s equivalent API methods if it is a native application. Other use cases, such as credential management, PIN establishment/maintenance, or biometric enrollment, are typically initiated by the client platform itself. -
The platform establishes a connection with a nominally appropriate available authenticator, having used criteria passed in by the Relying Party application and possibly other information it has to select the authenticator.
- The platform gets information about the authenticator using the authenticatorGetInfo command, which helps it determine the authenticator’s capabilities.
-
Depending upon the operation the Relying Party application, or the platform itself, initiated (in step 1), the options it supplied, and the authenticator’s capabilities, the platform will invoke one or more further Authenticator API commands.
5. Terminology
- Built-in User Verification method
-
The authenticator supports a built-in on-device user verification method like fingerprint or has a input UI with secure communication to the authenticator.
Note: clientPin is not a built-in user verification method.
- Evidence of user interaction
-
Collection of evidence of user interaction establishes a state of user presence. Also, if it is collected along with displaying a particular prompt to a user it may be considered collecting user consent. The general notion is that the user interacts with the authenticator in some fashion, also known as supplying a "user gesture"—e.g., touches a consent button, enters a password or a PIN, or supplies a biometric—in order to at least confirm their presence and possibly consent to some proposed action. Some "user gesture" approaches provide user verification in addition to establishing user presence, e.g., a fingerprint-based built-in user verification method.
Platform-mediated user interactions such as clientPin may provide user verification but are not considered to assert user presence. Thus, there are transport-based affordances affecting when and for how long user presence is established on a per-transport basis:
- NFC
-
For authenticators without a method to collect a user gesture inside the authenticator boundary other than through a power on gesture, the act of a user placing an NFC authenticator into the NFC reader’s field is considered a user gesture that establishes user presence and provides evidence of user interaction. This powers-up the authenticator, who then starts an NFC powered-up timer, and sets an NFC userPresent flag to
true
. There is an associated NFC user presence maximum time limit of two minutes (120 seconds).Upon the platform subsequently invoking either authenticatorMakeCredential or authenticatorGetAssertion (e.g., with the "up" option key set to 'true'):
-
If evidence of user interaction is requested then:
-
If the NFC userPresent flag's value is
true
, then consider the user as having granted permission, and set the NFC userPresent flag tofalse
. -
Otherwise, do not consider the user as having granted permission.
-
Upon expiry of the NFC user presence maximum time limit, the NFC userPresent flag is set to
false
if it is not alreadyfalse
.Note: This notion of user presence establishment is distinct due to the physical proximity and user action characteristics of devices employing NFC to communicate, i.e., the user placing the authenticator in the NFC field, also known as the "NFC tap". Thus, user presence is asserted even if the platform and authenticator then use a form of user verification that does not itself provide user presence, such as clientPin-based user verification (clientPin does not assert user presence when used over other transports).
For example, in an authentication scenario, the user places an NFC authenticator on an NFC reading device having a keyboard and display, and is prompted to enter a PIN. If PIN entry is completed (e.g., by pressing Enter) before the NFC user presence maximum time limit expires, the authenticator will return an assertion with the "UP" bit in authenticator data set to
true
and the NFC userPresent flag is then set tofalse
.If a user lays an NFC authenticator on an NFC reader and for whatever reason ignores it for greater than the NFC user presence maximum time limit they will need to remove the authenticator from the NFC field and re-insert it and start over to complete any interaction requiring user presence.
-
- All other transports
-
If evidence of user interaction is explicitly requested (i.e., even if a pinUvAuthToken is in use) it is interactively collected at that time in an authenticator-specific manner.
- pre-flight
-
In order to determine whether [[#authenticatorMakeCredential|authenticatorMakeCredential]'s excludeList or authenticatorGetAssertion's allowList contain credential IDs that are already present on an authenticator, a platform typically invokes authenticatorGetAssertion with the "up" option key set to
false
and optionally pinUvAuthParam one or more times. If a credential is found an assertion is returned. If a valid pinUvAuthParam was also provided, the response will contain "up"=0 and "uv"=1 within the "flags bits" of the authenticator data structure, otherwise the "flag bits" will contain "up"=0 and "uv"=0. - Protected by some form of User Verification
-
Either or both clientPin or built-in user verification methods are supported and enabled. I.e., in the authenticatorGetInfo response the pinUvAuthToken option ID is present and set to
true
, and either clientPin option ID is present and set totrue
or uv option ID is present and set totrue
or both. - Some form of User Verification
-
This term refers to either clientPin or built-in user verification methods.
- User action timeout
-
This refers to a timeout that occurs when the authenticator is waiting for direct action from the user, like a touch. (I.e. not a command from the platform.) The duration of this timeout is chosen by the authenticator but MUST be at least 10 seconds. Thirty seconds is a reasonable value.
6. Authenticator API
Each operation in the authenticator API can be performed independently of the others, and all operations are asynchronous. The authenticator may enforce a limit on outstanding operations to limit resource usage - in this case, the authenticator is expected to return a busy status and the host is expected to retry the operation later. Additionally, this protocol does not enforce in-order or reliable delivery of requests and responses; if these properties are desired, they must be provided by the underlying transport protocol or implemented at a higher layer by applications.
Note that this API level is conceptual and does not represent actual APIs. The actual APIs will be provided by each implementing platform.
Some commands or subcommands require the authenticator to maintain state. For example, the authenticatorCredentialManagement subcommand enumerateRPsGetNextRP
implicitly assumes that the authenticator remembers which RP is next to return. The following (sub)commands require such state and are called stateful commands. Each such command uses and updates state that is initialized by a corresponding state initializing command:
-
authenticatorGetNextAssertion, with state initialized by authenticatorGetAssertion.
-
authenticatorCredentialManagement/
enumerateRPsGetNextRP
, with state initialized by enumerateRPsBegin. -
authenticatorCredentialManagement/
enumerateCredentialsGetNextCredential
, with state initialized by enumerateCredentialsBegin. -
authenticatorLargeBlobs where the parameter
set
is given and the parameteroffset
is non-zero, with state initialized by a prior authenticatorLargeBlobs command withset
given and a zerooffset
.
In order to accommodate authenticators with limited capacity, the following accommodations are made:
-
The state SHOULD NOT be maintained across power cycles.
-
The authenticator MAY maintain state based on the assumption that each stateful command is exclusively preceded by either another instance of the same command, or by the corresponding state initializing command, and no more than 30 seconds will elapse between such commands. If this pattern is violated then the authenticator MAY fail any stateful command with the error CTAP2_ERR_NOT_ALLOWED. Here, “exclusively preceded” means that no other authenticator operation occurs in between. An authenticator MAY assume this globally, even when the transport-specific binding provides for independent streams of platform commands (e.g. § 11.2.3 Concurrency and channels).
-
An authenticator MUST discard the state for a stateful command command if the pinUvAuthToken that authenticated the state initializing command expires since the stateful commands do not themselves always verify a pinUvAuthToken.
The authenticator API has the following methods and data structures.
6.1. authenticatorMakeCredential (0x01)
This method is invoked by the host to request generation of a new credential in the authenticator. It takes the following input parameters, several of which correspond to those defined in the authenticatorMakeCredential operation section of the Web Authentication specification:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
clientDataHash (0x01) | Byte String | Required | Hash of the ClientData contextual binding specified by host. See [WebAuthn]. |
rp (0x02) | PublicKeyCredentialRpEntity
| Required |
This PublicKeyCredentialRpEntity data structure describes a Relying Party with which the new public key credential will be associated.
It contains the relying party identifier (rp.id of type text string,
(optionally) a human-friendly RP name of type text string.
The RP name is to be used by the authenticator when displaying the credential to the user
for selection and usage authorization.
The RP name and URL are optional so that the RP can be more privacy friendly if it chooses to.
For example, for authenticators with a display, RP may not want to display name for single-factor scenarios.
Note: [WebAuthn-2] has removed the optional |
user (0x03) | PublicKeyCredentialUserEntity
| Required |
This PublicKeyCredentialUserEntity data structure describes the user account to which the new public key credential will be associated at the RP. It contains an RP-specific user account identifier of type byte string, (optionally) a user name of type text string, (optionally) a user display name of type text string, and (optionally) a URL of type text string, referencing a user icon image (of a user avatar, for example). Note that while an empty account identifier is valid, it has known interoperability hurdles in practice and platforms are recommended to avoid sending them. The authenticator associates the created public key credential with the account identifier, and MAY also associate any or all of the user name, and user display name. The user name and display name are optional for privacy reasons for single-factor scenarios where only user presence is required. For example, in certain closed physical environments like factory floors, user presence only authenticators can satisfy RP’s productivity and security needs. In these environments, omitting user name and display name makes the credential more privacy friendly. Although this information is not available without user verification, devices which support user verification but do not have it configured, can be tricked into releasing this information by configuring the user verification. Note: [WebAuthn-2] has removed the optional |
pubKeyCredParams (0x04) | Array of PublicKeyCredentialParameters
| Required | List of supported algorithms for credential generation, as specified in [WebAuthn]. The array is ordered from most preferred to least preferred and MUST NOT include duplicate entries. PublicKeyCredentialParameters' algorithm identifiers are values that SHOULD be registered in the IANA COSE Algorithms registry [IANA-COSE-ALGS-REG]. |
excludeList (0x05) | Array of PublicKeyCredentialDescriptor
| Optional | An array of PublicKeyCredentialDescriptor structures, as specified in [WebAuthn]. The authenticator returns an error if the authenticator already contains one of the credentials enumerated in this array. This allows RPs to limit the creation of multiple credentials for the same account on a single authenticator. |
extensions (0x06) | CBOR map of extension identifier → authenticator extension input values | Optional | Parameters to influence authenticator operation, as specified in [WebAuthn]. These parameters might be authenticator specific. |
options (0x07) | Map of authenticator options | Optional | Parameters to influence authenticator operation, as specified in in the table below. |
pinUvAuthParam (0x08) | Byte String | Optional | Result of calling authenticate(pinUvAuthToken, clientDataHash) |
pinUvAuthProtocol (0x09) | Unsigned Integer | Optional | PIN/UV protocol version chosen by the platform |
enterpriseAttestation (0x0A) | Unsigned Integer | optional |
An authenticator supporting this enterprise attestation feature is enterprise attestation capable and signals its support via the ep Option ID in the authenticatorGetInfo command response.
If the If present with a valid value, the usual privacy concerns around attestation batching may not apply to the results of this operation and the platform is requesting an enterprise attestation that includes uniquely identifying information. |
The following option keys are defined for use in authenticatorMakeCredential's options parameter. All option keys have boolean values.
Note: For brevity, individual option keys are often referred to as simply an "option", below.
Option Key | Default value | Definition |
---|---|---|
rk | false | Specifies whether this credential is to be discoverable or not. |
up | true | user presence: Instructs the authenticator to require user consent to complete
the operation. Platforms MAY send the "up" option key to CTAP2.1 authenticators, and its value MUST be true if present. The value false will cause a CTAP2_ERR_INVALID_OPTION response regardless of authenticator version.
|
uv | false |
user verification: If true , instructs the authenticator to require a user-verifying gesture
in order to complete the request. Examples of such gestures are fingerprint
scan or a PIN.
Note: Use of this "uv" option key is deprecated in CTAP2.1. Instead, platforms SHOULD create a pinUvAuthParam by obtaining pinUvAuthToken via getPinUvAuthTokenUsingUvWithPermissions or getPinUvAuthTokenUsingPinWithPermissions, as appropriate. Platforms MUST NOT include the "uv" option key if the authenticator does not support built-in user verification. Platforms MUST NOT include both the "uv" option key and the pinUvAuthParam parameter in the same request. |
Note: For backwards compatibility, platforms must be aware that FIDO_2_0 (aka CTAP2.0) authenticators always require some form of user verification for authenticatorMakeCredential operations. If a platform attempts to create a non-discoverable credential on a CTAP2.0 authenticator without including the "uv" option key or the pinUvAuthToken parameter that authenticator will return an error. In contrast, a FIDO_2_1 (aka CTAP2.1) authenticator with the makeCredUvNotRqd option ID (set to true
) in the authenticatorGetInfo response structure, will allow creation of non-discoverable credentials without requiring some form of user verification.
Note: For backwards compatibility, platforms must be aware that FIDO_2_0 (aka CTAP2.0) authenticators will return a CTAP2_ERR_INVALID_OPTION response if "up" is present. Platforms SHOULD NOT send "up" to a CTAP2.0 authenticator.
Note: The [WebAuthn] specification defines an abstract authenticatorMakeCredential
operation, which corresponds to the operation described in this section. The parameters in the
abstract [WebAuthn] authenticatorMakeCredential
operation map to the above parameters
as follows:
[WebAuthn] authenticatorMakeCredential operation
| CTAP authenticatorMakeCredential operation
|
---|---|
hash | clientDataHash |
rpEntity | rp |
userEntity | user |
requireResidentKey | options.rk |
requireUserPresence |
options.up
Note: [WebAuthn-2] defines |
requireUserVerification | options.uv or pinUvAuthParam |
credTypesAndPubKeyAlgs | pubKeyCredParams |
excludeCredentialDescriptorList | excludeList |
extensions | extensions |
Note: Icon values used with authenticators can employ [RFC2397] "data" URLs so that the image data is passed by value, rather than by reference. This can enable authenticators with a display but no Internet connection to display icons.
Note: Text strings are UTF-8 encoded (CBOR major type 3).
6.1.1. Platform Actions for authenticatorMakeCredential
(non-normative)
To invoke authenticatorMakeCredential
, the platform performs the following steps, in general. Here, we are assuming that the platform has already queried the authenticator for its particulars using the authenticatorGetInfo command, and has determined that the authenticator’s present characteristics are likely sufficient to be able to satisfy the request(s) the platform will send it. In other words, this is only a brief sketch of plausible platform behavior.
For example, if the authenticator is not protected by some form of user verification and user verification is required for the present usage scenario, e.g., the Relying Party set options.
authenticatorSelection
.userVerification
to "required" in the WebAuthn API, then the platform recovers in some fashion out of scope of these actions.
-
The platform marshals the necessary and appropriate input parameters given the present usage scenario, and additionally:
-
If the authenticator is protected by some form of user verification, or the Relying Party prefers enforcing user verification (e.g., by setting
options.
authenticatorSelection
.userVerification
to "required", or "preferred" in the WebAuthn API):-
If the platform has already created a pinUvAuthParam parameter during this overall scenario, it uses that along with the other marshalled input parameters to invoke the authenticator operation: either
authenticatorMakeCredential
or possibly authenticatorGetAssertion. For example, in some situations (e.g., with CTAP2 authenticators) when an "exclude list" was provided by the Relying Party, the platform may first invoke theauthenticatorGetAssertion
operation multiple times to "pre-flight" the "exclude list" (i.e., to determine if any of the exclude list’s credential IDs are already present on the authenticator), prior to invokingauthenticatorMakeCredential
to create a new credential on this authenticator. -
Otherwise, the platform examines various option IDs in the authenticatorGetInfo response to determine its course of action:
-
If the uv option ID is present and set to
true
:-
If the pinUvAuthToken option ID is present and
true
then plan to use getPinUvAuthTokenUsingUvWithPermissions to obtain a pinUvAuthToken, and let it be the selected operation. Go to Step 1.1.2.3. -
Else (implying the pinUvAuthToken option ID is set to
false
or absent) use the "uv" option key when invoking theauthenticatorMakeCredential
operation and terminate these steps. (Note that if the authenticator returns a 0x36 error code (CTAP2_ERR_PUAT_REQUIRED (aka CTAP2_ERR_PIN_REQUIRED in CTAP2.0)) then "fall back" and go to Step 1.1.2.2.2.1)
-
-
Else (implying the uv option ID is present and set to
false
or absent):-
If the pinUvAuthToken option ID is present and
true
:-
To continue, ensure the clientPin option ID is present and
true
. Plan to use getPinUvAuthTokenUsingPinWithPermissions to obtain a pinUvAuthToken, and let it be the selected operation. Go to Step 1.1.2.3.
-
- Else (implying the pinUvAuthToken option ID is absent):
-
To continue, ensure the clientPin option ID is present and
true
. Plan to use getPinToken to obtain a pinUvAuthToken, and let it be the selected operation.
-
-
- In preparation for obtaining pinUvAuthToken, the platform:
-
Obtains a shared secret.
-
Sets the pinUvAuthProtocol parameter to the value as selected when it obtained the shared secret.
-
-
Then the platform obtains a pinUvAuthToken from the authenticator, with the mc (and likely also with the ga) permission (see "pre-flight", mentioned above), using the selected operation. If successful, the platform creates the pinUvAuthParam parameter by calling authenticate(pinUvAuthToken, clientDataHash), and goes to Step 1.1.1.
-
-
-
Otherwise, implying the authenticator is not presently protected by some form of user verification, or the Relying Party wants to create a non-discoverable credential and not require user verification (e.g., by setting
options.
authenticatorSelection
.userVerification
to "discouraged" in the WebAuthn API), the platform invokes theauthenticatorMakeCredential
operation using the marshalled input parameters along with the "uv" option key set tofalse
and terminate these steps.
-
6.1.2. authenticatorMakeCredential
Algorithm
Upon receipt of an authenticatorMakeCredential
request, the authenticator performs the
following procedure:
-
If authenticator supports either pinUvAuthToken or clientPin features and the platform sends a zero length pinUvAuthParam:
-
Request evidence of user interaction in an authenticator-specific way (e.g., flash the LED light).
-
If the user declines permission, or the operation times out, then end the operation by returning CTAP2_ERR_OPERATION_DENIED.
-
If evidence of user interaction is provided in this step then return either CTAP2_ERR_PIN_NOT_SET if PIN is not set or CTAP2_ERR_PIN_INVALID if PIN has been set.
Note: This is done for backwards compatibility with CTAP2.0 platforms in the case where multiple authenticators are attached to the platform and the platform wants to enforce pinUvAuthToken feature semantics, but the user has to select which authenticator to get the pinUvAuthToken from. CTAP2.1 platforms SHOULD use § 6.9 authenticatorSelection (0x0B).
-
-
If the pinUvAuthParam parameter is present and the pinUvAuthProtocol parameter’s value is not supported or pinUvAuthProtocol parameter is absent, return CTAP2_ERR_PIN_AUTH_INVALID error.
-
If the pubKeyCredParams parameter does not contain at least one element having both a
COSEAlgorithmIdentifier
value that is supported by the authenticator and atype
member containing a string value matching aPublicKeyCredentialType
value, terminate this procedure and return error code CTAP2_ERR_UNSUPPORTED_ALGORITHM. The authenticator MUST ignore pubKeyCredParams parameter elements having unknown values. - Create a new authenticatorMakeCredential response structure and initialize both its "uv" bit and "up" bit as
false
. - If the options parameter is present, process all option keys and values present in the parameter. Treat any option keys that are not understood as absent.
Note: As this specification defines normative behaviours for the "rk", "up", and "uv" option keys, they MUST be understood by all authenticators.
-
If the "uv" option is absent, let the "uv" option be treated as being present with the value
false
. (This is the default) -
If the pinUvAuthParam is present, let the "uv" option be treated as being present with the value
false
.Note: pinUvAuthParam and the "uv" option are processed as mutually exclusive with pinUvAuthParam taking precedence.
-
If the "uv" option is
true
then:-
If the authenticator does not support a built-in user verification method end the operation by returning CTAP2_ERR_INVALID_OPTION.
-
If the built-in user verification method has not yet been enabled, end the operation by returning CTAP2_ERR_INVALID_OPTION.
-
-
If the "rk" option is present then:
-
If the rk option ID is not present in authenticatorGetInfo response, end the operation by returning CTAP2_ERR_UNSUPPORTED_OPTION.
-
-
If the "up" option is absent, let the "up" option be treated as being present with the value
true
(i.e., this is the default for both CTAP2.0 and CTAP2.1 authenticators). -
If the alwaysUv option ID is present and
true
then:-
Let the makeCredUvNotRqd option ID be treated as
false
. -
If the authenticator is not protected by some form of user verification:
-
If the pinUvAuthParam is not present, and the uv option ID is
true
, let the "uv" option be treated as being present with the valuetrue
.Note: The above step 5.8.3 is for backwards compatibility with CTAP2.0 platforms who are not aware of the Always UV feature.
-
If the pinUvAuthParam is not present, and the "uv" option is
false
or absent:
-
-
-
If the makeCredUvNotRqd option ID is present and set to
true
in the authenticatorGetInfo response:-
If the following statements are all true:
Note: This step returns an error if the platform tries to create a discoverable credential without performing some form of user verification.
-
The authenticator is protected by some form of user verification.
-
The pinUvAuthParam parameter is not present.
Then:
-
-
-
Else: (the makeCredUvNotRqd option ID in authenticatorGetInfo's response is present with the value
false
or is absent):-
If the following statements are all true:
Note: This step returns an error if the platform tries to create a credential without performing some form of user verification when the makeCredUvNotRqd option ID in authenticatorGetInfo's response is present with the value
false
or is absent.-
The authenticator is protected by some form of user verification.
-
The pinUvAuthParam parameter is not present.
Then:
-
-
-
If the enterpriseAttestation parameter is present:
-
If the authenticator is not enterprise attestation capable, or the authenticator is enterprise attestation capable but enterprise attestation is disabled, then end the operation by returning CTAP1_ERR_INVALID_PARAMETER.
-
Else: (the authenticator is enterprise attestation capable and enterprise attestation is enabled; see also § 7.1.2 Platform Actions):
-
If the enterpriseAttestation parameter’s value is not 1 or 2, then end the operation by returning CTAP2_ERR_INVALID_OPTION.
-
Consider the following cases in order, until one matches, to learn whether the authenticator may return an enterprise attestation. (These substeps define when an authenticator is permitted to return an enterprise attestation. Authenticators MUST NOT do so in any other cases.)
-
If the authenticator supports only vendor-facilitated enterprise attestation and the request’s rp.id matches an entry on the authenticator’s pre-configured rp.id list, then the authenticator MAY return an enterprise attestation.
Note: An authenticator that only supports vendor-facilitated enterprise attestation is obliged to treat enterpriseAttestation parameter values 1 and 2 equivalently, otherwise it will yield unexpected results if used with an enterprise-managed platform (which will be setting enterpriseAttestation to 2).
-
If the authenticator supports vendor-facilitated enterprise attestation at all, the enterpriseAttestation parameter’s value is 1, and the request’s rp.id matches an entry on the authenticator’s pre-configured rp.id list, then the authenticator MAY return an enterprise attestation.
-
If the authenticator supports platform-managed enterprise attestation (whether or not vendor-facilitated enterprise attestation is also supported), and the enterpriseAttestation parameter’s value is 2, then the platform MUST have performed the necessary vetting of the request’s rp.id (e.g., via local policy lookup), and the authenticator MAY return an enterprise attestation without checking whether the request’s rp.id matches an entry on the authenticator’s pre-configured rp.id list (if any).
-
-
If, by considering the substeps of the previous step, the authenticator did not conclude that it may return an enterprise attestation then let the enterpriseAttestation parameter be treated as absent, terminate these steps, and go to Step 9. A non-enterprise attestation will be returned with the credential.
-
Apply any additional constraints that may prohibit returning an enterprise attestation. An authenticator has unlimited discretion to apply additional constraints which can further limit the contexts in which enterprise attestation is returned. They may be based on other parameters from the request or, indeed, on any other factor the authenticator wishes. It is the job of enterprise Relying Party to know the authenticators that it has deployed and thus to arrange the request so as to get its desired result.
-
If, by considering any additional constraints in the previous step, the authenticator concluded that it did not wish to return an enterprise attestation then let the enterpriseAttestation parameter be treated as absent, terminate these steps, and go to Step 9. A non-enterprise attestation will be returned with the credential.
-
If the authenticator has a display, then the authenticator SHOULD display an explicit warning to the user, including the rp.id, notifying the user that they are being uniquely identified to this Relying Party.
-
Let epAtt in the authenticatorMakeCredential response structure be set to
true
and return an enterprise attestation.
-
-
- If the following statements are all true:
Note: This step allows the authenticator to create a non-discoverable credential without requiring some form of user verification under the below specific criteria.
-
the makeCredUvNotRqd option ID in authenticatorGetInfo's response is present with the value
true
. -
the pinUvAuthParam parameter is not present.
Then go to Step 11.
Note: Step 4 has already ensured that the "uv" bit is
false
in the response. - If the authenticator is protected by some form of user verification, then:
-
If pinUvAuthParam parameter is present (implying the "uv" option is
false
(see Step 5)):-
Let userVerifiedFlagValue be the result of calling getUserVerifiedFlagValue().
-
If userVerifiedFlagValue is
false
then end the operation by returning CTAP2_ERR_PIN_AUTH_INVALID. -
Verify that the pinUvAuthToken has the mc permission, if not, then end the operation by returning CTAP2_ERR_PIN_AUTH_INVALID.
-
If the pinUvAuthToken has a permissions RPID associated:
-
If the permissions RPID does not match the rp.id in this request, then end the operation by returning CTAP2_ERR_PIN_AUTH_INVALID.
-
-
If the pinUvAuthToken does not have a permissions RPID associated:
-
Associate the request’s rp.id parameter value with the pinUvAuthToken as its permissions RPID.
-
-
Call verify(pinUvAuthToken, clientDataHash, pinUvAuthParam).
-
If the verification returns
error
, then end the operation by returning CTAP2_ERR_PIN_AUTH_INVALID error. -
If the verification returns
success
, set the "uv" bit totrue
in the response.
-
-
Go to Step 11.
-
-
If the "uv" option is present and set to
true
(implying the pinUvAuthParam parameter is not present, and that the authenticator supports an enabled built-in user verification method, see Step 5):Note: This step provides backwards compatibility for CTAP2.0 platforms.
-
Let internalRetry be
true
. -
Let uvState be the result of calling performBuiltInUv(internalRetry)
-
If uvState is
error
: -
If uvState is
success
:-
Set the "uv" bit to
true
in the response.
-
-
Note: If Step 10 was skipped, then the authenticator is NOT protected by some form of user verification, and Step 4 has already ensured that the "uv" bit is
false
in the response. -
- If the excludeList parameter is present and contains a credential ID created by this authenticator, that is bound to the specified rp.id:
-
If the credential’s credProtect value is not userVerificationRequired, then:
-
Let userPresentFlagValue be the result of calling getUserPresentFlagValue().
-
If userPresentFlagValue is
false
, then:-
Wait for user presence.
-
Regardless of whether user presence is obtained or the authenticator times out, terminate this procedure and return CTAP2_ERR_CREDENTIAL_EXCLUDED.
-
-
Else, (implying userPresentFlagValue is
true
) terminate this procedure and return CTAP2_ERR_CREDENTIAL_EXCLUDED.Note: A user presence test is required for CTAP2 authenticators, before the RP is told that the authenticator is already registered, to behave similarly to CTAP1/U2F authenticators.
-
-
-
Else (implying the credential’s credProtect value is userVerificationRequired):
-
If the "uv" bit is
true
in the response, wait for user presence and return CTAP2_ERR_CREDENTIAL_EXCLUDED. -
Else (implying user verification was not collected in Step 10), remove the credential from the excludeList and continue parsing the rest of the list.
-
-
-
If evidence of user interaction was provided as part of Step 10 (i.e., by invoking performBuiltInUv()):
Note: This step’s criteria implies that the "uv" option is present and set to
true
and the pinUvAuthParam parameter is not present. I.e., the pinUvAuthToken feature is not in use.-
Set the "up" bit to
true
in the response. -
Go to Step 14
-
-
If the "up" option is set to
true
:-
If the pinUvAuthParam parameter is present then:
-
Let userPresentFlagValue be the result of calling getUserPresentFlagValue().
-
If userPresentFlagValue is
false
:Note: An authenticator may be configured to collect user presence whenever the "up" option is
true
by setting the default user present time limit to zero.-
Request evidence of user interaction in an authenticator-specific way (e.g., flash the LED light). If the authenticator has a display, show the items contained within the user and rp parameter structures to the user, and request permission to create a credential.
-
If the user declines permission, or the operation times out, then end the operation by returning CTAP2_ERR_OPERATION_DENIED.
-
-
-
Else (implying the pinUvAuthParam parameter is not present):
-
If the "up" bit is
false
in the response :-
Request evidence of user interaction in an authenticator-specific way (e.g., flash the LED light). If the authenticator has a display, show the items contained within the user and rp parameter structures to the user, and request permission to create a credential.
-
If the user declines permission, or the operation times out, then end the operation by returning CTAP2_ERR_OPERATION_DENIED.
-
-
-
Set the "up" bit to
true
in the response. -
Call clearUserPresentFlag(), clearUserVerifiedFlag(), and clearPinUvAuthTokenPermissionsExceptLbw().
Note: This consumes both the "user present state", sometimes referred to as the "cached UP", and the "user verified state", sometimes referred to as "cached UV". These functions are no-ops if there is not an in-use pinUvAuthToken.
-
- If the extensions parameter is present:
-
Process any extensions that this authenticator supports, ignoring any that it does not support.
-
Authenticator extension outputs generated by the authenticator extension processing are returned in the authenticator data. The set of keys in the authenticator extension outputs map MUST be equal to, or a subset of, the keys of the authenticator extension inputs map.
Note: Some extensions may produce different output depending on the state of the "uv" bit and/or "up" bit in the response.
-
-
Generate a new credential key pair for the algorithm specified.
-
If the "rk" option is set to
true
:-
The authenticator MUST create a discoverable credential.
-
If a credential for the same rp.id and account ID already exists on the authenticator:
-
If the existing credential contains a largeBlobKey, an authenticator MAY erase any associated large-blob data. Platforms MUST NOT assume that authenticators will do this. Platforms can later garbage collect any orphaned large-blobs.
-
Overwrite that credential.
-
-
Store the user parameter along with the newly-created key pair.
-
If authenticator does not have enough internal storage to persist the new credential, return CTAP2_ERR_KEY_STORE_FULL.
-
-
Otherwise, if the "rk" option is
false
: the authenticator MUST create a non-discoverable credential.Note: This step is a change from CTAP2.0 where if the "rk" option is
false
the authenticator could optionally create a discoverable credential. -
Generate an attestation statement for the newly-created credential using clientDataHash, taking into account the value of the enterpriseAttestation parameter, if present, as described above in Step 8.
On success, the authenticator returns the following authenticatorMakeCredential response structure which contains an attestation object plus additional information.
Member name | Data type | Required? | Definition |
---|---|---|---|
fmt (0x01) | String | Required | The attestation statement format identifier. |
authData (0x02) | Byte String | Required | The authenticator data object. |
attStmt (0x03) | CBOR Map, the structure of which depends on the attestation statement format identifier | Required | The attestation statement, as specified in [WebAuthn]. |
epAtt (0x04) | Boolean | Optional | Indicates whether an enterprise attestation was returned for this credential. If epAtt is absent or
present and set to false , then an enterprise attestation was not returned. If epAtt is present and
set to true , then an enterprise attestation was returned.
|
largeBlobKey (0x05) | Byte string | Optional | Contains the largeBlobKey for the credential, if requested with the largeBlobKey extension. |
6.1.3. Discoverable credentials
A credential may, or may not, be discoverable. A discoverable credential [WebAuthn] has the property that, in response to an authenticatorGetAssertion request where the allowList
parameter is omitted, the authenticator is able to discover the appropriate public key credential source given only an RP ID, possibly with user assistance.
Each credential has a credential protection policy. For backwards compatibility with CTAP2.0 platforms, the default credential creation policy is userVerificationOptional (0x01). If a credential was created with credential protection values of userVerificationOptionalWithCredentialIDList (0x02) or userVerificationRequired (0x03) it will not be discoverable unless the platform invokes authenticatorGetAssertion with a valid pinUvAuthParam or the "uv" option key with a value of true
.
Note: Regarding user assistance, for example, the authenticator may provide the user a pick-list of credentials scoped to the RP ID.
In contrast, server-side credentials (also known as non-discoverable credentials) have the property that their credential IDs MUST be supplied by the Relying Party in authenticatorGetAssertion's allowList
parameter in order for the authenticator to discover and employ them.
Note that this definition does not speak to whether a credential is statefully maintained or not.
An authenticator may choose to keep state, such as the private key, whether a credential is discoverable or not (see also public key credential source). A discoverable credential, however, always involves maintaining some state because it must be discoverable using only the RP ID and the user
id
(also known as the user handle) must always be returned.
All state that is kept for a discoverable credential MUST be stored client side—i.e., such that the authenticator working together with the client platform, if necessary, can satisfy requested authenticator operations.
An authenticator specifies whether it is capable of creating discoverable credentials via the rk option ID in the authenticatorGetInfo response. A discoverable credential will be created if, and only if, the rk option key of the options parameter of an authenticatorMakeCredential request is true
.
An authenticator’s discoverable credentials may be managed via the authenticatorCredentialManagement command.
Note: Historically discoverable credentials have been called "resident keys", and this terminology can still be found in aspects of the protocol. (For example the name of the rk option key comes from the term “resident key”.) However, the word “resident” conflated the concepts of being discoverable and being statefully maintained by the authenticator, when it’s only the former that is externally observable and thus important.
6.2. authenticatorGetAssertion (0x02)
This method is used by a host to request cryptographic proof of user authentication as well as user consent to a given transaction, using a previously generated credential that is bound to the authenticator and relying party identifier. It takes the following input parameters, several of which correspond to those defined in the authenticatorGetAssertion operation section of the Web Authentication specification:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
rpId (0x01) | String | Required | relying party identifier. See [WebAuthn]. |
clientDataHash (0x02) | Byte String | Required | Hash of the serialized client data collected by the host. See [WebAuthn]. |
allowList (0x03) | Array of PublicKeyCredentialDescriptor
| Optional | An array of PublicKeyCredentialDescriptor structures, each denoting a credential, as specified in [WebAuthn]. A platform MUST NOT send an empty allowList—if it would be empty it MUST be omitted. If this parameter is present the authenticator MUST only generate an assertion using one of the denoted credentials. |
extensions (0x04) | CBOR map of extension identifier → authenticator extension input values | Optional | Parameters to influence authenticator operation. These parameters might be authenticator specific. |
options (0x05) | Map of authenticator options | Optional | Parameters to influence authenticator operation, as specified in the table below. |
pinUvAuthParam (0x06) | Byte String | Optional | Result of calling authenticate(pinUvAuthToken, clientDataHash) |
pinUvAuthProtocol (0x07) | Unsigned Integer | Optional | PIN/UV protocol version selected by client. |
The following option keys are defined for use in #authenticatorGetAssertion's options parameter. All option keys have boolean values.
Note: For brevity, individual option keys are often referred to as simply an "option", below.
Option Key | Default value | Definition |
---|---|---|
up | true | user presence: Instructs the authenticator to require user consent to complete the operation. |
uv | false |
user verification: If true , instructs the authenticator to require a user-verifying gesture
in order to complete the request. Examples of such gestures are fingerprint
scan or a PIN.
Note: Use of this "uv" option key is deprecated in CTAP2.1. Instead, platforms SHOULD create a pinUvAuthParam by obtaining pinUvAuthToken via getPinUvAuthTokenUsingUvWithPermissions or getPinUvAuthTokenUsingPinWithPermissions, as appropriate. Platforms MUST NOT include the "uv" option parameter if the authenticator does not support built-in user verification. Platforms MUST NOT include both "uv" and pinUvAuthParam parameters in same request. |
Note: Platforms MUST NOT send the "rk" option key.
Note: For backwards compatibility with CTAP2.0 platforms, the authenticator may perform a built-in user verification method even if not requested to enhance its security offering. Thus, platforms should be prepared to receive a CTAP2_ERR_PUAT_REQUIRED error even if the platform did not include the "uv" option key, or did include it and set it to false
. CTAP2.1 authenticators SHOULD use the authenticator always requires some form of user verification feature to signal this behaviour.
Note: The [WebAuthn] specification defines an abstract authenticatorGetAssertion
operation, which corresponds to the operation described in this section. The parameters in the
abstract [WebAuthn] authenticatorGetAssertion
operation map to the above parameters
as follows:
[WebAuthn] authenticatorGetAssertion operation
| CTAP authenticatorGetAssertion operation
|
---|---|
hash | clientDataHash |
rpId | rpId |
allowCredentialDescriptorList | allowList |
requireUserPresence |
options.up
Note: [WebAuthn-2] defines |
requireUserVerification | options.uv or pinUvAuthParam |
extensions | extensions |
6.2.1. Platform Actions for authenticatorGetAssertion
(non-normative)
To invoke authenticatorGetAssertion
, the platform performs the following steps, in general. Here, we are assuming that the platform has already queried the authenticator for its particulars using the authenticatorGetInfo command, and has determined that the authenticator’s present characteristics are likely sufficient to be able to satisfy the request(s) the platform will send it. In other words, this is only a brief sketch of plausible platform behavior.
For example, if the authenticator is not protected by some form of user verification and user verification is required for the present usage scenario, e.g., the Relying Party set options.
userVerification
to "required" in the WebAuthn API, then the platform recovers in some fashion out of scope of these actions.
-
The platform marshals the necessary and appropriate input parameters given the present usage scenario, and additionally:
-
If the authenticator is protected by some form of user verification or the Relying Party prefers enforcing user verification (e.g., by setting
options.
userVerification
to "required", or "preferred" in the WebAuthn API):-
If the platform has already created a pinUvAuthParam parameter during this overall scenario, it uses that along with the other marshalled input parameters to invoke the
authenticatorGetAssertion
. Or, in some situations (e.g., with CTAP2 authenticators) the platform may invoke theauthenticatorGetAssertion
operation multiple times using the pinUvAuthParam parameter to "pre-flight" an "allow list" (i.e., to determine if any of the allow list’s credential IDs are already present on the authenticator), prior to invokingauthenticatorGetAssertion
to have this authenticator issue an assertion using the selected credential. -
Otherwise, the platform examines various option IDs in the authenticatorGetInfo response to determine its course of action:
-
If the uv option ID is present and set to
true
:-
If the pinUvAuthToken option ID is present and
true
then plan to use getPinUvAuthTokenUsingUvWithPermissions to obtain a pinUvAuthToken, and let it be the selected operation. Go to Step 1.1.2.3. -
Else (implying the pinUvAuthToken option ID is set to
false
or absent) use the "uv" option key when invoking theauthenticatorGetAssertion
operation and terminate these steps. (Note that if the authenticator returns a 0x36 error code (CTAP2_ERR_PUAT_REQUIRED (aka CTAP2_ERR_PIN_REQUIRED in CTAP2.0)) then "fall back" and go to Step 1.1.2.2.2.1)
-
-
Else (implying the uv option ID is present and set to
false
or absent):-
If the pinUvAuthToken option ID is present and
true
:-
To continue, ensure the clientPin option ID is present and
true
. Plan to use getPinUvAuthTokenUsingPinWithPermissions to obtain a pinUvAuthToken, and let it be the selected operation. Go to Step 1.1.2.3.
-
- Else (implying the pinUvAuthToken option ID is absent):
-
To continue, ensure the clientPin option ID is present and
true
. Plan to use getPinToken to obtain a pinUvAuthToken, and let it be the selected operation.
-
-
- In preparation for obtaining pinUvAuthToken, the platform:
-
Obtains a shared secret.
-
Sets the pinUvAuthProtocol parameter to the value as selected when it obtained the shared secret.
-
-
Then the platform obtains a pinUvAuthToken from the authenticator, with the ga permission using the selected operation. If successful, the platform creates the pinUvAuthParam parameter by calling authenticate(pinUvAuthToken, clientDataHash), and goes to Step 1.1.1 to use it.
-
-
-
Otherwise, implying the authenticator is not presently protected by some form of user verification, or the Relying Party does not wish to require user verification (e.g., by setting
options.
userVerification
to "discouraged" in the WebAuthn API), the platform invokes theauthenticatorGetAssertion
operation using the marshalled input parameters along with an absent "uv" option key.
-
6.2.2. authenticatorGetAssertion
Algorithm
Upon receipt of a authenticatorGetAssertion
request, the authenticator performs the
following procedure:
-
If authenticator supports either pinUvAuthToken or clientPin features and the platform sends a zero length pinUvAuthParam:
-
Request evidence of user interaction in an authenticator-specific way (e.g., flash the LED light).
-
If the user declines permission, or the operation times out, then end the operation by returning CTAP2_ERR_OPERATION_DENIED.
-
If evidence of user interaction is provided in this step then return either CTAP2_ERR_PIN_NOT_SET if PIN is not set or CTAP2_ERR_PIN_INVALID if PIN has been set.
Note: This is done for backwards compatibility with CTAP2.0 platforms in the case where multiple authenticators are attached to the platform and the platform wants to enforce pinUvAuthToken semantics, but the user has to select which authenticator to get the pinUvAuthToken from. CTAP2.1 platforms SHOULD use § 6.9 authenticatorSelection (0x0B).
-
-
If the pinUvAuthParam parameter is present and the pinUvAuthProtocol value is not supported or pinUvAuthProtocol parameter is absent, return CTAP2_ERR_PIN_AUTH_INVALID error.
- Create a new authenticatorGetAssertion response structure and initialize both its "uv" bit and "up" bit as
false
. - If the options parameter is present, process all option keys and values present in the parameter. Treat any option keys that are not understood as absent.
Note: As this specification defines normative behaviours for the "rk", "up", and "uv" option keys, they MUST be understood by all authenticators.
-
If the "uv" option is absent, let the "uv" option be treated as being present with the value
false
. (This is the default) -
If the pinUvAuthParam is present, let the "uv" option be treated as being present with the value
false
.Note: pinUvAuthParam and the "uv" option are processed as mutually exclusive with pinUvAuthParam taking precedence.
-
If the "uv" option is present and
true
then:-
If the authenticator does not support a built-in user verification method end the operation by returning CTAP2_ERR_INVALID_OPTION.
-
If the built-in user verification method has not yet been enabled, end the operation by returning CTAP2_ERR_INVALID_OPTION.
-
-
If the "rk" option is present then:
-
Return CTAP2_ERR_UNSUPPORTED_OPTION.
-
-
If the alwaysUv option ID is present and
true
and the "up" option is present andtrue
then:-
If the authenticator is not protected by some form of user verification:
-
If the pinUvAuthParam is present then go to Step 5.
-
If the "uv" option is
false
and the authenticator supports a built-in user verification method, and the user verification method is enabled then: -
If the clientPin option ID is present and the pinUvAuthParam parameter is not present, then end the operation by returning CTAP2_ERR_PUAT_REQUIRED.
Note: This is to address the case of CTAP2.0 platforms not being aware of and ignoring the alwaysUv option ID.
-
-
- If authenticator is protected by some form of user verification, then:
-
If pinUvAuthParam parameter is present (implying the "uv" option is treated as
false
, see Step 4):-
Let userVerifiedFlagValue be the result of calling getUserVerifiedFlagValue().
-
If userVerifiedFlagValue is
false
then end the operation by returning CTAP2_ERR_PIN_AUTH_INVALID. -
Verify that the pinUvAuthToken has the ga permission, if not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
If the pinUvAuthToken has a permissions RPID associated:
-
If the permissions RPID does not match the RPID in this request, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
If the pinUvAuthToken does not have a permissions RPID associated:
-
Associate the request’s RPID parameter value with the pinUvAuthToken as its permissions RPID.
-
-
Call verify(pinUvAuthToken, clientDataHash, pinUvAuthParam).
-
If the verification returns
error
, return CTAP2_ERR_PIN_AUTH_INVALID error. -
If the verification returns
success
, set the "uv" bit totrue
in the response.
-
-
Go to Step 6.
-
-
If the "uv" option is present and set to
true
(implying the pinUvAuthParam parameter is not present, and that the authenticator supports an enabled built-in user verification method, see Step 4):Note: This step provides backwards compatibility for CTAP2.0 platforms.
-
Let internalRetry be
true
. -
Let uvState be the result of calling performBuiltInUv(internalRetry)
-
If uvState is
error
: -
If uvState is success:
-
Set the "uv" bit to
true
in the response.
-
-
Note: If Step 5 was skipped, then the authenticator is NOT protected by some form of user verification, and Step 3 has already ensured that the "uv" bit is
false
in the response. -
- Locate all credentials that are eligible for retrieval under the specified criteria:
-
If the allowList parameter is present and is non-empty, locate all denoted credentials created by this authenticator and bound to the specified rpId.
-
If an allowList is not present, locate all discoverable credentials that are created by this authenticator and bound to the specified rpId.
-
Create an applicable credentials list populated with the located credentials.
-
Iterate through the applicable credentials list, and if credential protection for a credential is marked as
userVerificationRequired
, and the "uv" bit isfalse
in the response, remove that credential from the applicable credentials list. -
Iterate through the applicable credentials list, and if credential protection for a credential is marked as
userVerificationOptionalWithCredentialIDList
and there is no allowList passed by the client or there has not been any user verification happened in above steps, remove that credential from the applicable credentials list. -
If the applicable credentials list is empty, return CTAP2_ERR_NO_CREDENTIALS.
-
Let
numberOfCredentials
be the number of applicable credentials found.
-
-
If evidence of user interaction was provided as part of Step 5.2 (i.e., by invoking performBuiltInUv()):
Note: This step’s criteria implies that the "uv" option is present and set to
true
and the pinUvAuthParam parameter is not present. I.e., the pinUvAuthToken feature is not in use.-
Set the "up" bit to
true
in the response. -
Go to Step 9
-
-
If the "up" option is set to
true
or not present:-
If the pinUvAuthParam parameter is present then:
-
Let userPresentFlagValue be the result of calling getUserPresentFlagValue().
-
If userPresentFlagValue is
false
:Note: An authenticator may be configured to collect user presence whenever the "up" option is
true
by setting the default user present time limit to zero.-
Request evidence of user interaction in an authenticator-specific way (e.g., flash the LED light). If the authenticator has a display, show the rpId parameter value to the user, and request permission to create an assertion.
-
If the user declines permission, or the operation times out, then end the operation by returning CTAP2_ERR_OPERATION_DENIED.
-
-
-
Set the "up" bit to
true
in the response. -
Call clearUserPresentFlag(), clearUserVerifiedFlag(), and clearPinUvAuthTokenPermissionsExceptLbw().
Note: This consumes both the "user present state", sometimes referred to as the "cached UP", and the "user verified state", sometimes referred to as "cached UV". These functions are no-ops if there is not an in-use pinUvAuthToken.
-
- If the extensions parameter is present:
-
Process any extensions that this authenticator supports, ignoring any that it does not support.
-
Authenticator extension outputs generated by the authenticator extension processing are returned in the authenticator data. The set of keys in the authenticator extension outputs map MUST be equal to, or a subset of, the keys of the authenticator extension inputs map.
Note: Some extensions may produce different output depending on the state of the "uv" and/or "up" bits set in the response.
-
-
If the allowList parameter is present:
-
Select any credential from the applicable credentials list.
-
Delete the
numberOfCredentials
member. -
Go to Step 12.
-
-
If allowList is not present:
-
If
numberOfCredentials
is one:-
Select that credential.
-
-
If
numberOfCredentials
is more than one:-
Order the credentials in the applicable credentials list by the time when they were created in reverse order. (I.e. the first credential is the most recently created.)
-
If the authenticator does not have a display, or the authenticator does have a display and the "uv" and "up" options are
false
:-
Remember the authenticatorGetAssertion parameters.
-
Create a credential counter (
credentialCounter
) and set it to 1. This counter signifies the next credential to be returned by the authenticator, assuming zero-based indexing. -
Start a timer. This is used during authenticatorGetNextAssertion command. This step is optional if transport is done over NFC.
-
Select the first credential.
-
-
If authenticator has a display and at least one of the "uv" and "up" options is
true
:-
Display all the credentials in the applicable credentials list to the user, using their friendly name along with other stored account information.
-
Also, display the rpId of the requester (specified in the request) and ask the user to select a credential.
-
If the user declines to select a credential or takes too long (as determined by the authenticator), terminate this procedure and return the CTAP2_ERR_OPERATION_DENIED error.
-
Update the response to set the
userSelected
member totrue
and to delete thenumberOfCredentials
member. -
Select the credential indicated by the user.
-
-
-
Update the response to include the selected credential’s publicKeyCredentialUserEntity information. User identifiable information (name, DisplayName, icon) inside the publicKeyCredentialUserEntity MUST NOT be returned if user verification is not done by the authenticator.
-
- Sign the clientDataHash along with authData with the selected credential, using the structure specified in [WebAuthn].
On success, the authenticator returns the following authenticatorGetAssertion response structure:
Member name | Data type | Required? | Definition |
---|---|---|---|
credential (0x01) | PublicKeyCredentialDescriptor
| Required | PublicKeyCredentialDescriptor structure containing the credential identifier whose private key was used to generate the assertion. |
authData (0x02) | Byte String | Required | The signed-over contextual bindings made by the authenticator, as specified in [WebAuthn]. |
signature (0x03) | Byte String | Required | The assertion signature produced by the authenticator, as specified in [WebAuthn]. |
user (0x04) | PublicKeyCredentialUserEntity
| Optional |
PublicKeyCredentialUserEntity structure containing the user account information.
User identifiable information (name, DisplayName, icon) MUST not be returned if user verification
is not done by the authenticator.
U2F Devices: For U2F devices, this parameter is not returned as this user information is not present for U2F credentials. FIDO Devices - server-side credentials: For server-side credentials on FIDO devices, this parameter is optional as server-side credentials behave the same as U2F credentials where they are discovered given the user information on the RP. Authenticators optionally MAY store user information inside the credential ID. FIDO Devices - discoverable credentials:
For discoverable credentials on FIDO devices, at least For single account per RP case, authenticator returns " For multiple accounts per RP case, where the authenticator does not have a display, authenticator returns "id" as well as other fields to the platform. Platform will use this information to show the account selection UX to the user and for the user selected account, it will ONLY return "id" back to the [WebAuthn] layer and discard other user details. |
numberOfCredentials (0x05) | Integer | Optional | Total number of account credentials for the RP. Optional; defaults to one. This member is required when more than one credential is found for an RP, and the authenticator does not have a display or the UV & UP flags are false. Omitted when returned for the authenticatorGetNextAssertion method. |
userSelected (0x06) | Boolean | Optional | Indicates that a credential was selected by the user via interaction directly with the authenticator,
and thus the platform does not need to confirm the credential. Optional; defaults to false .
MUST NOT be present in response to a request where an allowList was given,
where numberOfCredentials is greater than one,
nor in response to an authenticatorGetNextAssertion request.
|
largeBlobKey (0x07) | Byte string | Optional | The contents of the associated largeBlobKey if present for the asserted credential, and if largeBlobKey was true in the extensions input.
|
Within the "flags bits" of the authenticator data structure returned, the authenticator will report what was actually done within the authenticator boundary. The meanings of the combinations of the User Present (UP) and User Verified (UV) bit flags are as follows:
Flags | Meaning |
---|---|
"up"=0 "uv"=0 | Silent authentication |
"up"=1 "uv"=0 | Physical user presence verified, but no user verification |
"up"=0 "uv"=1 |
User verification performed, but physical user presence not verified.
Note: Returning an assertion with the "up" bit set to |
"up"=1 "uv"=1 | User verification performed and physical user presence verified |
6.3. authenticatorGetNextAssertion (0x08)
The client calls this method when the authenticatorGetAssertion response contains the numberOfCredentials member and the number of credentials exceeds 1. This method is used to obtain the next per-credential signature for a given authenticatorGetAssertion request. It takes no arguments.
Note: this is a stateful command and the specified implementation accommodations apply to it.
When this command is received, the authenticator performs the following procedure:
-
If authenticator does not remember any authenticatorGetAssertion parameters, return CTAP2_ERR_NOT_ALLOWED.
-
If the
credentialCounter
is equal to or greater thannumberOfCredentials
, return CTAP2_ERR_NOT_ALLOWED. -
If timer since the last call to authenticatorGetAssertion/authenticatorGetNextAssertion is greater than 30 seconds, discard the current authenticatorGetAssertion state and return CTAP2_ERR_NOT_ALLOWED. This step is optional if transport is done over NFC.
Note: the section on stateful commands makes this timeout optional for any stateful command. This section supersedes that and makes it mandatory in this instance, except over NFC, where maintaining timers for that length of time can be problematic.
-
Select the credential indexed by
credentialCounter
. (I.e. credentials[n] assuming a zero-based array.) -
Update the response to include the selected credential’s publicKeyCredentialUserEntity information. User identifiable information (name, DisplayName, icon) inside the publicKeyCredentialUserEntity MUST NOT be returned if user verification was not done by the authenticator in the original authenticatorGetAssertion call.
-
Sign the clientDataHash along with authData with the selected credential, using the structure specified in [WebAuthn].
-
Reset the timer. This step is optional if transport is done over NFC.
-
Increment
credentialCounter
.
On success, the authenticator returns the same structure as returned by the authenticatorGetAssertion method. The numberOfCredentials member is omitted.
6.3.1. Client Logic
If client receives numberOfCredentials member value exceeding 1 in response to the authenticatorGetAssertion call:
-
Call authenticatorGetNextAssertion numberOfCredentials minus 1 times.
-
Make sure ‘rp’ member matches the current request.
-
Remember the ‘response’ member.
-
Add credential user information to the ‘credentialInfo’ list.
-
-
Draw a UX that displays credentialInfo list.
-
Let user select which credential to use.
-
Return the value of the ‘response’ member associated with the user choice.
-
Discard all other responses.
6.4. authenticatorGetInfo (0x04)
Using this method, platforms can request that the authenticator report a list of its supported protocol versions and extensions, its AAGUID, and other aspects of its overall capabilities. Platforms should use this information to tailor their command parameters choices.
Note: The values of various authenticatorGetInfo response structure members and option IDs may change over time depending upon the commands the platform sends to the authenticator.
This method takes no inputs.
On success, the authenticator returns the following authenticatorGetInfo response structure:
Member name | Data type | Required? | Definition |
---|---|---|---|
versions (0x01) | Array of strings | Required | List of supported versions. Supported versions are: "FIDO_2_1" for CTAP2.1 / FIDO2 / Web Authentication authenticators, "FIDO_2_0" for CTAP2.0 / FIDO2 / Web Authentication authenticators, "FIDO_2_1_PRE" for CTAP2.1 Preview features and "U2F_V2" for CTAP1/U2F authenticators. |
extensions (0x02) | Array of strings | Optional | List of supported extensions. |
aaguid (0x03) | Byte String | Required | The claimed AAGUID. 16 bytes in length and encoded the same as MakeCredential AuthenticatorData, as specified in [WebAuthn]. |
options (0x04) | Map | Optional | List of supported options. |
maxMsgSize (0x05) | Unsigned Integer | Optional | Maximum message size supported by the authenticator. |
pinUvAuthProtocols (0x06) | Array of Unsigned Integers | Optional | List of supported PIN/UV auth protocols in order of decreasing authenticator preference. MUST NOT contain duplicate values nor be empty if present. |
maxCredentialCountInList (0x07) | Unsigned Integer | Optional | Maximum number of credentials supported in credentialID list at a time by the authenticator. MUST be greater than zero if present. |
maxCredentialIdLength (0x08) | Unsigned Integer | Optional | Maximum Credential ID Length supported by the authenticator. MUST be greater than zero if present. |
transports (0x09) | Array of strings | Optional | List of supported transports. Values are taken from the AuthenticatorTransport enum in [WebAuthn]. The list MUST NOT include duplicate values nor be empty if present. Platforms MUST tolerate unknown values. |
algorithms (0x0A) | Array of PublicKeyCredentialParameters
| Optional | List of supported algorithms for credential generation, as specified in [WebAuthn]. The array is ordered from most preferred to least preferred and MUST NOT include duplicate entries nor be empty if present. PublicKeyCredentialParameters' algorithm identifiers are values that SHOULD be registered in the IANA COSE Algorithms registry [IANA-COSE-ALGS-REG]. |
maxSerializedLargeBlobArray (0x0B) | Unsigned Integer | Optional | The maximum size, in bytes, of the serialized large-blob array that this authenticator can store. If the authenticatorLargeBlobs command is supported, this MUST be specified. Otherwise it MUST NOT be. If specified, the value must be ≥ 1024. Thus, 1024 bytes is the least amount of storage an authenticator must make available for per-credential serialized large-blob arrays if it supports the large, per-credential blobs feature. |
forcePINChange (0x0C) | Boolean | Optional |
If this member is:
|
minPINLength (0x0D) | Unsigned Integer | Optional | This specifies the current minimum PIN length, in Unicode code points, the authenticator enforces for ClientPIN This MUST be present if authenticator supports authenticatorClientPIN. This is applicable for ClientPIN only. The default pre-configured minimum PIN length is at least 4 Unicode code points. Authenticators may have a pre-configured default minPINLength of more than 4 code points in certain offerings. On reset, minPINLength reverts to its original pre-configured value. Authenticators MAY also have a pre-configured list of RPIDs authorized to retrieve the current minimum PIN length value via the minPinLength extension. |
firmwareVersion (0x0E) | Unsigned Integer | Optional | Indicates the firmware version of the authenticator model identified by AAGUID. Whenever releasing any code change to the authenticator firmware, authenticator MUST increase the version. |
maxCredBlobLength (0x0F) | Unsigned Integer | Optional | Maximum credBlob length in bytes supported by the authenticator.
Must be present if, and only if, credBlob is included in the supported extensions list.
If present, this value MUST be at least 32 bytes.
|
maxRPIDsForSetMinPINLength (0x10) | Unsigned Integer | Optional | This specifies the max number of RPIDs that authenticator can set via setMinPINLength subcommand. This is in addition to pre-configured list authenticator may have. If authenticator does not support adding additional RPIDs, its value is 0. This MUST ONLY be present if, and only if, the authenticator supports the setMinPINLength subcommand. |
preferredPlatformUvAttempts (0x11) | Unsigned Integer. (CBOR major type 0) | Optional | This specifies the preferred number of invocations of the getPinUvAuthTokenUsingUvWithPermissions subCommand the platform may attempt before falling back to the getPinUvAuthTokenUsingPinWithPermissions subCommand or displaying an error. MUST be greater than zero. If the value is 1 then all uvRetries are internal and the platform must only invoke the getPinUvAuthTokenUsingUvWithPermissions subCommand a single time. If the value is > 1 the authenticator must only decrement uvRetries by 1 for each iteration. |
uvModality (0x12) | Unsigned Integer. (CBOR major type 0) | Optional | This specifies the user verification modality supported by the authenticator via authenticatorClientPIN's getPinUvAuthTokenUsingUvWithPermissions subcommand. This is a hint to help the platform construct user dialogs. The values are defined in [FIDORegistry] Section 3.1 User Verification Methods. Combining multiple bit-flags from the [FIDORegistry] is allowed. If clientPin is supported it MUST NOT be included in the bit-flags, as clientPIN is not a built-in user verification method. |
certifications (0x13) | Map | Optional | This specifies a list of authenticator certifications. |
remainingDiscoverableCredentials (0x14) | Unsigned Integer | Optional |
If this member is present it indicates the estimated number of additional discoverable credentials that can be stored. If this value is zero then platforms SHOULD create non-discoverable credentials if possible. This estimate SHOULD be based on the assumption that all future discoverable credentials will have maximally-sized fields and SHOULD be zero whenever an attempt to create a discoverable credential may fail due to lack of space, even if it’s possible that some specific request might succeed. For example, a specific request might include fields that are smaller than the maximum possible size and thus succeed, but this value should be zero if a request with maximum-sized fields would fail. Also, a specific request might have an rp.id and |
vendorPrototypeConfigCommands (0x15) | Array of Unsigned Integers | Optional |
If present the authenticator supports the authenticatorConfig vendorPrototype subcommand, and its value is a list of authenticatorConfig vendorCommandId values supported, which MAY be empty. |
All options are in the form key-value pairs with string IDs and boolean values. When an option ID is not present, the default is applied per table below. The following table lists all defined option IDs as of CTAP version "FIDO_2_1":
Option ID | Definition | Default |
---|---|---|
plat | platform device: Indicates that the device is attached to the client and therefore can’t be removed and used on another client. | false |
rk | Specifies whether this authenticator can create discoverable credentials, and therefore can satisfy authenticatorGetAssertion requests with the allowList parameter omitted. | false |
clientPin |
ClientPIN feature support:
If present and set to true, it indicates that the device is capable of accepting a PIN from the client and PIN has been set. If present and set to false, it indicates that the device is capable of accepting a PIN from the client and PIN has not been set yet. If absent, it indicates that the device is not capable of accepting a PIN from the client. ClientPIN is one of the overall ways to do user verification, although ClientPIN is not considered a built-in user verification method. | Not supported |
up | user presence: Indicates that the device is capable of testing user presence. | true |
uv |
user verification:
Indicates that the authenticator supports a built-in user verification method.
For example, devices with UI, biometrics fall into this category.
If present and set to true, it indicates that the device is capable of built-in user verification and its user verification feature is presently configured. If present and set to false, it indicates that the authenticator is capable of built-in user verification and its user verification feature is not presently configured. For example, an authenticator featuring a built-in biometric user verification feature that is not presently configured will return this "uv" option id set to false. If absent, it indicates that the authenticator does not have a built-in user verification capability. A device that can only do Client PIN will not return the "uv" option id. If a device is capable of both built-in user verification and Client PIN, the authenticator will return both the "uv" and the "clientPin" option ids. | Not Supported |
pinUvAuthToken |
If pinUvAuthToken is:
| Not Supported |
noMcGaPermissionsWithClientPin |
If this noMcGaPermissionsWithClientPin is:
| false |
largeBlobs |
If largeBlobs is:
| Not supported |
ep |
Enterprise Attestation feature support:
If ep is:
| Not supported. |
bioEnroll |
If bioEnroll is:
| Not Supported |
userVerificationMgmtPreview |
"FIDO_2_1_PRE" Prototype Credential management support:
If userVerificationMgmtPreview is:
| Not Supported |
uvBioEnroll |
getPinUvAuthTokenUsingUvWithPermissions support for requesting the be permission:
This option ID MUST only be present if bioEnroll is also present. If uvBioEnroll is:
| Not Supported |
authnrCfg |
authenticatorConfig command support:
If authnrCfg is:
| Not Supported |
uvAcfg |
getPinUvAuthTokenUsingUvWithPermissions support for requesting the acfg permission:
This option ID MUST only be present if authnrCfg is also present. If uvAcfg is:
| Not Supported |
credMgmt |
Credential management support:
If credMgmt is:
| Not Supported |
credentialMgmtPreview |
"FIDO_2_1_PRE" Prototype Credential management support:
If credentialMgmtPreview is:
| Not Supported |
setMinPINLength |
Support for the Set Minimum PIN Length feature.
If setMinPINLength is:
| Not Supported |
makeCredUvNotRqd |
Support for making non-discoverable credentials without requiring User Verification.
If
true .
| false |
alwaysUv |
Support for the Always Require User Verification feature:
If
Note: If the alwaysUv option ID is present and | Not Supported |
6.5. authenticatorClientPIN (0x06)
This command exists so that plaintext PINs are not sent to the authenticator. Instead, a PIN/UV auth protocol (aka pinUvAuthProtocol) ensures that PINs are encrypted when sent to an authenticator and are exchanged for a pinUvAuthToken that serves to authenticate subsequent commands. Additionally, authenticators supporting built-in user verification methods can provide a pinUvAuthToken upon user verification.
The pinUvAuthToken is a randomly-generated, opaque bytestring that is large enough to be effectively unguessable. See § 6.5.2.1 pinUvAuthToken State for details.
Two PIN/UV auth protocols are defined herein:
Each PIN/UV auth protocol:
-
maintains its own pinUvAuthToken so that no unexpected, cross-protocol interactions occur, and
-
is a concrete instantiation of § 6.5.4 PIN/UV Auth Protocol Abstract Definition.
Note: The platform may flexibly manage the lifetime of its copy of the pinUvAuthToken based on the usage scenario. However, it should erase its copy of the pinUvAuthToken as soon as possible when it is no longer needed. The authenticator also can expire the pinUvAuthToken based on certain conditions like changing a PIN, authenticator timeouts, the platform system waking up from a suspend state, etc. If the pinUvAuthToken has expired, the authenticator will return CTAP2_ERR_PIN_TOKEN_EXPIRED and the platform can act on the error accordingly, e.g., by getting a new pinUvAuthToken from the authenticator.
6.5.1. PIN Composition Requirements
Platforms MUST enforce the following, baseline, requirements on PINs used with this specification:
-
Minimum PIN Length: 4 Unicode characters
-
Maximum PIN Length: UTF-8 representation must not exceed 63 bytes
-
PIN are in Unicode normalization form C.
-
PIN must not end in a 0x00 byte
Authenticators MUST enforce the following, baseline, requirements on PINs:
-
Minimum PIN Length: 4 code points.
Note: Authenticators can enforce a greater minimum length.
-
Maximum PIN Length: 63 bytes
-
PIN storage on the device has to provide the same, or better, security assurances as provided for private keys.
6.5.2. PIN/UV Auth Protocol Global State
Authenticators keep the following global state, independent of any specific PIN/UV auth protocol:
6.5.2.1. pinUvAuthToken State
A pinUvAuthToken has the following associated state variables. When initially generated via resetPinUvAuthToken(), the pinUvAuthToken's state variables are set to the initial values given below. The state variables values are managed via the interface given in § 6.5.3.2 pinUvAuthToken State Maintenance Functions.
Note: The pinUvAuthToken-issuing operations call beginUsingPinUvAuthToken() to update the pinUvAuthToken's state variables' values prior to issuing the pinUvAuthToken to the platform. For example, they will use the latter function to set both or either the userVerified flag and/or the userPresent flag to true
, and start the usage timer.
A pinUvAuthToken is initially denoted as not in use. It is associated with these state variables:
-
A permissions RPID, initially null.
-
A permissions set whose possible values are those of pinUvAuthToken permissions. It is initially empty.
-
A usage timer, initially not running.
Note: Once running, the timer is observed by pinUvAuthTokenUsageTimerObserver().
-
A initial usage time limit, initially not set. beginUsingPinUvAuthToken() sets this value according to the transport the platform is using to communicate with it. The platform MUST invoke an authenticator operation using the pinUvAuthToken within this time limit for the pinUvAuthToken to remain valid for the full max usage time period. The default maximum per-transport initial usage time limit values are:
-
usb: 30 seconds
-
nfc: 19.8 seconds (16 bit counter with 3311hz clock: max time before overflow)
-
ble: 30 seconds
-
internal: 30 seconds
Authenticators MAY use other values that are less than the default maximum values.
Authenticators MAY implement a rolling timer, initialized to the per-transport initial usage time limit, where the pinUvAuthToken and its state variables remain valid as long as the platform again uses the pinUvAuthToken in an operation before the rolling timer expires. If so, the rolling timer is again initialized to the initial usage time limit. This continues until the max usage time period expires. See pinUvAuthTokenUsageTimerObserver().
Note: Authenticators should utilize the rolling timer approach judiciously, e.g., because some features, such as authenticatorBioEnrollment and authenticatorCredentialManagement, may need to accommodate infrequent user interactions. Thus the rolling timer approach may be most applicable to authenticatorMakeCredential and authenticatorGetAssertion operations.
-
-
A user present time limit defining the length of time the user is considered "present", as represented by the userPresent flag, after user presence is collected. The user present time limit defaults to the same default maximum per-transport values as the initial usage time limit, although authenticators MAY use other values that are less than the default maximum values, including zero.
Note: The user present time limit value of zero accommodates the case where an authenticator does not wish to support maintaining "user present" state (i.e., "cached user presence").
-
A max usage time period value, which SHOULD default to a maximum of 10 minutes (600 seconds), though authenticators MAY use other values less than the latter default, possibly depending upon the use case, e.g., which transport is in use.
-
A userVerified flag, initially
false
. -
A userPresent flag, initially
false
.
6.5.2.2. PIN-Entry and User Verification Retries Counters
-
pinRetries counter:
-
pinRetries counter represents the number of attempts left before PIN is disabled.
-
Authenticators must allow no more than 8 retries but may set a lower maximum.
-
Each correct PIN entry resets the pinRetries and the uvRetries counters back to their maximum values unless the PIN is already disabled.
-
Each incorrect PIN entry decrements the pinRetries by 1.
-
Once the pinRetries counter reaches 0, both ClientPin as well as built-in user verification are disabled and can only be enabled if authenticator is reset.
-
-
uvRetries counter:
-
The uvRetries counter represents the number of user verification attempts left before built-in user verification is disabled.
-
maxUvRetries is a global value statically configured into an authenticator; it is the maximum number of retries that a user can experience. uvRetries is initialized to this value. Its value MUST be in the range of 1 to 25, inclusive.
Note: This value is determined by the Authenticator vendor based on the desired FIDO security certification level. This limit protects against brute force attacks. It is the total number of attempts allowed for all built-in user verification methods.
-
maxUvAttemptsForInternalRetries is a global value configured into an authenticator. It is the maximum number of times the authenticator will retry internally when internalRetry is true as part of the performBuiltInUv() algorithm. This is used for older platforms when the "uv" parameter is set as
true
OR when an authenticator vendor wants the platform to try calling it only once as indicated by the preferredPlatformUvAttempts value. If preferredPlatformUvAttempts is 1, maxUvAttemptsForInternalRetries value MUST be in range of 1 to maxUvRetries inclusive. If preferredPlatformUvAttempts is NOT 1, maxUvAttemptsForInternalRetries value MUST be in range of 1 to 5 inclusive. -
Once the uvRetries counter reaches 0, built-in user verification MUST be disabled and can only be re-enabled if the authenticator is reset or the correct clientPIN is provided via the authenticatorClientPIN's getPinUvAuthTokenUsingPinWithPermissions or getPinToken subCommands.
-
internalRetry is a authenticator-internal boolean parameter. It defaults to
false
. It is explicitly set totrue
if the authenticator intends to perform multiple internal uv retries before returning an error to the platform.
-
6.5.3. Utility Functions
These utility functions are independent of the particular PIN/UV auth protocol in use.
6.5.3.1. Perform Built-in User Verification Algorithm
performBuiltInUv(internalRetry) → success | error:
-
If internalRetry is
true
then let attemptsBeforeReturning be set tomaxUvAttemptsForInternalRetries
. -
Else let attemptsBeforeReturning be set to 1.
-
If uvRetries <= 0 then return error.
-
Decrement the uvRetries counter by 1.
Note: It is best practice to decrement the counter before performing built-in user verification. This prevents some hardware attacks that could provide an attacker with a unlimited number of presentation attempts.
-
Decrement attemptsBeforeReturning by 1.
-
Perform built-in user verification.
-
If built-in user verification succeeds then set the uvRetries counter to maxUvRetries and return
success
. -
Else (built-in user verification failed), if attemptsBeforeReturning > 0, go to Step 4.
-
Otherwise, return
error
.
6.5.3.2. pinUvAuthToken State Maintenance Functions
- beginUsingPinUvAuthToken(userIsPresent)
-
This function prepares the pinUvAuthToken for use by the platform, which has invoked one of the pinUvAuthToken-issuing operations, by setting particular pinUvAuthToken state variables to given use-case-specific values. See also § 6.5.5.7 Operations to Obtain a pinUvAuthToken.
-
Set the userPresent flag to the value of userIsPresent.
-
Set the userVerified flag to
true
. -
Set the initial usage time limit to a transport-specific value, as described in § 6.5.2.1 pinUvAuthToken State.
-
Start the pinUvAuthToken usage timer and assign pinUvAuthTokenUsageTimerObserver() to observe it.
-
Denote the pinUvAuthToken as in use.
-
- pinUvAuthTokenUsageTimerObserver()
-
This function observes the pinUvAuthToken usage timer and takes appropriate action upon the specified conditions:
-
If the usage timer is not running, return.
-
While the overall usage timer has not expired, perform the following substeps:
-
If the current user present time limit is reached, call clearUserPresentFlag().
-
If the initial usage time limit is reached without the platform using the pinUvAuthToken in an authenticator operation then call stopUsingPinUvAuthToken(), and terminate these steps.
-
If the authenticator does not utilize a rolling timer then continue.
-
If the authenticator utilizes a rolling timer then:
-
If the platform uses the pinUvAuthToken in an authenticator operation before the rolling timer expires then:
-
Set the rolling timer to the applicable initial usage time limit and continue.
-
-
Otherwise (implying the rolling timer expires) call stopUsingPinUvAuthToken(), and terminate these steps.
-
-
-
Call stopUsingPinUvAuthToken(), and terminate these steps.
-
- getUserPresentFlagValue() → userPresentFlagValue
-
-
If the pinUvAuthToken is in use then set the userPresentFlagValue to the current value of the pinUvAuthToken's userPresent flag.
-
Otherwise (implying a pinUvAuthToken exists and is not in use, or does not exist), set userPresentFlagValue to
false
.Note: The pinUvAuthToken may not exist because the pinUvAuthToken feature is not in use or is not supported.
-
Return userPresentFlagValue.
-
- getUserVerifiedFlagValue() → userVerifiedFlagValue
-
-
If the pinUvAuthToken is in use then set the userVerifiedFlagValue to the current value of the pinUvAuthToken's userVerified flag.
-
Otherwise (implying a pinUvAuthToken exists and is not in use, or does not exist), set userVerifiedFlagValue to
false
.Note: The pinUvAuthToken may not exist because the pinUvAuthToken feature is not in use or is not supported.
-
Return userVerifiedFlagValue.
-
- clearUserPresentFlag()
-
-
If the pinUvAuthToken is in use then set the pinUvAuthToken's userPresent flag to
false
, otherwise do nothing.
-
- clearUserVerifiedFlag()
-
-
If the pinUvAuthToken is in use then set the pinUvAuthToken's userVerified flag to
false
, otherwise do nothing.
-
- clearPinUvAuthTokenPermissionsExceptLbw()
-
-
If the pinUvAuthToken is in use then clear all of the pinUvAuthToken's permissions, except for lbw, otherwise do nothing.
-
- stopUsingPinUvAuthToken()
-
-
Set all of the pinUvAuthToken's state variables to their initial values as given in § 6.5.2.1 pinUvAuthToken State.
-
Denote the pinUvAuthToken as not in use.
-
6.5.4. PIN/UV Auth Protocol Abstract Definition
A specific PIN/UV auth protocol defines an implementation of two interfaces to cryptographic services: one for the authenticator, and one for the platform.
The authenticator interface is:
- initialize()
-
This process is run by the authenticator at power-on.
- regenerate()
-
Generates a fresh public key.
- resetPinUvAuthToken()
-
Generates a fresh pinUvAuthToken.
- getPublicKey() → coseKey
-
Returns the authenticator’s public key as a COSE_Key structure.
- decapsulate(peerCoseKey) → sharedSecret | error
-
Processes the output of encapsulate from the peer and produces a shared secret, known to both platform and authenticator.
- decrypt(sharedSecret, ciphertext) → plaintext | error
-
Decrypts a ciphertext, using sharedSecret as a key, and returns the plaintext.
- verify(key, message, signature) → success | error
-
Verifies that the signature is a valid MAC for the given message.
The platform interface is:
- initialize()
-
This is run by the platform when starting a series of transactions with a specific authenticator.
- encapsulate(peerCoseKey) → (coseKey, sharedSecret) | error
-
Generates an encapsulation for the authenticator’s public key and returns the message to transmit and the shared secret.
- encrypt(key, demPlaintext) → ciphertext
-
Encrypts a plaintext to produce a ciphertext, which may be longer than the plaintext. The plaintext is restricted to being a multiple of the AES block size (16 bytes) in length.
- decrypt(key, ciphertext) → plaintext | error
-
Decrypts a ciphertext and returns the plaintext.
- authenticate(key, message) → signature
-
Computes a MAC of the given message.
(In the pseudocode function definitions, above, a function takes a number of arguments that are given in parentheses and yields a result that is one of the types separated by a bar (‘|’). If a function doesn’t yield any meaningful result then it implicitly yields a value of the unit type, written “success”, which carries no information.)
The following PIN/UV auth protocols, specified herein, define concrete instantiations of the above interfaces:
6.5.5. authenticatorClientPIN (0x06) Command Definition
This authenticatorClientPIN command allows a platform to use a PIN/UV auth protocol to perform a number of actions:
The command takes the following input parameters:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
pinUvAuthProtocol (0x01) | Unsigned Integer | Required | PIN/UV protocol version chosen by the platform. This MUST be a value supported by the authenticator, as determined by the pinUvAuthProtocols field of the authenticatorGetInfo response. |
subCommand (0x02) | Unsigned Integer | Required | The specific action being requested. |
keyAgreement (0x03) | COSE_Key | Optional | The platform key-agreement key. This COSE_Key-encoded public key MUST contain the optional "alg" parameter and MUST NOT contain any other optional parameters. The "alg" parameter MUST contain a COSEAlgorithmIdentifier value. |
pinUvAuthParam (0x04) | Byte String | Optional | The output of calling authenticate on some context specific to the subcommand. |
newPinEnc (0x05) | Byte String | Optional | An encrypted PIN. |
pinHashEnc (0x06) | Byte String | Optional | An encrypted proof-of-knowledge of a PIN. |
permissions (0x09) | Unsigned Integer | Optional | Bitfield of permissions. If present, MUST NOT be 0. See § 6.5.5.7 Operations to Obtain a pinUvAuthToken. |
permissions RPID (0x0A) | String | Optional | RPID for certain permissions. |
The authenticatorClientPIN subCommands are:
subCommand Name | subCommand Number |
---|---|
getPINRetries | 0x01 |
getKeyAgreement | 0x02 |
setPIN | 0x03 |
changePIN | 0x04 |
getPinToken (superseded by getPinUvAuthTokenUsingUvWithPermissions or getPinUvAuthTokenUsingPinWithPermissions, thus for backwards compatibility only) | 0x05 |
getPinUvAuthTokenUsingUvWithPermissions | 0x06 |
getUVRetries | 0x07 |
getPinUvAuthTokenUsingPinWithPermissions | 0x09 |
On success, authenticator returns the following structure in its response:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
KeyAgreement (0x01) | COSE_Key | Optional | The result of the authenticator calling getPublicKey. Used to convey the authenticator’s public key to the platform so that the platform can call encapsulate. This COSE_Key-encoded public key MUST contain the optional "alg" parameter and MUST NOT contain any other optional parameters. The "alg" parameter MUST contain a COSEAlgorithmIdentifier value. |
pinUvAuthToken (0x02) | Byte String | Optional | The pinUvAuthToken, encrypted by calling encrypt with the shared secret as the key. |
| Unsigned Integer | Optional | Number of PIN attempts remaining before lockout. This is optionally used to show in UI when collecting the PIN in setting a new PIN, changing existing PIN and obtaining a pinUvAuthToken flows. |
| Boolean | Optional |
Present and true if the authenticator requires a power cycle before any future PIN operation, false if no power cycle needed.
If the field is omitted, no information is given about whether a power cycle is needed or not.
This field is only valid in response to a getRetries request and authenticators MUST NOT use this field as an alternative to returning CTAP2_ERR_PIN_AUTH_BLOCKED when that is required by this specification: the power cycle behaviour is a security property and cannot be delegated to the platform to enforce. |
| Unsigned Integer | Optional | Number of uv attempts remaining before lockout. |
6.5.5.1. Authenticator Configuration Operations Upon Power Up
At power-up, the authenticator calls initialize for each pinUvAuthProtocol that it supports.
6.5.5.2. Platform getting PIN retries from Authenticator
PIN retries count is the number of PIN attempts remaining before PIN is disabled on the device. When the PIN retries count nears zero, the platform can optionally warn the user to be careful while entering the PIN.
Platform performs the following operations to get pinRetries:
-
Platform sends authenticatorClientPIN command with following parameters to the authenticator:
-
pinUvAuthProtocol: 0x01
-
subCommand: getPINRetries(0x01)
-
-
Authenticator responds back with pinRetries and, optionally, powerCycleState.
6.5.5.3. Platform getting UV Retries from Authenticator
UV retries count is the number of built-in UV attempts remaining before built-in UV is disabled on the device. When the UV retries count nears zero, the platform can optionally warn the user to be careful while performing user verification.
Platform performs the following operations to get uvRetries:
-
Platform sends authenticatorClientPIN command with following parameters to the authenticator:
-
pinUvAuthProtocol: 0x01
-
subCommand: getUVRetries(0x07)
-
-
Authenticator responds back with uvRetries.
6.5.5.4. Obtaining the Shared Secret
Platforms obtain a shared secret for each transaction. The authenticator does not have to keep a list of sharedSecrets for all active sessions. If there are subsequent authenticatorClientPIN transactions, a new sharedSecret is generated every time.
Platform performs the following operations to arrive at the sharedSecret:
-
The platform selects a mutually supported PIN/UV auth protocol by considering the list of protocols supported by the authenticator, as reported in the pinUvAuthProtocols member of the authenticatorGetInfo response. If there are multiple mutually supported protocols, and the platform has no preference, it SHOULD select the one listed first in pinUvAuthProtocols.
-
The platform sends authenticatorClientPIN command with following parameters to the authenticator:
-
pinUvAuthProtocol: as chosen above
-
subCommand: getKeyAgreement(0x02)
-
-
If the authenticator does not support the selected pinUvAuthProtocol, it returns CTAP1_ERR_INVALID_PARAMETER.
-
Otherwise the authenticator sends a response with the following parameters:
-
keyAgreement: the result of calling getPublicKey for the selected pinUvAuthProtocol.
-
-
The platform calls encapsulate with the public key that the authenticator returned in order to generate the platform key-agreement key and the shared secret.
6.5.5.5. Setting a New PIN
The following operations are performed to set up a new PIN:
An arbitrary Unicode character corresponds to one or more Unicode code points. While the platform enforces a user-visible limit of at least four Unicode characters for the PIN length (e.g., by counting grapheme clusters), this results in actually collecting at the very minimum four Unicode code points, and perhaps (many) more, depending on the script employed.
-
The platform collects the new PIN ( newPinUnicode ) from the user as Unicode characters in Normalization Form C.
-
Let platformCollectedPinLengthInCodePoints be the length in code points of newPinUnicode after normalization is applied.
-
If the minPINLength member of the authenticatorGetInfo response is absent, then let platformMinPINLengthInCodePoints be 4. (The default minimum value)
-
Else let platformMinPINLengthInCodePoints be the value of the minPINLength member of the authenticatorGetInfo response.
-
If platformCollectedPinLengthInCodePoints is less than platformMinPINLengthInCodePoints then the platform SHOULD display a "PIN too short" error message to the user.
-
Let "newPin" be the UTF-8 representation of newPinUnicode.
-
If the byte length of "newPin" is greater than the max UTF-8 representation limit of 63 bytes, then the platform SHOULD display a "PIN too long" error message to the user.
Note: The platform collects the PIN before obtaining the shared secret. This prevents the shared secret from being reset if a NFC transport is used and the user removes the authenticator from the NFC reader’s field while typing the PIN.
-
-
The Platform obtains the shared secret from the authenticator.
-
Platform sends authenticatorClientPIN command with following parameters to the authenticator:
-
pinUvAuthProtocol: as selected when getting the shared secret.
-
subCommand: setPIN(0x03).
-
keyAgreement: the platform key-agreement key.
-
newPinEnc: the result of calling encrypt(shared secret,
paddedPin
) wherepaddedPin
isnewPin
padded on the right with 0x00 bytes to make it 64 bytes long. (Since the maximum length ofnewPin
is 63 bytes, there is always at least one byte of padding.) -
pinUvAuthParam: the result of calling authenticate(shared secret, newPinEnc).
-
-
Authenticator performs following operations upon receiving the request:
-
If Authenticator does not receive mandatory parameters for this command, it returns CTAP2_ERR_MISSING_PARAMETER error.
-
If a PIN has already been set, authenticator returns CTAP2_ERR_PIN_AUTH_INVALID error.
-
The authenticator calls decapsulate on the provided platform key-agreement key to obtain the shared secret. If an error results, it returns CTAP1_ERR_INVALID_PARAMETER.
-
The authenticator calls verify(shared secret, newPinEnc, pinUvAuthParam)
-
If an error results, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
-
The authenticator calls decrypt(shared secret, newPinEnc) to produce
paddedNewPin
. If an error results, it returns CTAP2_ERR_PIN_AUTH_INVALID. -
If
paddedNewPin
is NOT 64 bytes long, it returns CTAP1_ERR_INVALID_PARAMETER. -
The authenticator drops all trailing 0x00 bytes from
paddedNewPin
to producenewPin
. -
The authenticator checks the length of
newPin
against the current minimum PIN length, returning CTAP2_ERR_PIN_POLICY_VIOLATION if it is too short. -
An authenticator MAY impose arbitrary, additional constraints on PINs. If newPin fails to satisfy such additional constraints, the authenticator returns CTAP2_ERR_PIN_POLICY_VIOLATION.
-
Authenticator remembers newPin length internally as PINCodePointLength.
-
Authenticator stores
LEFT(SHA-256(newPin), 16)
internally as CurrentStoredPIN, sets the pinRetries counter to maximum count, and returns CTAP2_OK.
-
6.5.5.6. Changing existing PIN
The following operations are performed to change an existing PIN:
-
The Platform collects the current PIN ( curPinUnicode ) and new PIN ( newPinUnicode ) from the user as Unicode characters in Normalization Form C.
-
Let platformCollecteNewPinLengthInCodePoints be the length in code points of newPinUnicode after applying normalization.
-
If the minPINLength member of the authenticatorGetInfo response is absent, then let platformMinPINLengthInCodePoints be 4. (The default minimum value)
-
Else let platformMinPINLengthInCodePoints be the value of the minPINLength member of the authenticatorGetInfo response.
-
If platformCollecteNewPinLengthInCodePoints is less than platformMinPINLengthInCodePoints then the platform SHOULD display a "PIN too short" error message to the user.
-
Let "newPin" be the UTF-8 representation of newPinUnicode.
-
If the byte length of "newPin" is greater than the max UTF-8 representation limit of 63 bytes, then the platform should display a "New PIN too long" error message to the user.
-
-
Let "curPin" be the UTF-8 representation of curPinUnicode.
-
If the byte length of "curPin" is greater than the max UTF-8 representation limit of 63 bytes, then the platform should display a "Current PIN too long" error message to the user.
-
Note: The platform collects the PIN before obtaining the shared secret. This prevents the shared secret from being reset if a NFC transport is used and the user removes the authenticator from the NFC reader’s field while typing the PIN.
-
-
Platform obtains the shared secret from the authenticator.
-
Platform sends authenticatorClientPIN command. with following parameters to the authenticator:
-
pinUvAuthProtocol: as selected when getting the shared secret.
-
subCommand: changePIN(0x04).
-
keyAgreement: the platform key-agreement key.
-
pinHashEnc: The result of calling encrypt(shared secret, LEFT(SHA-256(curPin), 16)).
-
newPinEnc: the result of calling encrypt(shared secret,
paddedPin
) wherepaddedPin
isnewPin
padded on the right with 0x00 bytes to make it 64 bytes long. (Since the maximum length ofnewPin
is 63 bytes, there is always at least one byte of padding.) -
pinUvAuthParam: the result of calling authenticate(shared secret, newPinEnc || pinHashEnc).
-
-
Authenticator performs following operations upon receiving the request:
-
If Authenticator does not receive mandatory parameters for this command, it returns CTAP2_ERR_MISSING_PARAMETER error.
-
If the pinRetries counter is 0, return CTAP2_ERR_PIN_BLOCKED error.
-
The authenticator calls decapsulate on the provided platform key-agreement key to obtain the shared secret. If an error results, it returns CTAP1_ERR_INVALID_PARAMETER.
-
The authenticator calls verify(shared secret, newPinEnc || pinHashEnc, pinUvAuthParam)
-
If an error results, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator decrements the pinRetries counter by 1.
-
Authenticator decrypts pinHashEnc using decrypt(shared secret, pinHashEnc) and verifies against its internal stored
LEFT(SHA-256(curPin), 16)
.-
If an error results, or a mismatch is detected, the authenticator performs the following operations:
-
Calls regenerate for the selected pinUvAuthProtocol.
-
Authenticator returns errors according to following conditions:
-
If the pinRetries counter is 0, return CTAP2_ERR_PIN_BLOCKED error.
-
If the authenticator sees 3 consecutive mismatches, it returns CTAP2_ERR_PIN_AUTH_BLOCKED, indicating that power cycling is needed for further operations. This is done so that malware running on the platform should not be able to block the device without user interaction.
-
Else return CTAP2_ERR_PIN_INVALID error.
-
-
-
-
Authenticator sets the pinRetries counter to maximum value.
-
The authenticator calls decrypt(shared secret, newPinEnc) to produce
paddedNewPin
. If an error results, it returns CTAP2_ERR_PIN_AUTH_INVALID. -
If
paddedNewPin
is NOT 64 bytes long, it returns CTAP1_ERR_INVALID_PARAMETER. -
The authenticator drops all trailing 0x00 bytes from
paddedNewPin
to producenewPin
. -
The authenticator checks the length of
newPin
against the current minimum PIN length, returning CTAP2_ERR_PIN_POLICY_VIOLATION if it is too short. -
If the forcePINChange option ID is true and
LEFT(SHA-256(newPin), 16)
is equal to its internal storedLEFT(SHA-256(curPin), 16)
then authenticator returns CTAP2_ERR_PIN_POLICY_VIOLATION. -
An authenticator MAY impose arbitrary, additional constraints on PINs. If newPin fails to satisfy such additional constraints, the authenticator returns CTAP2_ERR_PIN_POLICY_VIOLATION.
-
Authenticator remembers newPin length internally as PINCodePointLength.
-
Authenticator sets the value of forcePINChange to
false
, -
Authenticator stores
LEFT(SHA-256(newPin), 16)
internally as the new value of CurrentStoredPIN. -
Authenticator sets the pinRetries counter to maximum count.
-
Authenticator calls resetPinUvAuthToken for all pinUvAuthProtocols supported by this authenticator. (I.e. all existing pinUvAuthTokens are invalidated.)
-
Authenticator returns CTAP2_OK.
-
6.5.5.7. Operations to Obtain a pinUvAuthToken
Invoking one of the below operations only has to be performed once for the lifetime of the pinUvAuthToken. Obtaining a pinUvAuthToken once allows high security without any additional roundtrips each time a subsequent authenticator operation is invoked (except for the first key-agreement phase) and its overhead is minimal.
To obtain a pinUvAuthToken, the platform SHOULD first try using getPinUvAuthTokenUsingUvWithPermissions. If that fails, try using getPinUvAuthTokenUsingPinWithPermissions. Once the platform obtains a pinUvAuthToken, it can be used in subsequent authenticator operations for the length of its max usage time period (see § 6.5.2.1 pinUvAuthToken State), thereby avoiding asking the user for verification for each authenticator operation.
When obtaining a pinUvAuthToken, the platform requests permissions appropriate for the operations it intends to perform. Consequently, the pinUvAuthToken can only be used for those operations. Some permissions require the presence of the RPID parameter, known as a permissions RPID. See also § 6.5.2.1 pinUvAuthToken State.
The following pinUvAuthToken permissions are defined:
Permission name | Role | Value | RPID | Definition |
---|---|---|---|---|
mc | MakeCredential | 0x01 | Required | This allows the pinUvAuthToken to be used for authenticatorMakeCredential operations with the provided RPID. |
ga | GetAssertion | 0x02 | Required | This allows the pinUvAuthToken to be used for authenticatorGetAssertion operations with the provided RPID. |
cm | Credential Management | 0x04 | Optional | This allows the pinUvAuthToken to be used with the authenticatorCredentialManagement command. The RPID parameter is optional, if it is present, the pinUvAuthToken can only be used for Credential Management operations on Credentials associated with that RPID. |
be | Bio Enrollment | 0x08 | Ignored | This allows the pinUvAuthToken to be used with the authenticatorBioEnrollment command. The RPID is ignored for this permission. |
lbw | Large Blob Write | 0x10 | Ignored | This allows the pinUvAuthToken to be used with the authenticatorLargeBlobs command. The RPID is ignored for this permission. |
acfg | Authenticator Configuration | 0x20 | Ignored | This allows the pinUvAuthToken to be used with the authenticatorConfig command. The RPID is ignored for this permission. |
When a pinUvAuthToken is used with an operation that tests user presence, it is updated to remove all permissions except lbw. If lbw was not originally requested then the pinUvAuthToken becomes permission-less and cannot be used for future operations. However, the platform can fetch a fresh pinUvAuthToken in order to perform any future operations.
If authenticatorClientPIN's permissions parameter is not present in the getPinToken (0x05) subcommand, the default permissions granted for the returned pinUvAuthToken are mc and ga (value 0x03). Other permissions can only be acquired by providing the permissions parameter to the getPinUvAuthTokenUsingPinWithPermissions (0x09) or getPinUvAuthTokenUsingUvWithPermissions (0x06) subcommands.
Following operations are performed to get pinUvAuthToken:
6.5.5.7.1. Getting pinUvAuthToken using getPinToken (superseded)
-
Platform collects PIN from the user.
Note: The platform collects the PIN before obtaining the shared secret. This prevents the shared secret from being reset if a NFC transport is used and the user removes the authenticator from the NFC reader’s field while typing the PIN.
-
Platform obtains the shared secret from the authenticator.
-
Platform sends authenticatorClientPIN command. with following parameters to the authenticator:
-
pinUvAuthProtocol: as selected when getting the shared secret.
-
subCommand: getPinToken (0x05).
-
keyAgreement: the platform key-agreement key.
-
pinHashEnc: the result of calling encrypt(shared secret, LEFT(SHA-256(PIN), 16)).
-
-
Authenticator performs following operations upon receiving the request:
-
If Authenticator does not receive mandatory parameters for this command, it returns CTAP2_ERR_MISSING_PARAMETER error.
-
If
authenticatorClientPIN
's permissions parameter is present in the getPinToken (0x05) subcommand, return CTAP1_ERR_INVALID_PARAMETER. -
If
authenticatorClientPIN
's RPID parameter is present in the getPinToken (0x05) subcommand, return CTAP1_ERR_INVALID_PARAMETER. -
If the pinRetries counter is 0, return CTAP2_ERR_PIN_BLOCKED error.
-
The authenticator calls decapsulate on the provided platform key-agreement key to obtain the shared secret. If an error results, it returns CTAP1_ERR_INVALID_PARAMETER.
-
If the authenticator has a display, request user consent for the default permissions. If this is not approved, return CTAP2_ERR_OPERATION_DENIED.
-
Authenticator decrements the pinRetries counter by 1.
-
Authenticator decrypts pinHashEnc using decrypt and verifies against its internally stored CurrentStoredPIN.
-
If an error results, or a mismatch is detected, the authenticator performs the following operations:
-
Calls regenerate for the selected pinUvAuthProtocol.
-
Authenticator returns errors according to following conditions:
-
If the pinRetries counter is 0, return CTAP2_ERR_PIN_BLOCKED error.
-
If the authenticator sees 3 consecutive mismatches, it returns CTAP2_ERR_PIN_AUTH_BLOCKED, indicating that power cycling is needed for further operations. This is done so that malware running on the platform should not be able to block the device without user interaction.
-
Else return CTAP2_ERR_PIN_INVALID error.
-
-
-
-
Authenticator sets the pinRetries counter to maximum value.
-
If the value of forcePINChange is
true
, authenticator returns CTAP2_ERR_PIN_INVALID error.Note: The above error value is for backwards compatibility with CTAP2.0 platforms where the authenticator implements the forcePINChange feature as part of the setMinPINLength command. A pinUvAuthToken MUST NOT be returned if PINCodePointLength is less than current minimum PIN length. This is intended to force a user to change their PIN to one that conforms to the current authenticator policy. A CTAP2.1 platform will check the forcePINChange member of the authenticatorGetInfo response, and not invoke this command without forcing the user to change PIN first.
-
Create a new pinUvAuthToken by calling resetPinUvAuthToken().
-
Call beginUsingPinUvAuthToken(userIsPresent:
false
). -
If the noMcGaPermissionsWithClientPin option ID is present and set to
false
, or absent, then assign the pinUvAuthToken the default permissions.Note: If noMcGaPermissionsWithClientPin option ID is true, default permissions of mc and ga are not given, but the token is still used by older CTAP 2.0 platforms for userVerificationMgmtPreview and credentialMgmtPreview commands.
-
The authenticator returns the encrypted pinUvAuthToken for the specified pinUvAuthProtocol, i.e. encrypt(shared secret, pinUvAuthToken).
-
6.5.5.7.2. Getting pinUvAuthToken using getPinUvAuthTokenUsingPinWithPermissions (ClientPIN)
This subCommand MUST be implemented if the authenticator includes both clientPin and pinUvAuthToken Option IDs set to true
in the authenticatorGetInfo response.
-
Platform collects PIN from the user.
Note: The platform collects the PIN before obtaining the shared secret. This prevents the shared secret from being reset if a NFC transport is used and the user removes the authenticator from the NFC reader’s field while typing the PIN.
-
Platform obtains the shared secret from the authenticator.
-
Platform sends authenticatorClientPIN command. with following parameters to the authenticator:
-
pinUvAuthProtocol: as selected when getting the shared secret.
-
subCommand: getPinUvAuthTokenUsingPinWithPermissions (0x09).
-
keyAgreement: the platform key-agreement key.
-
pinHashEnc: the result of calling encrypt(shared secret, LEFT(SHA-256(PIN), 16)).
-
permissions: mandatory, the permissions associated with this pinUvAuthToken.
Note: The platform SHOULD request only the permissions absolutely necessary.
-
RPID: Required for some permissions, optional for others.
-
-
Authenticator performs following operations upon receiving the request:
-
If Authenticator does not receive mandatory parameters for this command, it returns CTAP2_ERR_MISSING_PARAMETER error.
-
If the Authenticator receives a permissions parameter with value 0, return CTAP1_ERR_INVALID_PARAMETER.
-
The below statements each relate a pinUvAuthToken permission to a given state for a authenticatorGetInfo option ID. For each pinUvAuthToken permission present in the permissions parameter, if the statement corresponding to the permission is currently true, terminate these steps and return CTAP2_ERR_UNAUTHORIZED_PERMISSION. Undefined permissions present in the permissions parameter are ignored.
-
lbw: largeBlobs is
false
or absent. -
mc: noMcGaPermissionsWithClientPin is present and set to true.
-
ga: noMcGaPermissionsWithClientPin is present and set to true.
-
If the pinRetries counter is 0, return CTAP2_ERR_PIN_BLOCKED error.
-
The authenticator calls decapsulate on the provided platform key-agreement key to obtain the shared secret. If an error results, it returns CTAP1_ERR_INVALID_PARAMETER.
-
If the authenticator has a display, request user consent for the requested permissions. If this is not approved, return CTAP2_ERR_OPERATION_DENIED.
-
Authenticator decrements the pinRetries counter by 1.
-
Authenticator decrypts pinHashEnc using decrypt and verifies against its internally stored CurrentStoredPIN.
-
If an error results, or a mismatch is detected, the authenticator performs the following operations:
-
Calls regenerate for the selected pinUvAuthProtocol.
-
Authenticator returns errors according to following conditions:
-
If the pinRetries counter is 0, return CTAP2_ERR_PIN_BLOCKED error.
-
If the authenticator sees 3 consecutive mismatches, it returns CTAP2_ERR_PIN_AUTH_BLOCKED, indicating that power cycling is needed for further operations. This is done so that malware running on the platform should not be able to block the device without user interaction.
-
Else return CTAP2_ERR_PIN_INVALID error.
-
-
-
-
Authenticator sets the pinRetries counter to maximum value.
-
If the value of forcePINChange is
true
, authenticator returns CTAP2_ERR_PIN_POLICY_VIOLATION. Platform on receiving such error response SHOULD direct the user to change the PIN. -
Create a new pinUvAuthToken by calling resetPinUvAuthToken().
-
Call beginUsingPinUvAuthToken(userIsPresent:
false
). -
Assign the requested permissions to the pinUvAuthToken, ignoring any undefined permissions.
-
If the RPID parameter is present, associate the permissions RPID with the pinUvAuthToken.
-
The authenticator returns the encrypted pinUvAuthToken for the specified pinUvAuthProtocol, i.e. encrypt(shared secret, pinUvAuthToken).
-
6.5.5.7.3. Getting pinUvAuthToken using getPinUvAuthTokenUsingUvWithPermissions (built-in user verification methods)
This subCommand is only applicable when the authenticator supports built-in user verification methods.
This subCommand MUST be implemented if the authenticator returns both uv and pinUvAuthToken option IDs set to true
in the authenticatorGetInfo response.
-
Platform obtains the shared secret from the authenticator.
-
Platform sends authenticatorClientPIN command. with following parameters to the authenticator:
-
pinUvAuthProtocol: as selected when getting the shared secret.
-
subCommand: getPinUvAuthTokenUsingUvWithPermissions (0x06).
-
keyAgreement: the platform key-agreement key.
-
permissions: mandatory, the permissions associated with this pinUvAuthToken.
Note: The platform SHOULD request only the permissions absolutely necessary.
-
RPID: Required for some permissions, optional for others.
-
-
Authenticator performs following operations upon receiving the request:
-
If Authenticator does not receive mandatory parameters for this command, it returns CTAP2_ERR_MISSING_PARAMETER error.
-
If the Authenticator receives a permissions parameter with value 0, return CTAP1_ERR_INVALID_PARAMETER.
-
The below statements each relate a pinUvAuthToken permission to a given state for a authenticatorGetInfo option ID. For each pinUvAuthToken permission present in the permissions parameter, if the statement corresponding to the permission is currently true, terminate these steps and return CTAP2_ERR_UNAUTHORIZED_PERMISSION. The mc and ga permissions are always considered authorized, thus they are not listed below. Undefined permissions present in the permissions are ignored.
-
be: uvBioEnroll is
false
or absent. -
lbw: largeBlobs is
false
or absent.
Note: Some authenticators with multiple built-in user verification methods may wish to support the uvBioEnroll and authnrCfg features that enable the getPinUvAuthTokenUsingUvWithPermissions subcommand to return the be and acfg permissions, allowing the platform to enroll fingerprints or perform authenticatorConfig subCommands based, e.g., on a built-in PIN or other modality.
-
If a built-in user verification method is supported but not configured, the authenticator returns CTAP2_ERR_NOT_ALLOWED.
-
If preferredPlatformUvAttempts > 1 then let internalRetry be
false
. This indicates that the platform will try invoking this sub command preferably about preferredPlatformUvAttempts times. Else let internalRetry betrue
. -
If the uvRetries counter is <= 0, return CTAP2_ERR_UV_BLOCKED error.
-
If the authenticator has a display, request user consent for the requested permissions. If this is not approved, return CTAP2_ERR_OPERATION_DENIED.
-
Let uvState be the result of calling performBuiltInUv(internalRetry)
-
If uvState is
error
:-
If the uvRetries counter is <= 0, return CTAP2_ERR_UV_BLOCKED.
-
Otherwise, return CTAP2_ERR_UV_INVALID.
Note: The platform, upon receipt of CTAP2_ERR_UV_INVALID, should check the uvRetries value using authenticatorClientPIN's getUVRetries subCommand. If uvRetries > 0 and preferredPlatformUvAttempts > 1, then, platforms can materialize a UI to inform the user (if appropriate) of the number of remaining retries remaining before user verification is blocked, in conjunction with retrying getPinUvAuthTokenUsingUvWithPermissions. If the platform receives CTAP2_ERR_UV_BLOCKED or uvRetries <= 0 and clientPin option ID is set to
true
then the platform MAY fall back to invoking getPinUvAuthTokenUsingPinWithPermissions.
-
-
Create a new pinUvAuthToken by calling resetPinUvAuthToken().
-
If the employed built-in user verification method supplied evidence of user interaction, then call beginUsingPinUvAuthToken(userIsPresent:
true
).Note: Whether or not a particular built-in user verification method supplies user presence can vary between authenticators.
-
Otherwise (implying that user presence was not collected), call beginUsingPinUvAuthToken(userIsPresent:
false
). -
Assign the requested permissions to the pinUvAuthToken, ignoring any undefined permissions.
-
If the RPID parameter is present, use its value as the permissions RPID and associate it with the pinUvAuthToken.
-
The authenticator returns the encrypted pinUvAuthToken for the specified pinUvAuthProtocol, i.e. encrypt(shared secret, pinUvAuthToken).
-
6.5.6. PIN/UV Auth Protocol One
This section specifies a concrete instance of the abstract PIN/UV auth protocol interfaces. It is given the numeric identifier 1
, and that is the value to pass in the pinUvAuthProtocol
parameter in various commands, to select it.
Note: This PIN protocol was essentially defined in CTAP2.0, the difference between the original definition and this updated definition is that originally the pinToken
(herein termed a pinUvAuthToken) length was unlimited. The definition given here states specific lengths for pinUvAuthTokens in both this PIN/UV Auth Protocol 1, and in PIN/UV Auth Protocol 2.
This PIN/UV auth protocol maintains the following state:
-
Key agreement key: a P-256 private key, x, and the associated public point xB, which is the result of a scalar-multiplication of the P-256 base point, B, by the private key.
-
pinUvAuthToken, a random, opaque byte string that MUST be either 16 or 32 bytes long. This is generated afresh at power-on and reset when specified below.
This PIN/UV auth protocol defines the following internal functions:
- ecdh(peerCoseKey) → sharedSecret | error
-
-
Parse peerCoseKey as specified for getPublicKey, below, and produce a P-256 point, Y. If unsuccessful, or if the resulting point is not on the curve, return error.
-
Calculate xY, the shared point. (I.e. the scalar-multiplication of the peer’s point, Y, with the local private key agreement key.)
-
Let Z be the 32-byte, big-endian encoding of the x-coordinate of the shared point.
-
Return kdf(Z).
-
- kdf(Z) → sharedSecret
-
Return SHA-256(Z)
(See [RFC6090] Section 4.1 and appendix (C.2) of [SP800-56A] for more ECDH key agreement protocol details and key representation.)
The operations of PIN/UV auth protocol 1 are defined as follows:
- initialize()
-
Calls regenerate followed by resetPinUvAuthToken.
- regenerate()
-
Generate a fresh, random P-256 private key, x, and compute the associated public point.
- resetPinUvAuthToken()
-
-
Generate a fresh, random, pinUvAuthToken.
-
Associate pinUvAuthToken state variables with the new pinUvAuthToken, initialized per § 6.5.2.1 pinUvAuthToken State.
-
- getPublicKey()
-
Return a COSE_Key with the following header parameters:
-
1 (kty) = 2 (EC2)
-
3 (alg) = -25 (although this is not the algorithm actually used)
-
-1 (crv) = 1 (P-256)
-
-2 (x) = 32-byte, big-endian encoding of the x-coordinate of xB (the key agreement key's public point)
-
-3 (y) = 32-byte, big-endian encoding of the y-coordinate of xB
-
- encapsulate(peerCoseKey) → (coseKey, sharedSecret) | error
-
-
Let sharedSecret be the result of calling ecdh(peerCoseKey). Return any resulting error.
-
Return (getPublicKey(), sharedSecret)
-
- decapsulate(peerCoseKey) → sharedSecret | error
-
Return ecdh(peerCoseKey)
- encrypt(key, demPlaintext) → ciphertext
-
Return the AES-256-CBC encryption of demPlaintext using an all-zero IV. (No padding is performed as the size of demPlaintext is required to be a multiple of the AES block length.)
- decrypt(key, demCiphertext) → plaintext | error
-
If the size of demCiphertext is not a multiple of the AES block length, return error. Otherwise return the AES-256-CBC decryption of demCiphertext using an all-zero IV.
- authenticate(key, message) → signature
-
Return the first 16 bytes of the result of computing HMAC-SHA-256 with the given key and message.
- verify(key, message, signature) → success | error
-
Compute HMAC-SHA-256 with the given key and message. Return success if signature is equal to the first 16 bytes of the result, otherwise return error.
6.5.7. PIN/UV Auth Protocol Two
This section provides a PIN/UV auth protocol that is intended to aid FIPS [CMVP] certification of authenticators. It is given the numeric identifier 2
, and that is the value to pass in the pinUvAuthProtocol
parameter in various commands, to select it.
Note: support for this is mandatory in some cases. See § 9 Mandatory features.
The length of the pinUvAuthToken for PIN/UV auth protocol two MUST be 32 bytes. Otherwise, it inherits all the behavior of PIN protocol one and overrides only these functions:
- kdf(Z) → sharedSecret
-
Return
HKDF-SHA-256(salt = 32 zero bytes, IKM = Z, L = 32, info = "CTAP2 HMAC key") ||
HKDF-SHA-256(salt = 32 zero bytes, IKM = Z, L = 32, info = "CTAP2 AES key")
(see [RFC5869] for the definition of HKDF).Note: This is two separate invocations of HKDF whose results are concatenated together. It can NOT be equivalently performed using a single invocation with L=64.
- resetPinUvAuthToken()
-
Generate a fresh, random, 32-byte, pinUvAuthToken. Clear all pinUvAuthToken permissions and permissions RPIDs.
- encrypt(key, demPlaintext) → ciphertext
-
-
Discard the first 32 bytes of key. (This selects the AES-key portion of the shared secret.)
-
Let iv be a 16-byte, random bytestring.
-
Let ct be the AES-256-CBC encryption of demPlaintext using key and iv. (No padding is performed as the size of demPlaintext is required to be a multiple of the AES block length.)
-
Return iv || ct.
-
- decrypt(key, demCiphertext) → plaintext | error
-
-
Discard the first 32 bytes of key. (This selects the AES-key portion of the shared secret.)
-
If demPlaintext is less than 16 bytes in length, return an error
-
Split demPlaintext after the 16th byte to produce two subspans, iv and ct.
-
Return the AES-256-CBC decryption of ct using key and iv.
-
- authenticate(key, message) → signature
-
-
If key is longer than 32 bytes, discard the excess. (This selects the HMAC-key portion of the shared secret. When key is the pinUvAuthToken, it is exactly 32 bytes long and thus this step has no effect.)
-
Return the result of computing HMAC-SHA-256 on key and message.
-
- verify(key, message, signature) → success | error
-
-
If key is longer than 32 bytes, discard the excess. (This selects the HMAC-key portion of the shared secret. When key is the pinUvAuthToken, it is exactly 32 bytes long and thus this step has no effect.)
-
Compute HMAC-SHA-256 with the given key and message. Return success if the signature is equal to the result, otherwise return an error.
-
6.5.8. PRF values used
Throughout this protocol, the pseudo-random function defined by HMAC-SHA-256 and the pinUvAuthToken is evaluated for various values in order to authenticate requests from the platform. It is important that these values uniquely identify the salient parameters of the requests that they authenticate otherwise a PRF output from one context could be observed by an attacker and replayed in a different context.
(It is a known weakness that, within the scope of a single pinUvAuthToken value, requests may be reordered or replayed by an attacker.)
For clarity, all the patterns of values used by this protocol are enumerated in the following table:
Context | Pattern of PRF argument |
---|---|
authenticatorMakeCredential | 32 arbitrary bytes |
authenticatorGetAssertion | 32 arbitrary bytes |
authenticatorClientPIN | 32×0xff || 0608 || 32-bit value || CBOR array
|
authenticatorBioEnrollment | 0101 || CBOR map0102 || CBOR map0104 0105 || CBOR map |
authenticatorCredentialManagement | 01 02 04 || CBOR map06 || CBOR map |
authenticatorLargeBlobs | 32×0xff || 0c00 || 32-bit value || SHA-256(contents of set byte string, i.e. not including an outer CBOR tag with major type two)
|
authenticatorConfig | 32×0xff || 0d || 8-bit value || CBOR map
|
In order to avoid collisions with values already used the following pattern will be used for future commands: 32 0xff bytes, followed by the command code as a single byte, followed by an unambiguous substructure defined by each command.
The leading 0xff bytes in the pattern separate the value from any possible value used in an authenticatorMakeCredential or authenticatorGetAssertion command. As motivation, consider the authenticatorBioEnrollment command which does not use this pattern. The argument to authenticatorGetAssertion is a clientDataHash which, in a WebAuthn context, is the hash of a potentially predictable JSON string containing an attacker-controlled nonce. Offline, an attacker can iterate over many nonces until they find one which will produce a clientDataHash that starts with 0101a1
, is followed by a CBOR string or integer not equal to three, and then by a CBOR value that exactly fills the remaining space. This requires around 232 offline hash evaluations but, if the attacker can observe the PRF output sent by the platform for an authenticatorGetAssertion command using that nonce, then they can replay it to start a fingerprint enrollment as the PRF argument also matches the pattern for enrolling a fingerprint. (Although note that more work is required to complete the enrollment as that requires further commands to be authenticated.)
6.6. authenticatorReset (0x07)
Resetting an authenticator is a potentially destructive operation. Authenticators may thus choose, for each transport they support, whether this command will be supported when received on that transport. For example, an authenticator may choose not to support this command over NFC, fearing that coincidentally nearby readers may send malicious reset commands.
However this command MUST be supported on at least one transport. If the USB HID transport is supported then this command MUST be supported on that transport.
This method is used by the client to reset an authenticator back to a factory default state. Specifically this action at least:
-
Invalidates all generated credentials.
-
Erases all discoverable credentials.
-
Resets the serialized large-blob array storage, if any, to the initial serialized large-blob array value.
-
Disables those features that are denoted as being subject to disablement by authenticatorReset:
-
Resets those features that are denoted as being subject to reset by authenticatorReset to their default values:
Additionally:
-
In order to prevent an accidental triggering of this mechanism, evidence of user interaction is required.
-
In case of authenticators with no display, request MUST have come to the authenticator within 10 seconds of powering up of the authenticator.
If all conditions are met, authenticator returns CTAP2_OK. If this command is disabled for the transport used, the authenticator returns CTAP2_ERR_OPERATION_DENIED. If user presence is explicitly denied, the authenticator returns CTAP2_ERR_OPERATION_DENIED. If a user action timeout occurs, the authenticator returns CTAP2_ERR_USER_ACTION_TIMEOUT. If request comes after 15 seconds of powering up, or the last reset, the authenticator returns CTAP2_ERR_NOT_ALLOWED.
6.7. authenticatorBioEnrollment (0x09)
This command is used by the platform to provision/enumerate/delete bio enrollments in the authenticator.
It takes the following input parameters:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
modality (0x01) | Unsigned Integer | Optional | The user verification modality being requested |
subCommand (0x02) | Unsigned Integer | Optional | The authenticator user verification sub command currently being requested |
subCommandParams (0x03) | CBOR Map | Optional | Map of subCommands parameters. This parameter is optional and may be omitted when the subCommand does not take any arguments. |
pinUvAuthProtocol (0x04) | Unsigned Integer | Optional | PIN/UV protocol version chosen by the platform. |
pinUvAuthParam (0x05) | Byte String | Optional | First 16 bytes of HMAC-SHA-256 of contents using pinUvAuthToken. |
getModality (0x06) | Boolean | Optional | Get the user verification type modality. This MUST be set to true. |
The type of modalities supported are as under:
modality Name | modality Number |
---|---|
fingerprint | 0x01 |
The list of sub commands for fingerprint(0x01) modality is:
subCommand Name | subCommand Number |
---|---|
enrollBegin | 0x01 |
enrollCaptureNextSample | 0x02 |
cancelCurrentEnrollment | 0x03 |
enumerateEnrollments | 0x04 |
setFriendlyName | 0x05 |
removeEnrollment | 0x06 |
getFingerprintSensorInfo | 0x07 |
subCommandParams Fields:
Field name | Data type | Required? | Definition |
---|---|---|---|
templateId (0x01) | Byte String | Optional | Template Identifier. |
templateFriendlyName (0x02) | String | Optional | Template Friendly Name. |
timeoutMilliseconds (0x03) | Unsigned Integer | Optional | Timeout in milliSeconds. |
On success, authenticator returns the following structure in its response:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
modality (0x01) | Unsigned Integer | Optional | The user verification modality. |
fingerprintKind (0x02) | Unsigned Integer | Optional | Indicates the type of fingerprint sensor. For touch type sensor, its value is 1. For swipe type sensor its value is 2. |
maxCaptureSamplesRequiredForEnroll (0x03) | Unsigned Integer | Optional | Indicates the maximum good samples required for enrollment. |
templateId (0x04) | Byte String | Optional | Template Identifier. |
lastEnrollSampleStatus (0x05) | Unsigned Integer | Optional | Last enrollment sample status. |
remainingSamples (0x06) | Unsigned Integer | Optional | Number of more sample required for enrollment to complete |
templateInfos (0x07) | CBOR ARRAY | Optional | Array of templateInfo’s |
TemplateInfo definition:
Field name | Data type | Required? | Definition |
---|---|---|---|
templateId (0x01) | Byte String | Required | Template Identifier. |
templateFriendlyName (0x02) | String | Optional | Template Friendly Name. |
lastEnrollSampleStatus types:
lastEnrollSampleStatus Name | lastEnrollSampleStatus Value | Definition |
---|---|---|
CTAP2_ENROLL_FEEDBACK_FP_GOOD | 0x00 | Good fingerprint capture. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_HIGH | 0x01 | Fingerprint was too high. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_LOW | 0x02 | Fingerprint was too low. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_LEFT | 0x03 | Fingerprint was too left. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_RIGHT | 0x04 | Fingerprint was too right. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_FAST | 0x05 | Fingerprint was too fast. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_SLOW | 0x06 | Fingerprint was too slow. |
CTAP2_ENROLL_FEEDBACK_FP_POOR_QUALITY | 0x07 | Fingerprint was of poor quality. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_SKEWED | 0x08 | Fingerprint was too skewed. |
CTAP2_ENROLL_FEEDBACK_FP_TOO_SHORT | 0x09 | Fingerprint was too short. |
CTAP2_ENROLL_FEEDBACK_FP_MERGE_FAILURE | 0x0A | Merge failure of the capture. |
CTAP2_ENROLL_FEEDBACK_FP_EXISTS | 0x0B | Fingerprint already exists. |
(unused) | 0x0C | (this error number is available) |
CTAP2_ENROLL_FEEDBACK_NO_USER_ACTIVITY | 0x0D | User did not touch/swipe the authenticator. |
CTAP2_ENROLL_FEEDBACK_NO_USER_PRESENCE_TRANSITION | 0x0E | User did not lift the finger off the sensor. |
6.7.1. Feature detection
The bioEnroll option ID in the authenticatorGetInfo response defines feature support detection for this feature.
6.7.2. Get bio modality
Following operations are performed to get bio modality supported by the authenticator:
-
Platform sends authenticatorBioEnrollment command with following parameters:
-
getModality (0x06): true.
-
-
Authenticator returns authenticatorBioEnrollment response with following parameters:
-
modality (0x01): It represents the type of modality authenticator supports. For fingerprint, its value is 1.
-
6.7.3. Get fingerprint sensor info
Following operations are performed to get fingerprint sensor information:
-
Platform sends authenticatorBioEnrollment command with following parameters:
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): getFingerprintSensorInfo (0x07)
-
-
Authenticator returns authenticatorBioEnrollment response with following parameters:
-
fingerprintKind (0x02):
-
For touch type fingerprints, its value is 1.
-
For swipe type fingerprints, its value is 2.
-
-
maxCaptureSamplesRequiredForEnroll (0x03): Indicates the maximum good samples required for enrollment.
-
6.7.4. Enrolling fingerprint
Following operations are performed to enroll a fingerprint:
-
Platform gets pinUvAuthToken from the authenticator with the be permission.
-
Platform sends authenticatorBioEnrollment command with following parameters to begin the enrollment:
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): enrollBegin (0x01).
-
subCommandParams (0x03): Map containing following parameters
-
timeoutMilliseconds (0x03) (optional): timeout in milliseconds
-
-
pinUvAuthProtocol (0x04): as selected when getting the shared secret.
-
pinUvAuthParam (0x05): authenticate(pinUvAuthToken, fingerprint (0x01) || enrollBegin (0x01) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, fingerprint (0x01) || enrollBegin (0x01) || subCommandParams, pinUvAuthParam)
-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator verifies that the token has be permission, if not, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
If there is no space available, authenticator returns CTAP2_ERR_FP_DATABASE_FULL.
-
Authenticator cancels any unfinished ongoing enrollment.
-
Authenticator generates templateId for new enrollment.
-
Authenticator sends the command to the sensor to capture the sample.
-
Authenticator returns authenticatorBioEnrollment response with following parameters:
-
templateId (0x04): template identifier of the new template being enrolled.
-
lastEnrollSampleStatus (0x05) : Status of enrollment of last sample.
-
remainingSamples (0x06) : Number of sample remaining to complete the enrollment.
-
-
-
Platform sends authenticatorBioEnrollment command with following parameters to continue enrollment in a loop till remainingSamples is zero or authenticator errors out with unrecoverable error or platform wants to cancel current enrollment:
-
Platform sends authenticatorBioEnrollment command with following parameters
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): enrollCaptureNextSample (0x02).
-
subCommandParams (0x03): Map containing following parameters
-
templateId (0x01) : template identifier platform received from enrollBegin subCommand.
-
timeoutMilliseconds (0x03) (optional): timeout in milliseconds
-
-
pinUvAuthProtocol (0x04): as selected when getting the shared secret.
-
pinUvAuthParam (0x05): authenticate(pinUvAuthToken, fingerprint (0x01) || enrollCaptureNextSample (0x02) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, fingerprint (0x01) || enrollBegin (0x01) || enrollCaptureNextSample (0x02) || subCommandParams, pinUvAuthParam)
-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator verifies that the pinUvAuthToken has be permission, if not, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
If there is no space available, authenticator returns CTAP2_ERR_FP_DATABASE_FULL.
-
If fingerprint is already present on the sensor, authenticator waits for user to lift finger from the sensor.
-
Authenticator sends the command to the sensor to capture the sample.
-
Authenticator returns authenticatorBioEnrollment response with following parameters:
-
lastEnrollSampleStatus (0x05) : Status of enrollment of last sample.
-
remainingSamples (0x06) : Number of sample remaining to complete the enrollment.
-
-
-
6.7.5. Cancel current enrollment
Following operations are performed to cancel current enrollment:
-
Platform sends authenticatorBioEnrollment command with following parameters:
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): cancelCurrentEnrollment (0x03).
-
-
Authenticator on receiving such command, cancels current ongoing enrollment, if any, and returns CTAP2_OK.
6.7.6. Enumerate enrollments
Following operations are performed to enumerate enrollments:
-
Platform gets pinUvAuthToken from the authenticator with the be permission.
-
Platform sends authenticatorBioEnrollment command with following parameters:
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): enumerateEnrollments (0x04).
-
pinUvAuthProtocol (0x04): as selected when getting the shared secret.
-
pinUvAuthParam (0x05): authenticate(pinUvAuthToken, fingerprint (0x01) || enumerateEnrollments (0x04)).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, fingerprint (0x01) || enumerateEnrollments (0x04), pinUvAuthParam)
-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator verifies that the token has be permission, if not, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
If there are no enrollments existing on authenticator, it returns CTAP2_ERR_INVALID_OPTION.
-
Authenticator returns authenticatorBioEnrollment response following parameters:
-
templateInfos (0x07) : Array of templateInfo’s for all the enrollments available on the authenticator.
-
-
6.7.7. Rename/Set FriendlyName
Following operations are performed to rename a fingerprint:
-
Platform gets pinUvAuthToken from the authenticator with the be permission.
-
Platform sends authenticatorBioEnrollment command with following parameters:
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): setFriendlyName (0x05).
-
subCommandParams (0x03): Map containing following parameters
-
templateId (0x01) : template identifier.
-
templateFriendlyName (0x02): Friendly name of the template
-
-
pinUvAuthProtocol (0x04): as selected when getting the shared secret.
-
pinUvAuthParam (0x05): authenticate(pinUvAuthToken, fingerprint (0x01) || setFriendlyName (0x05) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, fingerprint (0x01) || setFriendlyName (0x05) || subCommandParams, pinUvAuthParam)
-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator verifies that the token has be permission, if not, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
If there are no enrollments existing on authenticator for the passed templateId, it returns CTAP2_ERR_INVALID_OPTION.
-
If there is an existing enrollment with that identifier, rename its friendly name and return CTAP2_OK.
-
6.7.8. Remove enrollment
Following operations are performed to remove a fingerprint:
-
Platform gets pinUvAuthToken from the authenticator with the be permission.
-
Platform sends authenticatorBioEnrollment command with following parameters:
-
modality (0x01): fingerprint (0x01).
-
subCommand (0x02): removeEnrollment (0x06).
-
subCommandParams (0x03): Map containing following parameters
-
templateId (0x01) : template identifier.
-
-
pinUvAuthProtocol (0x04): as selected when getting the shared secret.
-
pinUvAuthParam (0x05): authenticate(pinUvAuthToken, fingerprint (0x01) || removeEnrollment (0x06) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, fingerprint (0x01) || removeEnrollment (0x06) || subCommandParams, pinUvAuthParam)
-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator verifies that the token has be permission, if not, it returns CTAP2_ERR_PIN_AUTH_INVALID.
-
If there are no enrollments existing on authenticator for passed templateId, it returns CTAP2_ERR_INVALID_OPTION.
-
If there is an exiting enrollment with passed in templateInfo, delete that enrollment and return CTAP2_OK.
-
6.8. authenticatorCredentialManagement (0x0A)
This command is used by the platform to manage discoverable credentials on the authenticator.
Note: support for this command is mandatory in some cases. See § 9 Mandatory features.
It takes the following input parameters:
Parameter name | Data type | Definition |
---|---|---|
subCommand (0x01) | Unsigned Integer | subCommand currently being requested |
subCommandParams (0x02) | CBOR Map | Map of subCommands parameters. |
pinUvAuthProtocol (0x03) | Unsigned Integer | PIN/UV protocol version chosen by the platform. |
pinUvAuthParam (0x04) | Byte String | First 16 bytes of HMAC-SHA-256 of contents using pinUvAuthToken. |
The list of sub commands for credential management is:
subCommand Name | subCommand Number |
---|---|
getCredsMetadata | 0x01 |
enumerateRPsBegin | 0x02 |
enumerateRPsGetNextRP | 0x03 |
enumerateCredentialsBegin | 0x04 |
enumerateCredentialsGetNextCredential | 0x05 |
deleteCredential | 0x06 |
updateUserInformation | 0x07 |
subCommandParams Fields:
Field name | Data type | Definition |
---|---|---|
rpIDHash (0x01) | Byte String | RPID SHA-256 hash |
credentialID (0x02) | PublicKeyCredentialDescriptor | Credential Identifier |
user (0x03) | PublicKeyCredentialUserEntity
| User Entity |
On success, authenticator returns the following structure in its response:
Parameter name | Data type | Definition |
---|---|---|
existingResidentCredentialsCount (0x01) | Unsigned Integer | Number of existing discoverable credentials present on the authenticator. |
maxPossibleRemainingResidentCredentialsCount (0x02) | Unsigned Integer | Number of maximum possible remaining discoverable credentials which can be created on the authenticator. |
rp (0x03) | PublicKeyCredentialRpEntity | RP Information |
rpIDHash (0x04) | Byte String | RPID SHA-256 hash |
totalRPs (0x05) | Unsigned Integer | total number of RPs present on the authenticator |
user (0x06) | PublicKeyCredentialUserEntity | User Information |
credentialID (0x07) | PublicKeyCredentialDescriptor | PublicKeyCredentialDescriptor |
publicKey (0x08) | COSE_Key | Public key of the credential. |
totalCredentials (0x09) | Unsigned Integer | Total number of credentials present on the authenticator for the RP in question |
credProtect (0x0A) | Unsigned Integer | Credential protection policy. |
largeBlobKey (0x0B) | Byte string | Large blob encryption key. |
-
The platform may want to do actual credential management, e.g. list, update, or delete credentials. In this case, a permissions RPID is not associated with the pinUvAuthToken and all credentials can be enumerated and retrieved.
-
The platform may need to fetch the public key of a credential for use in some protocols like SSH. When making the authenticatorGetAssertion request, a permissions RPID is present (because it is required for the ga permission) but now the cm permission will only allow you to retrieve credentials related to that authenticatorGetAssertion request. This works because you do not need access to all credentials, just the ones relevant for the request’s associated RPID.
-
The platform may want to garbage collect large-blobs because it finds that there is insufficient space to store a desired blob. Since it’s possible that a credential has been deleted without also deleting its large blob, the platform may be able to free up enough space with garbage collection. In this case, additional user interaction may be needed because a permissions RPID needs to be associated with the pinUvAuthToken for the ga or mc permission to be obtained, but a full enumeration needs the cm permission without any RPID limitation. Thus the user may need to perform user verification a second time if garbage collection of just the single RPID is insufficient.
6.8.1. Feature detection
The credMgmt option ID in the authenticatorGetInfo response defines feature support detection for this feature.
6.8.2. Getting Credentials Metadata
Following operations are performed to get credentials metadata information :
-
Platform gets pinUvAuthToken from the authenticator with the cm permission, and MUST NOT include a permissions RPID parameter.
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): getCredsMetadata (0x01).
-
pinUvAuthProtocol (0x03): as selected when getting the shared secret.
-
pinUvAuthParam (0x04): authenticate(pinUvAuthToken, getCredsMetadata (0x01)).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, getCredsMetadata (0x01), pinUvAuthParam)
-
If pinUvAuthParam verification fails, authenticator returns CTAP2_ERR_PIN_AUTH_INVALID error.
-
The Authenticator verifies that the pinUvAuthToken has the cm permission and no associated permissions RPID. If not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
Authenticator returns authenticatorCredentialManagement response with following parameters:
-
existingResidentCredentialsCount (0x01) : total number of discoverable credentials existing on the authenticator.
-
maxPossibleRemainingResidentCredentialsCount (0x02) : maximum number of possible remaining discoverable credentials that can be created on the authenticator. Note that this number is an estimate as actual space consumed to create a credential depends on various conditions such as which algorithm is picked, user entity information etc.
-
-
6.8.3. Enumerating RPs
Following operations are performed to enumerate RPs present on the authenticator:
-
Platform gets pinUvAuthToken from the authenticator with the cm permission, and MUST NOT include a permissions RPID parameter.
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): enumerateRPsBegin (0x02).
-
pinUvAuthProtocol (0x03): as selected when getting the shared secret.
-
pinUvAuthParam (0x04): authenticate(pinUvAuthToken, enumerateRPsBegin (0x02)).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, enumerateRPsBegin (0x02), pinUvAuthParam).
-
If pinUvAuthParam verification fails, authenticator returns CTAP2_ERR_PIN_AUTH_INVALID error.
-
The Authenticator verifies that the pinUvAuthToken has the cm permission and no associated permissions RPID. If not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
Authenticator returns an authenticatorCredentialManagement response with following parameters:
-
rp (0x03):
PublicKeyCredentialRpEntity
, where theid
field SHOULD be included and other fields MAY be included. (See § 6.8.7 Truncation of relying party identifiers about possible truncation of theid
field and [WebAuthn] about other fields.) -
rpIDHash (0x04) : RP ID SHA-256 hash.
-
totalRPs (0x05) : Total number of RPs present on the authenticator.
-
-
-
Platform on receiving more than 1 totalRPs, performs following procedure for (totalRPs - 1 ) number of times:
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): enumerateRPsGetNextRP (0x03).
-
Note: this is a stateful command and the specified implementation accommodations apply to it.
-
Authenticator on receiving such enumerateCredentialsGetNext subCommand returns authenticatorCredentialManagement response with following parameters:
-
rp (0x03):
PublicKeyCredentialRpEntity
-
rpIDHash (0x04) : RP ID SHA-256 hash.
-
-
6.8.4. Enumerating Credentials for an RP
Following operations are performed to enumerate credentials for an RP:
-
Platform gets pinUvAuthToken from the authenticator with the cm permission.
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): enumerateCredentialsBegin (0x04).
-
subCommandParams (0x02): Map containing following parameters
-
rpIDHash (0x01): RPID SHA-256 hash.
-
-
pinUvAuthProtocol (0x03): as selected when getting the shared secret.
-
pinUvAuthParam (0x04): authenticate(pinUvAuthToken, enumerateCredentialsBegin (0x04) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, enumerateCredentialsBegin (0x04) || subCommandParams, pinUvAuthParam)
-
If pinUvAuthParam verification fails, authenticator returns CTAP2_ERR_PIN_AUTH_INVALID error.
-
The Authenticator verifies that the pinUvAuthToken has the cm permission and that the pinUvAuthToken does not have an permissions RPID associated or that the pinUvAuthToken permissions RPID matches the RPID of this request. If not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
If no credentials were found for this RPID hash, authenticator returns CTAP2_ERR_NO_CREDENTIALS.
-
Authenticator returns authenticatorCredentialManagement response with following parameters:
-
user (0x06): PublicKeyCredentialUserEntity
-
credentialID (0x07): PublicKeyCredentialDescriptor
-
publicKey (0x08): public key of the credential in COSE_Key format
-
totalCredentials (0x09): total number of credentials for this RP
-
credProtect (0x0A): credential protection policy
-
largeBlobKey (0x0B): the contents, if any, of the stored largeBlobKey.
-
-
-
Platform on receiving more than 1 totalCredentials, performs following procedure for (totalCredentials - 1 ) number of times:
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): enumerateCredentialsGetNextCredential (0x05).
-
Note: this is a stateful command and the specified implementation accommodations apply to it.
-
Authenticator on receiving such enumerateCredentialsGetNext subCommand returns with following parameters:
-
user (0x06): PublicKeyCredentialUserEntity
-
credentialID (0x07): PublicKeyCredentialDescriptor
-
publicKey (0x08): public key of the credential in COSE_Key format
-
credProtect (0x0A): credential protection policy
-
largeBlobKey (0x0B): the contents, if any, of the stored largeBlobKey.
-
-
Note: when enumerating credentials, platforms SHOULD take the opportunity to perform large-blob garbage collection, if applicable.
6.8.5. DeleteCredential
Following operations are performed to delete a credential:
-
Platform gets pinUvAuthToken from the authenticator with the cm permission.
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): deleteCredential (0x06).
-
subCommandParams (0x02): Map containing following parameters
-
credentialId (0x02): PublicKeyCredentialDescriptor of the credential to be deleted.
-
-
pinUvAuthProtocol (0x03): as selected when getting the shared secret.
-
pinUvAuthParam (0x04): authenticate(pinUvAuthToken, deleteCredential (0x06) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, deleteCredential (0x06) || subCommandParams, pinUvAuthParam)
-
If pinUvAuthParam verification fails, authenticator returns CTAP2_ERR_PIN_AUTH_INVALID error.
-
The Authenticator verifies that the pinUvAuthToken has the cm permission and that the pinUvAuthToken does not have a permissions RPID associated or that the pinUvAuthToken permissions RPID matches the RPID of the credential. If not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
If there are not credential existing matching credentialDescriptor, return CTAP2_ERR_NO_CREDENTIALS.
-
Delete the credential and return CTAP2_OK.
-
Note: when deleting a credential, platforms SHOULD also delete any associated large blobs.
6.8.6. Updating user information
Following operations are performed to update user information associated to a credential:
-
Platform gets pinUvAuthToken from the authenticator with the cm permission.
-
Platform sends authenticatorCredentialManagement command with following parameters:
-
subCommand (0x01): updateUserInformation (0x07).
-
subCommandParams (0x02): Map containing the parameters that need to be updated.
-
credentialId (0x02): PublicKeyCredentialDescriptor of the credential to be updated.
-
user (0x03): a
PublicKeyCredentialUserEntity
with the updated information.
-
-
pinUvAuthProtocol (0x03): as selected when getting the shared secret.
-
pinUvAuthParam (0x04): authenticate(pinUvAuthToken, updateUserInformation (0x07) || subCommandParams).
-
-
Authenticator on receiving such request performs following procedures.
-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Authenticator calls verify(pinUvAuthToken, updateUserInformation (0x07) || subCommandParams, pinUvAuthParam)
-
If pinUvAuthParam verification fails, authenticator returns CTAP2_ERR_PIN_AUTH_INVALID error.
-
The authenticator verifies that the pinUvAuthToken has the cm permission and that the pinUvAuthToken does not have a permissions RPID associated or that the pinUvAuthToken permissions RPID matches the RPID of the credential. If not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
If there is not any existing credential matching
credentialId
, return CTAP2_ERR_NO_CREDENTIALS. -
If the authenticator does not have enough internal storage to update the credential, return CTAP2_ERR_KEY_STORE_FULL.
-
Replace the matching credential’s
PublicKeyCredentialUserEntity
'sname
,displayName
, andicon
with the passeduser
details. (Theid
field MUST be ignored.) -
Return CTAP2_OK.
-
6.8.7. Truncation of relying party identifiers
An authenticator may store relying party identifiers in order to implement authenticatorCredentialManagement. As there is no bound on their length, authenticators may truncate them using a procedure that produces the same results as the code included below. If authenticators store relying party identifiers at all, they MUST store at least 32 bytes. Truncation of relying party identifiers only applies to returning a PublicKeyCredentialRpEntity
structure in the context of this command. I.e. authenticators MUST NOT use truncated relying party identifiers for comparisons at any time, including in the context of this command.
#define MAX_STORED_RPID_LENGTH 32 /* MUST be >= 32 */ void maybe_truncate_rpid(uint8_t stored_rpid[MAX_STORED_RPID_LENGTH], size_t *stored_len, const uint8_t *rpid, size_t rpid_len) { if (rpid_len <= MAX_STORED_RPID_LENGTH) { memcpy(stored_rpid, rpid, rpid_len); *stored_len = rpid_len; return; } size_t used = 0; const uint8_t *colon_position = memchr(rpid, ':', rpid_len); if (colon_position != NULL) { const size_t protocol_len = colon_position - rpid + 1; const size_t to_copy = protocol_len <= MAX_STORED_RPID_LENGTH ? protocol_len : MAX_STORED_RPID_LENGTH; memcpy(stored_rpid, rpid, to_copy); used += to_copy; } if (MAX_STORED_RPID_LENGTH - used < 3) { *stored_len = used; return; } // U+2026, horizontal ellipsis. stored_rpid[used++] = 0xe2; stored_rpid[used++] = 0x80; stored_rpid[used++] = 0xa6; const size_t to_copy = MAX_STORED_RPID_LENGTH - used; memcpy(&stored_rpid[used], rpid + rpid_len - to_copy, to_copy); assert(used + to_copy == MAX_STORED_RPID_LENGTH); *stored_len = MAX_STORED_RPID_LENGTH; }
For illutrative purposes, here are some examples of the truncation in effect:
Input RP ID | Stored RP ID | Comment |
---|---|---|
example.com | example.com | No truncation applied |
myfidousingwebsite.hostingprovider.net | …ngwebsite.hostingprovider.net | Truncation applied on the left |
mygreatsite.hostingprovider.info | mygreatsite.hostingprovider.info | No truncation applied to strings of length 32; any sentinel values (e.g. NUL bytes in C) are internal to the authenticator implementation and do not count towards the protocol defined length |
otherprotocol://myfidousingwebsite.hostingprovider.net | otherprotocol:…ingprovider.net | Protocol strings are preserved if possible |
veryexcessivelylargeprotocolname://example.com | veryexcessivelylargeprotocolname | Protocol strings may consume the entire space |
6.9. authenticatorSelection (0x0B)
This command allows the platform to let a user select a certain authenticator by asking for user presence.
The command has no input parameters.
When the authenticatorSelection command is received, the authenticator will ask for user presence:
-
If User Presence is received, the authenticator will return CTAP2_OK.
-
If User Presence is explicitly denied by the user, the authenticator will return CTAP2_ERR_OPERATION_DENIED. The platform SHOULD NOT repeat the command for this authenticator.
-
If a user action timeout occurs, the authenticator will return CTAP2_ERR_USER_ACTION_TIMEOUT. The platform MAY repeat the command for this authenticator.
If an authenticator is selected, the platform SHOULD send a cancel to all other authenticators.
6.10. authenticatorLargeBlobs (0x0C)
The credBlob extension allows for a small amount of additional, secret information to be stored with a credential. In contrast, this command allows a platform to store a larger amount of information associated with a credential, protected by a key that is then stored and accessed using the largeBlobKey extension. The opaque large-blob data that is stored for a credential is a byte string with RP-specific structure. This is only applicable to discoverable credentials so that garbage collection is possible.
This command allows at least 1024 bytes of large blob data to be stored on CTAP2 authenticators. For the purposes of this command, this data is serialized as a CBOR-encoded array (called the large-blob array) of large-blob maps, concatenated with 16 following bytes. Those final 16 bytes are the truncated SHA-256 hash of the preceding bytes. This concatenation is referred to as the serialized large-blob array.
The initial serialized large-blob array is the value of the serialized large-blob array on a fresh authenticator, as well as immediately after a reset. It is the byte string h'8076be8b528d0075f7aae98d6fa57a6d3c'
, which is an empty CBOR array (80
) followed by LEFT(SHA-256(h'80'), 16)
.
Note: the minimum length of a serialized large-blob array is 17 bytes. Omitting 16 bytes for the trailing SHA-256 hash, this leaves just one byte. This is the size of an empty CBOR array.
6.10.1. Feature detection
The largeBlobs option ID in the authenticatorGetInfo response defines feature support detection for this feature.
6.10.2. Reading and writing serialised data
The command takes the following input parameters:
Parameter name | Data type | Required? | Notes |
---|---|---|---|
get (0x01) | Unsigned integer | Optional | The number of bytes requested to read. MUST NOT be present if set is present.
|
set (0x02) | Byte String | Optional | A fragment to write. MUST NOT be present if get is present.
|
offset (0x03) | Unsigned integer | Required | The byte offset at which to read/write. |
length (0x04) | Unsigned integer | Optional | The total length of a write operation. Present if, and only if, set is present and offset is zero.
|
pinUvAuthParam (0x05) | Byte String | Optional | authenticate(pinUvAuthToken, 32×0xff || h’0c00' || uint32LittleEndian(offset ) || SHA-256(contents of set byte string, i.e. not including an outer CBOR tag with major type two))
|
pinUvAuthProtocol (0x06) | Unsigned integer | Optional | PIN/UV protocol version chosen by the platform. |
A per-authenticator constant, maxFragmentLength
, is here defined as the value of maxMsgSize
(from the authenticatorGetInfo response) minus 64. The value 64 is a comfortable over-estimate of the encoding overhead of the messages defined in this section such that a byte string of length maxFragmentLength
can be transferred without exceeding the maximum message size of the authenticator. If no maxMsgSize
is given in the authenticatorGetInfo response) then it defaults to 1024, leaving maxFragmentLength
to default to 960.
In addition to persistently storing the serialized large-blob array, authenticators implementing this command are required to maintain two unsigned integers in volatile memory named expectedNextOffset
and expectedLength
, both initially zero. This makes this command a stateful command and the specified implementation accommodations apply to it.
An authenticator performs the following actions upon receipt of this command:
-
If
offset
is not present in the input map, return CTAP1_ERR_INVALID_PARAMETER. -
If neither
get
norset
are present in the input map, return CTAP1_ERR_INVALID_PARAMETER. -
If both
get
andset
are present in the input map, return CTAP1_ERR_INVALID_PARAMETER. -
If
get
is present in the input map:-
If
length
is present, return CTAP1_ERR_INVALID_PARAMETER. -
If either of
pinUvAuthParam
orpinUvAuthProtocol
are present, return CTAP1_ERR_INVALID_PARAMETER. -
If the value of
get
is greater thanmaxFragmentLength
, return CTAP1_ERR_INVALID_LENGTH. -
If the value of
offset
is greater than the length of the stored serialized large-blob array, return CTAP1_ERR_INVALID_PARAMETER. -
Return a CBOR map, as defined below, where the value of
config
is a substring of the stored serialized large-blob array. The substring should start at the offset given inoffset
and contain the number of bytes specified asget
's value. If too few bytes exist at that offset, return the maximum number available. Note that ifoffset
is equal to the length of the serialized large-blob array then this will result in a zero-length substring.
-
-
Else (implying that
set
is present in the input map):-
If the length of the value of
set
is greater thanmaxFragmentLength
, return CTAP1_ERR_INVALID_LENGTH. (The “value ofset
” means the contents of the byte string corresponding to the keyset
(0x02), not including the outer CBOR tag with major type two.) -
If the value of
offset
is zero:-
If
length
is not present, return CTAP1_ERR_INVALID_PARAMETER. -
If the value of
length
is greater than 1024 bytes and exceeds the capacity of the device, return CTAP2_ERR_LARGE_BLOB_STORAGE_FULL. (Authenticators MUST be capable of storing at least 1024 bytes.) -
If the value of
length
is less than 17, return CTAP1_ERR_INVALID_PARAMETER. (See note above about minimum lengths.) -
Set
expectedLength
to the value oflength
. -
Set
expectedNextOffset
to zero.
-
-
Else (i.e. the value of
offset
is not zero):-
If
length
is present, return CTAP1_ERR_INVALID_PARAMETER.
-
-
If the value of
offset
is not equal toexpectedNextOffset
, return CTAP1_ERR_INVALID_SEQ. -
If the authenticator is protected by some form of user verification or the alwaysUv option ID is present and
true
:-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, then end the operation by returning CTAP2_ERR_PUAT_REQUIRED. -
If
pinUvAuthProtocol
is not supported, return CTAP2_ERR_PIN_AUTH_INVALID. -
Check if the pinUvAuthToken has the lbw permission, if not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
The authenticator calls
verify(pinUvAuthToken, 32×0xff || h’0c00' || uint32LittleEndian(
.offset
) || SHA-256(contents ofset
byte string, i.e. not including an outer CBOR tag with major type two), pinUvAuthParam)-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
-
If the sum of
offset
and the length of the value ofset
is greater than the value ofexpectedLength
, return CTAP1_ERR_INVALID_PARAMETER. -
If the value of
offset
is zero, prepare a buffer to receive a new serialized large-blob array. -
Append the value of
set
to the buffer containing the pending serialized large-blob array. -
Update
expectedNextOffset
to be the new length of the pending serialized large-blob array. -
If the length of the pending serialized large-blob array is equal to
expectedLength
:-
Verify that the final 16 bytes in the buffer are the truncated SHA-256 hash of the preceding bytes. If the hash does not match, return CTAP2_ERR_INTEGRITY_FAILURE.
-
Commit the contents of the buffer as the new serialized large-blob array for this authenticator.
-
Return CTAP2_OK and an empty response.
-
-
Else:
-
More data is needed to complete the pending serialized large-blob array.
-
Return CTAP2_OK and an empty response. Await further writes.
-
-
Note: user verification is only checked above if user verification is configured on a device or the authenticator always requires some form of user verification feature is enabled. This implies that a serialized large-blob array can be written without user verification if user verification is not configured.
Note: To read (i.e., "get") per-credential large-blob data given a credential ID, the platform must first use an authenticatorGetAssertion operation to obtain the associated largeBlobKey in order to be able to decrypt the large-blob data (if any). Thus the confidentiality of any large-blob data associated with the credential is dependent upon the credential’s protection policy. This means that even though a platform may obtain the large-blob array at will, it will be unable to obtain large-blob plaintexts if it cannot successfully perform authenticatorGetAssertion operations using the associated credential(s), e.g., without obtaining user verification. Also, the "trial decryption" approach employed for obtaining plaintext means that large-blobs do not disclose a priori the existence of credentials having a credProtect level 3 userVerificationRequired policy.
The response to a get
request, referenced above, takes the following form:
Parameter name | Data type | Required? | Notes |
---|---|---|---|
config (0x01) | Byte String | Required | Contains the requested substring of the serialized large-blob array. |
In order to read a serialized large-blob array, a platform is expected to first issue a request where offset
is zero and get
equals the value of maxFragmentLength
, which is maxMsgSize
− 64 bytes, as defined above. If the length of the response is equal to the value of get
then more data may be available and the platform should repeatedly issue requests, each time updating offset
to equal the amount of data received so far. It stops once a short (or empty) fragment is returned. Once complete, the platform MUST confirm that the embedded SHA-256 hash is correct, based on the definition above. If not, the configuration is corrupt and the platform MUST discard it and act as if the initial serialized large-blob array was received.
In order to write a serialized large-blob array, a platform is expected to first issue a request where offset
is zero, length
is the full length of the data to be written, and set
contains a prefix of the data to be written, truncated at maxFragmentLength
bytes, if length
is greater than maxFragmentLength
. If truncation is needed then one or more further requests are needed to complete the transfer, with offset
updated each time to contain the amount of data written so far and set
containing consecutive substrings of the data. The authenticator will implicitly know when the transfer is complete because of the length given in the first request.
The algorithm to be performed by the authenticator given above assumes that the authenticator double-buffers the serialized large-blob array. (I.e. it writes proposed updates into a separate buffer and only overwrites the effective config once validation has completed.) A compliant authenticator MAY be implemented using only a single buffer as follows: when appending to the buffer, use expectedLength
to buffer the final 16 bytes of the serialized large-blob array in volatile storage. Once the transfer is complete, perform validation and only write the final 16 bytes to persistent storage if successful. This prevents the SHA-256 checksum of an invalid serialized large-blob array from being persisted.
Note: even with double-buffering, the copy from the temporary buffer might be interrupted, resulting in a “torn write”. This will be detected by the platform when reading because the checksum won’t match, but results in an unusable config. Thus double-buffering minimises the chance of corruption, but does not always eliminate it.
Despite best efforts, torn writes, platform errors, and storage corruption may result in a situation where an authenticator finds itself having stored an invalid serialized large-blob array. (I.e. the SHA-256 hash does not match.) In this case, the authenticator MAY reset the stored value with the initial serialized large-blob array.
An authenticator MUST NOT act on the contents of the serialized large-blob array except for checking the trailing hash: it is purely for platforms to adjust their behavior in response to.
Authenticators MUST set the serialized large-blob array to the initial serialized large-blob array byte string when reset.
Platforms MUST ensure that the large-blob array (i.e. without the trailing 16 bytes) is a CBOR array where all entries conform to the large-blob map structure defined below. The maps and array MUST be encoded using the canonical rules. Platforms MUST NOT attempt to write a serialized large-blob array that exceeds the maxSerializedLargeBlobArray
reported by the authenticator in the authenticatorGetInfo response. Platforms SHOULD take care to preserve existing entries in a large-blob array where space permits. For example, platforms should read, and then insert values into, an existing large-blob array as opposed to blindly writing a fresh array.
6.10.3. Large, per-credential blobs
The elements of the large-blob array MUST conform to the following large-blob map structure. Conformance, in this context, means that a map MUST include all required elements, MAY include optional elements, and MAY include unknown elements. The values of all documented elements present MUST match the specified type and MUST comply with any additional restrictions documented for them.
Element name | Data type | Required? | Notes |
---|---|---|---|
ciphertext (0x01) | Byte String | Required | AEAD_AES_256_GCM ciphertext, implicitly including the AEAD “authentication tag” at the end. |
nonce (0x02) | Byte String | Required | AEAD_AES_256_GCM nonce. MUST be exactly 12 bytes long. |
origSize (0x03) | Unsigned Integer | Required | Contains the length, in bytes, of the uncompressed data. |
The ciphertext
member contains the output of encrypting the opaque large-blob data with the AEAD_AES_256_GCM algorithm from [RFC5116]. The inputs to the AEAD are:
-
Nonce: the 12-byte value from
nonce
. -
Plaintext: the compressed opaque large-blob data.
-
Associated data: The value 0x626c6f62 ("blob") || uint64LittleEndian(
origSize
). -
Key: the 32-byte value stored using the largeBlobKey extension.
6.10.4. Reading per-credential large-blob data
The platform SHOULD perform the following steps in order to read the opaque large-blob data for a given credential. The platform must know the credential ID of the intended credential a priori, which it might have been given, or might have learnt from performing an authenticatorGetAssertion operation without an allowList parameter.
-
If the authenticator does not support the largeBlobKey extension, as defined in that section, return an error.
-
Perform an authenticatorGetAssertion operation with "largeBlobKey":
true
in theextensions
map in order to fetch the largeBlobKey for the credential. (This step may be skipped if the pertinent output is already known.) -
If
largeBlobKey
is not included in the authenticatorGetAssertion response structure (i.e., not in the extensions field of the authenticator data) then return that no large blob exists. -
Let
key
be the value oflargeBlobKey
in the assertion result. If it is not 32 bytes long, return an error. -
Fetch the large-blob array. If this fails, return an error.
-
For each element in that array:
-
If the element is not a map conforming to the large-blob map structure defined above, skip this array element.
-
Perform an AEAD_AES_256_GCM authenticated decryption of
ciphertext
usingkey
,nonce
, and the associated data specified above. If the decryption fails, skip this array element. -
Decompress the resulting plaintext with DEFLATE [RFC1951]. If decompression fails, return an error.
-
If the length of the decompression result is not equal to
origSize
, return an error. -
Return the decompression result as the opaque large-blob data for the credential.
-
-
Return that no large blob exists.
Note: DEFLATE has a maximum compression ratio of over 1000:1, thus the result of decompressing a small amount of data can be extremely large which might cause excessive memory use. Platforms SHOULD limit the maximum permitted value of origSize
and that maximum SHOULD be at least 1MiB.
6.10.5. Writing per-credential large-blob data for a new credential
The platform SHOULD perform the following steps in order to write the opaque large-blob data for a new credential.
-
If the authenticator does not support the largeBlobKey extension, as defined in that section, return an error.
-
If the authenticatorMakeCredential operation for the new credential does not map
rk
totrue
in theoptions
map, return an error. (Large blobs are only applicable for discoverable credentials.) -
Perform the authenticatorMakeCredential operation for the new credential. In the
extensions
input additionally maplargeBlobKey
totrue
. -
Let
key
be the largeBlobKey returned in the authenticatorMakeCredential response structure. -
Let
origData
equal the opaque large-blob data. -
Let
origSize
be the length, in bytes, oforigData
. -
Let
plaintext
equalorigData
after compression with DEFLATE [RFC1951]. -
Let
nonce
be a fresh, random, 12-byte value. -
Let
ciphertext
be the AEAD_AES_256_GCM authenticated encryption ofplaintext
usingkey
,nonce
, and the associated data as specified above. -
Fetch the large-blob array. If this fails, return an error.
-
Append an element to the array, following the structure above, containing
nonce
,origSize
, andciphertext
. -
Perform the actions for writing the new large-blob array.
6.10.6. Updating per-credential large-blob data
Unlike the underlying largeBlobKey data, the opaque large-blob data for a credential may be updated or deleted. Given a credential, the platform SHOULD perform the following steps in order to update or delete it:
-
If the authenticator does not support the largeBlobKey extension, as defined in that section, return an error.
-
Perform an authenticatorGetAssertion operation with "largeBlobKey":
true
in theextensions
map in order to fetch the largeBlobKey for the credential. (This step may be skipped if the pertinent output is already known.) -
If
largeBlobKey
is not included in the authenticatorGetAssertion response structure (i.e., not in the extensions field of the authenticator data) then return that no large blob exists. -
Let
key
be the value oflargeBlobKey
in the authenticatorGetAssertion response structure. If it is not 32 bytes long, return an error. -
Fetch the large-blob array. If this fails, return an error.
-
For each element in that array:
-
If the element is not a map conforming to the large-blob map structure defined above, skip this array element.
-
Perform an AEAD_AES_256_GCM authenticated decryption of
ciphertext
usingkey
,nonce
, and the associated data specified above. If the decryption fails, skip this array element. -
If the platform wishes to delete the opaque large-blob data:
-
Erase the current array element.
-
-
Else (i.e. the platform wishes to update the opaque large-blob data):
-
Let
origData
equal the new opaque large-blob data. -
Let
origSize
be the length, in bytes, oforigData
. -
Let
plaintext
equalorigData
after compression with DEFLATE [RFC1951]. -
Let
nonce
be a fresh, random, 12-byte value. -
Let
ciphertext
be the AEAD_AES_256_GCM authenticated encryption ofplaintext
usingkey
,nonce
, and the associated data as specified above. -
Replace the current array element with a map, following the structure above, containing
nonce
,origSize
, andciphertext
.
-
-
Perform the actions for writing the new large-blob array.
-
Return success.
-
-
Return an error.
6.10.7. Garbage collection of large-blob data
Large blobs may remain even when the linked credential has been erased. This can occur when a platform that doesn’t support large blobs deletes a credential, or when a credential is implicitly deleted because a new credential with the same user ID and RP ID is created. Thus platform MAY perform a garbage collection at will and SHOULD perform a garbage collection when a large-blob cannot be stored because of lack of space, or when using credential management to enumerate credentials for other reasons.
Performing a garbage collection involves the following steps:
-
If
credMgmt
is not present in theoptions
field of the authenticatorGetInfo response, garbage collection is not possible. -
Use the authenticatorCredentialManagement command to enumerate all RPs with discoverable credentials, and then to enumerate all credentials for each of them.
-
Collect the set of
largeBlobKey
values returned, ignoring any that are not 32 bytes long. -
Fetch the large-blob array. If this fails, return an error.
-
For each element in that array:
-
If the element is not a map conforming to the large-blob map structure defined above, skip this array element. (The large-blob map is permitted to include extra elements.)
-
Perform an AEAD_AES_256_GCM authenticated decryption of
ciphertext
usingnonce
, the associated data specified above, and each of thelargeBlobKey
values in turn as the key. If the decryption fails in every case, erase this array element.
-
-
If any array elements were erased then perform the actions for writing the updated large-blob array.
6.11. authenticatorConfig (0x0D)
Note: Platforms MUST NOT invoke this command unless the authnrCfg option ID is present and true
in the response to an authenticatorGetInfo command.
This command is used to configure various authenticator features through the use of its subcommands.
It takes the following input map containing its input parameters:
Parameter name | Data type | Required? | Notes |
---|---|---|---|
subCommand (0x01) | Unsigned Integer | Required | subCommand currently being requested |
subCommandParams (0x02) | CBOR Map | Optional | Map of subCommands parameters. |
pinUvAuthProtocol (0x03) | Unsigned Integer | Optional | PIN/UV protocol version chosen by the client. |
pinUvAuthParam (0x04) | Byte String | Optional | First 16 bytes of HMAC-SHA-256 of contents using pinUvAuthToken. |
The currently defined authenticatorConfig subcommands are:
subCommand Name | subCommand Number |
---|---|
enableEnterpriseAttestation | 0x01 |
toggleAlwaysUv | 0x02 |
setMinPINLength | 0x03 |
vendorPrototype | 0xFF |
This authenticatorConfig command allows the platform to invoke various simple configuration operations on an authenticator. Parameters may be passed into subcommands, and only status codes are returned (i.e. no response map is defined). Typically, the platform may subsequently request and examine an authenticatorGetInfo response, per directions given for each subcommand, in order to ascertain results of having invoked the subcommand.
Authenticators MAY implement none, some, or all currently defined authenticatorConfig subcommands.
Note: The vendorPrototype subCommand is reserved for vendor-specific authenticator configuration and experimentation. Platforms are not expected to generally utilize this subCommand.
To invoke authenticatorConfig
the platform performs the following actions:
-
The platform sends the
authenticatorConfig
command with the following parameters:-
subCommand (0x01): The subcommand selected by the platform from the currently defined authenticatorConfig subcommands.
-
subCommandParams (0x02): Map containing subcommand parameters, if the selected subcommand takes parameters.
-
pinUvAuthProtocol (0x03): as selected when obtaining the shared secret.
-
pinUvAuthParam (0x04): the result of calling
authenticate(pinUvAuthToken, 32×0xff || 0x0d || uint8(subCommand) || subCommandParams)
.
-
The authenticator performs the following actions upon receipt of this command:
-
If
subCommand
is not present in the input map, return CTAP2_ERR_MISSING_PARAMETER. -
If the authenticator does not support the subcommand being invoked, per
subCommand
's value, return CTAP1_ERR_INVALID_PARAMETER. -
If the following statements are all true:
-
subCommand
value is toggleAlwaysUv (0x02). -
The authenticator is not protected by some form of user verification.
then go to Step 5.
Note: This allows for initial configuration of authenticators that have the Always UV feature enabled by default.
-
-
If the authenticator is protected by some form of user verification or the alwaysUv option ID is present and
true
:-
If either of
pinUvAuthParam
orpinUvAuthProtocol
are missing from the input map, then end the operation by returning CTAP2_ERR_PUAT_REQUIRED.-
End the operation by returning CTAP2_ERR_OPERATION_DENIED.
-
-
Call
verify(pinUvAuthToken, 32×0xff || 0x0d || uint8(subCommand) || subCommandParams, pinUvAuthParam)
.-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Check whether the pinUvAuthToken has the acfg permission. If not, return CTAP2_ERR_PIN_AUTH_INVALID.
-
- Invoke
subCommand
(see below subsections for each defined subcommand), passing it the subCommandParams map. -
Return the resulting status code as produced by
subCommand
, as defined in each subcommand subsection below.
Note: User verification is only checked above if user verification is configured on a device. This implies that authenticatorConfig
can be invoked without user verification if user verification is not configured, and the Always UV feature is disabled. This allows organisations to configure authenticators suitably for their environment before distributing them to users. See also authenticatorLargeBlobs.
6.11.1. Enable Enterprise Attestation
This enableEnterpriseAttestation
subcommand is only implemented if the enterprise attestation feature is supported. This subcommand does not take any parameters: subCommandParams
is ignored.
This subcommand performs the following steps:
-
If the enterprise attestation feature is disabled, then re-enable the enterprise attestation feature and return CTAP2_OK.
Note: Upon re-enabling the enterprise attestation feature, the authenticator will return an ep option id with the value of
true
in the authenticatorGetInfo command response upon receipt of subsequent authenticatorGetInfo commands. -
Else (implying the enterprise attestation feature is enabled) take no action and return CTAP2_OK.
6.11.2. Toggle Always Require User Verification
This toggleAlwaysUv
subcommand is only implemented if the Always Require User Verification feature is supported. This subcommand does not take any parameters: subCommandParams
is ignored.
This subcommand performs the following steps:
-
If the alwaysUv feature is disabled:
-
If the makeCredUvNotRqd option ID is present and
true
, then disable the makeCredUvNotRqd feature and set the makeCredUvNotRqd option ID tofalse
or absent. -
Enable the alwaysUv feature and return CTAP2_OK.
Note: Upon enabling the Always Require User Verification feature, the authenticator will return an alwaysUv option ID with the value of
true
in the authenticatorGetInfo command response upon receipt of subsequent authenticatorGetInfo commands. -
-
Else (implying the alwaysUv feature is enabled)
-
If disabling the feature is supported:
-
Set the makeCredUvNotRqd option ID to its default.
-
Disable the alwaysUv feature and return CTAP2_OK.
-
-
Else return CTAP2_ERR_OPERATION_DENIED.
Note: Authenticators SHOULD support users disabling the Always Require User Verification feature unless required not to by specific external certifications such as [CMVP].
-
6.11.3. Vendor Prototype Command
This subCommand allows vendors to test authenticator configuration features.
This vendorPrototype
subcommand is only implemented if the vendorPrototypeConfigCommands member in the authenticatorGetInfo response is present.
Vendors SHOULD place implemented vendorCommandId values in the vendorPrototypeConfigCommands array.
subCommandParams Fields:
Field name | Data type | Required? | Definition |
---|---|---|---|
vendorCommandId (0x01) | Unsigned Integer | Required |
Vendor-assigned command ID
Note: If, and only if, this vendorCommandId (0x01) appears in this subCommandParams map and has a non-empty value, then other fields MAY also appear in the map, the map keys and associated values of which are vendor-defined. |
This subCommand MUST include a subCommandParams map that MUST contain vendorCommandId as a member.
The vendor randomly selects a 64-bit Unsigned Integer value to use for the value of vendorCommandId, e.g., by using a cryptographic random number generator. An example of such a vendorCommandId value is (in hex): 0x4e5a15aa89d2b8b6
. This approach avoids collisions amongst different vendors' vendorCommandIds. Thus there is no need for a registry of vendorCommandId values. One way to easily generate such values is by using the commonly available openssl tool.
This subCommand performs the following steps:
-
If the vendorCommandId value is unknown:
-
return CTAP2_ERR_INVALID_SUBCOMMAND
-
-
Else: (implying the vendorCommandId value is known)
-
Extract any additional members form the subCommandParams map.
-
Perform Vendor Command specific processing and return any status code it generates. Success MUST be indicated by returning CTAP2_OK.
Note: Vendors MUST NOT count on obscurity of the vendorCommandId value as any sort of security.
-
6.11.4. Setting a minimum PIN Length
This setMinPINLength
subcommand is only implemented if the setMinPINLength option ID is present.
This command sets the minimum PIN length in Unicode code points to be enforced by the authenticator while changing/setting up a ClientPIN.
Note: This is not applicable for any other type of PIN functionality the authenticator may have.
subCommandParams
members defined for this subcommand:
Parameter name | Data type | Required? | Definition |
---|---|---|---|
newMinPINLength (0x01) | Unsigned Integer | Optional | Minimum PIN length in code points |
minPinLengthRPIDs (0x02) | Array of strings | Optional | RPIDs which are allowed to get this information via the minPinLength extension. This parameter MUST NOT be used unless the minPinLength extension is supported. |
forceChangePin (0x03) | Boolean | Optional | The authenticator returns CTAP2_ERR_PIN_POLICY_VIOLATION until changePIN is successful. |
-
Platform sends the following subCommandParams (0x03) map containing following parameters:
-
newMinPINLength (0x01) (Optional): Minimum PIN length in code points
-
minPinLengthRPIDs (0x02) (Optional): List of RPIDs allowed to get the current newMinPINLength via minPinLength extension.
-
forceChangePin (0x03) (Optional): If
true
a PIN change is required after this command.
-
-
Authenticator performs following operations upon receiving the request:
-
If newMinPINLength is absent, then let newMinPINLength be present with the value of current minimum PIN length.
-
If minPinLengthRPIDs is present and the authenticator does not support the minPinLength extension, return CTAP1_ERR_INVALID_PARAMETER.
-
If newMinPINLength is less than the current minimum PIN length, return CTAP2_ERR_PIN_POLICY_VIOLATION.
Note: Minimum PIN lengths may only be increased; they cannot be made shorter.
NOTE: The authenticator must be reset to return the current minimum PIN length to the pre-configured minimum PIN length.
-
If the value of forceChangePin is
true
, then:-
If the value of clientPIN is
false
, then return CTAP2_ERR_PIN_NOT_SET. -
Let the value of the forcePINChange authenticatorGetInfo response member be
true
.Note: This will force the user to change their PIN upon the next use of the authenticator, if a PIN is set.
-
-
If the value of PINCodePointLength is less than newMinPINLength and the value of clientPIN is
true
then let the value of forcePINChange betrue
. -
Authenticator stores newMinPINLength as minPINLength.
-
If minPinLengthRPIDs is present and contains at least one string, then:
-
If the authenticator does not have a pre-configured list of RP IDs authorized to receive the current minimum PIN length value, the authenticator stores the minPinLengthRPIDs parameter’s list as the entire list of RP IDs authorized to receive the current minimum PIN length value.
-
Otherwise, if the authenticator has a pre-configured list of RP IDs authorized to receive the current minimum PIN length value, it adds the minPinLengthRPIDs parameter’s list to the immutable pre-configured list. Any previously added RP IDs are overwritten.
Note: How the authenticator "adds" the minPinLengthRPIDs parameter’s list to the pre-configured list is an implementation detail.
-
If Authenticator cannot store or add the minPinLengthRPIDs, it returns CTAP2_ERR_KEY_STORE_FULL.
-
-
Authenticator returns CTAP2_OK.
-
6.12. Prototype authenticatorBioEnrollment (0x40) (For backwards compatibility with "FIDO_2_1_PRE")
This superseded command is OPTIONAL and ONLY provided for backwards compatibility with platforms that implemented "FIDO_2_1_PRE" functionality, and have not been updated to "FIDO_2_1". CTAP2.1 platforms MUST NOT use this command if bioEnroll option ID is present in the authenticatorGetInfo response.
If a CTAP2.1 authenticator implements this prototype (0x40) command:
-
The authenticator MUST also implement the authenticatorBioEnrollment (0x09) commands.
-
The authenticator MUST provide the bioEnroll option ID in the authenticatorGetInfo response for feature detection of the CTAP2.1 feature.
The feature detection logic for the Bio Enrollment Prototype vendor specific feature is:
-
"FIDO_2_1_PRE" is present in the authenticatorGetInfo response versions member.
-
The userVerificationMgmtPreview option ID in the authenticatorGetInfo response is present and
true
.
This preview command does not require permissions, thus it is compatible with a pinUvAuthToken generated by the getPinToken command. CTAP 2.1 platforms MUST use the newer authenticatorBioEnrollment (0x09) command if the authenticator supports it.
6.13. Prototype authenticatorCredentialManagement (0x41) (For backwards compatibility with "FIDO_2_1_PRE" )
This superseded command is OPTIONAL and ONLY provided for backwards compatibility with platforms that implemented "FIDO_2_1_PRE" functionality, and have not been updated to "FIDO_2_1". CTAP2.1 platforms MUST NOT use this command if credMgmt option ID is present in the authenticatorGetInfo response.
If a CTAP2.1 authenticator implements this prototype (0x41) command:
-
The authenticator MUST also implement the authenticatorCredentialManagement (0x0A) commands.
-
The authenticator MUST provide the credMgmt option ID in the authenticatorGetInfo response for feature detection of the CTAP2.1 feature.
The feature detection logic for the Credential Management Prototype vendor specific feature is:
-
"FIDO_2_1_PRE" is present in the authenticatorGetInfo response versions member.
-
The credentialMgmtPreview option ID in the authenticatorGetInfo response is present and
true
.
This preview command does not require permissions, thus it is compatible with a pinUvAuthToken generated by the getPinToken command. CTAP 2.1 platforms MUST use the newer authenticatorCredentialManagement (0x0A) command if the authenticator supports it.
7. Feature-Specific Descriptions and Actions
This section provides detailed descriptions of specific features along with normative feature-specific platform (and possibly authenticator) actions whose specification is not appropriate to include in other parts of this specification.
7.1. Enterprise Attestation
An enterprise is some form of organization, often a business entity. An enterprise context is in effect when a device, e.g., a computer, an authenticator, etc., is controlled by an enterprise.
An enterprise attestation is an attestation that may include uniquely identifying information. This is intended for controlled deployments within an enterprise where the organization wishes to tie registrations to specific authenticators.
The expectation is that enterprises will work directly with their authenticator vendor(s) in order to source their enterprise attestation capable authenticators.
An enterprise attestation capable authenticator may be configured to support either or both:
-
Vendor-facilitated enterprise attestation:
In this case, an enterprise attestation capable authenticator, on which enterprise attestation is enabled, upon receiving the
enterpriseAttestation
parameter with a value of 1 (or 2, see Note below) on aauthenticatorMakeCredential
command, will provide enterprise attestation to a non-updateable pre-configured RP ID list, as identified by the enterprise and provided to the authenticator vendor, which is "burned into" the authenticator by the vendor.If enterprise attestation is requested for any RP ID other than the pre-configured RP ID(s), the attestation returned along with the new credential is a regular privacy-preserving attestation, i.e., NOT an enterprise attestation.
-
Platform-managed enterprise attestation:
In this case, an enterprise attestation capable authenticator on which enterprise attestation is enabled, upon receiving the
enterpriseAttestation
parameter with a value of 2 on aauthenticatorMakeCredential
command, will return an enterprise attestation. The platform is enterprise-managed and has already performed the necessary vetting of the RPID.Note: Authenticators wishing to support only vendor-facilitated enterprise attestation MAY treat
enterpriseAttestation = 2
the same asenterpriseAttestation = 1
.
7.1.1. Feature detection
The ep option ID in the authenticatorGetInfo response defines feature support detection for this feature.
7.1.2. Platform Actions
A platform wishing to obtain an enterprise attestation, e.g., when running in an enterprise context, SHOULD invoke the authenticatorMakeCredential
operation in the following manner:
-
Invoke the
authenticatorGetInfo
command and examine the returned response structure for the ep Option ID. If ep is not present or present and set to false, the platform SHOULD either terminate these steps or invoke theauthenticatorMakeCredential
command without theenterpriseAttestation
parameter, and skip the following steps. -
Invoke the
authenticatorMakeCredential
command and pass theenterpriseAttestation
parameter with a value of either 1 or 2. -
If the platform is operating in a non-enterprise context, it SHOULD display an explicit warning to the user, including the RPID, notifying the user that they are being uniquely identified to this Relying Party.
7.1.3. Authenticator Actions
If an enterprise attestation capable authenticator receives an authenticatorReset command, it MUST disable the enterprise attestation feature. The enterprise attestation feature may be re-enabled by invoking the authenticatorConfig command’s enable-enterprise-attestation subcommand.
7.2. Always Require User Verification
This feature allows a user to protect the credentials on their authenticator with some form of user verification independent of the Relying Party requesting some form of user verification in its higher-level API request, e.g., via [WebAuthn].
Platform authenticators and other authenticators with the alwaysUv feature enabled will always perform user verification and set the "uv" bit to true
in the response, e.g., even if the Relying Party sets user verification to Discouraged
in a [WebAuthn] request.
Some external certification programs such as [CMVP] for [FIPS140-3] prohibit the authenticator performing signing operations without authentication. This feature allows authenticators to conform to such non FIDO certification requirements.
Note: Platform authenticators typically provide users and platforms this sort of behaviour via private API.
7.2.1. Feature detection
The alwaysUv option ID in the authenticatorGetInfo response defines feature support detection for this feature.
7.2.2. Platform Actions
-
If the feature is supported and enabled: (alwaysUv is present and
true
)-
The platform SHOULD treat all Relying Party requests (e.g., those being made by a Relying Party via [WebAuthn] or a platform API) as requiring user verification.
-
If the authenticator is not protected by some form of user verification, the platforms SHOULD help users enroll a clientPin and or a built-in user verification method, if either or both are supported.
-
-
Platforms may enable or disable this feature by invoking the authenticatorConfig command’s toggleAlwaysUv subcommand.
7.2.3. Authenticator Actions
-
If the feature is supported and enabled: (alwaysUv is present and
true
)-
The authenticator MUST require some form of user verification for the authenticatorMakeCredential and authenticatorGetAssertion commands.
-
Authenticators supporting CTAP1/U2F MUST protect the credentials with built-in user verification methods, or disable CTAP1/U2F when the alwaysUv option ID is present and
true
. -
If the "uv" bit set in the response is
false
some authenticators conforming to [FIPS140-3] or other security requirements may return an syntactically-correct but invalid signature (i.e., one that no credential public key minted by this authenticator, now or ever, will match) rather than the private key from the selected credential. An example for a ECDSA signature is to return a fixed value of (1, 1). Thus the returned signature will not be verifiable, which is up to the Relying Party to handle. This approach avoids returning an error to the platform because doing that would interfere with some platforms' approach of "pre-flighting" the allowList or excludeList.
-
-
If the feature is supported and disabled: (alwaysUv is present and
false
)-
The authenticator does not always require user verification for its operations. It is dependent on the parameters passed to individual operations as specified herein.
-
-
After an authenticator reset:
-
Set the makeCredUvNotRqd option ID to its default.
-
7.2.4. Disabling CTAP1/U2F
Authenticators MUST disable CTAP1/U2F when the alwaysUv option ID is present and true
in the authenticatorGetInfo response, unless the CTAP1/U2F authenticator is protected by a built-in user verification method. When CTAP1/U2F is disabled:
-
The authenticator MUST NOT return "U2F_V2" in the versions array.
-
The U2F_REGISTER and U2F_AUTHENTICATE commands MUST immediately fail and return SW_COMMAND_NOT_ALLOWED.
7.3. Authenticator Certifications
The certifications member provides a hint to the platform with additional information about certifications that the authenticator has received. Certification programs may revoke certification of specific devices at any time. Relying partys are responsible for validating attestations and AAGUID via appropriate methods. Platforms may alter their behaviour based on these hints such as selecting a PIN protocol or credProtect level.
7.3.1. Authenticator Actions
An authenticator’s supported certifications MAY be returned in the certifications member of an authenticatorGetInfo response.
All certifications are in the form key-value pairs with string IDs and integer values. The following table lists all defined certification types as of CTAP version "FIDO_2_1":
certification ID | Definition |
---|---|
FIPS-CMVP-2 | The [FIPS140-2] Cryptographic-Module-Validation-Program overall certification level. This is a integer from 1 to 4. |
FIPS-CMVP-3 | The [FIPS140-3] [CMVP] or ISO/IEC 19790:2012(E) and ISO/IEC 24759:2017(E) overall certification level. This is a integer from 1 to 4. |
FIPS-CMVP-2-PHY | The [FIPS140-2] Cryptographic-Module-Validation-Program physical certification level. This is a integer from 1 to 4. |
FIPS-CMVP-3-PHY | The [FIPS140-3] [CMVP] or ISO/IEC 19790:2012(E) and ISO/IEC 24759:2017(E) physical certification level. This is a integer from 1 to 4. |
CC-EAL | Common Criteria Evaluation Assurance Level [CC1V3-1R5]. This is a integer from 1 to 7. The intermediate-plus levels are not represented. |
FIDO | FIDO Alliance certification level. This is an integer from 1 to 6. The numbered levels are mapped to the odd numbers, with the plus levels mapped to the even numbers eg level 3+ is mapped to 6. |
7.4. Set Minimum PIN Length
This feature allows a Relying Party (e.g., an enterprise) to enforce a minimum pin length policy for authenticators registering credentials by examining the return value of the Minimum PIN Length Extension (minPinLength). The authenticatorConfig command’s setMinPINLength subCommand allows the platform to set the minimum pin length policy for authenticator, force a change of PIN before allowing User Verification, and setting the list of minPinLengthRPIDs that allow the specified RPID to receive the extension response.
If this feature is supported:
-
The authenticator MUST implement the setMinPINLength subCommand of the authenticatorConfig command.
-
The authenticator MUST implement the Minimum PIN Length Extension (minPinLength).
7.4.1. Feature detection
The setMinPinLength option ID in the authenticatorGetInfo response defines feature support detection for this feature.
7.4.2. Platform Actions
Note: Because ClientPIN must be implemented for this set minimum PIN length feature to be implemented, basic minimum PIN length enforcement already occurs. This feature is only about providing for the minimum PIN length to be altered from its pre-configured value.
-
If the forcePINChange member of the authenticatorGetInfo response is present and
true
:-
The platform should guide the user to change the PIN before invoking the getPinToken or getPinUvAuthTokenUsingPinWithPermissions subcommands.
-
-
Platforms may perform the following actions by invoking the authenticatorConfig command’s setMinPINLength subcommand:
-
Increase the minimum pin length for clientPin.
-
Set the minPinLengthRPIDs parameter’s list to allow Relying Parties receiving the minPinLength extension.
-
Set the authenticator to require a PIN change before allowing clientPin based authentication.
-
7.4.3. Authenticator Actions
-
If this feature is enabled the extension identifier minpinlength in the extensions member of the authenticatorGetInfo response MUST be present.
-
After an authenticator reset:
-
Set the minPINLength member of the authenticatorGetInfo response to its default pre-configured minimum PIN length.
-
Set the minPinLengthRPIDs parameter’s list to the immutable pre-configured list, if any. Any previously added RP IDs are removed.
-
8. Message Encoding
Many transports (e.g., Bluetooth Smart) are bandwidth-constrained, and serialization formats such as JSON are too heavy-weight for such environments. For this reason, all encoding is done using the concise binary encoding CBOR [RFC7049].
To reduce the complexity of the messages and the resources required to parse and validate them, all messages MUST use the CTAP2 canonical CBOR encoding form as specified below, which differs from the canonicalization suggested in Section 3.9 of [RFC7049]. All encoders MUST serialize CBOR in the CTAP2 canonical CBOR encoding form without duplicate map keys. All decoders SHOULD reject CBOR that is not validly encoded in the CTAP2 canonical CBOR encoding form and SHOULD reject messages with duplicate map keys.
The CTAP2 canonical CBOR encoding form uses the following rules:
-
Integers must be encoded as small as possible.
-
0 to 23 and -1 to -24 must be expressed in the same byte as the major type;
-
24 to 255 and -25 to -256 must be expressed only with an additional uint8_t;
-
256 to 65535 and -257 to -65536 must be expressed only with an additional uint16_t;
-
65536 to 4294967295 and -65537 to -4294967296 must be expressed only with an additional uint32_t.
-
-
The representations of any floating-point values are not changed.
Note: The size of a floating point value—16-, 32-, or 64-bits—is considered part of the value for the purpose of CTAP2. E.g., a 16-bit value of 1.5, say, has different semantic meaning than a 32-bit value of 1.5, and both can be canonical for their own meanings.
-
The expression of lengths in major types 2 through 5 must be as short as possible. The rules for these lengths follow the above rule for integers.
-
Indefinite-length items must be made into definite-length items.
-
The keys in every map must be sorted lowest value to highest. The sorting rules are:
-
If the major types are different, the one with the lower value in numerical order sorts earlier.
-
If two keys have different lengths, the shorter one sorts earlier;
-
If two keys have the same length, the one with the lower value in (byte-wise) lexical order sorts earlier.
Note: These rules are equivalent to a lexicographical comparison of the canonical encoding of keys for major types 0-3 and 7 (integers, strings, and simple values). They differ for major types 4-6 (arrays, maps, and tags), which CTAP2 does not use as keys in maps. These rules should be revisited if CTAP2 does start using the complex major types as keys.
-
-
Tags as defined in Section 2.4 in [RFC7049] MUST NOT be present.
Because some authenticators are memory constrained, the depth of nested CBOR structures used by all message encodings is limited to at most four (4) levels of any combination of CBOR maps and/or CBOR arrays. Authenticators MUST support at least 4 levels of CBOR nesting. Clients, platforms, and servers MUST NOT use more than 4 levels of CBOR nesting.
Likewise, because some authenticators are memory constrained, the maximum message size supported by an authenticator MAY be limited. By default, authenticators MUST support messages of at least 1024 bytes. Authenticators MAY declare a different maximum message size supported using the maxMsgSize authenticatorGetInfo result parameter. Clients, platforms, and servers MUST NOT send messages larger than 1024 bytes unless the authenticator’s maxMsgSize indicates support for the larger message size. Authenticators MAY return the CTAP2_ERR_REQUEST_TOO_LARGE error if size or memory constraints are exceeded.
If map keys are present that an implementation does not understand, they MUST be ignored. Note that this enables additional fields to be used as new features are added without breaking existing implementations.
Messages from the host to authenticator are called "commands" and messages from authenticator to host are called "replies". All values are big endian encoded.
Authenticators SHOULD return the CTAP2_ERR_INVALID_CBOR error if received CBOR does not conform to the requirements above.
8.1. Command Codes
The assigned values for vendor specific commands and their descriptions are:
Command Name | Command Code | Has parameters? |
---|---|---|
authenticatorVendorFirst | 0x40 | NA |
Vendor - Bio Enrollment Prototype | 0x40 | yes |
Vendor - Credential Management Prototype | 0x41 | yes |
authenticatorVendorLast | 0xBF | NA |
If an authenticator receives a command code it does not implement, it MUST return CTAP1_ERR_INVALID_COMMAND. If the authenticator implements a command code having subcommands, but does not implement an invoked subcommand, it MUST return CTAP2_ERR_INVALID_SUBCOMMAND.
Note: Some authenticators implementing earlier versions of this specification may not behave as specified by the prior paragraph, because this behavior was only implied at that time.
Command codes in the range between authenticatorVendorFirst and authenticatorVendorLast may be used for vendor-specific implementations. For example, the vendor may choose to put in some testing commands. Note that the FIDO client will never generate these commands. All other command codes are reserved for future use and may not be used.
Command parameters are encoded using a CBOR map (CBOR major type 5). The CBOR map must be encoded using the definite length variant.
Some commands have optional parameters. Therefore, the length of the parameter map for these commands may vary. For example, authenticatorMakeCredential may have 4, 5, 6, or 7 parameters, while authenticatorGetAssertion may have 2, 3, 4, or 5 parameters.
All command parameters are CBOR encoded following the JSON to CBOR conversion procedures as per the CBOR specification [RFC7049]. Specifically, parameters that are represented as DOM objects in the Authenticator API layers (formally defined in the Web API [WebAuthn]) are converted first to JSON and subsequently to CBOR.
8.2. Status codes
The error response values range from 0x01 - 0xff. This range is split based on error type.
Error response values in the range between CTAP2_OK and CTAP2_ERR_SPEC_LAST are reserved for spec purposes.
Error response values in the range between CTAP2_ERR_VENDOR_FIRST and CTAP2_ERR_VENDOR_LAST may be used for vendor-specific implementations. All other response values are reserved for future use and may not be used. These vendor specific error codes are not interoperable and the platform should treat these errors as any other unknown error codes.
Error response values in the range between CTAP2_ERR_EXTENSION_FIRST and CTAP2_ERR_EXTENSION_LAST may be used for extension-specific implementations. These errors need to be interoperable for vendors who decide to implement such optional extension.
Code | Name | Description |
---|---|---|
0x00 | CTAP1_ERR_SUCCESS, CTAP2_OK | Indicates successful response. |
0x01 | CTAP1_ERR_INVALID_COMMAND | The command is not a valid CTAP command. |
0x02 | CTAP1_ERR_INVALID_PARAMETER | The command included an invalid parameter. |
0x03 | CTAP1_ERR_INVALID_LENGTH | Invalid message or item length. |
0x04 | CTAP1_ERR_INVALID_SEQ | Invalid message sequencing. |
0x05 | CTAP1_ERR_TIMEOUT | Message timed out. |
0x06 | CTAP1_ERR_CHANNEL_BUSY | Channel busy. Client SHOULD retry the request after a short delay. Note that the client may abort the transaction if the command is no longer relevant. |
0x0A | CTAP1_ERR_LOCK_REQUIRED | Command requires channel lock. |
0x0B | CTAP1_ERR_INVALID_CHANNEL | Command not allowed on this cid. |
0x11 | CTAP2_ERR_CBOR_UNEXPECTED_TYPE | Invalid/unexpected CBOR error. |
0x12 | CTAP2_ERR_INVALID_CBOR | Error when parsing CBOR. |
0x14 | CTAP2_ERR_MISSING_PARAMETER | Missing non-optional parameter. |
0x15 | CTAP2_ERR_LIMIT_EXCEEDED | Limit for number of items exceeded. |
0x17 | CTAP2_ERR_FP_DATABASE_FULL | Fingerprint data base is full, eg during enrollment. |
0x18 | CTAP2_ERR_LARGE_BLOB_STORAGE_FULL | Large blob storage is full. (See § 6.10.3 Large, per-credential blobs.) |
0x19 | CTAP2_ERR_CREDENTIAL_EXCLUDED | Valid credential found in the exclude list. |
0x21 | CTAP2_ERR_PROCESSING | Processing (Lengthy operation is in progress). |
0x22 | CTAP2_ERR_INVALID_CREDENTIAL | Credential not valid for the authenticator. |
0x23 | CTAP2_ERR_USER_ACTION_PENDING | Authentication is waiting for user interaction. |
0x24 | CTAP2_ERR_OPERATION_PENDING | Processing, lengthy operation is in progress. |
0x25 | CTAP2_ERR_NO_OPERATIONS | No request is pending. |
0x26 | CTAP2_ERR_UNSUPPORTED_ALGORITHM | Authenticator does not support requested algorithm. |
0x27 | CTAP2_ERR_OPERATION_DENIED | Not authorized for requested operation. |
0x28 | CTAP2_ERR_KEY_STORE_FULL | Internal key storage is full. |
0x2B | CTAP2_ERR_UNSUPPORTED_OPTION | Unsupported option. |
0x2C | CTAP2_ERR_INVALID_OPTION | Not a valid option for current operation. |
0x2D | CTAP2_ERR_KEEPALIVE_CANCEL | Pending keep alive was cancelled. |
0x2E | CTAP2_ERR_NO_CREDENTIALS | No valid credentials provided. |
0x2F | CTAP2_ERR_USER_ACTION_TIMEOUT | A user action timeout occurred. |
0x30 | CTAP2_ERR_NOT_ALLOWED | Continuation command, such as, authenticatorGetNextAssertion not allowed. |
0x31 | CTAP2_ERR_PIN_INVALID | PIN Invalid. |
0x32 | CTAP2_ERR_PIN_BLOCKED | PIN Blocked. |
0x33 | CTAP2_ERR_PIN_AUTH_INVALID | PIN authentication,pinUvAuthParam, verification failed. |
0x34 | CTAP2_ERR_PIN_AUTH_BLOCKED | PIN authentication using pinUvAuthToken blocked. Requires power cycle to reset. |
0x35 | CTAP2_ERR_PIN_NOT_SET | No PIN has been set. |
0x36 | CTAP2_ERR_PUAT_REQUIRED | A pinUvAuthToken is required for the selected operation. See also the pinUvAuthToken option ID. |
0x37 | CTAP2_ERR_PIN_POLICY_VIOLATION | PIN policy violation. Currently only enforces minimum length. |
0x38 | CTAP2_ERR_PIN_TOKEN_EXPIRED | pinUvAuthToken expired on authenticator. |
0x39 | CTAP2_ERR_REQUEST_TOO_LARGE | Authenticator cannot handle this request due to memory constraints. |
0x3A | CTAP2_ERR_ACTION_TIMEOUT | The current operation has timed out. |
0x3B | CTAP2_ERR_UP_REQUIRED | User presence is required for the requested operation. |
0x3C | CTAP2_ERR_UV_BLOCKED | built-in user verification is disabled. |
0x3D | CTAP2_ERR_INTEGRITY_FAILURE | A checksum did not match. |
0x3E | CTAP2_ERR_INVALID_SUBCOMMAND | The requested subcommand is either invalid or not implemented. |
0x3F | CTAP2_ERR_UV_INVALID | built-in user verification unsuccessful. The platform should retry. |
0x40 | CTAP2_ERR_UNAUTHORIZED_PERMISSION | The permissions parameter contains an unauthorized permission. |
0x7F | CTAP1_ERR_OTHER | Other unspecified error. |
0xDF | CTAP2_ERR_SPEC_LAST | CTAP 2 spec last error. |
0xE0 | CTAP2_ERR_EXTENSION_FIRST | Extension specific error. |
0xEF | CTAP2_ERR_EXTENSION_LAST | Extension specific error. |
0xF0 | CTAP2_ERR_VENDOR_FIRST | Vendor specific error. |
0xFF | CTAP2_ERR_VENDOR_LAST | Vendor specific error. |
8.3. Utility functions
This protocol uses the following utility functions for encoding various values in various algorithms:
- uint8(x)
-
Returns the least-significant eight bits of x as a single byte.
- uint32LittleEndian(x)
-
Returns a sequence of four bytes whose values are the least-significant eight bits of x, x >> 8, x >> 16, and x >> 24, respectively.
- uint64LittleEndian(x)
-
Returns a sequence of eight bytes whose values are the least-significant eight bits of x, x >> 8, x >> 16, x >> 24, x >> 32, x >> 40, x >> 48, x >> 56, respectively.
9. Mandatory features
Authenticators that include FIDO_2_1
in versions:
-
MUST support the hmac-secret extension.
-
MUST include the clientPin option ID or the uv option ID (or both), with the value
true
, in the authenticatorGetInfo response’s options member if the rk option ID has the valuetrue
. -
MUST either include the credMgmt option ID with the value
true
in the authenticatorGetInfo response’s options member, or support all the same functionality via a built-in UI, if the rk option ID has the valuetrue
. -
MUST support the credProtect extension if some form of user verification is supported, unless all credentials are implicitly created at credProtect level three.
-
MUST include the pinUvAuthToken option ID with the value
true
in the authenticatorGetInfo response’s options member if either the clientPin or uv option IDs have the valuetrue
. -
MUST include an array element with the value
2
in the authenticatorGetInfo response’s pinUvAuthProtocols member (i.e. support PIN/UV auth protocol two) if it includes any values at all.
10. Interoperating with CTAP1/U2F authenticators
This section defines:
-
How a platform maps a subset of CTAP2 requests to CTAP1/U2F requests and, conversely, how it maps the CTAP1/U2F responses to CTAP2 responses. (Only requests that do not require CTAP2-only features can be so mapped.)
-
How RPs verify CTAP1/U2F-based authenticatorMakeCredential and authenticatorGetAssertion responses.
-
How authenticators allow credentials to be exposed via both CTAP2 and CTAP1/U2F.
Platforms MAY implement support for CTAP1/U2F, but authenticators SHOULD support it. Not supporting U2F may result in an authenticator that does not function on all websites and thus may appear to be broken to users. Thus authenticators that do not support CTAP1/U2F are not suitable for sale to the general public but may be manufactured for specific cases where it is known that CTAP1/U2F support is unnecessary.
10.1. Framing of U2F commands
The U2F protocol is based on a request-response mechanism, where a requester sends a request message to a U2F device, which always results in a response message being sent back from the U2F device to the requester.
The request message has to be "framed" to send to the lower layer. Taking the signature request as an example, the "framing" is a way for the FIDO client to tell the lower transport layer that it is sending a signature request and then send the raw message contents. The framing also specifies how the transport will carry back the response raw message and any meta-information such as an error code if the command failed.
In this current version of U2F, the framing is defined based on the ISO7816-4:2005 extended APDU format. This is very appropriate for the USB transport since devices are typically built around secure elements which understand this format already. This same argument may apply for futures such as Bluetooth based devices. For other futures based on other transports, such as a built-in u2f token on a mobile device TEE, this framing may not be appropriate, and a different framing may need to be defined.
10.1.1. U2F Request Message Framing
The raw request message is framed as a command APDU:
CLA | INS | P1 | P2 | LC1 | LC2 | LC3 |
Where:
CLA: Reserved to be used by the underlying transport protocol (if applicable). The host application shall set this byte to zero.
INS: U2F command code, defined in the following sections.
P1, P2: Parameter 1 and 2, defined by each command.
LC1-LC3: Length of the request data, big-endian coded, i.e. LC1 being MSB and LC3 LSB
10.1.2. U2F Response Message Framing
The raw response data is framed as a response APDU:
SW1 | SW2 |
Where:
SW1, SW2: Status word bytes 1 and 2, forming a 16-bit status word, defined below. SW1 is MSB and SW2 LSB.
Status Codes
The following ISO7816-4 defined status words have a special meaning in U2F:
SW_NO_ERROR: The command completed successfully without error.
SW_CONDITIONS_NOT_SATISFIED: The request was rejected due to test-of-user-presence being required.
SW_WRONG_DATA: The request was rejected due to an invalid key handle.
SW_COMMAND_NOT_ALLOWED: The command is not allowed at this time, e.g. because U2F is disabled.
Each implementation may define any other vendor-specific status codes, providing additional information about an error condition. Only the error codes listed above will be handled by U2F FIDO clients, whereas others will be seen as general errors and logging of these is optional.
10.2. Using the CTAP2 authenticatorMakeCredential Command with CTAP1/U2F authenticators
Platform follows the following procedure (Fig: Mapping: WebAuthn authenticatorMakeCredential to and from CTAP1/U2F Registration Messages):
-
Platform tries to get information about the authenticator by sending authenticatorGetInfo command as specified in CTAP2 protocol overview.
-
CTAP1/U2F authenticator returns a command error or improperly formatted CBOR response. For any failure, platform may fall back to CTAP1/U2F protocol.
-
-
Map CTAP2 authenticatorMakeCredential request to U2F_REGISTER request.
-
Platform verifies that CTAP2 request does not have any parameters that CTAP1/U2F authenticators cannot fulfill.
-
All of the below conditions must be true for the platform to proceed to next step. If any of the below conditions is not true, platform errors out with CTAP2_ERR_UNSUPPORTED_OPTION.
-
pubKeyCredParams must use the ES256 algorithm (-7).
-
Options must not include "rk" set to true.
-
Options must not include "uv" set to true.
-
-
If excludeList is not empty:
-
If the excludeList is not empty, the platform must send signing request with check-only control byte to the CTAP1/U2F authenticator using each of the credential ids (key handles) in the excludeList. If any of them does not result in an error, that means that this is a known device. Afterwards, the platform must still send a dummy registration request (with a dummy appid and invalid challenge) to CTAP1/U2F authenticators that it believes are excluded. This makes it so the user still needs to touch the CTAP1/U2F authenticator before the RP gets told that the token is already registered.
-
-
-
Use clientDataHash parameter of CTAP2 request as CTAP1/U2F challenge parameter (32 bytes).
-
Let
rpIdHash
be a byte string of size 32 initialized with SHA-256 hash ofrp.id
parameter as CTAP1/U2F application parameter (32 bytes).
-
-
Send the U2F_REGISTER request to the authenticator as specified in [U2FRawMsgs] spec.
-
If the authenticator response message contains the status code SW_COMMAND_NOT_ALLOWED, U2F is disabled at this time. Abandon this operation. The platform SHOULD retry using CTAP2 if present in the versions array.
-
Map the U2F registration response message (see: FIDO U2F Raw Message Formats v1.2 §registration-response-message-success) to a CTAP2 authenticatorMakeCredential response message:
-
Generate
authenticatorData
from the U2F registration response message (FIDO U2F Raw Message Formats v1.2 §registration-response-message-success) received from the authenticator:-
Initialize
attestedCredData
:-
Let
credentialIdLength
be a 2-byte unsigned big-endian integer representing length of the Credential ID initialized with CTAP1/U2F response key handle length. -
Let
credentialId
be acredentialIdLength
byte string initialized with CTAP1/U2F response key handle bytes. -
Let
x9encodedUserPublicKey
be theuser public key
returned in the U2F registration response message [U2FRawMsgs]. LetcoseEncodedCredentialPublicKey
be the result of convertingx9encodedUserPublicKey
’s value from ANS X9.62 / Sec-1 v2 uncompressed curve point representation [SEC1V2] to COSE_Key representation ([RFC8152] Section 7). -
Let
attestedCredData
be a byte string with following structure:Length (in bytes) Description Value 16 The AAGUID of the authenticator. Initialized with all zeros. 2 Byte length L of Credential ID Initialized with credentialIdLength
bytes.credentialIdLength
Credential ID. Initialized with credentialId
bytes.77 The credential public key. Initialized with coseEncodedCredentialPublicKey
bytes. -
Initialize
authenticatorData
:-
Let
flags
be a byte whose zeroth bit (bit 0, UP) is set, and whose sixth bit (bit 6, AT) is set, and all other bits are zero (bit zero is the least significant bit). See also Authenticator Data section of [WebAuthn]. -
Let
signCount
be a 4-byte unsigned integer initialized to zero. -
Let
authenticatorData
be a byte string with the following structure:Length (in bytes) Description Value 32 SHA-256 hash of the rp.id
.Initialized with rpIdHash
bytes.1 Flags Initialized with flags
' value.4 Signature counter (signCount). Initialized with signCount
bytes.Variable Length Attested credential data. Initialized with attestedCredData
’s value.
-
-
-
-
Let
attestationStatement
be a CBOR map (see "attStmtTemplate" in Generating an Attestation Object [WebAuthn]) with the following keys, whose values are as follows:-
Set "x5c" as an array of the one attestation cert extracted from CTAP1/U2F response.
-
Set "sig" to be the "signature" bytes from the U2F registration response message [U2FRawMsgs]. Note: An ASN.1-encoded ECDSA signature value ranges over 8–72 bytes in length. [U2FRawMsgs] incorrectly states a different length range.
-
-
Let
attestationObject
be a CBOR map (see "attObj" in Generating an Attestation Object [WebAuthn]) with the following keys, whose values are as follows:-
Set "authData" to
authenticatorData
. -
Set "fmt" to "fido-u2f".
-
Set "attStmt" to
attestationStatement
.
-
-
-
Return
attestationObject
to the caller.
10.3. Using the CTAP2 authenticatorGetAssertion Command with CTAP1/U2F authenticators
Platform follows the following procedure (Fig: Mapping: WebAuthn authenticatorGetAssertion to and from CTAP1/U2F Authentication Messages):
-
Platform tries to get information about the authenticator by sending authenticatorGetInfo command as specified in CTAP2 protocol overview.
-
CTAP1/U2F authenticator returns a command error or improperly formatted CBOR response. For any failure, platform may fall back to CTAP1/U2F protocol.
-
-
Map CTAP2 authenticatorGetAssertion request to U2F_AUTHENTICATE request:
-
Platform verifies that CTAP2 request does not have any parameters that CTAP1/U2F authenticators cannot fulfill:
-
All of the below conditions must be true for the platform to proceed to next step. If any of the below conditions is not true, platform errors out with CTAP2_ERR_UNSUPPORTED_OPTION.
-
Options must not include "uv" set to true.
-
allowList must have at least one credential.
-
-
-
If allowList has more than one credential, platform has to loop over the list and send individual different U2F_AUTHENTICATE commands to the authenticator. For each credential in credential list, map CTAP2 authenticatorGetAssertion request to U2F_AUTHENTICATE as below:
-
Let
controlByte
be a byte initialized as follows:-
If "up" is set to false, set it to 0x08 (dont-enforce-user-presence-and-sign).
-
For USB, set it to 0x07 (check-only). This should prevent call getting blocked on waiting for user input. If response returns success, then call again setting the enforce-user-presence-and-sign.
-
For NFC, set it to 0x03 (enforce-user-presence-and-sign). The tap has already provided the presence and won’t block.
-
-
Use clientDataHash parameter of CTAP2 request as CTAP1/U2F challenge parameter (32 bytes).
-
Let
rpIdHash
be a byte string of size 32 initialized with SHA-256 hash ofrp.id
parameter as CTAP1/U2F application parameter (32 bytes). -
Let
credentialId
is the byte string initialized with the id for this PublicKeyCredentialDescriptor. -
Let
keyHandleLength
be a byte initialized with length ofcredentialId
byte string. -
Let
u2fAuthenticateRequest
be a byte string with the following structure:Length (in bytes) Description Value 32 Challenge parameter Initialized with clientDataHash parameter bytes. 32 Application parameter Initialized with rpIdHash
bytes.1 Key handle length Initialized with keyHandleLength
’s value.keyHandleLength
Key handle Initialized with credentialId
bytes.and let
Control Byte
be P1 of the framing.
-
-
-
Send
u2fAuthenticateRequest
to the authenticator. -
If the authenticator response message contains the status code SW_COMMAND_NOT_ALLOWED, U2F is disabled at this time. Abandon this operation. The platform SHOULD retry using CTAP2.
-
Map the U2F authentication response message (see the "Authentication Response Message: Success" section of [U2FRawMsgs]) to a CTAP2 authenticatorGetAssertion response message:
-
Generate
authenticatorData
from the U2F authentication response message received from the authenticator:-
Copy bits 0 (the UP bit) and bit 1 from the CTAP2/U2F response user presence byte to bits 0 and 1 of the CTAP2 flags, respectively. Set all other bits of flags to zero. Note: bit zero is the least significant bit. See also Authenticator Data section of [WebAuthn].
-
Let
signCount
be a 4-byte unsigned integer initialized with CTAP1/U2F response counter field. -
Let
authenticatorData
is a byte string of following structure:Length (in bytes) Description Value 32 SHA-256 hash of the rp.id
.Initialized with rpIdHash
bytes.1 Flags Initialized with flags
' value.4 Signature counter (signCount) Initialized with signCount
bytes.
-
-
Let
authenticatorGetAssertionResponse
be a CBOR map with the following keys whose values are as follows:-
Set 0x01 with the credential from allowList that whose response succeeded.
-
Set 0x02 with
authenticatorData
bytes. -
Set 0x03 with signature field from CTAP1/U2F authentication response message. Note: An ASN.1-encoded ECDSA signature value ranges over 8–72 bytes in length. [U2FRawMsgs] incorrectly states a different length range.
-
-
10.4. Cross-version Credential Compatibility
If an authenticator supports both CTAP1/U2F and CTAP2 then a credential created using CTAP1/U2F MUST be assertable over CTAP2. (Credentials created over CTAP1/U2F MUST NOT be discoverable credentials though.) From § 10.3 Using the CTAP2 authenticatorGetAssertion Command with CTAP1/U2F authenticators, this means that an authenticator MUST accept, over CTAP2, the credential ID of a credential that was created using U2F where the application parameter at the time of creation was the SHA-256 digest of the RP ID that is given at assertion time.
11. Transport-specific Bindings
11.1. Secure protocol implementation
In order to ensure that the interaction between the platform and any authenticators is secure, authenticators SHALL:
-
Ensure that all state (e.g. discoverable credentials, signature counters, PINs, etc) that is observable or alterable over FIDO interfaces is not observable or alterable over any other interfaces on transports that FIDO has defined.
-
Ensure that all non-discoverable credentials that are created over FIDO interfaces are not valid over any other interfaces on transports that FIDO has defined. (For example, if non-discoverable credentials store state in the credential ID, protected by an authenticator-global secret, then that secret must only be used for requests received over FIDO interfaces.)
Note: Above recommendations are also valid for future transports.
FIDO interfaces are defined as:
-
USB, when using USB HID and the FIDO_USAGE_PAGE/FIDO_USAGE_CTAPHID combination.
-
NFC, when the applet is selected as specified.
-
Authenticator SHALL NOT allow FIDO applet to be implicitly selected or enabled.
-
Recommended: Authenticator SHALL NOT have default applet selected on power cycle. All CTAP commands SHALL be preceded by an explicit applet selection command as described in Applet selection section.
-
Alternative: If authenticator has a FIDO applet selected for some reason at power cycle, it SHALL be in disabled mode and SHALL ONLY be enabled once it receives explicit applet selection command as described in Applet selection section.
-
-
Authenticator SHALL disable FIDO interface when it receives applet deselect command.
-
-
BLE, when using the FIDO GATT service.
11.2. USB Human Interface Device (USB HID)
See also § 11.1 Secure protocol implementation.11.2.1. Design rationale
CTAP messages are framed for USB transport using the HID (Human Interface Device) protocol. We henceforth refer to the protocol as CTAPHID. The CTAPHID protocol is designed with the following design objectives in mind
-
Driver-less installation on all major host platforms
-
Multi-application support with concurrent application access without the need for serialization and centralized dispatching.
-
Fixed latency response and low protocol overhead
-
Scalable method for CTAPHID device discovery
Since HID data is sent as interrupt packets and multiple applications may access the HID stack at once, a non-trivial level of complexity has to be added to handle this.
11.2.2. Protocol structure and data framing
The CTAP protocol is designed to be concurrent and state-less in such a way that each performed function is not dependent on previous actions. However, there has to be some form of "atomicity" that varies between the characteristics of the underlying transport protocol, which for the CTAPHID protocol introduces the following terminology:
-
Transaction
-
Message
-
Packet
A transaction is the highest level of aggregated functionality, which in turn consists of a request, followed by a response message. Once a request has been initiated, the transaction has to be entirely completed or aborted before a second transaction can take place and a response is never sent without a previous request. Transactions exist only at the highest CTAP protocol layer.
Request and response messages are in turn divided into individual fragments, known as packets. The packet is the smallest form of protocol data unit, which in the case of CTAPHID are mapped into HID reports.
11.2.3. Concurrency and channels
Additional logic and overhead is required to allow a CTAPHID device to deal with multiple "clients", i.e. multiple applications accessing the single resource through the HID stack. Each client communicates with a CTAPHID device through a logical channel, where each application uses a unique 32-bit channel identifier for routing and arbitration purposes.
A channel identifier is allocated by the FIDO authenticator to ensure its system-wide uniqueness. The actual algorithm for generation of channel identifiers is vendor specific and not defined by this specification.
Channel ID 0 is reserved and 0xffffffff
is reserved for
broadcast commands, i.e. at the time of channel allocation.
11.2.4. Message and packet structure
Packets are one of two types, initialization packets and continuation packets. As the name suggests, the first packet sent in a message is an initialization packet, which also becomes the start of a transaction. If the entire message does not fit into one packet (including the CTAPHID protocol overhead), one or more continuation packets have to be sent in strict ascending order to complete the message transfer.
A message sent from a host to a device is known as a request and a message sent from a device back to the host is known as a response. A request always triggers a response and response messages are never sent ad-hoc, i.e. without a prior request message. However, a keep-alive message can be sent between a request and a response message.
The request and response messages have an identical structure. A transaction is started with the initialization packet of the request message and ends with the last packet of the response message. The client starting a transaction may also abort it.
Packets are always fixed size (defined by the endpoint and HID report descriptors) and although all bytes may not be needed in a particular packet, the full size always has to be sent. Unused bytes SHOULD be set to zero.
An initialization packet is defined as
Offset | Length | Mnemonic | Description |
---|---|---|---|
0 | 4 | CID | Channel identifier |
4 | 1 | CMD | Command identifier (bit 7 always set) |
5 | 1 | BCNTH | High part of payload length |
6 | 1 | BCNTL | Low part of payload length |
7 | (s - 7) | DATA | Payload data (s is equal to the fixed packet size) |
The command byte has always the highest bit set to distinguish it from a continuation packet, which is described below.
A continuation packet is defined as
Offset | Length | Mnemonic | Description |
---|---|---|---|
0 | 4 | CID | Channel identifier |
4 | 1 | SEQ | Packet sequence 0x00..0x7f (bit 7 always cleared) |
5 | (s - 5) | DATA | Payload data (s is equal to the fixed packet size) |
With this approach, a message with a payload less or equal to (s - 7) may be sent as one packet. A larger message is then divided into one or more continuation packets, starting with sequence number 0, which then increments by one to a maximum of 127.
With a packet size of 64 bytes (max for full-speed devices), this means that the maximum message payload length is 64 - 7 + 128 * (64 - 5) = 7609 bytes.
11.2.5. Arbitration
In order to handle multiple channels and clients concurrency, the CTAPHID protocol has to maintain certain internal states, block conflicting requests and maintain protocol integrity. The protocol relies on each client application (channel) behaves politely, i.e. does not actively act to destroy for other channels. With this said, a malign or malfunctioning application can cause issues for other channels. Expected errors and potentially stalling applications should however, be handled properly.
11.2.5.1. Transaction atomicity, idle and busy states.
A transaction always consists of three stages:
-
A message is sent from the host to the device
-
The device processes the message
-
A response is sent back from the device to the host
The protocol is built on the assumption that a plurality of concurrent applications may try ad-hoc to perform transactions at any time, with each transaction being atomic, i.e. it cannot be interrupted by another application once started.
The application channel that manages to get through the first initialization packet when the device is in idle state will keep the device locked for other channels until the last packet of the response message has been received or the transaction is aborted. The device then returns to idle state, ready to perform another transaction for the same or a different channel. Between two transactions, the device might need to keep some state. A host application must assume that any other process may execute other transactions at any time and former state will be dropped.
If an application tries to access the device from a different channel while the device is busy with a transaction, that request will immediately fail with a busy-error message sent to the requesting channel.
11.2.5.2. Transaction timeout
A transaction has to be completed within a specified period of time to prevent a stalling application to cause the device to be completely locked out for access by other applications. If for example an application sends an initialization packet that signals that continuation packets will follow and that application crashes, the device will back out that pending channel request and return to an idle state.
11.2.5.3. Transaction abort and re-synchronization
If an application for any reason "gets lost", gets an unexpected response or error, it may at any time issue an abort-and-resynchronize command. If the device detects an INIT command during a transaction that has the same channel id as the active transaction, the transaction is aborted (if possible) and all buffered data flushed (if any). The device then returns to idle state to become ready for a new transaction.
If an application wishes to abort a command after the request has been fully sent, e.g. while an authenticator is waiting for user presence, the application may do this by sending a CTAPHID_CANCEL command.
11.2.5.4. Packet sequencing
The device keeps track of packets arriving in correct and ascending order and that no expected packets are missing. The device will continue to assemble a message until all parts of it has been received or that the transaction times out. Spurious continuation packets appearing without a prior initialization packet will be ignored.
11.2.6. Channel locking
In order to deal with aggregated transactions that may not be interrupted, such as tunneling of vendor-specific commands, a channel lock command may be implemented. By sending a channel lock command, the device prevents other channels from communicating with the device until the channel lock has timed out or been explicitly unlocked by the application.
This feature is optional and has not to be considered by general CTAP HID applications.
11.2.7. Protocol version and compatibility
The CTAPHID protocol is designed to be extensible yet maintain backwards compatibility, to the extent it is applicable. This means that a CTAPHID host SHALL support any version of a device with the command set available in that particular version.
11.2.8. HID device implementation
This description assumes knowledge of the USB and HID specifications and is intended to provide the basics for implementing a CTAPHID device. There are several ways to implement USB devices and reviewing these different methods is beyond the scope of this document. This specification targets the interface part, where a device is regarded as either a single or multiple interface (composite) device.
The description further assumes (but is not limited to) a full-speed USB device (12 Mbit/s). Although not excluded per se, USB low-speed devices are not practical to use given the 8-byte report size limitation together with the protocol overhead.
11.2.8.1. Interface and endpoint descriptors
The device implements two endpoints (except the control endpoint 0), one for IN and one for OUT transfers. The packet size is vendor defined, but the reference implementation assumes a full-speed device with two 64-byte endpoints.
Interface Descriptor
Mnemonic | Value | Description |
---|---|---|
bNumEndpoints | 2 | One IN and one OUT endpoint |
bInterfaceClass | 0x03 | HID |
bInterfaceSubClass | 0x00 | No interface subclass |
bInterfaceProtocol | 0x00 | No interface protocol |
Mnemonic | Value | Description |
---|---|---|
bmAttributes | 0x03 | Interrupt transfer |
bEndpointAdress | 0x01 | 1, OUT |
bMaxPacketSize | 64 | 64-byte packet max |
bInterval | 5 | Poll every 5 millisecond |
Mnemonic | Value | Description |
---|---|---|
bmAttributes | 0x03 | Interrupt transfer |
bEndpointAdress | 0x81 | 1, IN |
bMaxPacketSize | 64 | 64-byte packet max |
bInterval | 5 | Poll every 5 millisecond |
The actual endpoint order, intervals, endpoint numbers and endpoint packet size may be defined freely by the vendor and the host application is responsible for querying these values and handle these accordingly. For the sake of clarity, the values listed above are used in the following examples.
11.2.8.2. HID report descriptor and device discovery
A HID report descriptor is required for all HID devices, even though the reports and their interpretation (scope, range, etc.) makes very little sense from an operating system perspective. The CTAPHID just provides two "raw" reports, which basically map directly to the IN and OUT endpoints. However, the HID report descriptor has an important purpose in CTAPHID, as it is used for device discovery.
For the sake of clarity, a bit of high-level C-style abstraction is provided
// HID report descriptor const uint8_t HID_ReportDescriptor[] = { HID_UsagePage ( FIDO_USAGE_PAGE ), HID_Usage ( FIDO_USAGE_CTAPHID ), HID_Collection ( HID_Application ), HID_Usage ( FIDO_USAGE_DATA_IN ), HID_LogicalMin ( 0 ), HID_LogicalMaxS ( 0xff ), HID_ReportSize ( 8 ), HID_ReportCount ( HID_INPUT_REPORT_BYTES ), HID_Input ( HID_Data | HID_Absolute | HID_Variable ), HID_Usage ( FIDO_USAGE_DATA_OUT ), HID_LogicalMin ( 0 ), HID_LogicalMaxS ( 0xff ), HID_ReportSize ( 8 ), HID_ReportCount ( HID_OUTPUT_REPORT_BYTES ), HID_Output ( HID_Data | HID_Absolute | HID_Variable ), HID_EndCollection };
A unique Usage Page is defined (0xF1D0) for the FIDO alliance and under this realm, a CTAPHID Usage is defined as well (0x01). During CTAPHID device discovery, all HID devices present in the system are examined and devices that match this usage pages and usage are then considered to be CTAPHID devices.
The length values specified by the HID_INPUT_REPORT_BYTES
and
the HID_OUTPUT_REPORT_BYTES
should typically match the
respective endpoint sizes defined in the endpoint descriptors.
11.2.9. CTAPHID commands
The CTAPHID protocol implements the following commands.
11.2.9.1. Mandatory commands
The following list describes the minimum set of commands required by a CTAPHID device. Optional and vendor-specific commands may be implemented as described in respective sections of this document.
11.2.9.1.1. CTAPHID_MSG (0x03)
This command sends an encapsulated CTAP1/U2F message to the device. The semantics of the data message is defined in the U2F Raw Message Format encoding specification.
Request
CMD | CTAPHID_MSG |
BCNT | 1..(n + 1) |
DATA | U2F command byte |
DATA + 1 | n bytes of data |
Response at success
CMD | CTAPHID_MSG |
BCNT | 1..(n + 1) |
DATA | U2F status code |
DATA + 1 | n bytes of data |
11.2.9.1.2. CTAPHID_CBOR (0x10)
This command sends an encapsulated CTAP CBOR encoded message. The semantics of the data message is defined in the CTAP Message encoding specification. Please note that keep-alive messages MAY be sent from the device to the client before the response message is returned.
Request
CMD | CTAPHID_CBOR |
BCNT | 1..(n + 1) |
DATA | CTAP command byte |
DATA + 1 | n bytes of CBOR encoded data |
Response at success
CMD | CTAPHID_CBOR |
BCNT | 1..(n + 1) |
DATA | CTAP status code |
DATA + 1 | n bytes of CBOR encoded data |
11.2.9.1.3. CTAPHID_INIT (0x06)
This command has two functions.
If sent on an allocated CID, it synchronizes a channel, discarding the current transaction, buffers and state as quickly as possible. It will then be ready for a new transaction. The device then responds with the CID of the channel it received the INIT on, using that channel.
If sent on the broadcast CID, it requests the device to allocate a unique 32-bit channel identifier (CID) that can be used by the requesting application during its lifetime. The requesting application generates a nonce that is used to match the response. When the response is received, the application compares the sent nonce with the received one. After a positive match, the application stores the received channel id and uses that for subsequent transactions.
To allocate a new channel, the requesting application SHALL use the broadcast channel CTAPHID_BROADCAST_CID (0xFFFFFFFF). The device then responds with the newly allocated channel in the response, using the broadcast channel.
Request
CMD | CTAPHID_INIT |
BCNT | 8 |
DATA | 8-byte nonce |
Response at success
CMD | CTAPHID_INIT |
BCNT | 17 (see note below) |
DATA | 8-byte nonce |
DATA+8 | 4-byte channel ID |
DATA+12 | CTAPHID protocol version identifier |
DATA+13 | Major device version number |
DATA+14 | Minor device version number |
DATA+15 | Build device version number |
DATA+16 | Capabilities flags |
The protocol version identifies the protocol version implemented by the device. This version of the CTAPHID protocol is 2.
A CTAPHID host SHALL accept a response size that is longer than the anticipated size to allow for future extensions of the protocol, yet maintaining backwards compatibility. Future versions will maintain the response structure of the current version, but additional fields may be added.
The meaning and interpretation of the device version number is vendor defined.
The capability flags value is a bitfield where the following bits values are defined. Unused values are reserved for future use and must be set to zero by device vendors.
Name | Value | Description |
---|---|---|
CAPABILITY_WINK | 0x01 | If set to 1, authenticator implements CTAPHID_WINK function |
CAPABILITY_CBOR | 0x04 | If set to 1, authenticator implements CTAPHID_CBOR function |
CAPABILITY_NMSG | 0x08 | If set to 1, authenticator DOES NOT implement CTAPHID_MSG function |
11.2.9.1.4. CTAPHID_PING (0x01)
Sends a transaction to the device, which immediately echoes the same data back. This command is defined to be a uniform function for debugging, latency and performance measurements.
Request
CMD | CTAPHID_PING |
BCNT | 0..n |
DATA | n bytes |
Response at success
CMD | CTAPHID_PING |
BCNT | n |
DATA | N bytes |
11.2.9.1.5. CTAPHID_CANCEL (0x11)
Cancel any outstanding requests on this CID. If there is an outstanding request that can be cancelled, the authenticator MUST cancel it and that cancelled request will reply with the error CTAP2_ERR_KEEPALIVE_CANCEL.
As the CTAPHID_CANCEL command is sent during an ongoing transaction, transaction semantics do not apply. Whether a request was cancelled or not, the authenticator MUST NOT reply to the CTAPHID_CANCEL message itself. The CTAPHID_CANCEL command MAY be sent by the client during ongoing processing of a CTAPHID_CBOR request. The CTAP2_ERR_KEEPALIVE_CANCEL response MUST be the response to that request, not an error response in the HID transport.
A CTAPHID_CANCEL received while no CTAPHID_CBOR request is being processed, or on a non-active CID SHALL be ignored by the authenticator.
CMD | CTAPHID_CANCEL |
BCNT | 0 |
11.2.9.1.6. CTAPHID_ERROR (0x3F)
This command code is used in response messages only.
CMD | CTAPHID_ERROR |
BCNT | 1 |
DATA | Error code |
The following error codes are defined
ERR_INVALID_CMD | 0x01 | The command in the request is invalid |
ERR_INVALID_PAR | 0x02 | The parameter(s) in the request is invalid |
ERR_INVALID_LEN | 0x03 | The length field (BCNT) is invalid for the request |
ERR_INVALID_SEQ | 0x04 | The sequence does not match expected value |
ERR_MSG_TIMEOUT | 0x05 | The message has timed out |
ERR_CHANNEL_BUSY | 0x06 | The device is busy for the requesting channel. The client SHOULD retry the request after a short delay. Note that the client may abort the transaction if the command is no longer relevant. |
ERR_LOCK_REQUIRED | 0x0A | Command requires channel lock |
ERR_INVALID_CHANNEL | 0x0B | CID is not valid. |
ERR_OTHER | 0x7F | Unspecified error |
11.2.9.1.7. CTAPHID_KEEPALIVE (0x3B)
This command code is sent while processing a CTAPHID_MSG. It should be sent at least every 100ms and whenever the status changes. A KEEPALIVE sent by an authenticator does not constitute a response and does therefore not end an ongoing transaction.
CMD | CTAPHID_KEEPALIVE |
BCNT | 1 |
DATA | Status code |
The following status codes are defined
STATUS_PROCESSING | 1 | The authenticator is still processing the current request. |
STATUS_UPNEEDED | 2 | The authenticator is waiting for user presence. |
11.2.9.2. Optional commands
The following commands are defined by this specification but are optional and does not have to be implemented.
11.2.9.2.1. CTAPHID_WINK (0x08)
The wink command performs a vendor-defined action that provides some visual or audible identification a particular authenticator. A typical implementation will do a short burst of flashes with a LED or something similar. This is useful when more than one device is attached to a computer and there is confusion which device is paired with which connection.
Request
CMD | CTAPHID_WINK |
BCNT | 0 |
DATA | N/A |
Response at success
CMD | CTAPHID_WINK |
BCNT | 0 |
DATA | N/A |
11.2.9.2.2. CTAPHID_LOCK (0x04)
The lock command places an exclusive lock for one channel to communicate with the device. As long as the lock is active, any other channel trying to send a message will fail. In order to prevent a stalling or crashing application to lock the device indefinitely, a lock time up to 10 seconds may be set. An application requiring a longer lock has to send repeating lock commands to maintain the lock.
Request
CMD | CTAPHID_LOCK |
BCNT | 1 |
DATA | Lock time in seconds 0..10. A value of 0 immediately releases the lock |
Response at success
CMD | CTAPHID_LOCK |
BCNT | 0 |
DATA | N/A |
11.2.9.3. Vendor specific commands
A CTAPHID may implement additional vendor specific commands that are not defined in this specification, while being CTAPHID compliant. Such commands, if implemented, must use a command in the range between CTAPHID_VENDOR_FIRST (0x40) and CTAPHID_VENDOR_LAST (0x7F).
11.3. ISO7816, ISO14443 and Near Field Communication (NFC)
See also § 11.1 Secure protocol implementation.11.3.1. Conformance
Please refer to [ISO7816-4] for APDU definition.
11.3.2. Protocol
The general protocol between a FIDO2 client and an authenticator over ISO7816/ISO14443 is as follows:
-
Client sends an applet selection command
-
Authenticator replies with success if the applet is present
-
Client sends a command for an operation
-
Authenticator replies with response data or error
-
Return to 3.
Because of timeouts that may otherwise occur on some platforms, it is RECOMMENDED that the Authenticators reply to APDU commands within 800 milliseconds.
11.3.3. Applet selection
Note: See also § 11.1 Secure protocol implementation
A successful Select allows the client to know that the applet is present and active. A client SHALL send a Select to the authenticator before any other command.
The FIDO2 AID consists of the following fields:
Field | Value |
---|---|
RID
| 0xA000000647 |
PIX
| 0x2F0001 |
The command to select the FIDO applet is:
CLA | INS | P1 | P2 | Data In | Le |
---|---|---|---|---|---|
0x00 | 0xA4 | 0x04 | 0x00 | AID | Variable |
In response to the applet selection command, the FIDO authenticator replies with its version information string in the successful response.
Clients and authenticators MAY support additional selection mechanisms. Clients MUST fall back to the previously defined selection process if the additional selection mechanisms fail to select the applet. Authenticators MUST at least support the previously defined selection process.
Given legacy support for CTAP1/U2F, the client must determine the capabilities of the device at the selection stage.
-
If the authenticator implements CTAP1/U2F, the version information SHALL be the string "U2F_V2", or 0x5532465f5632, to maintain backwards-compatibility with CTAP1/U2F-only clients.
-
If the authenticator ONLY implements CTAP2, the device SHALL respond with "FIDO_2_0", or 0x4649444f5f325f30.
-
If the authenticator implements both CTAP1/U2F and CTAP2, the version information SHALL be the string "U2F_V2", or 0x5532465f5632, to maintain backwards-compatibility with CTAP1/U2F-only clients. CTAP2-aware clients may then issue a CTAP authenticatorGetInfo command to determine if the device supports CTAP2 or not.
11.3.4. Applet deselection
Note: See also § 11.1 Secure protocol implementation
-
Authenticator SHALL deselect or disable FIDO applet upon receiving below
NFCCTAP_CONTROL END CTAP_MSG
command.-
Authenticators SHALL ignore subsequent FIDO CTAP commands until it receives the next explicit FIDO Applet selection command.
-
NFCCTAP_CONTROL END CTAP_MSG
command is as follows:CLA INS P1 P2 0x80 0x12 (NFCCTAP_CONTROL) 0x01 (End CTAP_MSG Control Byte) 0x00
-
11.3.5. Framing
Conceptually, framing defines an encapsulation of FIDO2 commands. This encapsulation is done in an APDU following [ISO7816-4]. Authenticators MUST support short and extended length encoding for this APDU. Fragmentation, if needed, is discussed in the following paragraph.
11.3.5.1. Commands
Commands SHALL have the following format:
CLA | INS | P1 | P2 | Data In | Le |
---|---|---|---|---|---|
0x80 | 0x10 | 0x00 | 0x00 | CTAP Command Byte || CBOR Encoded Data | Variable |
11.3.5.2. Response
Response SHALL have the following format in case of success:
Case | Data | Status word |
---|---|---|
Success | CTAP Status code || Response data | "9000" - Success |
Status update | Status data | "9100" - OK When receiving this, the ISO transport layer will immediately issue an NFCCTAP_GETREPONSE command unless a cancel was issued. The ISO transport layer will provide the status data to the higher layers. |
Errors | See [ISO7816-4] |
11.3.6. Fragmentation
APDU command may hold up to 255 or 65535 bytes of data using short or extended length encoding respectively. APDU response may hold up to 256 or 65536 bytes of data using short or extended length encoding respectively.
Some requests may not fit into a short APDU command, or the expected response may not fit in a short APDU response. For this reason, FIDO2 client MAY encode APDU command in the following way:
-
The request may be encoded using extended length APDU encoding.
-
The request may be encoded using short APDU encoding. If the request does not fit a short APDU command, the client MUST use ISO 7816-4 APDU chaining.
Short APDU Chaining commands SHALL have the following format:
CLA | INS | P1 | P2 | Data In |
---|---|---|---|---|
0x90 | 0x10 | 0x00 | 0x00 | CTAP Payload |
Some responses may not fit into a short APDU response. For this reason, FIDO2 authenticators MUST respond in the following way:
-
If the request was encoded using extended length APDU encoding, the authenticator MUST respond using the extended length APDU response format.
-
If the request was encoded using short APDU encoding, the authenticator MUST respond using ISO 7816-4 APDU chaining.
11.3.7. Commands
11.3.7.1. NFCCTAP_MSG (0x10)
The NFCCTAP_MSG command send a CTAP message to the authenticator. This command SHALL return as soon as processing is done. If the operation was not completed, it MAY return a 0x9100 result to trigger NFCCTAP_GETRESPONSE functionality if the client indicated support by setting the relevant bit in P1.
The values for P1 for the NFCCTAP_MSG command are:
P1 Bits | Meaning |
---|---|
0x80 | The client supports NFCCTAP_GETRESPONSE |
0x7F | RFU, must be (0x00) |
Values for P2 are all RFU and MUST be set to 0.
11.3.7.2. NFCCTAP_GETRESPONSE (0x11)
The NFCCTAP_GETRESPONSE command is issued up to receiving 0x9100 unless a cancel was issued. This command SHALL return a 0x9100 result with a status indication if it has a status update, the reply to the request with a 0x9000 result code to indicate success or an error value.
All values for P1 and P2 are RFU and MUST be set to 0x00.
11.4. Bluetooth Smart / Bluetooth Low Energy Technology
See also § 11.1 Secure protocol implementation.11.4.1. Conformance
Authenticator and client devices using Bluetooth Low Energy Technology SHALL conform to Bluetooth Core Specification 4.0 or later [BTCORE]. Bluetooth SIG specified UUID values SHALL be found on the Assigned Numbers website [BTASSNUM].
11.4.2. Pairing
Bluetooth Low Energy Technology is a long-range wireless protocol and thus has several implications for privacy, security, and overall user-experience. Because it is wireless, Bluetooth Low Energy Technology may be subject to monitoring, injection, and other network-level attacks.
For these reasons, clients and authenticators MUST create and use a long-term link key (LTK) and SHALL encrypt all communications. Authenticator MUST never use short term keys.
Because Bluetooth Low Energy Technology has poor ranging (i.e., there is no good indication of proximity), it may not be clear to a FIDO client with which Bluetooth Low Energy Technology authenticator it should communicate. Pairing is the only mechanism defined in this protocol to ensure that FIDO clients are interacting with the expected Bluetooth Low Energy Technology authenticator. As a result, authenticator manufacturers SHOULD instruct users to avoid performing Bluetooth pairing in a public space such as a cafe, shop or train station.
One disadvantage of using standard Bluetooth pairing is that the pairing is "system-wide" on most operating systems. That is, if an authenticator is paired to a FIDO client which resides on an operating system where Bluetooth pairing is "system-wide", then any application on that device might be able to interact with an authenticator. This issue is discussed further in Implementation Considerations.
11.4.3. Link Security
For Bluetooth Low Energy Technology connections, the authenticator
SHALL enforce Security Mode 1, Level 2
(unauthenticated
pairing with encryption) or Security Mode 1, Level 3
(authenticated pairing with encryption) before any FIDO messages
are exchanged.
11.4.4. Framing
Conceptually, framing defines an encapsulation of FIDO raw messages responsible for correct transmission of a single request and its response by the transport layer.
All requests and their responses are conceptually written as a single frame. The format of the requests and responses is given first as complete frames. Fragmentation is discussed next for each type of transport layer.
11.4.4.1. Request from Client to Authenticator
Request frames must have the following format
Offset | Length | Mnemonic | Description |
---|---|---|---|
0 | 1 | CMD
| Command identifier |
1 | 1 | HLEN
| High part of data length |
2 | 1 | LLEN
| Low part of data length |
3 | s | DATA
| Data (s is equal to the length) |
Supported commands are PING
, MSG
and CANCEL
.
The constant values for them are described below.
The CANCEL
command cancels any outstanding MSG
commands.
The data format for the MSG
command is defined in § 8 Message Encoding.
11.4.4.2. Response from Authenticator to Client
Response frames must have the following format, which share a similar format to the request frames:
Offset | Length | Mnemonic | Description |
---|---|---|---|
0 | 1 | STAT
| Response status |
1 | 1 | HLEN
| High part of data length |
2 | 1 | LLEN
| Low part of data length |
3 | s | DATA
| Data (s is equal to the length) |
When the status byte in the response is the same as the command
byte in the request, the response is a successful response. The
value ERROR
indicates an error, and the response data
contains an error code as a variable-length, big-endian integer. The
constant value for ERROR
is described below.
Note that the errors sent in this response are errors at the
encapsulation layer, e.g., indicating an incorrectly
formatted request, or possibly an error communicating with the
authenticator’s FIDO message processing layer. Errors reported by the
FIDO message processing layer itself are considered a success from
the encapsulation layer’s point of view and are reported as a
complete MSG
response.
Data format is defined in § 8 Message Encoding.
11.4.4.3. Command, Status, and Error constants
The COMMAND constants and values are:
Constant | Value |
---|---|
PING
| 0x81 |
KEEPALIVE
| 0x82 |
MSG
| 0x83 |
CANCEL
| 0xbe |
ERROR
| 0xbf |
The KEEPALIVE command contains a single byte with the following possible values:
Status Constant | Value |
---|---|
PROCESSING
| 0x01 |
UP_NEEDED
| 0x02 |
RFU
| 0x00, 0x03-0xFF |
The ERROR constants and values are:
Error Constant | Value | Meaning |
---|---|---|
ERR_INVALID_CMD
| 0x01 | The command in the request is unknown/invalid |
ERR_INVALID_PAR
| 0x02 | The parameter(s) of the command is/are invalid or missing |
ERR_INVALID_LEN
| 0x03 | The length of the request is invalid |
ERR_INVALID_SEQ
| 0x04 | The sequence number is invalid |
ERR_REQ_TIMEOUT
| 0x05 | The request timed out |
ERR_BUSY
| 0x06 | The device is busy and can’t accept commands at this time. The client SHOULD retry the request after a short delay. Note that the client may abort the transaction if the command is no longer relevant. |
NA
| 0x0a | Value reserved (HID) |
NA
| 0x0b | Value reserved (HID) |
ERR_OTHER
| 0x7f | Other, unspecified error |
11.4.5. GATT Service Description
This profile defines two roles: FIDO Authenticator and FIDO Client.
-
The FIDO Client SHALL be a GATT Client.
-
The FIDO Authenticator SHALL be a GATT Server.
The following figure illustrates the mandatory services and characteristics that SHALL be offered by a FIDO Authenticator as part of its GATT server:
The table below summarizes additional GATT sub-procedure requirements for a FIDO Authenticator (GATT Server) beyond those required by all GATT Servers.
GATT Sub-Procedure | Requirements |
---|---|
Write Characteristic Value | Mandatory
|
Notifications | Mandatory
|
Read Characteristic Descriptors | Mandatory
|
Write Characteristic Descriptors | Mandatory
|
The table below summarizes additional GATT sub-procedure requirements for a FIDO Client (GATT Client) beyond those required by all GATT Clients.
GATT Sub-Procedure | Requirements |
---|---|
Discover All Primary Services | (*)
|
Discover Primary Services by Service UUID | (*)
|
Discover All Characteristics of a Service | (**)
|
Discover Characteristics by UUID | (**)
|
Discover All Characteristic Descriptors | Mandatory
|
Read Characteristic Value | Mandatory
|
Write Characteristic Value | Mandatory
|
Notification | Mandatory
|
Read Characteristic Descriptors | Mandatory
|
Write Characteristic Descriptors | Mandatory
|
(*): Mandatory to support at least one of these sub-procedures. (**): Mandatory to support at least one of these sub-procedures. Other GATT sub-procedures may be used if supported by both client and server.
Specifics of each service are explained below. In the following descriptions: all values are big-endian coded, all strings are in UTF-8 encoding, and any characteristics not mentioned explicitly are optional.
11.4.5.1. FIDO Service
An authenticator SHALL implement the FIDO Service described below.
The UUID for the FIDO GATT service is 0xFFFD
; it SHALL be declared as a Primary Service.
The service contains the following characteristics:
Characteristic Name | Mnemonic | Property | Length | UUID |
---|---|---|---|---|
FIDO Control Point | fidoControlPoint
| Write | Defined by Vendor (20-512 bytes) | F1D0FFF1-DEAA-ECEE-B42F-C9BA7ED623BB |
FIDO Status | fidoStatus
| Notify | N/A | F1D0FFF2-DEAA-ECEE-B42F-C9BA7ED623BB |
FIDO Control Point Length | fidoControlPointLength
| Read | 2 bytes | F1D0FFF3-DEAA-ECEE-B42F-C9BA7ED623BB |
FIDO Service Revision Bitfield | fidoServiceRevisionBitfield
| Read/Write | Defined by Vendor (1+ bytes) | F1D0FFF4-DEAA-ECEE-B42F-C9BA7ED623BB |
FIDO Service Revision | fidoServiceRevision
| Read | Defined by Vendor (20-512 bytes) | 0x2A28 |
fidoControlPoint
is a write-only command buffer.
fidoStatus
is a notify-only response attribute.
The authenticator will send a series of notifications on this attribute
with a maximum length of (ATT_MTU-3) using the response frames defined
above. This mechanism is used because this results in a faster transfer
speed compared to a notify-read combination.
fidoControlPointLength
defines the maximum size in
bytes of a single write request to fidoControlPoint
.
This value SHALL be between 20 and 512.
fidoServiceRevision
is superseded and is only relevant to
U2F 1.0 support. It defines the revision of the U2F Service.
The value is a UTF-8 string. For version 1.0 of the specification,
the value fidoServiceRevision
SHALL be 1.0
or in
raw bytes: 0x312e30
. This field SHALL be omitted if protocol
version 1.0 is not supported.
The fidoServiceRevision
Characteristic MAY include
a Characteristic Presentation Format descriptor with format value
0x19, UTF-8 String
.
fidoServiceRevisionBitfield
defines the revision of the FIDO Service.
The value is a bit field which each bit representing a version. For each
version bit the value is 1 if the version is supported, 0 if it is not.
The length of the bitfield is 1 or more bytes. All bytes that are 0 are
omitted if all the following bytes are 0 too. The byte order is big endian.
The client SHALL write a value to this characteristic with exactly 1 bit
set before sending any FIDO commands unless u2fServiceRevision is present
and U2F 1.0 compatibility is desired. If only U2F version 1.0 is supported,
this characteristic SHALL be omitted.
Byte (left to right) | Bit | Version |
---|---|---|
0 | 7 | U2F 1.1 |
0 | 6 | U2F 1.2 |
0 | 5 | FIDO2 |
0 | 4-0 | Reserved |
For example, a device that only supports FIDO2 Rev 1 will only have a fidoServiceRevisionBitfield characteristic of length 1 with value 0x20.
11.4.5.2. Device Information Service
An authenticator SHALL implement the Device Information Service [BTDIS] with the following characteristics:
-
Manufacturer Name String
-
Model Number String
-
Firmware Revision String
All values for the Device Information Service are left to the vendors. However, vendors should not create uniquely identifiable values so that authenticators do not become a method of tracking users.
11.4.5.3. Generic Access Profile Service
Every authenticator SHALL implement the Generic Access Profile Service [BTGAS] with the following characteristics:
-
Device Name
-
Appearance
11.4.6. Protocol Overview
The general overview of the communication protocol follows:
-
Authenticator advertises the FIDO Service.
-
Client scans for authenticator advertising the FIDO Service.
-
Client performs characteristic discovery on the authenticator.
-
If not already paired, the client and authenticator SHALL perform BLE pairing and create a LTK. Authenticator SHALL only allow connections from previously bonded clients without user intervention.
-
Client checks if the
fidoServiceRevisionBitfield
characteristic is present. If so, the client selects a supported version by writing a value with a single bit set. -
Client reads the
fidoControlPointLength
characteristic. -
Client registers for notifications on the
fidoStatus
characteristic. -
Client writes a request (e.g., an enroll request) into the
fidoControlPoint
characteristic. -
Optionally, the client writes a CANCEL command to the
fidoControlPoint
characteristic to cancel the pending request. -
Authenticator evaluates the request and responds by sending notifications over
fidoStatus
characteristic. -
The protocol completes when either:
-
The client unregisters for notifications on the
fidoStatus
characteristic, or: -
The connection times out and is closed by the authenticator.
-
11.4.7. Authenticator Advertising Format
When advertising, the authenticator SHALL advertise the FIDO service UUID.
When advertising, the authenticator MAY include the TxPower value in the advertisement (see [BTXPLAD]).
When advertising in pairing mode, the authenticator SHALL either: (1) set the LE Limited Mode bit to zero and the LE General Discoverable bit to one OR (2) set the LE Limited Mode bit to one and the LE General Discoverable bit to zero. When advertising in non-pairing mode, the authenticator SHALL set both the LE Limited Mode bit and the LE General Discoverable Mode bit to zero in the Advertising Data Flags.
The advertisement MAY also carry a device name which is distinctive and user-identifiable. For example, "ACME Key" would be an appropriate name, while "XJS4" would not be.
The authenticator SHALL also implement the Generic Access Profile [BTGAP] and Device Information Service [BTDIS], both of which also provide a user-friendly name for the device that could be used by the client.
It is not specified when or how often an authenticator should advertise, instead that flexibility is left to manufacturers.
11.4.8. Requests
Clients SHOULD make requests by connecting to the authenticator
and performing a write into the fidoControlPoint
characteristic.
Upon receiving a CANCEL request, if there is an outstanding request that can be cancelled, the authenticator MUST cancel it and that cancelled request will reply with the error CTAP2_ERR_KEEPALIVE_CANCEL. Whether a request was cancelled or not, the authenticator MUST NOT reply to the cancel message itself.
11.4.9. Responses
Authenticators SHOULD respond to clients by sending notifications
on the fidoStatus
characteristic.
Some authenticators might alert users or prompt them to complete the
test of user presence (e.g., via sound, light, vibration)
Upon receiving any request, the authenticators SHALL send
KEEPALIVE commands every kKeepAliveMillis
milliseconds until completing processing the commands. While the
authenticator is processing the request the KEEPALIVE command will
contain status PROCESSING
. If the authenticator is
waiting to complete the Test of User Presence, the KEEPALIVE command
will contains status UP_NEEDED
. While waiting to
complete the Test of User Presence, the authenticator MAY alert the
user (e.g., by flashing) in order to prompt the user to complete the
test of user presence.
As soon the authenticator has completed processing and confirmed
user presence, it SHALL stop sending KEEPALIVE commands, and send the
reply.
Upon receiving a KEEPALIVE command, the client SHALL assume the
authenticator is still processing the command; the client SHALL not
resend the command. The authenticator SHALL continue sending
KEEPALIVE messages at least every kKeepAliveMillis
to indicate that it is still handling the request. Until a
client-defined timeout occurs, the client SHALL NOT move on to other
devices when it receives a KEEPALIVE with UP_NEEDED
status, as it knows this is a device that can satisfy its request.
11.4.10. Framing fragmentation
A single request/response sent over Bluetooth Low Energy Technology MAY be split over multiple writes and notifications, due to the inherent limitations of Bluetooth Low Energy Technology which is not currently meant for large messages. Frames are fragmented in the following way:
A frame is divided into an initialization fragment and zero or more continuation fragments.
An initialization fragment is defined as:
Offset | Length | Mnemonic | Description |
---|---|---|---|
0 | 1 | CMD
| Command identifier |
1 | 1 | HLEN
| High part of data length |
2 | 1 | LLEN
| Low part of data length |
3 | 0 to (maxLen - 3) | DATA
| Data |
where maxLen
is the maximum packet size supported by
the characteristic or notification.
In other words, the start of an initialization fragment is
indicated by setting the high bit in the first byte. The subsequent
two bytes indicate the total length of the frame, in big-endian
order. The first maxLen
- 3 bytes of data follow.
Continuation fragments are defined as:
Offset | Length | Mnemonic | Description |
---|---|---|---|
0 | 1 | SEQ
| Packet sequence 0x00..0x7f (high bit always cleared) |
1 | 0 to (maxLen - 1) | DATA
| Data |
where maxLen
is the maximum packet size supported
by the characteristic or notification.
In other words, continuation fragments begin with a sequence number, beginning at 0, implicitly with the high bit cleared. The sequence number must wraparound to 0 after reaching the maximum sequence number of 0x7f.
Example for sending a PING
command with 40 bytes of
data with a maxLen
of 20 bytes:
Frame | Bytes |
---|---|
0 | [810028] [17 bytes of data]
|
1 | [00] [19 bytes of data]
|
2 | [01] [4 bytes of data]
|
Example for sending a ping command with 400 bytes of data with a maxLen
of 512 bytes:
Frame | Bytes |
---|---|
0 | [810190] [400 bytes of data]
|
11.4.11. Notifications
A client needs to register for notifications before it can receive them. Bluetooth Core Specification 4.0 or later [BTCORE] forces a device to remember the notification registration status over different connections [BTCCC]. Unless a client explicitly unregisters for notifications, the registration will be automatically restored when reconnecting. A client MAY therefor check the notification status upon connection and only register if notifications aren’t already registered. Please note that some clients MAY disable notifications from a power management point of view (see below) and the notification registration is remembered per bond, not per client. A client MUST NOT remember the notification status in its own data storage.
11.4.12. Request Collisions
Because there is no concept of a session between the authenticator and a client (only between the host and the client), a BLE Authenticator cannot distinguish between different clients. If two clients on the same host register for notifications from an authenticator at the same time, some existing host platforms will allow this by reusing the same underlying BLE connection. However, when the authenticator generates a notification, the host platform has insufficient information to route it to a particular client. Depending on the host platform implementation, the notification may be delivered to either or both clients. The result is undefined behavior which will likely result in both requests failing.
11.4.13. Implementation Considerations
11.4.13.1. Bluetooth pairing: Client considerations
As noted in § 11.4.2 Pairing, a disadvantage of using standard Bluetooth pairing is that the pairing is "system-wide" on most operating systems. That is, if an authenticator is paired to a FIDO client that resides on an operating system where Bluetooth pairing is "system-wide", then any application on that device might be able to interact with an authenticator. This poses both security and privacy risks to users.
While client operating system security is partly out of FIDO’s scope, further revisions of this specification MAY propose mitigations for this issue.
11.4.13.2. Bluetooth pairing: Authenticator considerations
The method to put the authenticator into Pairing Mode should be such that it is not easy for the user to do accidentally especially if the pairing method is Just Works. For example, the action could be pressing a physically recessed button or pressing multiple buttons. A visible or audible cue that the authenticator is in Pairing Mode should be considered. As a counter example, a silent, long press of a single non-recessed button is not advised as some users naturally hold buttons down during regular operation.
Note that at times, authenticators may legitimately receive communication from an unpaired device. For example, a user attempts to use an authenticator for the first time with a new client; he turns it on, but forgets to put the authenticator into pairing mode. In this situation, after connecting to the authenticator, the client will notify the user that he needs to pair his authenticator. The authenticator should make it easy for the user to do so, e.g., by not requiring the user to wait for a timeout before being able to enable pairing mode.
Some client platforms (most notably iOS) do not expose the AD Flag LE Limited and General Discoverable Mode bits to applications. For this reason, authenticators are also strongly recommended to include the Service Data field [BTSD] in the Scan Response. The Service Data field is 3 or more octets long. This allows the Flags field to be extended while using the minimum number of octets within the data packet. All octets that are 0x00 are not transmitted as long as all other octets after that octet are also 0x00 and it is not the first octet after the service UUID. The first 2 bytes contain the FIDO Service UUID, the following bytes are flag bytes.
To help clients show the correct UX, authenticators can use the Service Data field to specify whether or not authenticators will require a Passkey (PIN) during pairing.
Service Data Bit | Meaning (if set) |
---|---|
7 | Device is in pairing mode. |
6 | Device requires Passkey Entry [BTPESTK]. |
11.4.14. Handling command completion
It is important for low-power devices to be able to conserve power by shutting down or switching to a lower-power state when they have satisfied a client’s requests. However, the FIDO protocol makes this hard as it typically includes more than one command/response. This is especially true if a user has more than one key handle associated with an account or identity, multiple key handles may need to be tried before getting a successful outcome. Furthermore, clients that fail to send follow up commands in a timely fashion may cause the authenticator to drain its battery by staying powered up anticipating more commands.
A further consideration is to ensure that a user is not confused about which command she is confirming by completing the test of user presence. That is, if a user performs the test of user presence, that action should perform exactly one operation.
We combine these considerations into the following series of recommendations:
-
Upon initial connection to an authenticator, and upon receipt of a response from an authenticator, if a client has more commands to issue, the client MUST transmit the next command or fragment within
kMaxCommandTransmitDelayMillis
milliseconds. -
Upon final response from an authenticator, if the client decides it has no more commands to send it should indicate this by disabling notifications on the
fidoStatus
characteristic. When the notifications are disabled the authenticator may enter a low power state or disconnect and shut down. -
Any time the client wishes to send a FIDO message, it must have first enabled notifications on the
fidoStatus
characteristic and wait for the ATT acknowledgement to be sure the authenticator is ready to process messages. -
Upon successful completion of a command which required a test of user presence, e.g. upon a successful authentication or registration command, the authenticator can assume the client is satisfied, and MAY reset its state or power down.
Note: authenticators supporting large blobs SHOULD wait kMaxCommandTransmitDelayMillis if the command response contained a largeBlobKey, even after consuming user presence, otherwise they may miss such commands.
-
Upon sending a command response that did not consume a test of user presence, the authenticator MUST assume that the client may wish to initiate another command and leave the connection open until the client closes it or until a timeout of at least
kErrorWaitMillis
elapses. Examples of command responses that do not consume user presence include failed authenticate or register commands, as well as get version responses, whether successful or not. AfterkErrorWaitMillis
milliseconds have elapsed without further commands from a client, an authenticator MAY reset its state or power down.
Constant | Value |
---|---|
kMaxCommandTransmitDelayMillis
| 1500 milliseconds |
kErrorWaitMillis
| 2000 milliseconds |
kKeepAliveMillis
| 500 milliseconds |
11.4.15. Data throughput
Bluetooth Low Energy Technology does not have particularly high throughput, this can cause noticeable latency to the user if request/responses are large. Some ways that implementers can reduce latency are:
-
Support the maximum MTU size allowable by hardware (up to the 512-byte max from the Bluetooth specifications).
-
Make the attestation certificate as small as possible; do not include unnecessary extensions.
11.4.16. Advertising
Though the standard does not appear to mandate it (in any way that we’ve found thus far), advertising and device discovery seems to work better when the authenticators advertise on all 3 advertising channels and not just one.
11.4.17. Authenticator Address Type
In order to enhance the user’s privacy and specifically to guard against tracking, it is recommended that authenticators use Resolvable Private Addresses (RPAs) instead of static addresses.
The transports that FIDO has defined are thus USB, NFC, and BLE.
12. Defined Extensions
This section defines authenticator extensions and any necessary corresponding client extension processing for them.
Note: extensions may be defined such that extension processing may occur without any extension input.
12.1. Credential Protection (credProtect)
12.1.1. Feature detection
- Extension identifier
-
credProtect
This registration extension allows relying parties to specify a credential protection policy when creating a credential. Additionally, authenticators may choose to establish a default credential protection policy greater than userVerificationOptional (the lowest level) and unilaterally enforce such policy. Authenticators not supporting some form of user verification MUST NOT support this extension.
Authenticators supporting some form of user verification MUST process this extension and persist the credProtect value with the credential, even if the authenticator is not protected by some form of user verification at the time.
Note: support for this extension is mandatory in some cases. See § 9 Mandatory features.
- Client extension input
-
create()
: A single USVString specifying a protection level of the credential to be created.partial dictionary AuthenticationExtensionsClientInputs {USVString
;credentialProtectionPolicy boolean
=enforceCredentialProtectionPolicy false ; }; - Client extension processing
-
If this extension is not present in an authenticatorMakeCredential request:
-
The platform MAY enforce its own default
credentialProtectionPolicy
value by adding this extension.
If this extension is present in an authenticatorMakeCredential request:
-
Verify that the
credentialProtectionPolicy
string value is one of following:-
userVerificationOptional:
-
This reflects "FIDO_2_0" semantics. In this configuration, performing some form of user verification is optional with or without credentialID list. This is the default state of the credential if the extension is not specified.
-
-
userVerificationOptionalWithCredentialIDList:
-
In this configuration, credential is discovered only when its credentialID is provided by the platform or when some form of user verification is performed.
-
-
userVerificationRequired:
-
This reflects that discovery and usage of the credential MUST be preceded by some form of user verification.
-
-
-
Evaluate the boolean
enforceCredentialProtectionPolicy
's value. This controls whether it is better to fail to create a credential rather than ignore the protection policy. WhenenforceCredentialProtectionPolicy
is true, andcredentialProtectionPolicy
's value is either userVerificationOptionalWithCredentialIDList or userVerificationRequired, the platform SHOULD NOT create the credential in a way that does not implement the requested protection policy. (For example, by creating it on an authenticator that does not support this extension.)The platform SHOULD NOT alter the
credentialProtectionPolicy
value: the Relying Party's desired credential protection policy overrides any default credential protection policies imposed by the platform.
Note: Platforms may require enterprise policy, or other configuration to conform to standards like [FIPS140-3]. Those may require modification of the Relying Party's desired credential protection policy. The Relying Party's desired credential protection policy should not be modified in other circumstances.
Note: For non-discoverable credentials,
credentialProtectionPolicy
values userVerificationOptional and userVerificationOptionalWithCredentialIDList will both have the same authenticator behaviour since the Relying Party must always supply an allowList containing credential IDs when attempting to use authenticatorGetAssertion with such credentials. -
- Client extension output
-
None. Authenticator returns the result in authenticator extension output.
- Authenticator extension input
-
Map credentialProtectionPolicy value to credProtect and send it to the authenticator.
-
authenticatorMakeCredential additional behaviours
The list of possible values for credProtect is:
credentialProtectionPolicy | credProtect Value |
---|---|
userVerificationOptional | 0x01 |
userVerificationOptionalWithCredentialIDList | 0x02 |
userVerificationRequired | 0x03 |
The platform sends the authenticatorMakeCredential request with the following CBOR map entry in the "extensions" field to the authenticator:
-
"credProtect":
<credProtect Value>
The value of the map entry MUST be the credProtect value the authenticator set for the created credential.
Note: Some authenticators for high-security environments may be configured to always set credProtect 3 for all created credentials regardless of what the platform requests. In this case if a Relying Party causes an authenticatorMakeCredential request to be sent with credProtect 2 (using the credProtect extension), the authenticator will create the credential, set the credential’s credProtect policy to 3, and respond via the credProtect extension result that it set the policy to 3.
- Authenticator extension processing
-
credProtect value is persisted with the credential. If no credProtect extension was included in the request the authenticator SHOULD use the default value of 1 for compatibility with CTAP2.0 platforms. The authenticator MUST NOT return an unsolicited credProtect extension output.
- Authenticator extension output
-
-
The authenticator responds with the following CBOR map entry in the "extensions" field of the authenticator data object:
-
"credProtect":
<credProtect Value>
-
-
12.2. Credential Blob (credBlob)
This extension enables RPs to provide a small amount of extra credential configuration information(credBlob value) to the authenticator when a credential is made.
This information is an opaque blob to the authenticator. Authenticator MUST support at least 32 bytes to be stored.
Authenticator reflects amount of byte storage it supports as maxCredBlobLength
parameter in authenticatorGetInfo
.
If authenticator supports this extension, authenticator MUST support it for discoverable credentials.
Authenticator MAY choose to also support it for non-discoverable credentials.
If RPs want to put PII or sensitive information in this field, they MUST use the credProtect extension, setting the credentialProtectionPolicy
as userVerificationRequired
and enforceCredentialProtectionPolicy
as true
.
This will prevent a credential that is not protected by some form of user verification from being created.
Authenticators MUST support credProtect
extension if they wish to support credBlob
extension.
12.2.1. Feature detection
To detect whether authenticator supports this feature, following conditions MUST be met:
-
Authenticator MUST return
credBlob
in extensions field in authenticatorGetInfo in addition to other extensions it may support.-
Authenticator MUST also support dependent extension
credProtect
.
-
-
Authenticator MUST return
maxCredBlobLength (0x0F)
in authenticatorGetInfo.
- Extension identifier
-
credBlob
- Client extension input
-
create()
: ArrayBuffer containing opaque data in an RP-specific format.partial dictionary AuthenticationExtensionsClientInputs {ArrayBuffer
; };credBlob get()
: A boolean value to indicate that this extension is requested by the Relying Party.partial dictionary AuthenticationExtensionsClientInputs {boolean
; };getCredBlob - Client extension processing
-
create()
: If credBlob size is less than or equal to maxCredBlobLength, platform passes the information to the authenticator. Otherwise, platform ignores it.get()
: None. - Client extension output
-
None. Authenticator returns the result in authenticator extension output.
- Authenticator extension input
-
authenticatorMakeCredential authenticator extension input
-
The platform sends the credBlob value in authenticatorMakeCredential request with the following CBOR map entry in the "extensions" field to the authenticator:
-
"credBlob": Byte String containing the credBlob value
-
-
-
authenticatorGetAssertion authenticator extension input
-
The platform sends the authenticatorGetAssertion request with the following CBOR map entry in the "extensions" field to the authenticator:
-
"credBlob":true
-
-
- Authenticator extension processing
-
credBlob value is persisted with the Credential during authenticatorMakeCredential and returned during authenticatorGetAssertion.
- Authenticator extension output
-
authenticatorMakeCredential authenticator extension output
-
If the authenticator is able to store the credBlob value, it returns the following CBOR map entry in the "extensions" fields to the authenticator:
-
"credBlob": true
-
-
If the authenticator is not able to store the credBlob value (e.g. credBlob exceeds maxCredBlobLength, or extension is not supported for non-discoverable credentials), it returns the following CBOR map entry in the "extensions" field to to the authenticator:
-
"credBlob": false
-
-
-
authenticatorGetAssertion authenticator extension output
-
If the authenticator has the credBlob value for the credential, it returns the credBlob value in the following CBOR map entry in the "extensions" fields to the authenticator:
-
"credBlob": Byte String.
-
-
If the authenticator does NOT have the credBlob value for the credential, it returns an empty Byte String in the following CBOR map entry in the "extensions" fields to the authenticator:
-
"credBlob": (empty) Byte String.
-
-
12.3. Large Blob Key (largeBlobKey)
The credBlob extension allows for a small amount of opaque data to be stored with a credential. In contrast, this extension allows for a much larger amount of data to be stored in the large-blob array, protected by a key that is stored and accessed using this extension. Details of the interaction with the large-blob array are given in § 6.10.3 Large, per-credential blobs.
Conceptually this extension extends the state of a discoverable credential with 32 bytes of opaque storage that may, or may not, be present for any given credential. This is called the largeBlobKey. Since this value is a random key, an authenticator MAY derive it as needed from other key material, rather than storing the value itself. If an authenticator does this, the same value MUST NOT be plausibly derivable via other means. For example, it MUST NOT also obtainable via the hmac-secret extension using any salt that is predictable or constant across different credentials.
Note: Client platforms SHOULD use the largeBlobKey registration extension when creating the credential if they wish to later use the largeBlobKey authentication extension to fetch the largeBlobKey. Authenticators MAY optionally generate a largeBlobKey for a credential if the Large Blob Key (largeBlobKey) extension is absent, but MUST NOT return an unsolicited largeBlobKey extension response or largeBlobKey
(0x05) in the authenticatorMakeCredential response structure.
Platforms can detect support for this extension by checking for all of the following in the authenticatorGetInfo response:
-
largeBlobKey
in theextensions
field. -
largeBlobs
mapped totrue
in theoptions
field.
- Client extension input / output / processing
-
None. This extension is used to enable storage of large blobs in the large-blob array, which requires additional platform behaviour. It is not suitable to be directly exposed to RPs.
- Authenticator input for authenticatorMakeCredential
-
"largeBlobKey": boolean.
- Authenticator processing for authenticatorMakeCredential:
-
-
If the value of
largeBlobKey
is nottrue
, return CTAP2_ERR_INVALID_OPTION. (The extension should be omitted rather than asserted to be false.) -
If the
options
field of the authenticatorMakeCredential request does not maprk
totrue
, return CTAP2_ERR_INVALID_OPTION. -
If other processing steps for authenticatorMakeCredential complete successfully then update the new credential’s state to store a freshly generated 32-byte key as its largeBlobKey.
-
Set the value of
largeBlobKey
(0x05) in the authenticatorMakeCredential response structure (i.e., not in the extensions field of the authenticator data) to the value of the generated largeBlobKey.
-
- Authenticator authenticatorMakeCredential extension output
-
None. Since platforms cannot filter the content of the authenticator extension output, none is provided to avoid internal details of large-blob support leaking out of the abstraction layer.
- Authenticator authenticatorGetAssertion extension input
-
"largeBlobKey": boolean
- Authenticator authenticatorGetAssertion extension processing
-
-
If the value of
largeBlobKey
is nottrue
, return CTAP2_ERR_INVALID_OPTION. (The extension should be omitted rather than asserted to be false.) -
If other processing steps for authenticatorGetAssertion complete successfully, and the credential has an associated largeBlobKey, then set the value of
largeBlobKey
(0x07) in the authenticatorGetAssertion response structure (i.e., not in the extensions field of the authenticator data) to the storedlargeBlobKey
.
-
- Authenticator authenticatorGetAssertion extension output
-
None. Since platforms cannot filter the content of the authenticator extension output, none is provided to avoid internal details of large-blob support leaking out of the abstraction layer.
12.4. Minimum PIN Length Extension (minPinLength)
- Extension identifier
-
minPinLength
This extension returns the current minimum PIN length value. This value does not decrease unless the authenticator is reset, in which case, all the credentials are reset. This extension is only applicable during credential creation.
Note: An example use case for this extension is: an organization supplies configured authenticators to their users, with a current minimum PIN length value tailored to the organization’s requirements. Upon users registering their credentials with the organization’s systems using the authenticators, the organization may use this extension to determine whether the current minimum PIN length continues to meet the organization’s requirements.
- Client extension input
-
create()
: A boolean value to indicate that this extension is requested by the Relying Party.partial dictionary AuthenticationExtensionsClientInputs {boolean
; };minPinLength get()
: Not applicable. - Client extension processing
-
None, except creating the authenticator extension input from the client extension input.
- Client extension output
-
None. Authenticator returns the result in authenticator extension output.
- Authenticator extension input
-
Boolean asking for minimum PIN length value in Unicode code points. The platform sends the authenticatorMakeCredential request with the following CBOR map entry in the "extensions" field to the authenticator:
-
"minPinLength": true
-
- Authenticator extension processing
-
The authenticator checks whether the authenticatorMakeCredential's
rp.id
parameter is present on itsminPinLengthRPIDs
list. If so, the RP is authorized to receive the current minimum PIN length value. If not, the RP is not authorized to receive the current minimum PIN length value. - Authenticator extension output
-
-
If the RP is
- authorized, the authenticator sets the
minPinLength
return value to the current minimum PIN length value.- not authorized, the authenticator ignores the extension and does not return any authenticator extension output.
CDDL: "minPinLength": uint
- authorized, the authenticator sets the
-
12.5. HMAC Secret Extension (hmac-secret)
- Extension identifier
-
hmac-secret
This extension is used by the platform to retrieve a symmetric secret from the authenticator when it needs to encrypt or decrypt data using that symmetric secret. This symmetric secret is scoped to a credential. The authenticator and the platform each only have the part of the complete secret to prevent offline attacks. This extension can be used to maintain different secrets on different machines. If authenticator supports this extension, authenticator MUST support it for both discoverable and non-discoverable credentials.
- Client extension input
-
create()
: A boolean value to indicate that this extension is requested by the Relying Party.partial dictionary AuthenticationExtensionsClientInputs {boolean
; };hmacCreateSecret get()
: A JavaScript object defined as follows:dictionary
{HMACGetSecretInput required ArrayBuffer
; // 32-byte random datasalt1 ArrayBuffer
; // Optional additional 32-byte random data };salt2 partial dictionary AuthenticationExtensionsClientInputs {HMACGetSecretInput
; };hmacGetSecret The salt2 input is optional. It can be used when the platform wants to roll over the symmetric secret in one operation.
- Client extension processing
-
-
If present in a
create()
:-
If set to true, pass a CBOR true value as the authenticator extension input.
-
If set to false, do not process this extension.
-
-
If present in a
get()
:-
Verify that salt1 is a 32-byte ArrayBuffer.
-
If salt2 is present, verify that it is a 32-byte ArrayBuffer.
-
Pass salt1 and, if present, salt2 as the authenticator extension input.
-
-
- Client extension output
-
create()
: Boolean true value indicating that the authenticator has processed the extension.partial dictionary AuthenticationExtensionsClientOutputs {boolean
; };hmacCreateSecret get()
: A dictionary with the following data:dictionary
{HMACGetSecretOutput required ArrayBuffer
;output1 ArrayBuffer
; };output2 partial dictionary AuthenticationExtensionsClientOutputs {HMACGetSecretOutput
; };hmacGetSecret - Authenticator extension input
-
Same as the client extension input, except represented in CBOR.
- Authenticator extension processing
-
authenticatorGetInfo additional behaviors
The authenticator indicates to the platform that it supports the "hmac-secret" extension via the "extensions" parameter in the authenticatorGetInfo response.
-
authenticatorMakeCredential additional behaviors
The platform sends the authenticatorMakeCredential request with the following CBOR map entry in the "extensions" field to the authenticator:
-
"hmac-secret": true
-
The authenticator generates two random 32-byte values (called
CredRandomWithUV
andCredRandomWithoutUV
) and associates them with the credential.Note: Authenticator SHOULD generate
CredRandomWithUV
/CredRandomWithoutUV
and associate them with the credential, even ifhmac-secret
extension is not present in authenticatorMakeCredential request. -
If the platform has sent the
hmac-secret
extension to the authenticator, then-
If the authenticator succeeded in above step of generating
CredRandomWithUV
/CredRandomWithoutUV
and associating it with the credential, it responds with the following CBOR map entry in the "extensions" fields to the platform:-
"hmac-secret": true
-
-
Else (The authenticator did not succeed in above step of generating
CredRandomWithUV
/CredRandomWithoutUV
and associating it with the credential), it responds with the following CBOR map entry in the "extensions" fields to the platform:-
"hmac-secret": false
-
-
-
Else (the platform has not sent the hmac-secret extension to the authenticator)
-
Authenticator does not add any response from this extension to the "extensions" field of the authenticatorMakeCredential response.
-
-
-
authenticatorGetAssertion additional behaviors
-
The platform gets sharedSecret from the authenticator.
-
The platform sends the authenticatorGetAssertion request with the following CBOR map entry in the "extensions" field to the authenticator:
-
"hmac-secret":
-
keyAgreement(0x01): public key of platform key-agreement key.
-
saltEnc(0x02): Encryption of the one or two salts (called salt1 (32 bytes) and salt2 (32 bytes)) using the shared secret as follows:
-
One salt case: encrypt(shared secret, salt1)
-
Two salt case: encrypt(shared secret, salt1 || salt2)
-
-
saltAuth(0x03): authenticate(shared secret, saltEnc)
-
pinUvAuthProtocol(0x04): (optional) as selected when getting the shared secret. If omitted, the authenticator assumes that the value is
1
.
-
-
-
The authenticator performs the following operations when processing this extension:
-
If "up" is set to false, authenticator returns CTAP2_ERR_UNSUPPORTED_OPTION.
-
The authenticator waits for user consent.
-
If request asks for user verification, authenticator waits for user verification.
-
If user verification is requested via Client PIN mechanism, verify the user by verifying the Client PIN parameters in the request as mentioned in the authenticatorGetAssertion steps.
-
If user verification is requested via a built-in user verification method, verify the user by built-in user verification method as mentioned in the authenticatorGetAssertion steps.
-
-
The authenticator calls decapsulate on the provided platform key-agreement key to obtain a shared secret.
-
Authenticator calls verify(shared secret, saltEnc, saltAuth)
-
If the verification fails, return CTAP2_ERR_PIN_AUTH_INVALID.
-
-
Authenticator obtains salt1 and salt2 by calling decrypt(shared secret, saltEnc). If the decryption fails, or if the result is not 32 or 64 bytes long, return CTAP1_ERR_INVALID_PARAMETER. Otherwise salt1 is the first 32 bytes of the result and salt2 is the remaining bytes, if any.
-
The authenticator chooses which
CredRandom
to use for next step based on whether user verification was done or not in above steps.-
If uv bit is set to 1 in the response, let
CredRandom
beCredRandomWithUV
. -
If uv bit is set to 0 in the response, let
CredRandom
beCredRandomWithoutUV
.
-
-
If the authenticator cannot find corresponding CredRandom associated with the credential, authenticator ignores this extension and does not add any response from this extension to "extensions" field of the authenticatorGetAssertion response.
-
The authenticator generates one or two HMAC-SHA-256 values, depending upon whether it received one salt (32 bytes) or two salts (64 bytes):
-
output1:
HMAC-SHA-256(CredRandom, salt1)
-
output2:
HMAC-SHA-256(CredRandom, salt2)
-
-
The authenticator returns output1 and (when there were two salts) output2, encrypted to the platform using the shared secret, as part of "extensions" parameter:
-
One salt case:
"hmac-secret":
encrypt(shared secret, output1) -
Two salt case:
"hmac-secret":
encrypt(shared secret, output1 || output2)
-
-
-
- Authenticator extension output
-
Same as the client extension output, except represented in CBOR.
13. Related Documents
The following documents are published by other organisations and are not referenced by this specification but may be relevant to the same audience. They are gathered here purely as informational resources and are not necessarily endorsed by FIDO.
-
Windows provides a WebAuthn-like API to applications.
-
Android provides a WebAuthn-like API and provides a mechanism for apps to claim domain names as valid RP IDs.
14. IANA Considerations
14.1. WebAuthn Extension Identifier Registrations
This section registers the extension identifier values defined in Section § 12 Defined Extensions in the IANA "WebAuthn Extension Identifiers" registry [IANA-WebAuthn-Registries] established by [RFC8809].
-
WebAuthn Extension Identifier: credProtect
-
This registration extension allows relying parties to specify a credential protection policy when creating a credential. Additionally, authenticators may choose to establish a default credential protection policy greater than
userVerificationOptional
(the lowest level) and unilaterally enforce such policy. -
Specification Document: Section § 12.1 Credential Protection (credProtect) of this specification
-
WebAuthn Extension Identifier: hmac-secret
-
Description: This registration extension and authentication extension enables the platform to retrieve a symmetric secret scoped to the credential from the authenticator.
-
Specification Document: Section § 12.5 HMAC Secret Extension (hmac-secret) of this specification
15. Security Considerations
See FIDO Security Reference document [FIDOSecRef].