From 2ec45f8b34638b0c62bb4208507bc4a76cd0ef4f Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Thu, 1 Aug 2024 11:56:53 -0700 Subject: [PATCH 1/2] Drop the supplementalPubKeys extension This extension will not have two interoperable implementations within the Level 3 timeframe. --- index.bs | 489 ------------------------------------------------------- 1 file changed, 489 deletions(-) diff --git a/index.bs b/index.bs index ff283ed22..096e6c486 100644 --- a/index.bs +++ b/index.bs @@ -1209,11 +1209,6 @@ BCP 14 [[!RFC2119]] [[!RFC8174]] when, and only when, they appear in all capital : {{PublicKeyCredentialDescriptor/transports}} :: The [$credential record/transports$] of the [=credential record=]. -: Supplemental public key -:: A additional public key, associated with a [=user credential=], that can be obtained (and exercised) with the [=supplementalPubKeys=] extension. These public keys provide more specific continuity signals. For example, a supplemental public key with `device` scope never leaves the device, while a [=multi-device credential=] can. Other supplemental public keys might have a broader scope, as described by their [=attestation=]. - - Supplemental public keys MUST NOT have a scope that exceeds the scope of their [=user credential=]—i.e. they never link two [=user credentials=] together. While this specification defines norms around scopes, [=[RPS]=] have to evaluate supplemental public keys in light of their [=attestation=], if any, and assign credibility to claimed scopes accordingly. - : Generating Authenticator :: The Generating Authenticator is the authenticator involved in the [=authenticatorMakeCredential=] operation resulting in the creation of a given [=public key credential source=]. The [=generating authenticator=] is the same as the [=managing authenticator=] @@ -5582,8 +5577,6 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o Note: Since all extensions are OPTIONAL for both the [=client=] and the [=authenticator=], the [=[RP]=] MUST also be prepared to handle cases where none or not all of the requested extensions were acted upon. - - Note: The [=supplementalPubKeys=] extension has explicit verification procedures, see [[#sctn-supplemental-public-keys-extension-verification-create]]. 1. Determine the attestation statement format by performing a USASCII case-sensitive match on |fmt| against the set of @@ -5815,8 +5808,6 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o Note: Since all extensions are OPTIONAL for both the [=client=] and the [=authenticator=], the [=[RP]=] MUST also be prepared to handle cases where none or not all of the requested extensions were acted upon. - - Note: The [=supplementalPubKeys=] extension has explicit verification procedures, see [[#sctn-supplemental-public-keys-extension-verification-get]]. 1. Let |hash| be the result of computing a hash over the |cData| using SHA-256. @@ -7212,486 +7203,6 @@ However, [=authenticators=] that do not utilize [[!FIDO-CTAP]] do not necessaril : Authenticator extension processing :: [=largeblob|This extension=] directs the user-agent to cause the large blob to be stored on, or retrieved from, the authenticator. It thus does not specify any direct authenticator interaction for [=[RPS]=]. - -## Authenticator Extensions ## {#sctn-defined-authenticator-extensions} - -This section defines extensions that are both [=client extensions=] and [=authenticator extensions=]. - -### Supplemental public keys extension (supplementalPubKeys) ### {#sctn-supplemental-public-keys-extension} - -This [=authenticator extension|authenticator=] [=registration extension=] and [=authentication extension=] provides a [=[RP]=] with additional public key(s) for credentials. This is done by creating [=user credential=]-specific key pairs on the [=authenticator=], when required key pairs do not already exist for the [=user credential=] being created or exercised, and returning these supplemental keys (along with signatures by them) to the [=[RP]=]. This is done each time this [=supplementalPubKeys=] extension is included with either a {{CredentialsContainer/create()|navigator.credentials.create()}} or {{CredentialsContainer/get()|navigator.credentials.get()}} call. - -If the [=authenticator=] is incapable of generating a supplemental key pair, or the registration or authentication operation fails for any reason, that key pair is omitted from the output. If no supplemental key pairs remain then this extension is ignored. In this case, there is no [=supplementalPubKeys=] extension output generated. - -Supplemental keys are not [=user credentials=] and they do not have their own [=credential IDs=]. Instead, any returned keys are a contextual attribute of their associated [=user credential=]. That is, when that [=user credential=] is used—along with the [=supplementalPubKeys=] extension—on a particular [=authenticator=], a particular set of supplemental keys are returned by the extension, along with signatures demonstrating proof-of-possession of those keys. - -Supplemental keys never have a scope that is larger than the [=user credential=]. That is, they are never shared between any two [=user credentials=] and can never be used to link two [=user credentials=] together. They only communicate continuity of some property of their associated [=user credential=]. - - -#### Relying Party Usage #### {#sctn-supplemental-public-keys-extension-usage} - -This extension is intended for use by those [=[RPS]=] employing risk-analysis systems informing their sign-in decisions. This extension signals the continuity of some property when used consistently with both {{CredentialsContainer/create()|navigator.credentials.create()}} and {{CredentialsContainer/get()|navigator.credentials.get()}} operations. The property being signaled depends on the scope of the supplemental key and its [=attestation=] statement, if any. The clearest example of a supplemental key is one that is device-bound. Repeated observation of a device-bound supplemental key indicates that a credential is being used repeatedly from the same device. (Which cannot be otherwise assumed in the case of [=backup eligible=] credentials.) But supplemental keys with wider scopes are also defined and the exact properties that they communicate depend on the attestation included along with them. - -When a [=[RP]=] uses the `supplementalPubKeys` extension with a {{CredentialsContainer/create()|create()}} call to create a new [=user credential=], a signature by one or more new supplemental keys may be returned along with the new supplemental public keys themselves. For the sake of example, assume that a single supplemental public key is returned, called “SPK1”. For as long as the [=user credential=] is exercised within the scope of the supplemental key, the [=[RP]=]'s subsequent {{CredentialsContainer/get()|get()}} operations for that credential will likely generate [=assertions=] including further signatures by “SPK1”. - -The credential may move beyond the scope of that supplemental key (for example, by being exported and imported elsewhere, if [=backup eligible=]) and, if used in this new domain, the {{CredentialsContainer/get()|get()}} operation will return a new supplemental key, SPK2, and its signature. Subsequent {{CredentialsContainer/get()|get()}} operations may observe either SPK1 or SPK2, depending on the context in which the [=user credential=] is being used. - -A usage example is thus: - -> A sign-in request is received by a website that, by regulation, must require certain authentication standards. The sign-in is done with a [=multi-device credential=], but also includes a supplemental key with an attestation that states that the supplemental key is only synced after a user has met or exceeded those standards. Since that supplemental key has been seen before, and was initially verified to meet the site's authentication standards, additional sign-in challenges are not required. - -Another example of supplemental keys: - -> Say that a sign-in request appears at a website along with some geolocation signal that has not been seen for this [=user account=] before, and is outside of the typical usage hours observed for the account. The risk may be deemed high enough not to allow the request, even with an assertion by a [=multi-device credential=] on its own. But if a signature from a supplemental key that is device-bound, and that is well established for this user can also be presented, then that may tip the balance. - -The weight that [=[RPS]=] give to the presence of a signature from a supplemental key may be based on information learned from its optional attestation. An attestation can indicate the level of protection enjoyed by a hardware-bound key, or the policies for other types of supplemental key. - -#### Extension Definition #### {#sctn-supplemental-public-keys-extension-definition} - -: Extension identifier -:: `supplementalPubKeys` - -: Operation applicability -:: [=registration extension|Registration=] and [=authentication extension|authentication=] - -: Client extension input -:: - dictionary AuthenticationExtensionsSupplementalPubKeysInputs { - required sequence<DOMString> scopes; - DOMString attestation = "indirect"; - sequence<DOMString> attestationFormats = []; - }; - - partial dictionary AuthenticationExtensionsClientInputs { - AuthenticationExtensionsSupplementalPubKeysInputs supplementalPubKeys; - }; - -
- : scopes - :: This required member MUST be non-empty. It specifies the scopes of supplemental public keys that the [=[RP]=] requests. Values are taken from the CDDL below (i.e., currently defined values are `provider` and `device`); authenticators silently ignore unrecognized values. Specifying the scopes that a [=[RP]=] can use allows an [=authenticator=] to avoid the work of generating superfluous supplemental keys. - - : attestation - :: The [=[RP]=] MAY use this OPTIONAL member to specify a preference regarding [=attestation conveyance=]. - Its value SHOULD be a member of {{AttestationConveyancePreference}}. - [=Client platforms=] MUST ignore unknown values, treating an unknown value as if the [=map/exist|member does not exist=]. - - The default value is {{AttestationConveyancePreference/indirect}}. - - : attestationFormats - :: The [=[RP]=] MAY use this OPTIONAL member to specify a preference regarding the [=attestation=] statement format used by the [=authenticator=]. - Values SHOULD be taken from the IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]]. - Values are ordered from most preferable to least preferable. - This parameter is advisory and the [=authenticator=] MAY use an attestation statement not enumerated in this parameter. - - The default value is the empty list, which indicates no preference. -
- -: Client extension processing -:: If {{AuthenticationExtensionsClientInputs/supplementalPubKeys}} is present, the client creates the authenticator extension input from the client extension input. - -: Client extension output -:: A sequence of {{ArrayBuffer}}s containing the signatures returned as the [=unsigned extension output=]. - - dictionary AuthenticationExtensionsSupplementalPubKeysOutputs { - required sequence<ArrayBuffer> signatures; - }; - - partial dictionary AuthenticationExtensionsClientOutputs { - AuthenticationExtensionsSupplementalPubKeysOutputs supplementalPubKeys; - }; - - - -: Authenticator extension input -:: A CBOR expression of the client extension input - - ``` - supplementalPublicKeyInputs = { - scopes: [+ - ; A key that has a broader scope than a single device, but still more - ; limited than a multi-device credential. The precise scope is specified - ; by the attestation of this supplemental public key. - "provider" / - - ; A key with "device" scope MUST NOT leave the device on which it is - ; created. - "device"], - attestation: tstr, - attestationFormats: [* tstr], - } - $$extensionInput //= ( - supplementalPubKeys: supplementalPublicKeyInputs, - ) - ``` - -: Authenticator extension output -:: The supplemental public key attestation objects, defined by the `attObjForSupplementalPubKey` type: - - ``` - $$extensionOutput //= ( - ; This array of supplemental public keys MUST be ordered - ; lexicographically by scope and MUST NOT include more than one element - ; with a given scope. - - supplementalPubKeys: [+ attObjForSupplementalPubKey], - ) - - ; This object conveys an attested supplemental public key and is analogous - ; to \`attObj\`. - attObjForSupplementalPubKey = { - aaguid: bstr, ; AAGUID (16 bytes fixed-length) - ; https://www.w3.org/TR/webauthn/#aaguid - - spk: bstr, ; The public key (self-describing variable length, - ; COSE_Key format, CBOR-encoded)). - - ; See the definition of `scopes` in `supplementalPublicKeyInputs`. - - scope: "provider" / "device", - - ; An authenticator-generated random nonce for inclusion in the attestation - ; signature. If the authenticator chooses to not generate a nonce, it sets this - ; to a zero-length byte string. See the note below about "randomNonce" for a - ; discussion on the nonce's purpose. - - nonce: bstr .size (0..32), - - ; See https://www.w3.org/TR/webauthn/#sctn-generating-an-attestation-object - ; - ; Attestation statement formats define the \`fmt\` and \`attStmt\` members of - ; $$attStmtType. - ; Note that \`fmt\` and \`attStmt\` are top-level members of - ; \`attObjForSupplementalPubKey\`. - ; - ; In summary, the \`attStmt\` will (typically) contain: - ; (1) a SIGNATURE value calculated (using the attestation private key) - ; over (prefix || aaguid || spk || nonce) where \`prefix\` is - ; h'737570706c656d656e74616c5075624b657973206174746573746174696f6e2e - ; 00ffffffff'. - ; (See the attestation calculations section, below, for a discussion - ; about the purpose of this \`prefix\` value.) - ; (2) the attestation certificate or public key, and supporting certificates, - ; if any. - ; - ; Note that there are details dependent upon the particular attestation - ; statement format. - ; See https://www.w3.org/TR/webauthn/#sctn-defined-attestation-formats. - - $$attStmtType, - - ; An optional boolean that indicates whether the attestation statement - ; contains uniquely identifying information. This can only be true - ; when the \`attestation\` field of the extension input is "enterprise" - ; and either the user-agent or the authenticator permits uniquely - ; identifying attestation for the requested RP ID. - - ? epAtt: bool .default false, - } - - ``` - -: Unsigned extension output -:: A non-empty CBOR array of byte strings containing the signatures generated with the supplemental private keys, in the same order as in the authenticator extension output. - - ``` - supplementalPublicKeyOutputs = [+ bstr] - - $$unsignedExtensionOutputs //= ( - supplementalPubKeys: supplementalPublicKeyOutputs, - ) - ``` - -: Authenticator extension processing -:: For both [=authenticatorMakeCredential=] and [=authenticatorGetAssertion=] operations: - 1. Create or select the [=public key credential source=] as usual (see [[#sctn-op-make-cred]], or [[#sctn-op-get-assertion]] as appropriate). - - 1. Let |scopes| be the [=set=] of all supplemental public key scopes that the [=authenticator=] supports. Update |scopes| to be the [=set/intersection=] of itself and {{AuthenticationExtensionsSupplementalPubKeysInputs/scopes}}. If |scopes| is empty, terminate these processing steps with no extension output. - - 1. Let |spks| and |spkSigs| be empty arrays. - - 1. Sort |scopes| lexicographically. - - 1. [=map/For each=] |scope| in |scopes|: - - 1. If a supplemental key with scope |scope| does not already exist for this {[=public key credential source/id|Credential ID=], [=public key credential source/rpId|RP ID=], [=public key credential source/rpId|userHandle=]} tuple on the [=authenticator=], create it using the same public key algorithm as that used by the [=user credential=]'s [=credential key pair=], otherwise locate the existing supplemental key. - - 1. Let |attFormat| be the chosen [=attestation statement format=], and |attAaguid| be a 16-byte value, based on the value of {{AuthenticationExtensionsSupplementalPubKeysInputs/attestation}} in the extension input: - -
- : none - :: |attFormat| is "none" or "self", at the authenticator's discretion, and |attAaguid| is 16 zero bytes. (Note that, since the [=supplemental public key=] is already exercised during {{CredentialsContainer/create()|navigator.credentials.create()}} calls, the proof-of-possession property provided by "self" attestation is superfluous in that context.) - - : indirect, direct - :: |attFormat| is an [=attestation statement format=] appropriate for this [=authenticator=] based on {{AuthenticationExtensionsSupplementalPubKeysInputs/attestationFormats}}, and |attAaguid| is the corresponding [=/AAGUID=], which MAY be the [=authenticator's=] AAGUID. (Since the [=supplemental public key=]'s scope is different from the [=user credential=], it will often have a different attestation. For example, the attestation for a [=supplemental public key=] with “device” scope can be tied to hardware roots of trust, although it does not have to be.) - - : enterprise - :: The [=[RP]=] wants to receive an [=attestation statement=] 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. [=Authenticators=] MUST NOT provide such an attestation unless the user agent or authenticator configuration expressly permits it for the requested [=RP ID=]. If not permitted, then follow the steps for `direct` attestation. Otherwise |attFormat| is an [=attestation statement format=] appropriate for this [=authenticator=] based on {{AuthenticationExtensionsSupplementalPubKeysInputs/attestationFormats}}, and |attAaguid| is the corresponding [=/AAGUID=], which MAY be the [=authenticator's=] AAGUID. - - Note: CTAP2 does not currently provide for an enterpriseAttestation signal during an authenticatorGetAssertion call. Until that is changed, platform-managed enterprise attestation will not work in that context with CTAP2 [=authenticators=]. -
- - 1. Let |spk| be the newly created or existing supplemental public key, in COSE_Key format [=credentialPublicKey|in the same fashion as for the user credential's credentialPublicKey=] when the latter is conveyed in [=attested credential data=]. - - 1. Let |supplementalPrivateKey| be the newly created or existing private key corresponding to |spk|. - - 1. Let |randomNonce| be a fresh randomly-generated byte string of 32 bytes maximum length, or a zero length byte string if the authenticator chooses to not generate a nonce. - - Note: |randomNonce|'s purpose is to randomize the [=attestation signature=] value for [=supplemental public keys=]. If this is not done, then an [=attestation signature=] value remains constant for all such signatures issued on behalf of this [=user credential=], possibly exposing the [=authenticator=]'s [=attestation private key=] to side-channel attacks. The randomness-generation mechanism should be carefully chosen by the authenticator implementer. - - 1. Let |supplementalPubKey| be a [=CBOR=] map as defined by `attObjForSupplementalPubKey` above, with keys and values as follows: - - Note: as with all CBOR structures used in this specification, the [=CTAP2 canonical CBOR encoding form=] MUST be used. - - 1. Set a key and value for the `scope` group based on the value of |scope|. - - 1. Let the `aaguid` key's value be |attAaguid|. - - 1. Let the `spk` key's value be |spk|. - - 1. Let the `nonce` key's value be |randomNonce|. - - 1. Let the values of the `$$attStmtType` [=group socket=] be the result of generating an [=attestation statement=] with the [=attestation statement format=], |attFormat|. See [[#sctn-supplemental-public-keys-attestation-calculations]]. - - Note: The details of the `$$attStmtType` values are dependent upon the particular [=attestation statement=] format. See [[#sctn-attestation-formats]]. - - 1. If the `$$attStmtType` [=group socket=] contains uniquely identifying information then let `epAtt` be [TRUE]. Otherwise omit the `epAtt` field. (This field can only be [TRUE] when the {{AuthenticationExtensionsSupplementalPubKeysInputs/attestation}} field of the extension input is "enterprise" and either the user-agent or the authenticator permits uniquely identifying attestation for the requested RP ID.) - - 1. Append |supplementalPubKey| to |spks|. - - 1. Let |spkSig| be the result of signing the [=assertion signature=] [input](#fig-signature) with |supplementalPrivateKey|. - - Note: the [=assertion signature=] [input](#fig-signature), and thus |spkSig|, covers the [=[RP]=]'s {{PublicKeyCredentialCreationOptions/challenge}} because it includes the [=hash of the serialized client data=]. Thus the [=[RP]=] knows that |spkSig| is a fresh signature. - - 1. Append |spkSig| to |spkSigs|. - - 1. Let the `supplementalPubKeys` [=authenticator extension output=] value be the CBOR array |spks|. - - 1. Let the CBOR encoding of |spkSigs| be the extension's [=unsigned extension output=]. - - Note: |spkSigs| cannot be included in the [=authenticator extension output=] because it is returned inside the [=authenticator data=] and that would imply that the signature signs over itself. - -##### AAGUIDs ##### {#sctn-supplemental-public-keys-attestation-aaguid} - -Any non-zero [=/AAGUID=]s included in the [=supplementalPubKeys=] extension output aid a [=[RP]=] in validating the [=attestation statement=] of the supplemental public key. The interpretation of each AAGUID depends on the scope of the corresponding key. Some or all may differ from the [=authData/attestedCredentialData/aaguid=] in the [=attested credential data=] of a [=multi-device credential=]. Thus the AAGUID of a [=supplemental public key=] MAY be different in a single response and either, or both, may be zero depending on the options requested and authenticator behaviour. - -##### Attestation calculations ##### {#sctn-supplemental-public-keys-attestation-calculations} - -When computing attestations, the process in [[#sctn-generating-an-attestation-object]] takes two inputs: `authData` and `hash`. When calculating an attestation for a supplemental public key, the typical value for `authData` contains the attestation signature itself, which is impossible. Also the attestation of a supplemental public key is potentially used repeatedly, thus may want to be cached. But signing over values that include [=[RP]=]-chosen nonces, like the [=hash of the serialized client data=], makes that impossible. - -Therefore when calculating an attestation for a supplemental public key, the inputs are: - - * For `authData`, substitute the concatenation of the byte string h'737570706c656d656e74616c5075624b657973206174746573746174696f6e2e00ffffffff' and the value of |aaguid| from the extension output. - * For `hash`, substitute the concatenation of the |spk| and |nonce| fields from the extension output. (The nonce MAY be empty.) - -The attestation signature is thus typically calculated over the bytes of (h'737570706c656d656e74616c5075624b657973206174746573746174696f6e2e00ffffffff' || |aaguid| || |spk| || |nonce|). The 37-byte prefix ensures domain separation: it takes the place of the RP ID hash, flags, and signature counter fields in those messages and ensures that no attestation signature for a supplemental public key can be confused with a signature for a [=user credential=]. - -Note that when |nonce| is empty, then the (signed) authenticator extension output MAY be constant. However, the (unsigned) |spkSig| output is always unique and prevents replay of the (signed) extension output without knowledge of the supplemental private key. - -#### `supplementalPubKeys` Extension Output Verification Procedures #### {#sctn-supplemental-public-keys-extension-verification} - -Verifying the [=supplementalPubKeys=] extension output is performed by the [=[RP]=] whenever a supplemental public key is returned within the extension output. - -The [=supplementalPubKeys=] extension adds the following [=struct/item=] to [=credential records=]: - -
- : supplementalPubKeys - :: An initially [=set/empty=] [=set=] of [=supplemental public key records=] associated with this [=public key credential source=]. - - A supplemental public key record is an abstract representation of a registered supplemental public key. - It is a [=struct=] with the following [=struct/items=]: - -
- : aaguid - :: The [=/AAGUID=] included with the supplemental public key. - This MAY be different from the [=authData/attestedCredentialData/aaguid=] in the [$credential record/attestationObject$], if any, of the containing [=credential record=]. - - : spk - :: The public key portion of the supplemental public key. - - : scope - :: The scope of the supplemental public key. See [[#sctn-supplemental-public-keys-extension-definition]] for details. - - : fmt - :: The [=attestation statement format=] of the supplemental public key's [=attestation statement=]. - - : attStmt - :: The supplemental public key's [=attestation statement=]. -
-
- - -##### Registration (`create()`) ##### {#sctn-supplemental-public-keys-extension-verification-create} - -If the [=[RP]=] requested the `supplementalPubKeys` extension in a {{CredentialsContainer/create()|navigator.credentials.create()}} call, -then the below verification steps are performed in the context of [step 20](#reg-ceremony-verify-extension-outputs) -of [[#sctn-registering-a-new-credential]] using these variables established therein: |credential|, |clientExtensionResults|, |authData|, and |hash|. -[=[RP]=] policy may specify whether a response without a `supplementalPubKeys` extension output is acceptable. - -1. Verify that the {{AuthenticationExtensionsClientOutputs/supplementalPubKeys}} member of |clientExtensionResults| exists, and contains the {{AuthenticationExtensionsSupplementalPubKeysOutputs/signatures}} field. Let |signatures| be the value of that field. - -1. Let |attObjsForSupplementalPublicKey| be the value of the `supplementalPubKeys` member of the [=authenticator extension output=] from |authData|. - -1. If the [=list/size=] of |attObjsForSupplementalPublicKey| is not equal to the [=list/size=] of |signatures| then abort the registration process with an error. - -1. [=list/Iterate=] over the indices of |attObjsForSupplementalPublicKey| (which, after the check in the previous step, must also be the indices of |signatures|). Then, for each (|attObjForSupplementalPubKey|, |signature|) from the two lists: - - 1. Extract the contained fields from |attObjForSupplementalPubKey|: |aaguid|, |spk|, |nonce|, |fmt| and |attStmt|. Also let |scope| reflect the scope, specified by the member of the `scope` group that is present. - - Note: The latter |attObjForSupplementalPubKey| fields are referenced exclusively in the below steps and are not to be confused with other fields with the same names in other portions of the top-level [=attestation object=]. - - 1. Verify that |signature| is a valid signature over the [=assertion signature=] [input](#fig-signature) (i.e. `authData` and `hash`) by the [=supplemental public key=] |spk|. (The signature algorithm is the same as for the [=user credential=].) - - 1. Optionally, if attestation was requested and the [=[RP]=] wishes to verify it, verify that |attStmt| is a correct [=attestation statement=], conveying a valid [=attestation signature=], by using the [=attestation statement format=] |fmt|'s [=verification procedure=] given |attStmt|. See [[#sctn-supplemental-public-keys-attestation-calculations]]. [=[RP]=] policy may specifiy which attestations are acceptable. - - Note: If |fmt|'s value is "[=none=]" there is no attestation signature to verify. - - 1. Create a new [=supplemental public key record=] with the contents: - -
- : [$supplementalPubKeys record/aaguid$] - :: The value of |aaguid|. - - : [$supplementalPubKeys record/spk$] - :: The value of |spk|. - - : [$supplementalPubKeys record/scope$] - :: The value of |scope|. - - : [$supplementalPubKeys record/fmt$] - :: The value of |fmt|. - - : [$supplementalPubKeys record/attStmt$] - :: The value of |attStmt|. -
- - In [step 27](#reg-ceremony-store-credential-record) of [[#sctn-registering-a-new-credential]], - add this [=supplemental public key record=] to the [$credential record/supplementalPubKeys$] member of the new [=credential record=]. - -See also [[#sctn-supplemental-public-keys-extension-usage]] for further details. - -##### Authentication (`get()`) ##### {#sctn-supplemental-public-keys-extension-verification-get} - -If the [=[RP]=] requested the `supplementalPubKeys` extension in a {{CredentialsContainer/get()|navigator.credentials.get()}} call, -then the below verification steps are performed in the context of [step 19](#authn-ceremony-verify-extension-outputs) -of [[#sctn-verifying-assertion]] using these variables established therein: |credential|, |clientExtensionResults|, |authData|, |hash|, and |credentialRecord|. -[=[RP]=] policy may specify whether a response without a `supplementalPubKeys` extension output is acceptable. - -1. Let |recognizedSpks| be a new [=set/empty=] [=set=]. - -1. Verify that the {{AuthenticationExtensionsClientOutputs/supplementalPubKeys}} member of |clientExtensionResults| exists, and contains the {{AuthenticationExtensionsSupplementalPubKeysOutputs/signatures}} field. Let |signatures| be the value of that field. - -1. Let |attObjsForSupplementalPubKeys| be the value of the `supplementalPubKeys` member of the [=authenticator extension output=] from |authData|. - -1. If the [=list/size=] of |attObjsForSupplementalPubKeys| is not equal to the [=list/size=] of |signatures| then abort the authentication process with an error. - -1. [=list/Iterate=] over the indices of |attObjsForSupplementalPubKeys| (which, after the check in the previous step, must also be the indices of |signatures|). Then, for each (|attObjForSupplementalPubKey|, |signature|) from the two lists: - - 1. Extract the contained fields from |attObjForSupplementalPubKey|: |aaguid|, |spk|, |nonce|, |fmt|, |attStmt|. Also let |scope| reflect the scope, specified by the member of the `scope` group that is present. - - Note: The latter |attObjForSupplementalPubKey| fields are referenced exclusively in the below steps and are not to be confused with other fields with the same names in other portions of [=authenticator data=]. - - 1. Verify that |signature| is a valid signature over the [=assertion signature=] [input](#fig-signature) (i.e. `authData` and `hash`) by the [=supplemental public key=] |spk|. (The signature algorithm is the same as for the [=user credential=].) - - 1. Let |matchedSpkRecords| be a new [=set/empty=] [=set=]. - [=set/For each=] |spkRecord| in |credentialRecord|.[$credential record/supplementalPubKeys$]: - 1. If |spkRecord|.[$supplementalPubKeys record/aaguid$] equals |aaguid|, - |spkRecord|.[$supplementalPubKeys record/spk$] equals |spk|, - and |spkRecord|.[$supplementalPubKeys record/scope$] equals |scope|: - 1. [=set/Append=] |spkRecord| to |matchedSpkRecords|. - - 1. If |matchedSpkRecords| - -
- : has [=set/size=] greater than one: - :: Some form of error has occurred: |credentialRecord| invariants have been broken. Terminate these verification steps. - - : has [=set/size=] equal to one: - :: This is a known [=supplemental public key=] - - If |fmt|'s value is "none" then there is no attestation signature to verify and this is a known [=supplemental public key=] with a valid signature. Append |spkRecord| to |recognizedSpks| and continue to the next iteration, if any. - - Otherwise, let |spkRecord| be |matchedSpkRecords|[0]. If the |attStmt| in |attObjForSupplementalPubKey|: -
- : equals |spkRecord|.[$supplementalPubKeys record/attStmt$] by binary equality: - :: This is a known [=supplemental public key=] with a valid signature and valid attestation. Append |spkRecord| to |recognizedSpks| and continue to the next iteration, if any. - - Note: This authenticator is not generating a fresh per-response random nonce. - - : does not equal |spkRecord|.[$supplementalPubKeys record/attStmt$] by binary equality: - :: Optionally, if attestation was requested and the RP wishes to verify it, verify that |attStmt| is a correct [=attestation statement=], conveying a valid [=attestation signature=], by using the [=attestation statement format=] |fmt|'s [=verification procedure=] given |attStmt|. See [[#sctn-supplemental-public-keys-attestation-calculations]]. [=[RP]=] policy may specifiy which attestations are acceptable. - - If the result is: - -
- : successful - :: This is a known [=supplemental public key=] with a valid signature and valid attestation. Append |spkRecord| to |recognizedSpks| and continue to the next iteration, if any. - - : unsuccessful - :: Some form of error has occurred. It is indeterminate whether this is a valid [=supplemental public key=]. Either terminate these verification steps with an error or continue to the next iteration, if any, to ignore this key. - -
-
- - : is [=set/empty=]: - :: This is possibly a new [=supplemental public key=]. - - 1. Let |matchedSpkKeys| be a new [=set/empty=] [=set=]. - [=set/For each=] |spkRecord| in |credentialRecord|.[$credential record/supplementalPubKeys$]: - 1. If |spkRecord|.[$supplementalPubKeys record/spk$] equals |spk|: - 1. [=set/Append=] |spkRecord| to |matchedSpkKeys|. - - 1. If |matchedSpkKeys| is [=set/empty=]: - -
- : If |fmt|'s value is "none": - :: There is no attestation signature to verify and this is a new supplemental key. Unless [=[RP]=] policy specifies that this attestation is unacceptable, [$Create a new supplemental public key record$] and then continue to the next iteration, if any. - - : Otherwise: - :: Optionally, if attestation was requested and the RP wishes to verify it, verify that |attStmt| is a correct [=attestation statement=], conveying a valid [=attestation signature=], by using the [=attestation statement format=] |fmt|'s [=verification procedure=] given |attStmt|. See [[#sctn-supplemental-public-keys-attestation-calculations]]. [=[RP]=] policy may specifiy which attestations are acceptable. - - If the result is: - -
- : successful - :: This is a new [=supplemental public key=]. [$Create a new supplemental public key record$] then continue to the next iteration, if any. - - : unsuccessful - :: Some form of error has occurred and a supplemental public key record cannot be created. Either terminate these verification steps with an error or continue to the next iteration, if any, to ignore this supplemental public key. -
-
- - 1. Otherwise there is some form of error: we recieved a known |spk| value, but one or more of the accompanying |aaguid| or |scope| values did not match what the [=[RP]=] has stored along with that |spk| value. Terminate these verification steps. -
- -At the end of these steps, |recognizedSpks| contains zero or more [=supplemental public keys=] that were previously known for this [=user credential=]. These keys make claims about the continuity of certain factors between this authentication attempt and previous ones. The [=[RP]=] should judge those claims in light of the attestations provided, if any, and evaluate the risk of this authentication in light of this information. - -See also [[#sctn-supplemental-public-keys-extension-usage]]. - -To Create a new supplemental public key record, perform the following steps: - - 1. Create a new [=supplemental public key record=] with the contents: - -
- : [$supplementalPubKeys record/aaguid$] - :: The value of |aaguid|. - - : [$supplementalPubKeys record/spk$] - :: The value of |spk|. - - : [$supplementalPubKeys record/scope$] - :: The value of |scope|. - - : [$supplementalPubKeys record/fmt$] - :: The value of |fmt|. - - : [$supplementalPubKeys record/attStmt$] - :: The value of |attStmt|. -
- - In [step 23](#authn-ceremony-update-credential-record) of [[#sctn-verifying-assertion]], - [=set/append=] this [=supplemental public key record=] to |credentialRecord|.[$credential record/supplementalPubKeys$]. - - # User Agent Automation # {#sctn-automation} For the purposes of user agent automation and [=web application=] testing, this document defines a number of [[WebDriver]] [=extension commands=]. From c6defa8da7ed656784d609b6ac8821123e242091 Mon Sep 17 00:00:00 2001 From: Emil Lundberg Date: Wed, 7 Aug 2024 21:58:52 +0200 Subject: [PATCH 2/2] Restore (empty) Authenticator Extensions section --- index.bs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/index.bs b/index.bs index 096e6c486..125ed3d20 100644 --- a/index.bs +++ b/index.bs @@ -7203,6 +7203,14 @@ However, [=authenticators=] that do not utilize [[!FIDO-CTAP]] do not necessaril : Authenticator extension processing :: [=largeblob|This extension=] directs the user-agent to cause the large blob to be stored on, or retrieved from, the authenticator. It thus does not specify any direct authenticator interaction for [=[RPS]=]. + +## Authenticator Extensions ## {#sctn-defined-authenticator-extensions} + +This section defines extensions that are both [=client extensions=] and [=authenticator extensions=]. + +This section is currently empty. + + # User Agent Automation # {#sctn-automation} For the purposes of user agent automation and [=web application=] testing, this document defines a number of [[WebDriver]] [=extension commands=].