Skip to content

Don't use a protocol version that a device doesn't support (#367) - #370

Draft
micolous wants to merge 9 commits into
mozilla:ctap2-2021from
micolous:ctap2/issue-367
Draft

Don't use a protocol version that a device doesn't support (#367)#370
micolous wants to merge 9 commits into
mozilla:ctap2-2021from
micolous:ctap2/issue-367

Conversation

@micolous

@micolous micolous commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Draft PR, needs #374

This makes authenticator-rs never try to use CTAP1 / U2F on devices that won't support it (#367), and also never try to use CTAP2 on devices that won't support it (#371, repeat of #72).

API changes:

  • FidoDevice now requires (new) CtapVersionSupport trait. There is an impl for T: HIDDevice.

  • Replaced, with alias: FidoDevice::should_try_ctap2() is moved and renamed to CtapVersionSupport::supports_ctap2(). There is an alias for the old name. This replaces the duplicated definition of the function for each platform.

  • Added: CtapVersionSupport::supports_ctap1(), which checks for CAPABILITY_NMSG being unset.

  • Changed: FidoDevice::downgrade_to_ctap1() is now a fallible operation (returns Result), based on CtapVersionSupport::supports_ctap1().

Using supports_ctap1() fixes some incorrect behaviour:

  • CTAP2-only1 register() or sign() requests with use_ctap1_fallback = true (security.webauthn.ctap2 = false):

    The request will now immediately error out with UnsupportedOption(...) (or NotAllowedError in Firefox), rather than attempting device selection and then erroring out (with the same error).

  • CTAP2-only1 register() or sign() requests:

    CTAP1-only devices will now be completely ignored, rather than trying device selection and then erroring out if the CTAP1-only device is selected 2.

    This also excludes CTAP1-only devices that don't enforce user presence checks (like U2F NitroKeys that don't have a button), which would otherwise "capture" the request and then prevent use of a CTAP2 authenticator.

  • CTAP1-compatible register() or sign() requests with use_ctap1_fallback = true (security.webauthn.ctap2 = false):

    CTAP2-only devices will now be completely ignored, rather than trying device selection and then sending them an invalid command (which would probably error out) if selected 2.

When a device is ignored, it won't blink or respond to button press. This may lead a user to believe some of their devices are not working. Immediately erroring for impossible requests may lead a user to believe there is a browser bug.

However, prompting for a button press on a device that definitely won't work will just return an error anyway, and doesn't give the user clues about which of their authenticators would actually work.

There may be better ways to handle that (eg: "there are 2 devices connected, but none of them can handle this request"), but it'd require significant API and UI changes to support it, and risks being annoying (eg: corporate-issued devices that have an always-present nano-key that only supports CTAP1).

While here, I've added some more documentation, and fixed some incorrect comments.

Fixes #367, which is required to implement caBLE support in Firefox.

Fixes #371.

TODO (for me)

  • Bug: When there is a CTAP2-only authenticator initially connected, CTAP1 fallback mode doesn't consider other devices that are already connected or connected later.
  • Test this with some real authenticators on different platforms
  • Test this inside of Firefox
  • Add a supports_ctap2() guard to send_cbor_cancellable. There are a bunch of CTAP2 tests that use the device without initialising first, causing mock::HIDDevice::get_device_info to panic.
  • Add a supports_ctap1() guard to send_ctap1_cancellable.
  • Consider making HidDevice::get_device_info return an optional, rather than panicing.
  • Update authrs_bridge::TestToken (which uses FidoDevice but not HIDDevice) ▶️ https://bugzilla.mozilla.org/show_bug.cgi?id=2065013

Footnotes

  1. eg: uv = required, rk = required, not supporting ES256, etc. 2

  2. selected implicitly, as the only device, or selected explicitly among multiple devices with a button press 2

@micolous micolous changed the title Don't use CTAP1/U2F on devices that don't support it (#367) Don't use a protocol version that a device doesn't support (#367) Aug 13, 2026
@micolous
micolous force-pushed the ctap2/issue-367 branch 2 times, most recently from df6098b to e1f96c1 Compare August 18, 2026 05:23
micolous added a commit to micolous/firefox that referenced this pull request Aug 18, 2026
* Implement `CtapVersionSupport` trait for `TestToken`:
  mozilla/authenticator-rs#370

* Remove local version of `memoffset v0.8.999`, dependency removed in
  mozilla/authenticator-rs#361

Differential Revision: https://phabricator.services.mozilla.com/D318670
micolous added a commit to micolous/firefox that referenced this pull request Aug 19, 2026
* Implement `CtapVersionSupport` trait for `TestToken`:
  mozilla/authenticator-rs#370

* Make `TestToken` explicitly treat a version parameter as "this version and
  lower".

* Remove local version of `memoffset v0.8.999`, dependency removed in
  mozilla/authenticator-rs#361

Differential Revision: https://phabricator.services.mozilla.com/D318670
micolous added a commit to micolous/firefox that referenced this pull request Aug 20, 2026
* Implement `CtapVersionSupport` trait for `TestToken`:
  mozilla/authenticator-rs#370

* `TestToken` now treats a version parameter as "this version and lower".

* Remove local version of `memoffset v0.8.999`, dependency removed in
  mozilla/authenticator-rs#361

Differential Revision: https://phabricator.services.mozilla.com/D318670
* Update `AuthenticatorOptions::user_verification` docs to use the CTAP
  2.3 description, and note some caveats.

* Add `AuthenticatorOptions::supports_uv()` helper.
* Don't skip UV when `uv = required`

* Don't skip UV when `uv != discouraged` and UV is "possible" but
  unconfigured

This is rewritten to be closer to the CTAP 2.3 spec's steps.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CTAP1/U2F-only authenticators should not be used for CTAP2-only operations CTAP1/U2F commands should not be sent to devices that don't support it

1 participant