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:
If the |adjustedTimeout| timer expires,
- -
[=set/For each=] - |authenticator| in |issuedRequests| invoke the - authenticatorCancel operation on |authenticator| and - [=set/remove=] |authenticator| from |issuedRequests|.
+
[=set/For each=] |authenticator| in |issuedRequests| invoke the authenticatorCancel operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|.
If any |authenticator| returns a status indicating that the user cancelled the operation,
-
1. [=set/Remove=] |authenticator| from |issuedRequests|. - 2. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke - the authenticatorCancel operation on |authenticator| and - [=set/remove=] it from |issuedRequests|. - + 2. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the authenticatorCancel operation on + |authenticator| and [=set/remove=] it from |issuedRequests|.
If any |authenticator| returns an error status,
-
[=set/Remove=] |authenticator| from |issuedRequests|.
If any |authenticator| indicates success,
-
1. [=set/Remove=] |authenticator| from |issuedRequests|. 2. Let |value| be a new {{ScopedCredentialInfo}} object whose fields are: : {{ScopedCredentialInfo/clientDataJSON}} :: A new {{ArrayBuffer}} containing the bytes of |clientDataJSON|. : {{ScopedCredentialInfo/attestationObject}} - :: A new {{ArrayBuffer}} containing the bytes of the value returned - from the successful [=authenticatorMakeCredential=] operation - 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the - authenticatorCancel operation on |authenticator| and - [=set/remove=] it from |issuedRequests|. + :: A new {{ArrayBuffer}} containing the bytes of the value returned from the successful + [=authenticatorMakeCredential=] operation + 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the authenticatorCancel operation on + |authenticator| and [=set/remove=] it from |issuedRequests|. 4. [=Resolve=] |promise| with |value| and terminate this algorithm. -
+
-1. [=Reject=] |promise| with a {{DOMException}} whose name is - "{{NotAllowedError}}". - - Issue: {{NotAllowedError}} seems incorrect for at least the timeout and - cancelled exit conditions above. +1. [=Reject=] |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}". During the above process, the user agent SHOULD show some UI to the user to guide them in the process of selecting and authorizing an authenticator. @@ -635,7 +581,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Use {{assertionChallenge}}, |callerOrigin| and |rpId|, along with the token binding key associated with |callerOrigin| (if any), to create a {{ClientData}} structure representing this request. Choose a hash algorithm for {{ClientData/hashAlg}} and - compute the {{AuthenticationAssertion/clientDataJSON}} and clientDataHash. + compute the [=JSON-serialized client data=] |clientDataJSON| and the [=hash of the client data=] |clientDataHash|. 1. Initialize |issuedRequests| to an empty list. @@ -650,7 +596,7 @@ When this method is invoked, the user agent MUST execute the following algorithm be on this authenticator, do not perform any of the following steps for this authenticator, and proceed to the next authenticator (if any). - Asynchronously invoke the authenticatorGetAssertion operation on this authenticator with |rpId|, - clientDataHash, |credentialList|, and |clientExtensions| as parameters. + |clientDataHash|, |credentialList|, and |clientExtensions| as parameters. - Add an entry to |issuedRequests|, corresponding to this request. 1. While |issuedRequests| is not empty, perform the following actions depending upon the |adjustedTimeout| timer and responses @@ -664,7 +610,7 @@ When this method is invoked, the user agent MUST execute the following algorithm - If any authenticator returns success: - Remove this authenticator's entry from |issuedRequests|. - Create a new {{AuthenticationAssertion}} object named |value| and populate its fields with the values returned from the - authenticator as well as the {{AuthenticationAssertion/clientDataJSON}} computed earlier. + authenticator and |clientDataJSON|. - For each remaining entry in |issuedRequests| invoke the authenticatorCancel operation on that authenticator and remove its entry from the list. - Resolve |promise| with |value| and terminate this algorithm. @@ -691,9 +637,9 @@ authorizing an authenticator with which to complete the operation. to locate it later for use, and also contains metadata that can be used by the [RP] to assess the strength of the credential during registration. - The clientDataJSON attribute contains the clientDataJSON (see [[#cred-attestation]]) - passed to the authenticator by the client in order to generate this credential. The exact JSON serialization must be - preserved as a cryptographic hash (clientDataHash) has been computed over it. + The clientDataJSON attribute contains the [=JSON-serialized client data=] (see [[#cred-attestation]]) passed to + the authenticator by the client in order to generate this credential. The exact JSON serialization must be preserved as the + [=hash of the client data=] has been computed over it. The attestationObject attribute contains an attestation object. The contents of this object are determined by the attestation statement format used by the authenticator. This object is opaque to, and @@ -928,8 +874,8 @@ string-valued keys. Values may be any type that has a valid encoding in JSON. It The origin member contains the fully qualified origin of the requester, as provided to the authenticator by the client, in the syntax defined by [[RFC6454]]. - The hashAlg member is a [=recognized algorithm name=] that supports the `"digest"` operation, which specifies the hash algorithm used to compute clientDataHash. This algorithm is chosen by the - client at its sole discretion. + The hashAlg member is a [=recognized algorithm name=] that supports the `"digest"` operation, which specifies the + algorithm used to compute the [=hash of the client data=]. This algorithm is chosen by the client at its sole discretion. The tokenBinding member contains the base64url encoding of the Token Binding ID that this client uses for the Token Binding protocol when communicating with the [RP]. This can be omitted if no Token Binding has been negotiated between @@ -940,14 +886,13 @@ string-valued keys. Values may be any type that has a valid encoding in JSON. It This structure is used by the client to compute the following quantities: - : clientDataJSON - :: This is the UTF-8 encoded JSON serialization [[RFC7159]] of a {{ClientData}} dictionary. Any valid JSON - serialization may be used by the client. This specification imposes no canonicalization requirements. Instead, the - {{ScopedCredentialInfo}} and {{AuthenticationAssertion}} structures contain the actual serializations used by the client - to generate them. + : JSON-serialized client data + :: This is the [=UTF-8 encoding=] of the result of calling the initial value of {{JSON/stringify|JSON.stringify}} on a + {{ClientData}} dictionary. To avoid ambiguity, the {{ScopedCredentialInfo}} and {{AuthenticationAssertion}} structures + contain the actual serializations used by the client to generate them. - : clientDataHash - :: This is the hash (computed using {{hashAlg}}) of clientDataJSON, as constructed by the client. + : Hash of the client data + :: This is the hash (computed using {{hashAlg}}) of the [=JSON-serialized client data=], as constructed by the client. @@ -1085,8 +1030,8 @@ authenticator. In verifying a signature, the server checks these bindings agains are divided in two: Those added by the RP or the client, referred to as client data; and those added by the authenticator, referred to as the authenticator data. The authenticator signs over the client data, but is otherwise not interested in its contents. To save bandwidth and processing requirements on the authenticator, the client hashes the {{ClientData}} and sends -only the result to the authenticator. The authenticator signs over the combination of this clientDataHash, and its own -authenticator data. +only the result to the authenticator. The authenticator signs over the combination of the [=hash of the client data=], and its +own authenticator data. The goals of this design can be summarized as follows. @@ -1213,7 +1158,7 @@ This operation must be invoked in an authenticator session which has no other op input parameters: - The caller's RP ID, as determined by the user agent and the client. -- The clientDataHash, which is the hash of the serialized {{ClientData}} and is provided by the client. +- The [=hash of the client data=], provided by the client. - The {{Account}} information provided by the [RP]. - The {{ScopedCredentialType}} and cryptographic parameters requested by the [RP], with the cryptographic algorithms normalized as per the procedure in [[WebCryptoAPI#algorithm-normalization-normalize-an-algorithm]]. @@ -1242,8 +1187,8 @@ When this operation is invoked, the authenticator must perform the following pro the operation. - Process all the supported extensions requested by the client, and generate an authenticatorData structure with attestation data as specified in [[#sec-authenticator-data]]. Use this authenticatorData and the - clientDataHash received from the client to create an attestation object for the new credential using the - procedure specified in [[#generating-an-attestation-object]]. For more details on attestation, see [[#cred-attestation]]. + [=hash of the client data=] to create an attestation object for the new credential using the procedure specified in + [[#generating-an-attestation-object]]. For more details on attestation, see [[#cred-attestation]]. On successful completion of this operation, the authenticator returns the attestation object to the client. @@ -1254,7 +1199,7 @@ This operation must be invoked in an authenticator session which has no other op input parameters: - The caller's RP ID, as determined by the user agent and the client. -- The clientDataHash, which is the hash of the serialized {{ClientData}} and is provided by the client. +- The [=hash of the client data=], provided by the client. - A list of credentials acceptable to the [RP] (possibly filtered by the client). - Extension data created by the client based on the extensions requested by the [RP]. @@ -1271,10 +1216,10 @@ When this method is invoked, the authenticator must perform the following proced otherwise. - Process all the supported extensions requested by the client, and generate an authenticatorData structure without attestation data as specified in [[#sec-authenticator-data]]. Concatenate this authenticatorData with the - clientDataHash received from the client to generate an assertion signature using the private key of the selected - credential [as shown below](#fig-signature). A simple, undelimited concatenation is safe to use here because the - authenticatorData describes its own length. The clientDataHash (which potentially has a variable length) is - always the last element. + [=hash of the client data=] to generate an assertion signature using the private key of the selected credential + [as shown below](#fig-signature). A simple, undelimited concatenation is safe to use here because the + authenticatorData describes its own length. The [=hash of the client data=] (which potentially has a variable length) + is always the last element. - If any error occurred while generating the assertion signature, return an error code equivalent to UnknownError and terminate the operation. @@ -1423,10 +1368,12 @@ authenticator over a set of contextual bindings. Each attestation statement form defined in [[#generating-an-attestation-object]]. - The procedure for computing an attestation statement in this format given the credential to be attested, the - authenticatorData for the attestation, and a clientDataHash. + authenticatorData structure containing the authenticator data for the attestation, and the + [=hash of the client data=]. -- The procedure for verifying an attestation statement, which takes as inputs the authenticatorData claimed to have been - used for the attestation and the clientDataHash of the client's contextual bindings, and returns either: +- The procedure for verifying an attestation statement, which takes as inputs the authenticatorData containing the + authenticator data claimed to have been used for the attestation and the [=hash of the client data=], and returns + either: - An error indicating that the attestation is invalid, or - The attestation type, and the trust path of the attestation. This trust path is either empty (in case of self-attestation), a DAA root key (in the case of Direct Anonymous Attestation), or a set of X.509 certificates. @@ -1475,8 +1422,8 @@ In order to construct an attestation object for a given credential using format, the authenticator MUST first generate an authenticatorData structure. The authenticator MUST then run the signing procedure for the desired attestation statement format with this -authenticatorData and the client-supplied clientDataHash as input, and use this to construct an attestation -statement in that attestation statement format. +authenticatorData and the [=hash of the client data=] as input, and use this to construct an attestation statement in +that attestation statement format. Finally, the authenticator MUST construct the attestation object as a CBOR map with the following syntax: @@ -1592,7 +1539,8 @@ ceremony, a [RP] MUST proceed as follows: 5. Verify that the {{ClientData/extensions}} in |C| is a proper subset of the extensions requested by the RP. -6. Compute the clientDataHash over {{ScopedCredentialInfo/clientDataJSON}} using the algorithm identified by |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.