[0.2.4] — 2026-06-19
Added
- The
rskCLI can run without Nix. Atools/pyproject.tomlpackages the
CLI so it installs from any Python ≥ 3.9 toolchain —
uvx --from ./tools rsk …,uv tool install ./tools,pipx install ./tools,
or plainpip. The Nix dev shell stays the primary, pinned path; this mirrors
its CLI runtime deps (hidapi,cryptography,pyscard,fido2,
mnemonic,shamir-mnemonic) for hosts without Nix. See
tools/README.md. Host-tool only; nobcdDevicebump.
Changed
- FIDO2 PIN entry is now uniform across the CLI. Commands disagreed on how
to take a PIN: most accepted only--pin(and aborted on a PIN-protected
device when it was omitted), whilefido list-passkeysandfido set-pin
prompted interactively with no flag at all. Every PIN-gated command (backup export/restore,audit log/verify,lock enable/disable,inventory verify,fido list-passkeys/set-pin/attestation import/clear) now
accepts the PIN either way —--pinflag or an interactive prompt —
through one chokepoint (rsk.common.resolve_pin) that only prompts when the
device actually has a PIN, so touch-only devices are never asked. Host-tool
only; nobcdDevicebump. - The
rsk-tuicockpit now routes PIN entry through one chokepoint too. Its
four per-action PIN steps collapsed into a singleApp::gate_pin+
Step::PinThenRun, so "prompt for the FIDO2 PIN iff the device has one, else
run" lives in exactly one place (mirroring the CLI'sresolve_pin). PIN-vs-
phrase collection in the modal flow is now explicit instead of a catch-all (a
stray text input can no longer land in the PIN buffer), and the four
device requires a PINstrings were unified. No behaviour change for users;
host-tool only, nobcdDevicebump.
Fixed
rsk secure-bootno longer refuses provisioning on a chip with a benign
LOCK_NS.pages_locked()read the whole OTP lock row, so a pre-set
non-secure-page lock (LOCK_NS=1,0x040404) looked like a bootloader lock
and wrongly blockedload-key; it now masksLOCK_BLspecifically. Host-tool
only; a mutation-proven regression test was added.
Security
- Transparency-log monitoring for our release signing identity. A scheduled
GitHub Action (sigstore/rekor-monitor) watches the Rekor log for entries
signed under our release workflow's OIDC identity, so illegitimate use of it —
a signature we did not produce — becomes detectable, complementing the SLSA
Build L3 provenance. CI only; seedocs/supply-chain.md. - OATH credential secrets are now sealed at rest. Every other applet
(FIDO, PIV, OpenPGP, rescue) AES-encrypts its keys before they reach flash;
OATH alone stored its TOTP/HOTP shared secrets — and the SET CODE key — as
plaintext TLV. They are now AES-256-GCM-sealed under the devicekbase
(HKDF(serial_hash, kbase, "OATH/KEYS")), the same device-seal the PIV slot
keys use. A one-time boot migration re-seals any credential enrolled before
this release, so existing accounts keep working. With the OTP MKEK burned, an
extracted flash image no longer reveals OATH secrets.bcdDevice0x0765→
0x0766. - The at-rest seal path is now enforced by types, not convention. A slot
that holds a sealed secret is aKeyFid, distinct from a plaintextu16file
id, and the only writer that accepts one isFs::put_key(KeyFid, Sealed)—
whereSealedis produced only by a seal routine. A stray
fs.put(key_fid, raw_secret)no longer compiles (asserted by acompile_fail
doctest). This is the chokepoint whose absence let OATH ship its secrets in
the clear; every applet's key FIDs were moved onto it. - Resident-credential RP domains are now boxed at rest. A discoverable
credential'sEF_RPrecord stored the relying-party id (the site's domain)
in cleartext, so a flash dump revealed the list of sites you hold passkeys
for — a privacy leak, even though the keys themselves were sealed. The domain
is now ChaCha20-Poly1305-boxed under the device seed (the same seal the
credential body uses), with the rpId hash kept in cleartext as the O(1)
lookup key. A boot migration re-boxes records enrolled before this release.
Honest residual: the rpId hash remains, so a dump can still dictionary-attack
guessable domains — but the plaintext site list is gone.bcdDevice0x0766
→0x0767.
Verify a download: https://github.com/TheMaxMur/RS-Key/blob/v0.2.4/docs/supply-chain.md