Skip to content

fix: Assert credentials individually on U2F devices#45289

Merged
codingllama merged 5 commits intomasterfrom
codingllama/u2f-internal-error
Aug 12, 2024
Merged

fix: Assert credentials individually on U2F devices#45289
codingllama merged 5 commits intomasterfrom
codingllama/u2f-internal-error

Conversation

@codingllama
Copy link
Copy Markdown
Contributor

Fix a somewhat rare error in older authenticator models (reproduced with a FIDO U2F Security Key firmware 4.1.8).

The error is as follows: if certain key handles unknown to the authenticator exist in the allowed credentials set, the authenticator fails the assertion with an "internal error". This PR changes assertions in this specific scenario (U2F key, >1 allowed credential) to run sequentially through each key handle looking for a known credential to use.

#44912

Changelog: Fixes a rare "internal error" on older U2F authenticators when using tsh

@codingllama
Copy link
Copy Markdown
Contributor Author

Tested manually in various scenarios: login with multiple keys, registration with multiple keys, registration with device registered/not registered, login as single key, etc.

A few logs added below.

login with multiple keys:

2024-08-08T16:42:20-03:00 DEBU             FIDO2: Using libfido2 for assertion webauthncli/api.go:183
2024-08-08T16:42:20-03:00 DEBU             FIDO2: assertion: passwordless=false, uv=false, 4 allowed credentials webauthncli/fido2.go:168
Tap any security key
2024-08-08T16:42:20-03:00 DEBU             FIDO2: Device ioreg://4294988912: not a FIDO2 device webauthncli/fido2.go:862
2024-08-08T16:42:20-03:00 DEBU             FIDO2: Device ioreg://4294970869: info &libfido2.DeviceInfo{Versions:[]string{"U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE"}, Extensions:[]string{"credProtect", "hmac-secret"}, AAGUID:[]uint8{0xee, 0x88, 0x28, 0x79, 0x72, 0x1c, 0x49, 0x13, 0x97, 0x75, 0x3d, 0xfc, 0xce, 0x97, 0x7, 0x2a}, Options:[]libfido2.Option{libfido2.Option{Name:"rk", Value:"true"}, libfido2.Option{Name:"up", Value:"true"}, libfido2.Option{Name:"plat", Value:"false"}, libfido2.Option{Name:"clientPin", Value:"false"}, libfido2.Option{Name:"credentialMgmtPreview", Value:"true"}}, Protocols:[]uint8{0x2, 0x1}} webauthncli/fido2.go:860
2024-08-08T16:42:20-03:00 DEBU             FIDO2: Device ioreg://4294988912: Using credential 9d6b1b54b0... webauthncli/fido2.go:349
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Got 1 assertions webauthncli/fido2.go:251
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Authenticated: credential ID (b64) = nWsbVLAn7rxUE0byLwViJEAkUIOFBk369qeVctD3oLfBqMw-OV1jMpVbyqORUQouWUNxLAzC6HfQrbWTRnE6JQ, user ID (hex) = , user name = "" webauthncli/fido2.go:259
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Device ioreg://4294988912: callback returned, requiresPIN=false, err=<nil> webauthncli/fido2.go:883
Detected security key tap
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Cancel device ioreg://4294970869, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Close device ioreg://4294988912, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Cancel device ioreg://4294988912, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Device ioreg://4294970869: callback returned, requiresPIN=false, err=failed to get assertion: keep alive cancel webauthncli/fido2.go:883
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Close device ioreg://4294970869, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:42:23-03:00 DEBU             FIDO2: Device goroutines exited cleanly webauthncli/fido2.go:688

tsh mfa add (adding another key):

