Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

device public key extension #1663

Merged
merged 144 commits into from
Oct 7, 2022
Merged
Changes from 74 commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
6719e05
device-bound Public Key pair extension
equalsJeffH Apr 16, 2021
4a6b8fe
further hacking...
equalsJeffH Apr 21, 2021
5d1662d
nearly complete tho likely needs to be re-worked to include attestati…
equalsJeffH Apr 28, 2021
1622df2
add 'device-bound key'
equalsJeffH Apr 30, 2021
5e684aa
in-progress updates...
equalsJeffH May 6, 2021
71afdbe
further in-progress updates...
equalsJeffH May 6, 2021
8040d13
further in-progress updates...
equalsJeffH May 7, 2021
38131e6
Merge branch 'main' into jeffh-fix-1546-second-key-extension
equalsJeffH May 7, 2021
ad71ff1
devicePublicKey extension section functionally complete
equalsJeffH May 7, 2021
094d385
further edits...
equalsJeffH May 7, 2021
e66eb2d
cleanup trailing whitespace...
equalsJeffH May 7, 2021
618b2de
Device-bound public key ProVerif model
equalsJeffH Jun 9, 2021
1e97952
who-signs-what musings...
equalsJeffH Jun 9, 2021
8f0d66d
editorial polishing
equalsJeffH Jun 14, 2021
43e03c8
editorial polishing
equalsJeffH Jun 15, 2021
503a027
major reorg & clarifications
equalsJeffH Jun 16, 2021
87340d7
further reorg & polish
equalsJeffH Jun 17, 2021
cbb066f
proverif model cleanup
equalsJeffH Jun 18, 2021
1e72a00
remove unused 'cert'
equalsJeffH Jun 18, 2021
99a6b79
revise/correct objects hierarchy
equalsJeffH Jun 19, 2021
e9db523
clarifications
equalsJeffH Jun 21, 2021
68ebaa2
clarifications
equalsJeffH Jun 21, 2021
8b5702c
clarifications
equalsJeffH Jun 21, 2021
da82c2e
switch model starting-point to webauthn-basic.pv
equalsJeffH Jun 21, 2021
f84069b
clarifications
equalsJeffH Jun 22, 2021
f6663cb
clarifications to both DPK stuff and PV model
equalsJeffH Jun 22, 2021
22e325d
revise model significantly
equalsJeffH Jun 24, 2021
a3ed05b
further clarifications and musings
equalsJeffH Jun 25, 2021
6382444
editorial
equalsJeffH Jun 25, 2021
768d900
revised dpk syntax per agl review
equalsJeffH Jun 26, 2021
fd9ea00
further refined dpk syntax per feedback
equalsJeffH Jun 28, 2021
a34b489
select the more simple AttObjForDevicePublicKey
equalsJeffH Jun 30, 2021
2832b5e
begin reworking devicePubKey extension
equalsJeffH Jul 1, 2021
e47c5f8
editorial
equalsJeffH Jul 1, 2021
75c8f25
device-bound-key-pair.pv -> device-bound-key-pair.txt
equalsJeffH Jul 1, 2021
4515d63
add separate webauthn.pv file
equalsJeffH Jul 1, 2021
c208e19
editorial
equalsJeffH Jul 1, 2021
591cded
Merge branch 'main' into jeffh-fix-1546-second-key-extension
equalsJeffH Jul 1, 2021
59260f0
Merge branch 'main' into jeffh-fix-1546-second-key-extension
equalsJeffH Jul 1, 2021
c3487a2
fix attSecretKey in pv model
equalsJeffH Jul 2, 2021
0e8d3b3
add README.pv.md file
equalsJeffH Jul 2, 2021
6b216db
editorial cleanups
equalsJeffH Jul 2, 2021
25b07e6
processUser -> processClientAndAuthnr
equalsJeffH Jul 5, 2021
2da4504
define formal RegRequestMsg
equalsJeffH Jul 5, 2021
f943bbc
editorial
equalsJeffH Jul 5, 2021
e23ccfe
attPublicKey is public
equalsJeffH Jul 5, 2021
7a1e2ee
WIP: refine attestation object construction
equalsJeffH Jul 7, 2021
8a420eb
WIP: attObject parsing
equalsJeffH Jul 7, 2021
d2b529b
WIP: add Extensions.
equalsJeffH Jul 7, 2021
666718a
editorial
equalsJeffH Jul 7, 2021
f9e861c
COMPLETED: refine attestation object construction
equalsJeffH Jul 8, 2021
e1a4383
refine events
equalsJeffH Jul 8, 2021
9182fa1
editorial
equalsJeffH Jul 8, 2021
89e2660
editorial
equalsJeffH Jul 9, 2021
54eb767
more meaningful query wrt response msg.
equalsJeffH Jul 20, 2021
f6fcee8
add: set traceDisplay long
equalsJeffH Aug 13, 2021
1747dff
fix var rebindings, trim queries
equalsJeffH Aug 14, 2021
12ec079
update README.pv.md
equalsJeffH Aug 14, 2021
59f2909
edit README.pv.md
equalsJeffH Aug 14, 2021
8b4d51c
rename server name, plus other clieanups
equalsJeffH Aug 15, 2021
c5f3b2d
edit README.pv.md
equalsJeffH Aug 15, 2021
4ebd028
remove pv files from this branch
equalsJeffH Aug 17, 2021
4f18790
Merge branch 'main' into jeffh-fix-1658-device-bound-key-extension
equalsJeffH Aug 17, 2021
66e67bd
update Device-bound public key extension
equalsJeffH Aug 17, 2021
9ac274a
work in progress
equalsJeffH Aug 20, 2021
fcc6a68
finish Notes -- nominally complete for Draft PR
equalsJeffH Aug 21, 2021
73cc7ff
Merge branch 'main' into jeffh-fix-1658-device-bound-key-extension
equalsJeffH Aug 21, 2021
7c5393c
untraced device-bound-key-pair.txt
equalsJeffH Aug 21, 2021
3d16662
context is now scope
equalsJeffH Nov 12, 2021
aee534c
do binary equality checks
equalsJeffH Nov 12, 2021
7c3e2e8
Apply suggestions from emlun's code review, thanks!
equalsJeffH Nov 12, 2021
90593b9
fixes inspired by emlun's review
equalsJeffH Nov 12, 2021
d0bef33
apply and merge emlun's review suggestions, thx!
equalsJeffH Nov 12, 2021
89cec45
Merge branch 'main' into jeffh-fix-1658-device-bound-key-extension
equalsJeffH Nov 12, 2021
db63d69
incorp pascoej's correction, thx!
equalsJeffH Nov 15, 2021
9a78683
fix bug emlun caught (thx) & apply polish
equalsJeffH Nov 16, 2021
d52342c
Apply emlun's suggestions, thx!
equalsJeffH Jan 11, 2022
e23c4b9
polish emlun's suggestion to not be a Note
equalsJeffH Jan 11, 2022
b8ec5b8
polish Authenticator extension processing
equalsJeffH Jan 12, 2022
0bb9aaa
authnr extension rather than client extension
equalsJeffH Jan 12, 2022
3237896
minor editorial fixes
equalsJeffH Jan 14, 2022
d652787
Merge branch 'main' into jeffh-fix-1658-device-bound-key-extension
equalsJeffH Jan 18, 2022
55e64c9
revise intro and define most of verification procedure
equalsJeffH Jan 18, 2022
41ffcbf
finish roughing-out verification procedures
equalsJeffH Jan 18, 2022
f131d68
remove extraneous Note on permissions policy that crept in somehow
equalsJeffH Jan 18, 2022
e1e6d94
incorp emlun's suggestion on hardware-bound device key pair definition
equalsJeffH Jan 18, 2022
23ea3ef
add Notes to RP verification steps linking to DPK extension verificat…
equalsJeffH Feb 18, 2022
683ad4d
do not use 'synced' user cred term per TimC
equalsJeffH Feb 18, 2022
17f3aa2
update 'Relying Party Usage' section and note current issues
equalsJeffH Mar 4, 2022
b4e8d0e
clarification
equalsJeffH Mar 5, 2022
619ebb9
wordsmithing, thx emlun!
equalsJeffH Mar 9, 2022
2730294
incop & massage Emlun's suggestion, thx!
equalsJeffH Mar 17, 2022
f0fe8f2
rough WIP to fix issue #1701 side-channel attack
equalsJeffH Mar 19, 2022
f145234
further WIP re fixing #1701 authnr nonce, & noting #1711
equalsJeffH Mar 23, 2022
b8d8567
attempt at polishing various portions of devicePubKey
equalsJeffH Mar 23, 2022
d92bad2
The DPK is stored on the authenticator.
agl May 19, 2022
6d45aba
Provide attestation controls.
agl May 19, 2022
eb598ff
Pull out DPK attestation rules and add signature prefix.
agl May 19, 2022
b7289e1
Reflow CDDL to avoid a scroll bar.
agl May 19, 2022
dcfb392
Have the DPK sign over everything.
agl May 19, 2022
cbb6b5d
Note that CTAP2 CBOR is required in DPK.
agl May 19, 2022
ccfd0b4
Resolve comment by jovasco
agl May 19, 2022
f3315b5
Merge branch 'main' into dpk
agl Jun 17, 2022
27ef223
Link definitions from PR 1695.
agl Jun 17, 2022
bfce0cf
Make the DPK signature a different output field.
agl Jun 17, 2022
20dd35c
Update attestation and add it for assertions
agl Jun 17, 2022
27d0895
Introduce unsigned extension outputs and use it to return the dpk sig…
arnar Jun 22, 2022
e30cdb1
Fix build error
arnar Jun 22, 2022
38fb4e1
Review fixes and another indentation fix
arnar Jun 22, 2022
0c7fad0
Fix misplaced Note annotation
arnar Jun 22, 2022
844cff7
Merge pull request #1754 from arnar/jeffh-fix-1658-device-bound-key-e…
agl Jun 22, 2022
6fbfccf
Update attestation and add it for assertions
agl Jun 17, 2022
4e67faa
Various fixes and updates in light of comments
agl Jul 19, 2022
832c2e8
Merge branch 'main' into jeffh-fix-1658-device-bound-key-extension
emlun Aug 1, 2022
6940a43
Merge pull request #1787 from w3c/merge-main-into-1658
agl Aug 20, 2022
7b531a8
Apply more of emlun's suggestions from code review
agl Aug 20, 2022
04ddb48
Apply one of emlun's suggestions
agl Aug 20, 2022
3cba94c
Apply one of emlun's suggestions
agl Aug 20, 2022
47017e4
Apply one of emlun's suggestions
agl Aug 20, 2022
16a846a
Apply one of emlun's suggestions
agl Aug 20, 2022
2ec8861
Apply one of emlun's suggestions
agl Aug 20, 2022
5c1cd98
Apply suggestions from code review
agl Aug 20, 2022
5c6c23d
Apply suggestions from code review
agl Aug 20, 2022
a026a5b
Apply one of emlun's suggestions
agl Aug 20, 2022
ec03d4d
Have the authenticator output a bytestring, not a map.
agl Aug 20, 2022
88be1a6
Fix devicePubKey sub-heading levels
emlun Aug 23, 2022
3430c95
Hopefully fix up my misinterpretation of emlun's comment.
agl Aug 25, 2022
5af393d
RPs shouldn't check DPK attestation for equality.
agl Aug 25, 2022
fe333fe
Remove incorrect note about nonces.
agl Aug 25, 2022
ece61f0
Include enterpriseAttestationPossible when calling authenticatorGetAs…
agl Aug 25, 2022
4279e6e
Apply one of emlun's suggestions
agl Aug 25, 2022
d25fd53
Mention where authData and hash are used.
agl Aug 25, 2022
8966fe6
Apply emlun's suggestions from code review
agl Sep 10, 2022
d671894
Address emlun's comments.
agl Sep 10, 2022
ca1b0c6
Add a note to explain how the RP's challenge is included in dpkSig.
agl Sep 21, 2022
6112877
Remove a horizontal scrollbar on the DPK CDDL.
agl Sep 21, 2022
ed0b779
Remove now superfluous variable in DPK processing.
agl Sep 21, 2022
9bd0e3d
Apply Shane's suggestions
agl Sep 27, 2022
759ce04
DPK is only valid for backup eligible credentials.
agl Sep 27, 2022
8aa160c
Address Shane's comments.
agl Sep 27, 2022
bff403d
s/then/than, noticed by Shane.
agl Oct 1, 2022
fba2725
Add missing blank line. Thanks Emil.
agl Oct 5, 2022
f780870
Resolve last comment.
agl Oct 7, 2022
6ae32a0
Merge branch 'main' into dpk
agl Oct 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 151 additions & 5 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1068,8 +1068,9 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
: <dfn>Credential Private Key</dfn>
: <dfn>Credential Public Key</dfn>
: <dfn>User Public Key</dfn>
: <dfn>User Credential</dfn>
:: A [=credential key pair=] is a pair of asymmetric cryptographic keys generated by an [=authenticator=]
and [=scoped=] to a specific [=[WRP]=]. It is the central part of a [=public key credential=].
and [=scoped=] to a specific [=[WRP]=]. It thus forms the central part of a [=public key credential source=].

