Skip to content

Release v0.2.6 - #12

Merged
TheMaxMur merged 6 commits into
mainfrom
develop
Jun 21, 2026
Merged

TheMaxMur merged 6 commits into
mainfrom
develop

Conversation

@TheMaxMur

Copy link
Copy Markdown
Owner

RS-Key v0.2.6

Firmware bcdDevice 0x077B0x077E. Three fixes since v0.2.5 (all HW-verified on RP2350):

  • fix(fido): ML-DSA-44 (-48) getAssertion wedge (0x077D0x077E) — the post-quantum credential key is now heap-boxed off the worker stack; an inline ~16.6 KiB fips204 keypair overflowed the stack during sign (reachable DoS). Restores a measured 32–64 KiB margin; heap unchanged (no RSA impact); size_of::<CredKey>() regression guard. Verified tests/60 + tests/61.
  • fix(fido): advertise EdDSA (-8) in getInfo (0x077C0x077D) — ssh-keygen -t ed25519-sk now works on Windows (WebAuthn intersects requested algs with the advertised set).
  • fix(fs): two power-cut data-durability bugs (0x077B0x077C) — orphaned metadata on delete + a present-cache false-absent after a torn migration; cache is now tri-state. New kv_durability fuzz target.

Host gate (check.sh) green; fuzz workspace builds; full HW sweep (FIDO 00–26, PQC 60–62, OpenPGP 32–41, pico-fido 189✓, openpgp-card 166✓).

🤖 Generated with Claude Code

TheMaxMur and others added 6 commits June 21, 2026 12:14
…cache false-absent)

Both found by the power_cut / fs_ops fuzz targets, latent since the
present-cache landed in v0.2.3. Neither affects the shipped v0.2.5
artifacts (power-cut-edge, not artifact-integrity).

1. delete() orphaned metadata. It dropped a file's EF_META record only
   when the file's own data was present, so a file given metadata
   (meta_add) but never written (put) kept its metadata after deletion --
   the record read back alive across a reboot, diverging the live key set
   from the model. delete() now drops metadata unconditionally (O(1) when
   there is none); meta_delete skips the EF_META rewrite when the FID had
   no record, so the absent-slot reset sweep stays write-free.

2. The present-cache could go false-absent after a torn migration. The
   boot scan seeds its negative cache from a bulk for_each_key, which can
   silently under-count a key when a power-cut interrupts a
   sequential-storage page migration -- while the per-key fetch_item still
   recovers it. A clear bit was trusted as absent, so committed
   data/metadata read back lost, and a meta_add over a false-absent
   EF_META wiped every existing record. The cache is now tri-state
   (present + a decided authority bit): a clear bit is trusted as absent
   only once a backend probe confirms it, otherwise the reliable
   fetch_item decides and the answer is memoised -- a false-absent is now
   impossible. Cost: a one-time-per-boot first probe per absent FID, then
   O(1); +8 KiB .bss.

Verified: 20/20 rsk-fs unit tests (4 new), power_cut + fs_ops fuzz clean,
full miri 39/39, scripts/check.sh green, flashed + HW-verified.
bcdDevice 0x077B -> 0x077C.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ity)

Drives one sequential-storage MapStorage partition directly -- no rsk-fs,
no present-cache, no EF_META logic -- so a durability failure here pins
the fault to the dependency rather than the Fs layer. This isolation is
what proved the present-cache false-absent bug lived in our cache, not the
store: this target stays clean (349k+ runs) while power_cut reproduced the
bug. Key index 0 is rewritten on most ops to mirror EF_META, the hottest
key and the one most exposed to a torn migration. deep-checks
auto-discovers it via `cargo fuzz list`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dows

`ssh-keygen -t ed25519-sk` failed to create a credential on Windows while
working on macOS/Linux. The device has always supported EdDSA in
makeCredential, but `-8` was omitted from the advertised getInfo `algorithms`
(0x0A). The Windows WebAuthn API (the path Windows OpenSSH takes) intersects
the request's pubKeyCredParams with the authenticator's advertised set and
silently drops `-8`, so the create fails; macOS/Linux OpenSSH go through
libfido2 and send `-8` directly, so it worked there. (`ecdsa-sk`/ES256, which
is advertised, worked on Windows — confirming the advertised-algorithm gap.)

Advertise `-8` in the shipping/default build (getInfo + Metadata Statement).
The capability is unchanged; only the advertisement was added. ES256K (-47)
stays unadvertised (still negotiable from a request).

The FIDO Conformance tool's shared verifySignatureCOSE maps only -7/-35/-36,
so it cannot verify a packed EdDSA self-attestation (MakeCred-Resp P-06).
A new `fido-conformance` cargo feature suppresses `-8` again for the
conformance run, and `ea-conformance-rpid` implies it (an EA conformance build
is a conformance build). `metadata/rs-key.conformance.metadata.json` is the
matching EdDSA-free statement for the tool; tests/62 verifies it stays equal to
the shipping statement minus EdDSA and picks the right profile for the live
device. tests/26 reconciled (it asserted the pre-conformance advertised set).

bcdDevice 0x077C -> 0x077D.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three hardware tests hardcoded the pre-conformance FIDO algorithm set and a
4 MiB flash size; reconcile them with the shipping device:

- tests/60, tests/61: the advertised getInfo algorithms are now
  [-7,-35,-36,-8] (EdDSA -8 re-added for Windows WebAuthn; ES256K -47 stays
  unadvertised), advertise-pqc prepending -48. Both asserted the old
  [-7,-8,-35,-36,-47] order, which predates the FIDO-conformance unadvertise.
- tests/85: accept 16 MiB flash (TenStar) as well as 4 MiB; the device reports
  its size correctly, the assertion was hardcoded to 4 MiB.

All three were confirmed to pass their getInfo/flash assertions on hardware
(bcdDevice 0x077D).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ML-DSA-44 (COSE -48) getAssertion hard-wedged the device: the fips204
sign path overflowed the RP2350 worker stack, faulting into panic-halt
with FIDO dark until a USB replug. A reachable DoS even though -48 is
unadvertised by default -- an explicit -48 makeCredential then
getAssertion wedges the authenticator.

Root cause: CredKey::MlDsa44 held fips204's ~16.6 KiB of NTT-form keys
INLINE on the stack, directly below the stack-heavy rejection-sampling
sign. The MSP worker-stack ceiling had dropped from ~238.8 to ~222.4 KiB
between 0x0767 and 0x077D (.bss grew +16.3 KiB: the power-cut tri-state
present-cache and the hybrid ML-KEM seed-backup), pushing -48 ga's
high-water over the edge. keygen survives -- sign is the deeper frame.

Fix: box the keypair (Box<MlDsa44>) so it lives on the firmware heap,
which is idle during a FIDO request (applet keys are reconstructed
per-op, nothing persists). Frees ~16.6 KiB at sign depth, restoring a
measured 32-64 KiB margin (heap binary-search on HW: ga passes at -32
KiB stack, wedges at -64 KiB). Heap left at 128 KiB -- no RSA impact;
PQC-path-only. A size_of::<CredKey>() guard fails loudly if the key
regresses back inline.

Verified: host check.sh green; HW tests/60 (raw CTAPHID) + tests/61
(python-fido2 / OpenSSL) both pass on 0x077E (getAssertion ~0.4 s, was a
dark wedge); resident-upgrade sign path OK.

bcdDevice 0x077D -> 0x077E.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dDSA-sk, FS power-cut) + readme version

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TheMaxMur
TheMaxMur merged commit 87c0d3d into main Jun 21, 2026
12 checks passed
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.

1 participant