diff --git a/index.bs b/index.bs
index 3f0f1b832..bd25faf3e 100644
--- a/index.bs
+++ b/index.bs
@@ -413,65 +413,45 @@ This method takes the following parameters:
When this method is invoked, the user agent MUST execute the following algorithm:
-1. If the {{ScopedCredentialOptions/timeout}} member of {{options}} is present, check if its value lies within a reasonable range as defined by
- the platform and if not, correct it to the closest value lying within that range. Set |adjustedTimeout| to this adjusted
- value. If {{ScopedCredentialOptions/timeout}} was not specified, then set |adjustedTimeout| to a platform-specific
- default.
+1. If the {{ScopedCredentialOptions/timeout}} member of {{options}} is present, check if its value lies within a
+ reasonable range as defined by the platform and if not, correct it to the closest value lying within that range. Set
+ |adjustedTimeout| to this adjusted value. If {{ScopedCredentialOptions/timeout}} was not specified, then set
+ |adjustedTimeout| to a platform-specific default.
- Issue: Put some constraints on the "reasonable range".
+1. Set |callerOrigin| to the current settings object's origin. If |callerOrigin| is an opaque origin,
+ return [=a promise rejected with=] a {{DOMException}} whose name is "{{NotAllowedError}}", and terminate this algorithm.
-1. Set |callerOrigin| to the current settings object's origin. If |callerOrigin| is
- an opaque origin, [=reject=] |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and
- terminate this algorithm.
-
-1. If the {{ScopedCredentialOptions/rpId}} member of {{options}} is not present, then set |rpId| to
- |callerOrigin|. Otherwise,
+1. If the {{ScopedCredentialOptions/rpId}} member of {{options}} is not present, then set |rpId| to |callerOrigin|.
+ Otherwise,
1. Let |effectiveDomain| be the |callerOrigin|'s effective domain.
- 1. If |effectiveDomain| is null, then reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}"
- and terminate this algorithm.
- 1. If {{ScopedCredentialOptions/rpId}} is not a registrable domain suffix of and is not equal to
- |effectiveDomain|, reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}", and
- terminate this algorithm.
+ 1. If |effectiveDomain| is null, then return [=a promise rejected with=] a {{DOMException}} whose name is
+ "{{SecurityError}}" and terminate this algorithm.
+ 1. If {{ScopedCredentialOptions/rpId}} is not a registrable domain suffix of and is not equal to |effectiveDomain|,
+ return [=a promise rejected with=] a {{DOMException}} whose name is "{{SecurityError}}", and terminate this algorithm.
1. Set |rpId| to the {{ScopedCredentialOptions/rpId}}.
- Issue(w3c/webauthn#259): The rest of this algorithm assumes |rpId| is an
- [=origin=], but the above step sometimes produces a string.
-
-1. Let |normalizedParameters| be a new [=list=] whose [=list/items=] are pairs of
- ScopedCredentialType and a [=dictionary=] type (as returned by [=normalizing
- an algorithm=]).
+1. Let |normalizedParameters| be a new [=list=] whose [=list/items=] are pairs of ScopedCredentialType and a [=dictionary=] type
+ (as returned by [=normalizing an algorithm=]).
1. [=list/For each=] |current| of {{cryptoParameters}}:
- 1. If |current|.{{ScopedCredentialParameters/type}}
does not
- contain a {{ScopedCredentialType}} supported by this implementation,
- then [=continue=].
- 1. Let |normalizedAlgorithm| be the result of normalizing an algorithm
- [[!WebCryptoAPI]], with |alg| set to
- |current|.{{algorithm}}
and |op| set to `"generateKey"`. If
- an error occurs during this procedure, then [=continue=].
- 1. [=list/Append=] the pair of
- |current|.{{ScopedCredentialParameters/type}}
and
- |normalizedAlgorithm| to |normalizedParameters|.
-
-1. If |normalizedParameters| is empty and {{cryptoParameters}} was not empty,
- cancel the timer started in step 2, return [=a promise rejected with=] with
- a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this
- algorithm.
+ 1. If |current|.{{ScopedCredentialParameters/type}}
does not contain a {{ScopedCredentialType}} supported by
+ this implementation, then [=continue=].
+ 1. Let |normalizedAlgorithm| be the result of normalizing an algorithm [[!WebCryptoAPI]], with |alg| set to
+ |current|.{{algorithm}}
and |op| set to `"generateKey"`. If an error occurs during this procedure, then
+ [=continue=].
+ 1. [=list/Append=] the pair of |current|.{{ScopedCredentialParameters/type}}
and |normalizedAlgorithm| to
+ |normalizedParameters|.
+
+1. If |normalizedParameters| is empty and {{cryptoParameters}} was not empty, cancel the timer started in step 2, return
+ [=a promise rejected with=] with a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this algorithm.
1. Let |clientExtensions| be a new [=list=].
-1. If the {{ScopedCredentialOptions/extensions}} member of {{options}} is
- present, then [=map/for each=] |extension| → |argument| of
- {{options}}.{{ScopedCredentialOptions/extensions}}
:
- 1. If |extension| is not supported by this client platform, then either:
- * [=Continue=], or
- * Let |result| be a CBOR ([[!RFC7049]]) encoding of |extension|.
-
- Issue(w3c/webauthn#363): Define this encoding more precisely.
- 1. Otherwise, let |result| be the result of running |extension|'s [=client
- processing=] algorithm on |argument|. If the algorithm returned an
- error, [=continue=].
-
- Issue(w3c/webauthn#363): Ensure all extensions define a client
- processing algorithm.
+1. If the {{ScopedCredentialOptions/extensions}} member of {{options}} is present, then [=map/for each=]
+ |extension| → |argument| of {{options}}.{{ScopedCredentialOptions/extensions}}
:
+ 1. If |extension| is not supported by this client platform, then [=continue=].
+
+ 1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
+ algorithm returned an error, [=continue=].
+
1. [=list/Append=] |result| to |clientExtensions|.
1. Let |clientData| be a new {{ClientData}} instance whose fields are:
@@ -480,104 +460,70 @@ When this method is invoked, the user agent MUST execute the following algorithm
: {{origin}}
:: The [=unicode serialization of an origin|unicode serialization=] of |rpId|
: {{hashAlg}}
- :: UA-chosen
-
- Issue(w3c/webauthn#362): We need *some* constraints on the possible hash
- algorithms, or else sites will fail on unusual UAs.
+ :: The [=recognized algorithm name=] of the hash algorithm selected by the client for generating the
+ [=hash of the client data=]
: {{tokenBinding}}
:: The [=Token Binding ID=] associated with |callerOrigin| (if any)
-
- Issue(w3c/webauthn#360): Make sure this association was set up properly.
: {{ClientData/extensions}}
:: |clientExtensions|
-1. Let |clientDataJSON| be the [=UTF-8 encoding=] of the result of calling the
- initial value of {{JSON/stringify|JSON.stringify}} on |clientData|.
+1. Let |clientDataJSON| be the [=JSON-serialized client data=] constructed from |clientData|.
- Issue: Some extensions contain ArrayBuffers, which don't stringify well.
- What's the intent here?
-1. Let |clientDataHash| be the hash of |clientDataJSON| using
- |clientData|.{{hashAlg}}
.
+1. Let |clientDataHash| be the [=hash of the client data=] represented by |clientData|.
-1. Let |issuedRequests| and |currentlyAvailableAuthenticators| be new [=ordered
- sets=].
+1. Let |issuedRequests| and |currentlyAvailableAuthenticators| be new [=ordered sets=].
1. For each |authenticator| currently available on this platform, if
- {{options}}.{{ScopedCredentialOptions/attachment}}
is not
- [=present=] or its value matches |authenticator|'s attachment modality,
- [=set/append=] |authenticator| to |currentlyAvailableAuthenticators|.
+ {{options}}.{{ScopedCredentialOptions/attachment}}
is not [=present=] or its value matches |authenticator|'s
+ attachment modality, [=set/append=] |authenticator| to |currentlyAvailableAuthenticators|.
1. [=set/For each=] |authenticator| in |currentlyAvailableAuthenticators|:
1. Let |excludeList| be a new [=list=].
1. [=list/For each=] credential |C| in {{options}}.{{ScopedCredentialOptions/excludeList}}
:
- 1. If |C| has an empty {{transports}} list, [=list/append=] |C| to
- |excludeList| and [=continue=].
- 1. If |authenticator| is connected over a transport not mentioned in
+ 1. If |C| has a non-empty {{transports}} list, and |authenticator| is connected over a transport not mentioned in
|C|.{{transports}}
, the client MAY [=continue=].
-
- Issue: I'm not sure this captures the intent of the original wording.
- 1. [=list/Append=] |C| to |excludeList|.
- 1. [=In parallel=], invoke the authenticatorMakeCredential operation
- on |authenticator| with |rpId|, |clientDataHash|,
- {{accountInformation}}, |normalizedParameters|, |excludeList| and
- |clientExtensions| as parameters.
+ 1. Otherwise, [=list/Append=] |C| to |excludeList|.
+ 1. [=In parallel=], invoke the authenticatorMakeCredential operation on |authenticator| with |rpId|,
+ |clientDataHash|, {{accountInformation}}, |normalizedParameters|, |excludeList| and |clientExtensions| as parameters.
1. [=set/Append=] |authenticator| to |issuedRequests|.
-1. Let |promise| be [=a new promise=]. Return |promise| and start a timer for |adjustedTimeout| milliseconds.
- Then execute the following steps [=in parallel=]. If any fatal error is encountered in this algorithm other than the
- ones enumerated below, cancel the timer, [=reject=] |promise| with a DOMException whose name is "{{UnknownError}}", and terminate
- this algorithm.
-
- Issue: What kinds of fatal errors are you worried about? I suggest we just
- remove that sentence.
+1. Let |promise| be [=a new promise=]. Return |promise| and start a timer for |adjustedTimeout| milliseconds. Then execute the
+ following steps [=in parallel=].
1. While |issuedRequests| is not empty, perform the following actions depending upon the |adjustedTimeout| timer and responses
from the authenticators:
|C|.{{ClientData/hashAlg}}
.
+6. Compute the hash of {{ScopedCredentialInfo/clientDataJSON}} using the algorithm identified by
+ |C|.{{ClientData/hashAlg}}
.
7. Perform CBOR decoding on the {{ScopedCredentialInfo/attestationObject}} field of the {{ScopedCredentialInfo}} structure to
obtain the attestation statement format |fmt|, the authenticator data |authData|, and the attestation statement |attStmt|.
@@ -1603,7 +1551,7 @@ ceremony, a [RP] MUST proceed as follows:
WebAuthn Attestation Statement Format Identifiers given in the IANA Registry of the same name [[WebAuthn-Registries]].
10. Verify that |attStmt| is a correct, validly-signed attestation statement, using the attestation statement format |fmt|'s
- verification procedure given authenticator data |authData| and the clientDataHash computed in step 6.
+ verification procedure given authenticator data |authData| and the [=hash of the client data=] computed in step 6.
11. If validation is successful, obtain a list of acceptable trust anchors (attestation root certificates or DAA root keys)
for that attestation type and attestation statement format |fmt|, from a trusted source or from policy. For example, the
@@ -1757,40 +1705,45 @@ implementable by authenticators with limited resources (e.g., secure elem
:: The signing procedure for this attestation statement format is similar to [the procedure for generating assertion
signatures](#fig-signature).
- If Basic or Privacy CA attestation is in use, the authenticator produces the |sig| by concatenating the given
- authenticatorData and clientDataHash, and signing the result using an attestation private key selected through
- an authenticator-specific mechanism. It sets |x5c| to the certificate chain of the attestation public key and |alg| to the
- algorithm of the attestation private key.
+ Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
+ [=hash of the client data=].
+
+ If Basic or Privacy CA attestation is in use, the authenticator produces the |sig| by concatenating |authenticatorData| and
+ |clientDataHash|, and signing the result using an attestation private key selected through an authenticator-specific
+ mechanism. It sets |x5c| to the certificate chain of the attestation public key and |alg| to the algorithm of the
+ attestation private key.
- If DAA is in use, the authenticator produces |sig| by concatenating the given authenticatorData and
- clientDataHash, and signing the result using DAA-Sign with a DAA root key selected through an
- authenticator-specific mechanism (see [[!FIDOEcdaaAlgorithm]]). It sets |alg| to the algorithm of the DAA root key and
- |daaKey| to the DAA root key.
+ If DAA is in use, the authenticator produces |sig| by concatenating |authenticatorData| and |clientDataHash|, and signing
+ the result using DAA-Sign with a DAA root key selected through an authenticator-specific mechanism (see
+ [[!FIDOEcdaaAlgorithm]]). It sets |alg| to the algorithm of the DAA root key and |daaKey| to the DAA root key.
- If self attestation is in use, the authenticator produces |sig| by concatenating the given authenticatorData and
- clientDataHash, and signing the result using the credential private key. It sets |alg| to the algorithm of the
- credential private key, and omits the other fields.
+ If self attestation is in use, the authenticator produces |sig| by concatenating |authenticatorData| and |clientDataHash|,
+ and signing the result using the credential private key. It sets |alg| to the algorithm of the credential private key, and
+ omits the other fields.
: Verification procedure
:: Verify that the given attestation statement is valid CBOR conforming to the syntax defined above.
+ Let |authenticatorData| denote the [=authenticator data claimed to have been used for the attestation=], and let
+ |clientDataHash| denote the [=hash of the client data=].
+
If |x5c| is present, this indicates that the attestation type is not DAA. In this case:
- - Verify that |sig| is a valid signature over the concatenation of the given authenticatorData and
- clientDataHash using the attestation public key in |x5c| with the algorithm specified in |alg|.
+ - Verify that |sig| is a valid signature over the concatenation of |authenticatorData| and |clientDataHash| using the
+ attestation public key in |x5c| with the algorithm specified in |alg|.
- Verify that |x5c| meets the requirements in [[#packed-attestation-cert-requirements]].
- - If |x5c| contains an extension with OID `1 3 6 1 4 1 45724 1 1 4` (id-fido-gen-ce-aaguid) verify that
- the value of this extension matches the AAGUID in the claimed authenticatorData.
+ - If |x5c| contains an extension with OID `1 3 6 1 4 1 45724 1 1 4` (id-fido-gen-ce-aaguid) verify that the value of this
+ extension matches the AAGUID in |authenticatorData|.
- If successful, return attestation type Basic and trust path |x5c|.
If |daaKey| is present, then the attestation type is DAA. In this case:
- - Verify that |sig| is a valid signature over the concatenation of the given authenticatorData and
- clientDataHash using DAA-Verify with |daaKey| (see [[!FIDOEcdaaAlgorithm]]).
+ - Verify that |sig| is a valid signature over the concatenation of |authenticatorData| and |clientDataHash| using DAA-Verify
+ with |daaKey| (see [[!FIDOEcdaaAlgorithm]]).
- If successful, return attestation type DAA and trust path |daaKey|.
If neither |x5c| nor |daaKey| is present, self attestation is in use.
- - Validate that |alg| matches the algorithm of the credential private key in the claimed authenticatorData.
- - Verify that |sig| is a valid signature over the concatenation of the given authenticatorData and
- clientDataHash using the credential public key with |alg|.
+ - Validate that |alg| matches the algorithm of the credential private key in |authenticatorData|.
+ - Verify that |sig| is a valid signature over the concatenation of |authenticatorData| and |clientDataHash| using the
+ credential public key with |alg|.
- If successful, return attestation type Self and empty trust path.
@@ -1881,7 +1834,10 @@ engine.
:: The TPMT_PUBLIC structure (see [[TPMv2-Part2]] section 12.2.4) used by the TPM to represent the credential public key.
: Signing procedure
-:: Concatenate the given authenticatorData and clientDataHash to form |attToBeSigned|.
+:: Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
+ [=hash of the client data=].
+
+ Concatenate |authenticatorData| and |clientDataHash| to form |attToBeSigned|.
Generate a signature using the procedure specified in [[TPMv2-Part3]] Section 18.2, using the attestation private key and
setting the `qualifyingData` parameter to |attToBeSigned|.
@@ -1892,10 +1848,13 @@ engine.
: Verification procedure
:: Verify that the given attestation statement is valid CBOR conforming to the syntax defined above.
+ Let |authenticatorData| denote the [=authenticator data claimed to have been used for the attestation=], and let
+ |clientDataHash| denote the [=hash of the client data=].
+
Verify that the public key specified by the `parameters` and `unique` fields of |pubArea| is identical to the public key
- contained in the attestation data inside the claimed authenticatorData
+ contained in the attestation data inside |authenticatorData|.
- Concatenate the given authenticatorData and clientDataHash to form |attToBeSigned|.
+ Concatenate |authenticatorData| and |clientDataHash| to form |attToBeSigned|.
Validate that |certInfo| is valid:
- Verify that `magic` is set to `TPM_GENERATED_VALUE`.
@@ -1910,7 +1869,7 @@ engine.
algorithm specified in |alg|.
- Verify that |x5c| meets the requirements in [[#tpm-cert-requirements]].
- If |x5c| contains an extension with OID `1 3 6 1 4 1 45724 1 1 4` (id-fido-gen-ce-aaguid) verify that the value of this
- extension matches the AAGUID in the claimed authenticatorData.
+ extension matches the AAGUID in |authenticatorData|.
- If successful, return attestation type Privacy CA and trust path |x5c|.
If |daaKey| is present, then the attestation type is DAA.
@@ -1943,9 +1902,9 @@ TPM attestation certificate MUST have the following fields/extensions:
When the Authenticator in question is a platform-provided Authenticator on the Android "N" or later platform, the
attestation statement is based on the
[Android key attestation](https://developer.android.com/preview/api-overview.html#key_attestation). In these cases, the
-attestation statement is produced by a component running in a secure operating environment, but the authenticatorData
-is produced outside this environment. The [RP] is expected to check that the contents of authenticatorData are consistent
-with the fields of the attestation certificate's extension data.
+attestation statement is produced by a component running in a secure operating environment, but the [=authenticator data for the
+attestation=] is produced outside this environment. The [RP] is expected to check that the [=authenticator data claimed to have
+been used for the attestation=] is consistent with the fields of the attestation certificate's extension data.
: Attestation statement format identifier
@@ -1970,7 +1929,10 @@ with the fields of the attestation certificate's extension data.
```
: Signing procedure
-:: Concatenate the given authenticatorData and clientDataHash to form |attToBeSigned|.
+:: Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
+ [=hash of the client data=].
+
+ Concatenate |authenticatorData| and |clientDataHash| to form |attToBeSigned|.
Request a Android Key Attestation by calling "keyStore.getCertificateChain(myKeyUUID)") providing |attToBeSigned| as the
challenge value (e.g., by using
@@ -1980,11 +1942,13 @@ with the fields of the attestation certificate's extension data.
: Verification procedure
:: Verification is performed as follows:
+ - Let |authenticatorData| denote the [=authenticator data claimed to have been used for the attestation=], and let
+ |clientDataHash| denote the [=hash of the client data=].
- Verify that the public key in the first certificate in the series of certificates represented by the signature matches the
- credential public key in the attestation data field of the given authenticatorData.
+ credential public key in the attestation data field of |authenticatorData|.
- Verify that in the attestation certificate extension data:
- - The value of the `attestationChallenge` field is identical to the concatenation of the claimed
- authenticatorData and clientDataHash.
+ - The value of the `attestationChallenge` field is identical to the concatenation of |authenticatorData| and
+ |clientDataHash|.
- The `AuthorizationList.allApplications` field is not present, since ScopedCredentials must be bound to the
RP ID.
- The value in the `AuthorizationList.origin` field is equal to `KM_TAG_GENERATED`.
@@ -2032,7 +1996,10 @@ identity of the calling application.
in Compact Serialization.
: Signing procedure
-:: Concatenate the given authenticatorData and clientDataHash to form |attToBeSigned|.
+:: Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
+ [=hash of the client data=].
+
+ Concatenate |authenticatorData| and |clientDataHash| to form |attToBeSigned|.
Request a SafetyNet attestation, providing |attToBeSigned| as the nonce value. Set |response| to the result, and |ver| to
the version of Google Play Services running in the authenticator.
@@ -2041,8 +2008,7 @@ identity of the calling application.
:: Verification is performed as follows:
- Verify that the given attestation statement is valid CBOR conforming to the syntax defined above.
- Verify that |response| is a valid SafetyNet response of version |ver|.
- - Verify that the nonce in the |response| is identical to the concatenation of the claimed authenticatorData
- and clientDataHash.
+ - Verify that the nonce in the |response| is identical to the concatenation of the |authenticatorData| and |clientDataHash|.
- Verify that the attestation certificate is issued to the hostname "attest.android.com" (see
[SafetyNet online documentation](https://developer.android.com/training/safetynet/index.html#compat-check-response)).
- Verify that the `ctsProfileMatch` attribute in the payload of |response| is true.
@@ -2077,9 +2043,8 @@ This attestation statement format is used with FIDO U2F authenticators using the
The semantics of the above fields are as follows:
: x5c
- :: The elements of this array contain the attestation certificate and its
- certificate chain, each encoded in X.509 format. The attestation
- certificate must be the first element in the array.
+ :: The elements of this array contain the attestation certificate and its certificate chain, each encoded in X.509 format.
+ The attestation certificate must be the first element in the array.
: sig
:: The attestation signature.
@@ -2087,8 +2052,11 @@ This attestation statement format is used with FIDO U2F authenticators using the
: Signing procedure
:: If the credential public key of the given credential is not of algorithm "ES256", stop and return an error.
- If the given clientDataHash is 256 bits long, set |tbsHash| to this value. Otherwise set |tbsHash| to the SHA-256 hash
- of the given clientDataHash.
+ Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
+ [=hash of the client data=].
+
+ If |clientDataHash| is 256 bits long, set |tbsHash| to this value. Otherwise set |tbsHash| to the SHA-256 hash of
+ |clientDataHash|.
Generate a signature as specified in [[FIDO-U2F-Message-Formats]] section 4.3, with the application parameter set to the
SHA-256 hash of the RP ID associated with the given credential, the challenge parameter set to |tbsHash|, and the key handle
@@ -2099,10 +2067,11 @@ This attestation statement format is used with FIDO U2F authenticators using the
:: Verification is performed as follows:
- Verify that the given attestation statement is valid CBOR conforming to the syntax defined above.
- If |x5c| is not a certificate for an ECDSA public key over the P-256 curve, stop verification and return an error.
- - If the given clientDataHash is 256 bits long, set |tbsHash| to this value. Otherwise set |tbsHash| to the SHA-256
- hash of the given clientDataHash.
- - From the given authenticatorData, extract the claimed RP ID hash, the claimed credential ID and the claimed
- credential public key.
+ - Let |authenticatorData| denote the [=authenticator data claimed to have been used for the attestation=], and let
+ |clientDataHash| denote the [=hash of the client data=].
+ - If |clientDataHash| is 256 bits long, set |tbsHash| to this value. Otherwise set |tbsHash| to the SHA-256
+ hash of |clientDataHash|.
+ - From |authenticatorData|, extract the claimed RP ID hash, the claimed credential ID and the claimed credential public key.
- Generate the claimed to-be-signed data as specified in [[FIDO-U2F-Message-Formats]] section 4.3, with the application
parameter set to the claimed RP ID hash, the challenge parameter set to |tbsHash|, the key handle parameter set to the
claimed credential ID of the given credential, and the user public key parameter set to the claimed credential public key.