Closed Bug 1440044 Opened 7 years ago Closed 7 years ago

Confirmed bug in Firefox, sends incorrect message type when registering 2nd security key

Categories

(Core :: DOM: Device Interfaces, defect, P3)

58 Branch
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: admin, Assigned: ttaubert)

References

Details

(Whiteboard: [webauthn] [webauthn-interop][u2f])

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.73 Safari/537.36 Steps to reproduce: On any of the following sites: Github, Bitbucket, Dropbox, NextCloud Register a first security key, view with USB debugger that a u2f.register message is sent. Attempt to register a 2nd U2F security key, view with USB debugger that a u2f.sign message is sent first which results in an error message, then the u2f.register message is sent. Actual results: It is sending a u2f.sign message when it should be sending u2f.register. It still works with Yubikey because it errors out and tries again but does not work with many other U2F keys. Expected results: The same thing should happen for the first and second security key added to a site. For a detailed description of this issue see - https://groups.google.com/d/msg/onlykey/HZ-HWk_LibE/jQMxWgV4BQAJ
Unfortunately I don't have a Yubikey or another USB with U2F security key to test this. So I am going to assign the "Core: DOM: Device Interfaces" component to this issue and maybe someone with more knowledge in this area can investigate this issue further. In the meantime, can you please retest this using the latest Firefox release and latest Nightly build and report back the results?(You can download the latest Nightly build from here https://goo.gl/57dpxn) When doing this, please use a new clean Firefox profile, maybe even safe mode, to eliminate custom settings as a possible cause (https://goo.gl/AR5o9d).
Component: Untriaged → DOM: Device Interfaces
Flags: needinfo?(admin)
Product: Firefox → Core
Flags: needinfo?(jjones)
Priority: -- → P3
Thanks, Kyle. And thanks Emil & admin. I'm clearing your needinfos because I'm confident this isn't something that would have changed since 58. Tim: I'm not able to dig into the state machine to triage this tonight. The description in the linked discussion to onlykey sounds like the issue is with the state machine's implementation of u2f_is_keyhandle_valid before calling u2f_register. This could be the same or similar issue as seen in Bug 1440805.
Assignee: nobody → ttaubert
Flags: needinfo?(jjones)
Flags: needinfo?(admin)
Whiteboard: [webauthn] [webauthn-interop][u2f]
So AFAICT we do what Chrome does, not sure why it works there... https://chromium.googlesource.com/chromium/src/+/master/device/fido/u2f_register.cc#56
From the OnlyKey thread: "The differences shown in red. Yubikey when it gets the u2f.sign message responds with 6A 80 (SW_WRONG_DATA), OnlyKey on the other hand when it gets the u2f.sign message responds with 69 85 (SW_CONDITIONS_NOT_SATISFIED). Firefox when it receives SW_WRONG_DATA sends the u2f.register message that should have been sent the first time, when it receives SW_CONDITIONS_NOT_SATISFIED it does nothing, the web app stops responding."
From the FIDO spec: https://fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-message-formats-v1.1-id-20160915.html#authentication-request-message---u2f_authenticate When for u2f_authenticate the control byte is set to 0x07 (check-only) then there are two possible responses: 1) message:error:test-of-user-presence-required This means the key handle is valid and was created by the token. 2) message:error:bad-key-handle The key handle was not created by the token, or with a different AppId.
Per: https://fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-message-formats-v1.1-id-20160915.html#u2f-message-framing The status codes are the following: 1) SW_CONDITIONS_NOT_SATISFIED: The request was rejected due to test-of-user-presence being required. This clearly has to be the status code sent in branch (1) of the comment above, i.e. the handle was created by the token that responded. 2) SW_WRONG_DATA: The request was rejected due to an invalid key handle. IIUIC this must be the status code for branch (2).
(In reply to Tim Taubert [:ttaubert] from comment #4) > From the OnlyKey thread: > > "The differences shown in red. Yubikey when it gets the u2f.sign message > responds with 6A 80 (SW_WRONG_DATA), OnlyKey on the other hand when it gets > the u2f.sign message responds with 69 85 (SW_CONDITIONS_NOT_SATISFIED). > Firefox when it receives SW_WRONG_DATA sends the u2f.register message that > should have been sent the first time, when it receives > SW_CONDITIONS_NOT_SATISFIED it does nothing, the web app stops responding." The YubiKey responds with SW_WRONG_DATA because the key handle in the exclusion list doesn't match the token. And thus we proceed and allow the user to register the second key handle. The OnlyKey (and maybe the U2FZero too?) sends SW_CONDITIONS_NOT_SATISFIED, which signals that the token matches the handle in the exclusion list. It seems that the latter doesn't implement CTAP1 correctly...
I can't figure out though why this should work in Chrome. Here's where the sign response is handled: https://chromium.googlesource.com/chromium/src/+/master/device/fido/u2f_device.cc#92 Sending SW_CONDITIONS_NOT_SATISFIED should cause exclusion too. https://chromium.googlesource.com/chromium/src/+/master/device/fido/u2f_register.cc#70
(In reply to Tim Taubert [:ttaubert] from comment #7) > It seems that the latter doesn't implement CTAP1 correctly... FTR, GitHub's SoftU2F implementation matches the YubiKey behavior too: https://github.com/github/SoftU2F/blob/45825a5bd6e6bad7ae9bd681c8584cbcb6e7fb7b/SoftU2FTool/U2FAuthenticator.swift#L123
The problem is that the OnlyKey seems to not implement FIDO U2F v1.1 correctly, as described in comment #7. Firefox uses the same backend for U2F and WebAuthn, and always handles key exclusion lists given to u2f.register() or navigator.credentials.create(). Chrome implements a key exclusion list only for WebAuthn [1]. Their U2F API is a JS-based implementation using WebUSB [2] that ignores the "registeredKeyHandles" parameter, afaict. While OnlyKey works with Chrome/U2F, it won't with Chrome/WebAuthn as that has the same behavior as our implementation. It might break in the future if Chrome decides to use the C++-based implementation for U2F as well. [1] https://chromium.googlesource.com/chromium/src/+/ef10f86671cfedfe5257395ed3dc70756eaef935%5E%21/device/u2f/u2f_register.cc [2] https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/resources/cryptotoken/enroller.js#356
To summarize: there's nothing for us to do here. OnlyKey needs to fix their implementation or it will hit the same issue with Firefox/Chrome via the WebAuthn API soon. J.C., to double-check, do you agree? Let's close this if you do.
Flags: needinfo?(jjones)
I agree with your analysis, Tim. OP: I'm going to close this bug. Please point the hardware manufacturer to here and the spec. (I note that OnlyKey is not certified by the FIDO Alliance as compliant.) As Tim points out, they will have this same issue in Chrome with WebAuthn, which enters Beta in a few weeks in M65.
Status: UNCONFIRMED → RESOLVED
Closed: 7 years ago
Flags: needinfo?(jjones)
Resolution: --- → INVALID
Hi, I did some more digging and you are correct that both Chrome and Firefox send a u2f.sign request prior to sending u2f.register for adding a 2nd security key but they respond quite differently. The reason that Chrome works and Firefox does not is as follows: Output from Chrome, first security key registered attempting to register 2nd: 00000000 FF FF FF FF 86 00 08 CA 6F 72 AC 16 06 42 ÿ ÿ ÿ ÿ . . Ê o r ¬ . . B 0000000E 8C 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 FF FF FF FF 86 00 11 CA 6F 72 AC 16 06 42 ÿ ÿ ÿ ÿ . . Ê o r ¬ . . B 0000000E 8C 02 00 00 00 02 01 00 01 00 00 00 00 00 . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 07 00 03 00 00 00 00 00 . . . . . . . . . . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 08 55 32 46 5F 56 32 90 . . . . . . U 2 F _ V 2 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 8A 00 02 03 00 00 00 81 . . . . . . . . . . . 0000000E E3 B0 C4 42 98 FC 1C 14 9A FB F4 C8 99 6F ã ° Ä B ü . . û ô È o 0000001C B9 24 27 AE 41 E4 64 9B 93 4C A4 95 99 1B ¹ $ ' ® A ä d L ¤ . 0000002A 78 52 B8 55 C5 0F 8A 7B 70 8E 92 F8 2E 7A x R ¸ U Å . { p ø . z 00000038 50 E2 BD C5 5D 8F D9 1A P â ½ Å ] Ù . 00000000 02 00 00 00 00 22 FE 6B 29 C0 CD F7 80 55 . . . . . " þ k ) À Í ÷ U 0000000E 30 84 2A F5 81 40 15 E1 97 18 CD 51 25 67 0 * õ @ . á . Í Q % g 0000001C 96 8D 90 18 5C 30 1C 74 E9 8E 20 74 54 34 . \ 0 . t é t T 4 0000002A CF FE 1E 9F 46 E0 3C EA 18 2B 5B 53 76 32 Ï þ . F à < ê . + [ S v 2 00000038 60 50 04 B2 B1 A3 ED 0F ` P . ² ± £ í . 00000000 02 00 00 00 01 C3 7D BB B1 2F 21 1F DC D8 . . . . . Ã } » ± / ! . Ü Ø 0000000E 52 22 2F 4E 4D 0D 58 58 0F 37 32 00 00 00 R " / N M . X X . 7 2 . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 02 69 85 00 00 00 00 00 . . . . . . i . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 88 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 BF 00 01 01 00 00 00 00 00 00 . . . . ¿ . . . . . . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 8A 00 02 03 00 00 00 81 . . . . . . . . . . . 0000000E E3 B0 C4 42 98 FC 1C 14 9A FB F4 C8 99 6F ã ° Ä B ü . . û ô È o 0000001C B9 24 27 AE 41 E4 64 9B 93 4C A4 95 99 1B ¹ $ ' ® A ä d L ¤ . 0000002A 78 52 B8 55 C5 0F 8A 7B 70 8E 92 F8 2E 7A x R ¸ U Å . { p ø . z 00000038 50 E2 BD C5 5D 8F D9 1A P â ½ Å ] Ù . 00000000 02 00 00 00 00 22 FE 6B 29 C0 CD F7 80 55 . . . . . " þ k ) À Í ÷ U 0000000E 30 84 2A F5 81 40 15 E1 97 18 CD 51 25 67 0 * õ @ . á . Í Q % g 0000001C 96 8D 90 18 5C 30 1C 74 E9 8E 20 74 54 34 . \ 0 . t é t T 4 0000002A CF FE 1E 9F 46 E0 3C EA 18 2B 5B 53 76 32 Ï þ . F à < ê . + [ S v 2 00000038 60 50 04 B2 B1 A3 ED 0F ` P . ² ± £ í . 00000000 02 00 00 00 01 C3 7D BB B1 2F 21 1F DC D8 . . . . . Ã } » ± / ! . Ü Ø 0000000E 52 22 2F 4E 4D 0D 58 58 0F 37 32 00 00 00 R " / N M . X X . 7 2 . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 02 69 85 00 00 00 00 00 . . . . . . i . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 88 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 BF 00 01 01 00 00 00 00 00 00 . . . . ¿ . . . . . . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 8A 00 02 03 00 00 00 81 . . . . . . . . . . . 0000000E E3 B0 C4 42 98 FC 1C 14 9A FB F4 C8 99 6F ã ° Ä B ü . . û ô È o 0000001C B9 24 27 AE 41 E4 64 9B 93 4C A4 95 99 1B ¹ $ ' ® A ä d L ¤ . 0000002A 78 52 B8 55 C5 0F 8A 7B 70 8E 92 F8 2E 7A x R ¸ U Å . { p ø . z 00000038 50 E2 BD C5 5D 8F D9 1A P â ½ Å ] Ù . 00000000 02 00 00 00 00 22 FE 6B 29 C0 CD F7 80 55 . . . . . " þ k ) À Í ÷ U 0000000E 30 84 2A F5 81 40 15 E1 97 18 CD 51 25 67 0 * õ @ . á . Í Q % g 0000001C 96 8D 90 18 5C 30 1C 74 E9 8E 20 74 54 34 . \ 0 . t é t T 4 0000002A CF FE 1E 9F 46 E0 3C EA 18 2B 5B 53 76 32 Ï þ . F à < ê . + [ S v 2 00000038 60 50 04 B2 B1 A3 ED 0F ` P . ² ± £ í . 00000000 02 00 00 00 01 C3 7D BB B1 2F 21 1F DC D8 . . . . . Ã } » ± / ! . Ü Ø 0000000E 52 22 2F 4E 4D 0D 58 58 0F 37 32 00 00 00 R " / N M . X X . 7 2 . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . 00000000 02 00 00 00 83 00 02 6A 80 00 00 00 00 00 . . . . . . j . . . . 0000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000001C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 0000002A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . 00000038 00 00 00 00 00 00 00 00 . . . . . . . . Output from Firefox, first security key registered attempting to register 2nd: 00000000 FF FF FF FF 86 00 08 06 78 D9 4B A7 ÿ ÿ ÿ ÿ . . . x Ù K § 0000000C 22 70 25 00 00 00 00 00 00 00 00 00 " p % . . . . . . . . . 00000018 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000024 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000030 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 0000003C 00 00 00 00 . . . . 00000000 01 00 00 00 81 00 08 B7 8D C3 E1 80 . . . . . . · Ã á 0000000C BF FF 65 00 00 00 00 00 00 00 00 00 ¿ ÿ e . . . . . . . . . 00000018 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000024 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000030 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 0000003C 00 00 00 00 . . . . 00000000 01 00 00 00 83 00 09 00 03 00 00 00 . . . . . . . . . . . 0000000C 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000018 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000024 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000030 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 0000003C 00 00 00 00 . . . . 00000000 01 00 00 00 83 00 08 55 32 46 5F 56 . . . . . . U 2 F _ V 0000000C 32 90 00 00 00 00 00 00 00 00 00 00 2 . . . . . . . . . . 00000018 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000024 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000030 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 0000003C 00 00 00 00 . . . . 00000000 01 00 00 00 83 00 8A 00 02 07 00 00 . . . . . . . . . . 0000000C 00 81 B0 56 D5 99 CE 0D E1 CD D8 7D . ° V Õ Î . á Í Ø } 00000018 57 4E EC C1 0E 9E 5D 74 F5 D5 0A E2 W N ì Á . ] t õ Õ . â 00000024 DE DF B1 7B 6A 1A DF 02 FE 4B C5 0F Þ ß ± { j . ß . þ K Å . 00000030 8A 7B 70 8E 92 F8 2E 7A 50 E2 BD C5 { p ø . z P â ½ Å 0000003C 5D 8F D9 1A ] Ù . 00000000 01 00 00 00 00 22 FE 6B 29 C0 CD F7 . . . . . " þ k ) À Í ÷ 0000000C 80 55 30 84 2A F5 81 40 4B 0E 02 A0 U 0 * õ @ K . .   00000018 56 E7 9C DB E8 15 B7 0C 89 3C C7 70 V ç Û è . · . < Ç p 00000024 25 79 E1 89 44 2A 7C A9 7E 2C D8 90 % y á D * | © ~ , Ø 00000030 90 41 3F 48 3A 2C 52 AC 79 9F B0 3F A ? H : , R ¬ y ° ? 0000003C 5F 8A 89 36 _ 6 00000000 01 00 00 00 01 66 AC DA 31 5E 6E B4 . . . . . f ¬ Ú 1 ^ n ´ 0000000C 91 2E D0 73 0A FE B6 62 3A DC DD C5 . Ð s . þ ¶ b : Ü Ý Å 00000018 92 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . 00000024 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000030 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 0000003C 00 00 00 00 . . . . 00000000 01 00 00 00 83 00 02 69 85 07 00 00 . . . . . . i . . . 0000000C 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000018 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000024 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 00000030 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 0000003C 00 00 00 00 . . . . The difference that you can notice with how Chrome works vs. Firefox is: Chrome: -->U2F Ping <--U2F Version -->u2f.authenticate with 0x03 ("enforce-user-presence-and-sign") <--69 85 (SW_CONDITIONS_NOT_SATISFIED meaning button not pressed yet) -->U2F Wink (CMD 88) <--Error response -->resend u2f.authenticate with 0x03 ("enforce-user-presence-and-sign") <--69 85 (SW_CONDITIONS_NOT_SATISFIED meaning button not pressed yet) -->U2F Wink (CMD 88) <--Error response -->resend u2f.authenticate with 0x03 ("enforce-user-presence-and-sign") Firefox: -->U2F Ping <--U2F Version -->u2f.authenticate with 0x07 ("check-only") <--69 85 (SW_CONDITIONS_NOT_SATISFIED meaning button not pressed yet) So it looks like Chrome is a bit off on the FIDO spec("enforce-user-presence-and-sign"), I think you guys got it right here with sending u2f.authenticate with 0x07 ("check-only". However, the way that Chrome has implemented this there is what looks like a U2F Wink (CMD 88) that goes out after it gets the SW_CONDITIONS_NOT_SATISFIED response. I don't think the way Firefox stops responding after receiving SW_CONDITIONS_NOT_SATISFIED is according to FIDO spec, but as far as I can read it doesn't really specify this case. SOLUTION: Firefox should try again until it times out when it receives SW_CONDITIONS_NOT_SATISFIED like Chrome does. In regards to the OnlyKey implementation of U2F, the reason we did not implement a check prior to a user pressing a button is this introduces at least two potential security vulnerabilities in U2F as described here - https://groups.google.com/d/msg/onlykey/HZ-HWk_LibE/jQMxWgV4BQAJ I have developed a way to both check if the keyhandle is valid and not be vulnerable to "Potential YubiKey Vulnerability #1". It involves two layers of keyhandle encryption using two separate keys. Unfortunately, there is no way to be compliant with FIDO spec and avoid "Potential YubiKey Vulnerability #2". If Firefox would be willing to implement SOLUTION above it would be possible to mitigate this vulnerability. In regards to not being certified by the FIDO Alliance as compliant, unfortunately it is currently impossible for an open source device to be certified. This is why devices like OnlyKey, Trezor, and other open source implementations of FIDO U2F are uncertified and probably never will be. I wrote more about the reason its not possible here - https://docs.crp.to/features.html#universal-2nd-factor-authentication-u2f Last paragraph of section. TL;DR - Open source invalidates attestation, if I can modify the source the attestation isn't valid anymore, if I can't modify the source it's not open source. I am sure Mozilla, as an open source advocate understands why having an open source device is a higher priority than certification. All certified devices have proprietary components that are not auditable or verifiable. If anyone reading this is a member of the FIDO Alliance this would be a great topic to discuss.
Flags: needinfo?(ttaubert)
Flags: needinfo?(jjones)
Hey. Yuriy from FIDO Alliance is here. Authenticator must return SW_CONDITIONS_NOT_SATISFIED(i.e. busy waiting for TUP) while its waiting for TUP. So polling is totally fine, besides, this is what we do for conformance testing as we use sync HID calls. Don't do "check-only" as it can potentially reset authenticator response, and invalidate the transaction response. Just keep sending the same authenticate/register message. I think it's a good thing to call WINK. Most of the authenticators while they wait anyway providing some Visual signalling about incoming transaction, but additional WINK would not hurt. Just check that authenticator actually implements this feature as it's optional.
> In regards to not being certified by the FIDO Alliance as compliant, > unfortunately it is currently impossible for an open source device to be > certified. > This is why devices like OnlyKey, Trezor, and other open source > implementations of FIDO U2F are uncertified and probably never will be. I > wrote more about the reason its not possible here - > https://docs.crp.to/features.html#universal-2nd-factor-authentication-u2f > Last paragraph of section. TL;DR - Open source invalidates attestation, if I > can modify the source the attestation isn't valid anymore, if I can't modify > the source it's not open source. > > I am sure Mozilla, as an open source advocate understands why having an open > source device is a higher priority than certification. All certified devices > have proprietary components that are not auditable or verifiable. > > If anyone reading this is a member of the FIDO Alliance this would be a > great topic to discuss. FIDO never said that we don't certify FOSS. Quiet the opposite. We have certified FOSS UAF server https://github.com/lightfactor. Just quoting Adam Powers(FIDO Alliance Technical Director) on FIDO Certification for FOSS: > Hi, I found my way here through your bug report at Mozilla: > https://bugzilla.mozilla.org/show_bug.cgi?id=1440044 > I just wanted to comment on the certification of open source U2F implementations. FIDO loves open source, so I don't want to leave the impression out there that we aren't willing to support the FOSS community. > If you sign up here, you can get access to the U2F test tools (no fees, no membership required): https://fidoalliance.org/test-tool-access-request/ > You can also attend the interops for free. You won't get an official logo at the end of the day, but at least you'll know that things work as expected. > By the way, we've had conversations about free certification for open source in the past. Maybe we could round up a small contingency of open source solutions and see if we can show enough of a reason to follow through on free open source certification. https://groups.google.com/forum/#!category-topic/onlykey/other/kCfHt4N0nhU So yes, we do FOSS certification.
(In reply to admin from comment #13) > I don't think the way Firefox stops responding after receiving > SW_CONDITIONS_NOT_SATISFIED is according to FIDO spec, but as far as I can > read it doesn't really specify this case. > > SOLUTION: Firefox should try again until it times out when it receives > SW_CONDITIONS_NOT_SATISFIED like Chrome does.n. Firefox has one state machine per device. The WebAuthn authenticatorMakeCredential operation is defined here: https://w3c.github.io/webauthn/#authenticatormakecredential Point (3) says: "If looking up descriptor.id in this authenticator returns non-null, and the returned item's RP ID and type match rpEntity.id and excludeCredentialDescriptorList.type respectively, then obtain user consent for creating a new credential." Firefox actually doesn't do that, but that doesn't matter because the outcome of that can only be: InvalidStateError or NotAllowedError Point (20) of the Create() method now tells us how that's interpreted: https://w3c.github.io/webauthn/#createCredential An InvalidStateError means the user consented. But as the credential was in the excludeList the whole flow aborts and the promise is rejected. A NotAllowedError will remove the authenticator from issuedRequests and thus abort the flow only for the current authenticator. To summarize, that Chrome is trying a device again doesn't actually seem WebAuthn spec conform (?) and if so you couldn't rely on that behavior. Firefox doesn't conform to the spec because it doesn't send a u2f_register message before excluding an authenticator. TBH, I don't really understand why the spec demands the the last u2f_register message though. That would only make sense if one keeps polling, which is not what the spec says, iiuic. However, if point (19) by includes formerly excluded devices by saying "For each authenticator that becomes available on this platform during the lifetime of lifetimeTimer, do the following", then maybe Chrome's behavior is correct.
Flags: needinfo?(ttaubert)
@(In reply to Tim Taubert [:ttaubert] from comment #16) In CTAP1 authenticator return actually HID error KEEP_ALIVE, so it would not cause InvalidStateError. For CTAP1 you need to check if authr returned SW_CONDITIONS_NOT_SATISFIED.
(In reply to Yuriy Ackermann from comment #17) > @(In reply to Tim Taubert [:ttaubert] from comment #16) > > In CTAP1 authenticator return actually HID error KEEP_ALIVE, so it would not > cause InvalidStateError. For CTAP1 you need to check if authr returned > SW_CONDITIONS_NOT_SATISFIED. Busy for CTAPs: CTAP2 -> HID STATUSCODE KEEP_ALIVE(0x80 | 0x3b) CTAP1 -> HID STATUSCODE U2FHID_MSG(0x80 | 0x03) + SW12(SW_CONDITIONS_NOT_SATISFIED) Sorry, made typoe in my original comment
(In reply to Yuriy Ackermann from comment #17) > @(In reply to Tim Taubert [:ttaubert] from comment #16) > > In CTAP1 authenticator return actually HID error KEEP_ALIVE, so it would not > cause InvalidStateError. Per CTAP2 spec, wouldn't an authenticator return CTAP2_ERR_CREDENTIAL_EXCLUDED(0x19)? It says that "User presence check is required for CTAP2 authenticators before the RP gets told that the token is already registered to behave similarly to CTAP1/U2F authenticators." I assume the check is performed by the authenticator? And while that's waiting it keeps sending CTAPHID_KEEPALIVE? Which is equivalent to timing out or waiting until the user touches the token? If we wanted to emulate the same behavior for CTAP1 tokens we'd have to first check whether there's any credential associated with the current token, and then send u2f_register in a loop. Until we either time out or the user touches the token. When the latter happens we either fail or succeed, depending on whether there's an associated credential.
(In reply to Tim Taubert [:ttaubert] from comment #19) > If we wanted to emulate the same behavior for CTAP1 tokens we'd have to > first check whether there's any credential associated with the current > token, and then send u2f_register in a loop. Until we either time out or the > user touches the token. When the latter happens we either fail or succeed, > depending on whether there's an associated credential. That way we'd also be WebAuthn spec-compliant...
(In reply to Tim Taubert [:ttaubert] from comment #19) > (In reply to Yuriy Ackermann from comment #17) > > @(In reply to Tim Taubert [:ttaubert] from comment #16) > > > > In CTAP1 authenticator return actually HID error KEEP_ALIVE, so it would not > > cause InvalidStateError. > > Per CTAP2 spec, wouldn't an authenticator return > CTAP2_ERR_CREDENTIAL_EXCLUDED(0x19)? From CTAP2 specs: If the excludeList parameter is present and contains a credential ID that is present on this authenticator and bound to the specified rpId, wait for user presence, then terminate this procedure and return error code CTAP2_ERR_CREDENTIAL_EXCLUDED. User presence check is required for CTAP2 authenticators before the RP gets told that the token is already registered to behave similarly to CTAP1/U2F authenticators. So CTAP2_ERR_CREDENTIAL_EXCLUDED would only be returned if you would add credID to the exclude list. > It says that "User presence check is required for CTAP2 authenticators > before the RP gets told that the token is already registered to behave > similarly to CTAP1/U2F authenticators." > > I assume the check is performed by the authenticator? And while that's > waiting it keeps sending CTAPHID_KEEPALIVE? Which is equivalent to timing > out or waiting until the user touches the token? CTAPHID_KEEPALIVE is not timeout. It's only send while authentucator processing CTAPHID_MSG From specs: This command code is sent while processing a CTAPHID_MSG. It should be sent at least every 100ms and whenever the status changes. > If we wanted to emulate the same behavior for CTAP1 tokens we'd have to > first check whether there's any credential associated with the current > token, and then send u2f_register in a loop. Until we either time out or the > user touches the token. When the latter happens we either fail or succeed, > depending on whether there's an associated credential. Yes, you would do that before actually sending any signature request, and then if authenticator returns that cred exist, then you keep sending sign request
(In reply to Yuriy Ackermann from comment #15) Thanks for the great infomation here Yuriy! > > In regards to not being certified by the FIDO Alliance as compliant, > > unfortunately it is currently impossible for an open source device to be > > certified. > > This is why devices like OnlyKey, Trezor, and other open source > > implementations of FIDO U2F are uncertified and probably never will be. I > > wrote more about the reason its not possible here - > > https://docs.crp.to/features.html#universal-2nd-factor-authentication-u2f > > Last paragraph of section. TL;DR - Open source invalidates attestation, if I > > can modify the source the attestation isn't valid anymore, if I can't modify > > the source it's not open source. > > > > I am sure Mozilla, as an open source advocate understands why having an open > > source device is a higher priority than certification. All certified devices > > have proprietary components that are not auditable or verifiable. > > > > If anyone reading this is a member of the FIDO Alliance this would be a > > great topic to discuss. > > FIDO never said that we don't certify FOSS. Quiet the opposite. We have > certified FOSS UAF server https://github.com/lightfactor. The requirements for a server are different than an authenticator. For example, this requirement: "Access to the private component of any Authenticator's attestation key shall be restricted to security-qualified authorized factory personnel." "Only security-qualified authorized factory personnel shall have access to all means of processing the handling of attestation key life cycle (generation, provisioning, and verification)." This is not possible on a truly open source authenticator. If the user does not have access to the source dealing with the attestation key then it is not fully open source and has proprietary components. If the user does have access to the source dealing with the attestation key then attestation is no longer valid. Any requirement that restricts access to "authorized personnel" would not be open source compatible. https://fidoalliance.org/specs/fido-security-requirements-v1.1-fd-20171108/fido-authenticator-security-requirements-v1.1-fd-20171108.html > > Just quoting Adam Powers(FIDO Alliance Technical Director) on FIDO > Certification for FOSS: > > > Hi, I found my way here through your bug report at Mozilla: > > https://bugzilla.mozilla.org/show_bug.cgi?id=1440044 > > I just wanted to comment on the certification of open source U2F implementations. FIDO loves open source, so I don't want to leave the impression out there that we aren't willing to support the FOSS community. > > If you sign up here, you can get access to the U2F test tools (no fees, no membership required): > https://fidoalliance.org/test-tool-access-request/ > > You can also attend the interops for free. You won't get an official logo at the end of the day, but at least you'll know that things work as expected. > > By the way, we've had conversations about free certification for open source in the past. Maybe we could round up a small contingency of open source solutions and see if we can show enough of a reason to follow through on free open source certification. > > https://groups.google.com/forum/#!category-topic/onlykey/other/kCfHt4N0nhU > Thanks! We would be very willing to discuss the possibility of and proceed with a free open source certification. I think we have a lot to offer as a good part of the team comes from secure device vulnerability testing backgrounds. I will continue this conversation on the Google group. > So yes, we do FOSS certification. In regards to this bug, it sounds like you and Tim Taubert have it covered, let me know if you need additional information. The one thing that wasn't clear to me is this "Authenticator must return SW_CONDITIONS_NOT_SATISFIED(i.e. busy waiting for TUP)" Yubikey does not appear to do this, it checks the keyhandle and returns SW_WRONG_DATA if it is invalid prior to TUP.
Flags: needinfo?(ackermann.yuriy)
(In reply to admin from comment #22) > The one thing that wasn't clear to me is this "Authenticator must return > SW_CONDITIONS_NOT_SATISFIED(i.e. busy waiting for TUP)" Yubikey does not > appear to do this, it checks the keyhandle and returns SW_WRONG_DATA if it > is invalid prior to TUP. I don't see this behaviour on my side. I will dig up old yubikeys a try it my self
Flags: needinfo?(ackermann.yuriy)
Follow these steps to reproduce. - Register Yubikey A on dropbox in Firefox - Select Add new key - Observe that while attempting to add key that it sends response 69 85, because Yubikey checks the keyhandle and identifies that this key is already registered. Yubikey stops blinking as Firefox has stopped polling as mentioned in this bug. - Remove Yubikey A and insert Yubikey B. - Select Add new key - Observe that while attempting to add key that it sends response 6A 80 (SW_WRONG_DATA), because Yubikey checks the keyhandle and identifies that this key not from this device. Yubikey continues blinking as Firefox now sends u2f.register messages. Here at no point was TUP provided, yet Yubikey is performing a cryptographic operation in order to identify if the keyhandle is valid or not. This is what I described in my original writeup as "Potential YubiKey Vulnerability #2"
Flags: needinfo?(jjones)
Depends on: 1442557
So I have these Yubikeys: - Neo 2014 - Neo 2017 - U2F 2016 - 4 2017 - 4 Type-C 2017 Yubikey NEO 2014: Getting registered keyHandle - 69 85 Getting unknown keyHandle - 6A 80 Yubikey NEO 2017: Getting registered keyHandle - 69 85 Getting unknown keyHandle - 6A 80 Yubikey 4 2017: Getting registered keyHandle - 69 85 Getting unknown keyHandle - 6A 80 Yubikey 4 Type-C 2017: Getting registered keyHandle - 69 85 Getting unknown keyHandle - 6A 80 Yubikey U2F 2017: Getting registered keyHandle - 69 85 Getting unknown keyHandle - 6A 80 Sorry for delay, was really busy
I came across article here from J.C. Jones and Tim Taubert https://hacks.mozilla.org/2018/01/using-hardware-token-based-2fa-with-the-webauthn-api/ Just FYI as was identified in this bug this statement from the article is not completely accurate- "When the user touches a token it will try to either find the stored key handle with the given ID, or try to decrypt it with the internal secret key" The Firefox implementation of U2F requires that the token decrypt keyhandle and respond prior to a user pressing touching the token (YubiKey does this as Yuriy shows in tests above). I have implemented a solution for OnlyKey that utilizes outer encryption for checking keyhandle and a separate key used for inner encryption of the keyhandle itself. I also would be interested in implementing webauthn but have not found an open source example for tokens.
Flags: needinfo?(ttaubert)
Flags: needinfo?(jjones)
Not sure what information you're requesting, the comment doesn't contain a question.
Flags: needinfo?(ttaubert)
Flags: needinfo?(jjones)
I was hoping my comment would result in some feedback here. My question - Will Firefox be addressing the issue of currently only supporting U2F tokens that decrypt key handle prior to user touching the token? Chrome's U2F Implementation supports both. Or is the final answer here that Firefox's U2F implementation will only support tokens that decrypt key handle prior to user touching the token? As this is the case presently.
Flags: needinfo?(ttaubert)
Flags: needinfo?(jjones)
(In reply to admin from comment #28) > I was hoping my comment would result in some feedback here. Ah, sorry for the delay, and thanks for the clarification! > My question - Will Firefox be addressing the issue of currently only > supporting U2F tokens that decrypt key handle prior to user touching the > token? Chrome's U2F Implementation supports both. Or is the final answer > here that Firefox's U2F implementation will only support tokens that decrypt > key handle prior to user touching the token? As this is the case presently. Tim, can you open a Github issue for the state machine change needed here, include a brief rundown of what the changes would be, and link it back? Then we can address it there rather than on this closed bug. Perhaps we can get this fixed for 61 or 62.
Flags: needinfo?(jjones)
Depends on: 1456080
Flags: needinfo?(ttaubert)
You need to log in before you can comment on or make changes to this bug.