Skip to content

FIDO2 PIN permanently blocked (CTAP error: 0x32) after accessing FIDO2 credentials from a secondary hardware profile #83

@net-fall

Description

@net-fall

Description

Using the FIDO2 module across different hardware profiles (Primary and Secondary/Plausible Deniability profiles) causes a critical state corruption. Accessing FIDO2 data from the secondary profile permanently breaks the FIDO2 module for the primary profile, resulting in an irrecoverable PIN_BLOCKED state.

It appears the FIDO2 module state (PIN retry counters, pinTokens, or resident keys encryption) is shared globally but gets corrupted or locked to the context of the currently active hardware profile.

Environment

  • OnlyKey CLI v1.2.10
  • OnlyKey Firmware Version 3.0.4-prodc

Steps to Reproduce

  • Unlock the OnlyKey into the Primary hardware profile.
  • Set a FIDO2 Client PIN using onlykey-cli set-pin.
  • Create some FIDO2 Resident Keys (e.g., generate an SSH key using ssh-keygen -t ed25519-sk or register on a WebAuthn site).
  • Re-plug the OnlyKey and unlock it into the Secondary hardware profile (Plausible Deniability profile).
  • Run onlykey-cli credential ls. The CLI will prompt for the FIDO2 PIN. Enter the PIN that was set in step 2.
  • Re-plug the OnlyKey again and unlock it back into the Primary hardware profile.
  • Attempt to use any FIDO2 function (e.g., run onlykey-cli credential ls or try to authenticate via SSH/WebAuthn).

Expected Behavior

FIDO2 Resident Keys and the FIDO2 PIN should either be completely isolated per hardware profile, OR they should be globally shared without corrupting the CTAP state when switching between profiles. Reading credentials from the secondary profile should not break the primary profile.

Actual Behavior

The FIDO2 module stops recognizing the correct FIDO2 PIN on the primary profile. Because the internal state was altered while under the secondary profile's context, the primary profile fails to validate the PIN. This quickly triggers the CTAP brute-force protection, resulting in a permanent lockout:

File "/usr/local/lib/python3.14/site-packages/fido2/ctap2/base.py", line 675, in send_cbor
    raise CtapError(status)
fido2.ctap.CtapError: CTAP error: 0x32 - PIN_BLOCKED

The only workaround is a complete onlykey-cli reset, which wipes all FIDO2 credentials and SSH keys.

This issue makes the "Plausible Deniability" feature fundamentally incompatible with standard FIDO2 usage (like ed25519-sk SSH keys). If a user happens to trigger any FIDO2 operation while in the secondary profile, they will lose all their FIDO2 credentials on the primary profile.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions