A Flipper Zero app that turns an NFC FIDO2/U2F security key (YubiKey, JavaCard running FIDO2Applet, …) into a USB security key. The Flipper enumerates on USB as a CTAPHID authenticator; every CTAP2 (CBOR) or CTAP1/U2F command from the host is relayed over NFC to a token held against the Flipper's back, and the response is relayed back.
Inspired by Bryan Jacobs'
fido2-hid-bridge, which does
the same USB-HID↔NFC bridging on Linux in Python via /dev/uhid and PC/SC.
Hold the token flat against the center of the Flipper's back. The GUI shows card state, key version, and the last activity; long-press Back to exit.
Requires ufbt pointed at
a matching SDK (developed against Momentum mntm-dev, Target 7, API 87.1).
ufbt # build dist/fido2_nfc_bridge.fap
ufbt launch # deploy to an attached Flipper and runTwo workers share one job slot (bridge.h, guarded by a single mutex):
ctaphid.c— USB worker: swaps USB to the U2F HID interface, does CTAPHID framing/reassembly, KEEPALIVE, CANCEL, 30 s deadlines.nfc_ctap.c— NFC side, driven by the firmware poller callback. Runs the poller at ISO14443-3A level and implements the ISO-DEP (14443-4) block layer itself — RATS/ATS, S(WTX) with extended waits, chained-response reassembly via R(ACK), R(NAK) recovery — because the firmware's 4A poller cannot reassemble chained I-blocks, which real tokens send for large responses. On top of that: FIDO applet SELECT, NFCCTAP_MSG command chaining, 61xx GET RESPONSE drain, and the 9100/NFCCTAP_GETRESPONSE keepalive loop.apdu.c— pure APDU build/parse helpers, no I/O (host-testable; unit tests live outside this directory because fbt globs app sources recursively).
USB CDC logging dies while the app runs (the CLI interface is replaced by the
HID one), but UART/GPIO logging works throughout: apdu_xfer logs every APDU
header TX and RX length at debug level, and the GUI activity line shows errors
(Err SW=…, Err CTAP=0x…) in the field.