2024-08-08T16:44:24-03:00 DEBU             FIDO2: Using libfido2 for credential creation webauthncli/api.go:230
2024-08-08T16:44:24-03:00 DEBU             FIDO2: registration: resident key=false webauthncli/fido2.go:449
Tap your *new* security key
2024-08-08T16:44:24-03:00 DEBU             FIDO2: Device ioreg://4294988912: not a FIDO2 device webauthncli/fido2.go:862
2024-08-08T16:44:24-03:00 DEBU             FIDO2: Device ioreg://4294970869: info &libfido2.DeviceInfo{Versions:[]string{"U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE"}, Extensions:[]string{"credProtect", "hmac-secret"}, AAGUID:[]uint8{0xee, 0x88, 0x28, 0x79, 0x72, 0x1c, 0x49, 0x13, 0x97, 0x75, 0x3d, 0xfc, 0xce, 0x97, 0x7, 0x2a}, Options:[]libfido2.Option{libfido2.Option{Name:"rk", Value:"true"}, libfido2.Option{Name:"up", Value:"true"}, libfido2.Option{Name:"plat", Value:"false"}, libfido2.Option{Name:"clientPin", Value:"false"}, libfido2.Option{Name:"credentialMgmtPreview", Value:"true"}}, Protocols:[]uint8{0x2, 0x1}} webauthncli/fido2.go:860
2024-08-08T16:44:24-03:00 DEBU             FIDO2: Device ioreg://4294970869: filtered due to presence of excluded credential webauthncli/fido2.go:529
2024-08-08T16:44:24-03:00 DEBU             FIDO2: Device ioreg://4294970869 filtered, err=device already holds a registered credential webauthncli/fido2.go:869
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Device ioreg://4294988912: callback returned, requiresPIN=false, err=<nil> webauthncli/fido2.go:883
Detected security key tap
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Cancel device ioreg://4294970869, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Close device ioreg://4294988912, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Cancel device ioreg://4294988912, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Device touch status error: touch status: keep alive cancel webauthncli/fido2.go:1049
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Close device ioreg://4294970869, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:44:27-03:00 DEBU             FIDO2: Device goroutines exited cleanly webauthncli/fido2.go:688

tsh mfa add (already registered):

2024-08-08T16:46:14-03:00 DEBU             FIDO2: Using libfido2 for credential creation webauthncli/api.go:230
2024-08-08T16:46:14-03:00 DEBU             FIDO2: registration: resident key=false webauthncli/fido2.go:449
Tap your *new* security key
2024-08-08T16:46:14-03:00 DEBU             FIDO2: Device ioreg://4294988912: not a FIDO2 device webauthncli/fido2.go:862
2024-08-08T16:46:14-03:00 DEBU             FIDO2: Device ioreg://4294970869: info &libfido2.DeviceInfo{Versions:[]string{"U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE"}, Extensions:[]string{"credProtect", "hmac-secret"}, AAGUID:[]uint8{0xee, 0x88, 0x28, 0x79, 0x72, 0x1c, 0x49, 0x13, 0x97, 0x75, 0x3d, 0xfc, 0xce, 0x97, 0x7, 0x2a}, Options:[]libfido2.Option{libfido2.Option{Name:"rk", Value:"true"}, libfido2.Option{Name:"up", Value:"true"}, libfido2.Option{Name:"plat", Value:"false"}, libfido2.Option{Name:"clientPin", Value:"false"}, libfido2.Option{Name:"credentialMgmtPreview", Value:"true"}}, Protocols:[]uint8{0x2, 0x1}} webauthncli/fido2.go:860
2024-08-08T16:46:14-03:00 DEBU             FIDO2: Device ioreg://4294988912 filtered, err=device already holds a registered credential webauthncli/fido2.go:869
2024-08-08T16:46:14-03:00 DEBU             FIDO2: Device ioreg://4294970869: filtered due to presence of excluded credential webauthncli/fido2.go:529
2024-08-08T16:46:14-03:00 DEBU             FIDO2: Device ioreg://4294970869 filtered, err=device already holds a registered credential webauthncli/fido2.go:869
2024-08-08T16:46:17-03:00 DEBU             FIDO2: Cancel device ioreg://4294970869, err=failed to cancel: tx error webauthncli/fido2.go:826
2024-08-08T16:46:17-03:00 DEBU             FIDO2: Close device ioreg://4294988912, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:46:17-03:00 DEBU             FIDO2: Cancel device ioreg://4294988912, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:46:17-03:00 DEBU             FIDO2: Device touch status error: touch status: keep alive cancel webauthncli/fido2.go:1049
2024-08-08T16:46:17-03:00 DEBU             FIDO2: Close device ioreg://4294970869, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:46:17-03:00 DEBU             FIDO2: Device goroutines exited cleanly webauthncli/fido2.go:688

login (only authenticator):