A [=credential public key=] is the public key portion of a [=credential key pair=].
The [=credential public key=] is returned to the [=[RP]=] during a [=registration ceremony=].
Expand All @@ -1078,17 +1079,26 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
The [=credential private key=] is bound to a particular [=authenticator=] - its [=managing authenticator=] -
and is expected to never be exposed to any other party, not even to the owner of the [=authenticator=].

Note that in the case of [=self
attestation=], the [=credential key pair=] is also used as the [=attestation key pair=], see [=self attestation=]
for details.
Note: In the case of [=self attestation=], the [=credential key pair=] is also used as the [=attestation key pair=], see [=self attestation=] for details.

Note: The [=credential public key=] is referred to as the [=user public key=] in FIDO UAF [[UAFProtocol]], and in FIDO U2F
[[FIDO-U2F-Message-Formats]] and some parts of this specification that relate to it.
[[FIDO-U2F-Message-Formats]] and some parts of this specification that relate to it. Also, the term [=user credential=] is occasionally used to synonymously refer to [=credential public key=] and [=user public key=].

: <dfn>Credential Properties</dfn>
:: A [=credential property=] is some characteristic property of a [=public key credential source=], such as whether it is a
[=client-side discoverable credential=] or a [=server-side credential=].

: <dfn>Hardware-bound Device Key Pair</dfn>
: <dfn>Device-bound Key</dfn>
: <dfn>Device Private Key</dfn>
: <dfn>Device Public Key</dfn>
: <dfn>Device Key</dfn>
: <dfn>Secondary Key</dfn>
equalsJeffH marked this conversation as resolved.
Show resolved Hide resolved
:: A [=hardware-bound device key pair=], also known as a [=device-bound key=], is a [=[RP]=]-specific and [=user credential=]-specific public key pair created upon a [=[RP]=]'s request via the [=devicePubKey=] [=WebAuthn extension=].
The [=[RP]=] may supply this extension during both [=registration=] and [=authentication=].
The [=authenticator=] that a [=hardware-bound device key pair=] is created upon guarantees that the [=device private key=] is securely stored in hardware, i.e., it is unextractable. The [=device public key=] is returned only to the [=[RP]=] that created the [=hardware-bound device key pair=]. See [[#sctn-device-publickey-extension]].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth calling out that this is for authenticators where the [=credential public key=] might not be hardware-bound? I think in the minds of readers for some time they're probably coming to WebAuthn with that assumption and might be unmoored by this description without that context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch, I've submitted #1665 re explicitly defining the "synced | hardware-bound" credential notions.



: <dfn>Human Palatability</dfn>
:: An identifier that is [=human palatability|human-palatable=] is intended to be rememberable and reproducible by typical human
users, in contrast to identifiers that are, for example, randomly generated sequences of bits [[EduPersonObjectClassSpec]].
Expand Down Expand Up @@ -5952,6 +5962,142 @@ However, [=authenticators=] that do not utilize [[!FIDO-CTAP]] do not necessaril
:: [=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]=].


## Device-bound public key extension (<dfn>devicePubKey</dfn>) ## {#sctn-device-publickey-extension}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it fair to say this extension is only useful in cases where the credential public key registration is performed with direct attestation, and further that this not be a self attestation?

Really, what's the point in declaring a device public key if there is no real verifiable root of trust of the authenticator attestation of the associated credential public key?

In the case of "none" attestation, there is no AAGUID anyway, so you can't even provide a meaningful value for aaguid in devicePubKey extension output. I would argue that for "self" attestation it's meaningless as well since self attestation can be spoofed by any client.

If the above assertions are agreed, I think this needs to be made more explicit, and that there should be guidance to suggest that this extension only be used with authenticators and in contexts providing a direct attestation using a verifiable root of trust.

Copy link
Contributor Author

@equalsJeffH equalsJeffH Nov 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it fair to say this extension is only useful in cases where the credential public key registration is performed with direct attestation, and further that this not be a self attestation?

Really, what's the point in declaring a device public key if there is no real verifiable root of trust of the authenticator attestation of the associated credential public key?

The DPK is providing a device continuity signal whose usefulness is arguably independent of what sort of attestation of the user credential may have been supplied at the time the user credential public key was originally registered.

The devicePubKey extension output in conjunction with create() or get() output demonstrates authenticator's possession of both the (potentially synced) user credential private key and the device private key, simultaneously, by employing a nested set of signatures beginning with the authenticator's attestation private key.

In the case of "none" attestation, there is no AAGUID anyway, so you can't even provide a meaningful value for aaguid in devicePubKey extension output. I would argue that for "self" attestation it's meaningless as well...

"none" is an *attestation conveyance" preference (also having a corresponding "attestation statement format"), not an attestation type, and signals the client platform to modify the attestation returned by the authenticator before returning the attstn object to the RP. Thus the authnr may indeed have an AAGUID to employ with the device public key extension.

"self attestation" is an "attestation type" and (offhand) seems not applicable/appropriate for use in attesting to device public keys. "Basic" attestation type (aka "batch attestation") is the primarily applicable attestation type. The AttCA and AnonCA types require further thinking.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an RP, I can certainly receive a "none" attestation statement format, and that can and does happen at times regardless of the RP-requested attestation conveyance preference. One such example is the current use of Apple passkey credentials. I can't see any point in accepting values of this extension containing a "none" attestation statement format. I think when the TODO part of this PR is being done (how to verify a attObjForDevicePublicKey) that we should mention specifically what to accept/reject for allowed attestation statement formats.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an RP, I can certainly receive a "none" attestation statement format, and that can and does happen at times regardless of the RP-requested attestation conveyance preference. One such example is the current use of Apple passkey credentials.

Yes, though, the attestation you're referring to there is that of the user credential. As @agl notes in his above comment: "So the two attestations (user cred's, and DPK's) could happen to be equal, but that wouldn't generally be true.", and so the DPK attestation in this case could be tied to hardware roots of trust even though the user credential's attestation is not.

It will also depend on what DPK attestation types/formats/conveyances we determine are appropriate for DPKs spec-wise (i.e., on a technical basis), and then what a given DPK-supporting authenticator actually implements.

I can't see any point in accepting values of this extension containing a "none" attestation statement format. I think when the TODO part of this PR is being done (how to verify a attObjForDevicePublicKey) that we should mention specifically what to accept/reject for allowed attestation statement formats.

Is it not up to RPs to decide what to trust? E.g., presently in Step 20 of section 7.1. Registering a New Credential assessing "trustworthiness" is done by the RP according to the RP's policies, and the webauthn spec does not attempt to stipulate such policies.

Nominally, if an RP receives a "none" DPK attestation from an authenticator (which I suspect could potentially happen regardless of what the spec ends up saying), then it seems it is up to the RP to decide what to do, which could vary, e.g., based on how sophisticated (or not) the RP's session risk scoring is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nominally, if an RP receives a "none" DPK attestation from an authenticator (which I suspect could potentially happen regardless of what the spec ends up saying), then it seems it is up to the RP to decide what to do, which could vary, e.g., based on how sophisticated (or not) the RP's session risk scoring is.

Yes it is ultimately up to the RP to decide what to do, however practical guidance can and should be provided as to the verification rules for an RP. I do not find the use of the DPK extension intuitive, and the stronger the guardrails here the better.

For example I cannot think of any practical scenario in which an RP, having requested the DPK extension, should then accept a DPK attestation that cannot be verified back to a hardware root of trust. After all, that's the entire point of the extension in the first place - provide a device-bound continuity check. A DPK attestation containing attestation statement format of "none" or "self" provides no such assurance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardware may not be available all the time on every device user has. Which means that there may not be hardware root of trust all the time. Then it is up to the RP to decide what to do in its risk analysis. What DPK is telling that it is a new device in that case, which is still a requirement to figure out even when there may not be a hardware root of trust.

Copy link
Contributor

@sbweeden sbweeden Jul 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can logically "infer" or fallback to the posture of it being a new device if no DPK is present. For example, how does DPK provides any better or more reliable a trust signal over a persistent cookie if it isn't attested?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does DPK provides any better or more reliable a trust signal over a persistent cookie

The DPK lives in the authenticator, so it can be involved in a sign-in request on a new device as long as a known authenticator is used. It's also likely longer lived than a cookie.

agl marked this conversation as resolved.
Show resolved Hide resolved

This [=client extension|client=] [=registration extension=] and [=authentication extension=] provides a [=[RP]=] with a "device continuity" signal. This is done by creating a [=[RP]=]-specific [=hardware-bound device key pair=] on the [=client device=], if such a key pair does not already exist for the [=user credential=] being created or exercised, and returning the attested [=device public key=] along with a signature by the [=device private key=] to the [=[RP]=]. This is done each time this [=devicePubKey=] extension is included with either a <code>{{CredentialsContainer/create()|navigator.credentials.create()}}</code> or <code>{{CredentialsContainer/create()|navigator.credentials.get()}}</code> call.
emlun marked this conversation as resolved.
Show resolved Hide resolved

If the [=client device=] is incapable of generating a [=hardware-bound device key pair=], or the registration or authentication operation fails for any reason, this extension is ignored and no [=hardware-bound device key pair=] is created. In this case, there is no [=devicePubKey=] extension output generated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seem feeling here about giving context. Most authenticators are capable of creating a hardware-bound key pair but won't honour this extension :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. To be addressed along with issue #1665.

equalsJeffH marked this conversation as resolved.
Show resolved Hide resolved


<div class="note">
Note 1: This extension is intended for use by those [=[RPS]=] employing risk-analysis systems informing their sign-in decisions. This extension provides a "device continuity" signal when used consistently with both <code>{{CredentialsContainer/get()|navigator.credentials.create()}}</code> and <code>{{CredentialsContainer/get()|navigator.credentials.get()}}</code> operations. When a user's credential is synced to a new device, the [=[RP]=] will receive a new [=device public key=] on the initial <code>{{CredentialsContainer/get()|navigator.credentials.get()}}</code> invocation on the new device. Note that a synced credential will be exercised for authentication on a new device without a <code>{{CredentialsContainer/get()|navigator.credentials.create()}}</code> having been performed on that new device).
equalsJeffH marked this conversation as resolved.
Show resolved Hide resolved

A usage example is thus:

Say that a sign-in request appears along with some geolocation signal that has not been seen for this [=user account=] before, and is outside of the typical working hours observed for the account. The risk may be deemed high enough not to allow the request, even with a synced credential. But if a device-bound signature can also be presented and it's a [=device-bound key=] that is well established for this user, then that may tip the balance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“synced credential” is mentioned here but is probably the first mention of such a thing in the spec?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. To be addressed along with issue #1665.


Note 2: A [=[RP]=] utilizing this extension will only need to perform thorough verification of the [=device public key=]'s `attObjForDevicePublicKey` once: i.e., the first time a new [=device public key=] is received. "Thorough verification" means verifying the attestation statement `$$attStmtType` (per the [= attestation statement format=]'s signing procedure, see [[#sctn-generating-an-attestation-object]]) as well as the `sig` value. Upon successful verification, the [=[RP]=] SHOULD cache the `aaguid`, `dpk`, `scope`, and `$$attStmtType` values. Upon receiving subsequent `devicePubKey` extension output values, the [=[RP]=] can, along with verifying the `sig` value of each extension output occurrance, do binary equality checks against the cached `aaguid`, `dpk`, `scope`, and `$$attStmtType` values against those returned in the extension output.
</div>

Issue: TODO: write an explicit subsection wrt "how to verify a `attObjForDevicePublicKey`" ? (i.e., analogous to the "verification procedue" steps provided in [[#sctn-defined-attestation-formats|attestation statement format definitions]], and also steps 7 through 19 in [[#sctn-verifying-assertion]])

: Extension identifier
:: `devicePubKey`

: Operation applicability
:: [=registration extension|Registration=] and [=authentication extension|authentication=]

: Client extension input
:: The Boolean value [TRUE] to indicate that this extension is requested by the [=[RP]=].
<xmp class="idl">
partial dictionary AuthenticationExtensionsClientInputs {
boolean devicePubKey; // Explicitly set this to \`true\`!
};
</xmp>

: Client extension processing
:: If {{AuthenticationExtensionsClientInputs/devicePubKey}} is [TRUE], the client creates the authenticator extension input from the client extension input. If {{AuthenticationExtensionsClientInputs/devicePubKey}} is [FALSE], the client ignores this extension.

: Client extension output
:: An ArrayBuffer containing the [=device public key attestation object=] that was returned in the authenticator extension output.
<xmp class="idl">
partial dictionary AuthenticationExtensionsClientOutputs {
ArrayBuffer devicePubKey;
};
</xmp>


: Authenticator extension input
:: The Boolean value [TRUE], encoded in CBOR (major type 7, value 21).

```
$$extensionInput //= (
devicePubKey: true
)
```

: Authenticator extension output
:: The <dfn>device public key attestation object</dfn>, defined by the `attObjForDevicePublicKey` type:

```
$$extensionOutput //= (
devicePubKey: attObjForDevicePublicKey,
)
agl marked this conversation as resolved.
Show resolved Hide resolved

attObjForDevicePublicKey = { ; Note: This object conveys an attested
; device public key and is analogous to \`attObj\`.

sig: bstr, ; Result of sign((clientDataHash || userCredentialId), devicePrivateKey)
; Note that this signature value is unique per-response
; because the client data contains the per-request challenge.

aaguid: bstr, ; Authenticator's AAGUID (16 bytes fixed-length)
sbweeden marked this conversation as resolved.
Show resolved Hide resolved
; https://www.w3.org/TR/webauthn/#aaguid

dpk: bstr, ; The Device Public Key (self-describing variable length,
; COSE_Key format, CBOR-encoded)).

; Whether this key is scoped to the entire device, or a loosely-defined,
; narrower scope called "app". For example, a "device"-scoped key is expected
; to be the same between an app and a browser on the same device, while
; an "app"-scoped key would probably not be.
;
; Whatever the scope, a device key is still specific to a given credential
; and does not provide any ability to link credentials.
;
; Whether device-scoped or not, keys are still device-bound. I.e. an
; app-scoped key does not enjoy lesser protection from extraction.

scope: uint .size 1, ; a value of 0x00 means "entire device" ("all apps") scope.
; 0x01 means "per-app" scope.
; Values other than 0x00 or 0x01 are reserved for future use.

; See https://www.w3.org/TR/webauthn/#sctn-generating-an-attestation-object
;
; Attestation statement formats define the \`fmt\` and \`attStmt\` members of
; $$attStmtType.
agl marked this conversation as resolved.
Show resolved Hide resolved
;
; In summary, the \`attStmt\` will (typically) contain:
; (1) a SIGNATURE value calculated (using the attestation private key)
; over (aaguid || dpk).
; (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,
}

```

: Authenticator extension processing
:: For both [=authenticatorMakeCredential=] and [=authenticatorGetAssertion=] operations:
1. Create or select the [=user credential=] as usual, and let `userCredentialId` be its <code>[=credentialId=]</code>.

1. If a [=hardware-bound device key pair=] does not already exist for this [=user credential=] 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 [=device-bound key=].

1. Let `dpk` be the newly created or existing [=device 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 `devicePrivateKey` be the newly created or existing [=device private key=].

1. Let `clientDataHash` be the [=hash of the serialized client data=].

1. Let `sig` be the result of signing the concatenation of `clientDataHash` and `userCredentialId` using the `devicePrivateKey` and the signature algorithm appropriate for the `devicePrivateKey`'s public key algorithm: `sign((clientDataHash || userCredentialId), devicePrivateKey)`.

1. Let `scope` have the value zero (0x00) if this is an "entrie-device" [=device public key=]. Otherwise, let `scope` have the value one (0x01), indicating a more narrow per-app scope.
equalsJeffH marked this conversation as resolved.
Show resolved Hide resolved

1. Let the `$$attStmtType` values be the result of generating an attestation statement in the [=attestation statement format=] appropriate for the [=user credential=], although substituting the authenticator's <code>[=aaguid=]</code> for |authenticatorData|, and substituting `userCredentialId` for |clientDataHash| in the [=attestation statement format=]'s signing procedure (see [[#sctn-generating-an-attestation-object]]). Attestation statement formats define the `fmt` and `attStmt` members of the `$$attStmtType` expansion.

In summary, the `$$attStmtType` values typically contain a signature value calculated over the bytes of `(clientDataHash || userCredentialId)`, the attestation certificate or public key, and supporting certificates, if any.

Note: The details of the `$$attStmtType` values are dependent upon the particular [=attestation statement=] format. See [[#sctn-attestation-formats]].

1. Let the `devicePubKey` [=authenticator extension output=] be a [=CBOR=] map as defined by `attObjForDevicePublicKey` above, whose values for its `sig`, `aaguid`, `dpk`, `scope`, and `$$attStmtType` members are as calculated in the prior steps.



# 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=].
Expand Down