2024-08-08T16:52:46-03:00 DEBU             FIDO2: Using libfido2 for assertion webauthncli/api.go:183
2024-08-08T16:52:46-03:00 DEBU             FIDO2: assertion: passwordless=false, uv=false, 1 allowed credentials webauthncli/fido2.go:168
Tap any security key
2024-08-08T16:52:46-03:00 DEBU             FIDO2: Device ioreg://4294988912: not a FIDO2 device webauthncli/fido2.go:862
2024-08-08T16:52:46-03:00 DEBU             FIDO2: Device ioreg://4294970869: info &libfido2.DeviceInfo{Versions:[]string{"U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE"}, Extensions:[]string{"credProtect", "hmac-secret"}, AAGUID:[]uint8{0xee, 0x88, 0x28, 0x79, 0x72, 0x1c, 0x49, 0x13, 0x97, 0x75, 0x3d, 0xfc, 0xce, 0x97, 0x7, 0x2a}, Options:[]libfido2.Option{libfido2.Option{Name:"rk", Value:"true"}, libfido2.Option{Name:"up", Value:"true"}, libfido2.Option{Name:"plat", Value:"false"}, libfido2.Option{Name:"clientPin", Value:"false"}, libfido2.Option{Name:"credentialMgmtPreview", Value:"true"}}, Protocols:[]uint8{0x2, 0x1}} webauthncli/fido2.go:860
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Got 1 assertions webauthncli/fido2.go:251
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Authenticated: credential ID (b64) = e598-1ehGzWQY9liUvjYsaTDFKcClVlsIgT8VP4zkP9qAnkxWYKA7PcNVeToMZUuR1xaQa9HiPglEqJZcKnKrg, user ID (hex) = , user name = "" webauthncli/fido2.go:259
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Device ioreg://4294988912: callback returned, requiresPIN=false, err=<nil> webauthncli/fido2.go:883
Detected security key tap
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Cancel device ioreg://4294970869, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Close device ioreg://4294988912, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Cancel device ioreg://4294988912, err=<nil> webauthncli/fido2.go:826
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Device ioreg://4294970869: callback returned, requiresPIN=false, err=failed to get assertion: keep alive cancel webauthncli/fido2.go:883
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Close device ioreg://4294970869, err=<nil> webauthncli/fido2.go:842
2024-08-08T16:52:48-03:00 DEBU             FIDO2: Device goroutines exited cleanly webauthncli/fido2.go:688

@codingllama codingllama requested a review from ravicious August 8, 2024 20:20
@codingllama
Copy link
Copy Markdown
Contributor Author

@ravicious, would you mind cloning this branch and running a final local test to make sure the fix is solid?

@codingllama
Copy link
Copy Markdown
Contributor Author

Re backports: I've no plans to backport this as of now. I don't like changing this logic much, so I would rather only do that after v17 testplans (or if someone else raises the issue).

Comment thread lib/auth/webauthncli/fido2_test.go Outdated
Comment thread lib/auth/webauthncli/fido2.go
@codingllama
Copy link
Copy Markdown
Contributor Author

Friendly ping @gzdunek @ravicious ?

Copy link
Copy Markdown
Member

@ravicious ravicious left a comment

Choose a reason for hiding this comment

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

I tested this locally and these changes let me log in with the old key.

@public-teleport-github-review-bot public-teleport-github-review-bot Bot removed the request for review from gzdunek August 12, 2024 13:21
@codingllama
Copy link
Copy Markdown
Contributor Author

Thanks everyone!

@codingllama codingllama enabled auto-merge August 12, 2024 14:07
@codingllama codingllama disabled auto-merge August 12, 2024 14:15
@codingllama
Copy link
Copy Markdown
Contributor Author

FYI, I've moved the errorOnUnknownCredential after the tap check, as this better matches the behavior described by Rafal. (929de20)

@codingllama codingllama enabled auto-merge August 12, 2024 14:19
@codingllama codingllama added this pull request to the merge queue Aug 12, 2024
Merged via the queue into master with commit ca2ce88 Aug 12, 2024
@codingllama codingllama deleted the codingllama/u2f-internal-error branch August 12, 2024 14:57
codingllama added a commit that referenced this pull request Nov 4, 2024
* Simulate "internal error" on multiple credentials

* fix: Assert credentials individually on U2F devices

* Use bytes.Repeat

* Comment on U2F and libfido2.ErrUserPresenceRequired

* Move errorOnUnknownCredential failure after the "tap"
codingllama added a commit that referenced this pull request Nov 4, 2024
* Simulate "internal error" on multiple credentials

* fix: Assert credentials individually on U2F devices

* Use bytes.Repeat

* Comment on U2F and libfido2.ErrUserPresenceRequired

* Move errorOnUnknownCredential failure after the "tap"
github-merge-queue Bot pushed a commit that referenced this pull request Nov 5, 2024
* Simulate "internal error" on multiple credentials

* fix: Assert credentials individually on U2F devices

* Use bytes.Repeat

* Comment on U2F and libfido2.ErrUserPresenceRequired

* Move errorOnUnknownCredential failure after the "tap"
github-merge-queue Bot pushed a commit that referenced this pull request Nov 5, 2024
* Simulate "internal error" on multiple credentials

* fix: Assert credentials individually on U2F devices

* Use bytes.Repeat

* Comment on U2F and libfido2.ErrUserPresenceRequired

* Move errorOnUnknownCredential failure after the "tap"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants