Conversation
…elease.yml The documented `cosign verify-blob` recipe pinned the certificate identity to .github/workflows/release.yml, but since v0.2.2 the build+sign runs in the reusable release-build.yml (workflow_call). A workflow_call job's OIDC identity is its own job_workflow_ref, so the Fulcio cert SAN carries release-build.yml -- following the docs verbatim failed for every release since v0.2.2. Pin the regex to release-build.yml and explain why. Found and confirmed while verifying the v0.2.4 release: cosign reported "Verified OK" only with release-build.yml; release.yml was correctly rejected, and the SLSA provenance signer is release-build.yml@refs/tags/v0.2.4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Take RS-Key through the FIDO Alliance Conformance Tools v1.8.5.1 self-validation (track E2) over USB-HID: the CTAP2.3 Authenticator Tests pass 235/0 under the strictest "featureful" profile, and U2F 1.1/1.2 passes 55/0. CTAP2.3: - CTAPHID_CANCEL aborts an in-flight user-presence wait via a cross-executor abort signal (HID-1 P-10/P-15); CANCEL is no longer acknowledged. - makeCredential input validation (rp.name / pubKeyCredParams), options.up=true succeeds, getAssertion withholds user name/displayName without uv, enumerateCredentials always reports credProtect, largeBlobs accepts get=0, updateUserInformation keeps the credentialId stable for deleteCredential. - Enterprise attestation: advertise options.ep + reflect state, enforce type-1 eligibility, basic_full for a non-eligible type-1 request (F-6). The conformance test RPID is added to the type-1 list only under the never-shipped `ea-conformance-rpid` build feature. - Advertise only the tool-verifiable curves (ES256/ES384/ES512); EdDSA (-8) and ES256K (-47) stay implemented but unadvertised (MakeCred-Resp P-06). - getInfo advertises authenticatorConfigCommands (0x1F) and the alwaysUv option; authenticatorConfig gains toggleAlwaysUv (0x02), enforced in makeCredential / getAssertion (UV required while enabled). Completes the featureful profile. - forcePINChange returns the per-subcommand code the tool asserts: CTAP2_ERR_PIN_INVALID for getPinToken (0x05), CTAP2_ERR_PIN_POLICY_VIOLATION for getPinUvAuthTokenUsingPinWithPermissions (0x09). - getInfo versions advertise the backward-compatible FIDO_2_0..FIDO_2_3 superset. U2F 1.1/1.2: - basic_full attestation via an imported batch cert; out-of-order SEQ rejected as ERR_INVALID_SEQ, keyHandle resolved before the touch, and no stray PROCESSING keepalive before a fast MSG reply. New U2F metadata statement. Also: CTAPHID/CCID IN-endpoint write timeouts, an FS present-cache covering delete/has_data, and authenticatorReset clears the new config flags. Metadata statements and tests/62 drift guard kept in sync. bcdDevice -> 0x0776. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round out CTAP2.3 getInfo coverage with the cheap, purely informational members the FIDO conformance Authr-Generic test strict-compares against the metadata: - 0x09 transports = ["usb"] - 0x10 maxRPIDsForSetMinPINLength = 8 - 0x14 remainingDiscoverableCredentials = the live free resident-key-slot count (capacity minus the occupied EF_CRED slots, via the in-RAM present-key index — cheap, no flash scan, safe on the getInfo hot path) - 0x16 attestationFormats = ["packed"] - 0x1D maxPINLength = 63 Advertisement only — no behaviour change. All five are mirrored in the metadata statement (each is strict-equal compared by the tool), and in the tests/62 drift guard, with the stateful remainingDiscoverableCredentials excluded from the static comparison (and tests/62's live whitelist caught up to authenticatorConfigCommands). MAX_MIN_PIN_RPIDS moves to consts so getInfo and authenticatorConfig share it. getInfo map 15 -> 20 members. bcdDevice -> 0x0777. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EF_KEY_DEV / EF_KEY_DEV_ENC became typed KeyFid in the at-rest seal chokepoint, but the fuzz workspace (fido_vendor target, miri test) still passed them to the u16 fs.put/delete API, so the fuzz workspace stopped compiling -- caught only in weekly deep-checks, not the main gate. Use the .get() escape hatch; sync fuzz/Cargo.lock (zeroize) while here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ice 0x0778)
The vendor seed-backup channel (authenticatorVendor 0x41, MSE) is the one place
the device hands out a normally non-exportable key — the 32-byte master seed —
which makes a recorded exchange the prime harvest-now-decrypt-later target: break
the ephemeral P-256 ECDH with a future quantum computer and the wrapped seed
falls out. The MSE handshake now accepts an optional ML-KEM-768 (FIPS 203)
encapsulation key in subCommandParams key 2; when present the device encapsulates
to it and derives the channel key as
HKDF-SHA256("RSK-MSE-PQ-v1", z || ss_mlkem, dev_pub || ct), returning the
ciphertext as response key 2. Both shared secrets feed the KDF, so the channel
stays confidential unless BOTH P-256 and ML-KEM-768 are broken (defense in depth,
never PQC-only). Only the cheap encapsulate direction runs on-device; the host
keeps the ML-KEM keypair and decapsulates. A host that sends no key 2 gets the
classical channel byte-for-byte, so this is backward/forward compatible.
- rsk-fido/vendor.rs: parse the optional ek, mlkem_leg() does encapsulate + the
hybrid HKDF and returns ct; 4 new tests (end-to-end export roundtrip,
hybrid != classical key, short/unreduced ek rejected); the classical path stays
covered by the existing tests.
- rsk-crypto/mlkem.rs: mlkem_interop_kat (#[ignore]) emits a deterministic KAT so
the host's OpenSSL ML-KEM can be cross-checked against this RustCrypto
implementation off-device (proven: same seed -> same ek, OpenSSL decapsulates
RustCrypto's ct -> same ss).
- tools/rsk/backup.py: hybrid mse_handshake (soft ML-KEM import, two-way
fallback) + test_backup.py (simulated-device roundtrip over both paths).
Full scripts/check.sh green. HW-verified on bcdDevice 0x0778 (Yubico identity,
key2): clean ~1s boot, on-device encapsulate stable over 1 export + 8 stress
handshakes (no stack overflow, unlike ML-DSA-65), and host<->device key agreement
confirmed (the seed roundtripped over the hybrid channel).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…3.10 tools/uv.lock is a universal lock that pinned cryptography 44.0.3 and pytest 8.4.2 for the Python 3.9 branch, which Dependabot flagged: - cryptography subgroup attack on SECT curves (high, fixed 46.0.5) - vulnerable OpenSSL bundled in cryptography wheels (high, fixed 48.0.1) - cryptography incomplete DNS name-constraint check (low, fixed 46.0.6) - pytest predictable tmpdir handling (moderate, fixed 9.0.3) The patched cryptography/pytest releases need Python >=3.10 (pytest 9 dropped 3.9 outright), so the only complete fix is to drop EOL Python 3.9 (end-of-life 2025-10; already second-class here, too old for fido2 2.x). Setting requires-python = ">=3.10" collapses the universal lock to single patched versions — cryptography 48.0.1, pytest 9.1.1, fido2 2.2.0 — with no <3.10 markers and no vulnerable pins left. rsk touches none of the vulnerable code paths (no SECT curves, no TLS / DNS name constraints; tmpdir is test-only), so real exposure was nil — this clears the alerts and hardens the supply chain. `uv run --extra test pytest`: 24 passed on the patched env. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 2026-06 cryptography/pytest CVEs in tools/uv.lock surfaced as Dependabot security alerts but no auto-PR, because dependabot.yml only watched github-actions. Add the native uv ecosystem (Dependabot reads pyproject.toml + uv.lock directly; version updates GA 2025-03, security updates 2025-12) on /tools so future cryptography/fido2/pyscard/pytest bumps arrive as a weekly grouped PR. Cargo stays covered by the audit/deny/vet merge gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A preflight job now runs before the monitor: if the previous run was cancelled or timed_out (the 60-min job timeout that wedges the monitor once its checkpoint artifact falls too far behind the ~1.75B-entry Rekor log), it deletes the stuck `checkpoint` artifact so the monitor re-seeds to the current log size. Caps the failure at one cancelled run instead of a permanent spiral that burned ~1 runner-hour/hour and needed a manual artifact delete (2026-06-20). Best-effort: the step always exits 0 so it never blocks the monitor; it needs actions:write to read run conclusions and delete the artifact. actionlint clean; preflight gh-api/jq logic verified locally (happy path = no-op, no spurious delete). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…none) The status engine (blink timing + the EF_LED_CONF colour/brightness) was already backend-agnostic; only the render half was hard-wired to the Waveshare's WS2812. Factor the render into a shared Blinker::tick() -> RGB8 plus one cfg-gated *_task per backend, chosen at build time by the new LED_KIND knob (env -> build.rs -> cfg, the same mechanism as LED_PIN): - ws2812 (default): the addressable RGB on LED_PIN — behaviour unchanged. - gpio: a plain on/off LED on LED_PIN; hue/brightness collapse to lit/unlit but the blink pattern still distinguishes statuses, so RS-Key now runs on boards with a simple LED (a bare RP2350 / Pico 2), not just WS2812 boards. - pimoroni: a 3-pin PWM common-anode RGB (Tiny 2350: R=GPIO18/1A, G=GPIO19/1B, B=GPIO20/2A). - none: headless — the engine still runs (vendor SET/GET LED work), nothing renders it. Only the chosen backend and its PIO/PWM dependencies are compiled. All four LED_KINDs build and clippy-clean for thumbv8m; full scripts/check.sh is green on the default (ws2812). gpio/pimoroni/none are build-verified only — no board on hand to test them live. CYW43 (Pico 2 W) was deliberately left out: it would embed a ~230 KB wifi-firmware blob and the cyw43 driver, a poor trade for a security key's TCB. Closes the WS2812-only board-portability gap. bcdDevice 0x0778 -> 0x0779. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The WS2812 wire byte order was hard-wired to RGB — the reference Waveshare RP2350-One is unusually RGB. Standard WS2812B parts (e.g. the TenStar RP2350-USB) are GRB, and driving one with the wrong order swaps red and green (blue is unaffected). LED_ORDER (env -> build.rs -> cfg, like LED_PIN) picks the order by cfg-selecting the embassy color-order type (Rgb/Grb); the construction in main is unchanged (the order is inferred from the task param type). Default rgb keeps the Waveshare behaviour. Verified: all LED configs (rgb/grb/gpio/none) build + clippy clean; full scripts/check.sh green; HW-verified on a TenStar RP2350-USB (16 MB, WS2812 on GP22) with LED_KIND=ws2812 LED_ORDER=grb LED_PIN=22 FLASH_SIZE=16M (unsigned — secure boot off): red/green now correct. bcdDevice 0x0779 -> 0x077A. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ble) The LED hardware — data pin, driver backend, and WS2812 wire order — is now runtime-configurable from the device's phy record, like the USB identity, with no reflash. A non-`none` build compiles all three backends and, at boot, applies led_gpio / led_driver (1=gpio / 2=pimoroni / 3=ws2812, matching pico-fido / PicoForge) and an RS-Key vendor wire-order tag (led_order, 0x0D) from EF_PHY, falling back to the build LED_PIN / LED_KIND / LED_ORDER defaults when a field is absent. A `none` build stays headless and ignores the phy LED fields. The runtime pin reaches the PIO state machine through a `match` over GPIO 0..=29 (embassy has no `PioPin for AnyPin`, but doesn't need one: every `PioWs2812` erases the pin type, so all arms share one type — refuting an earlier assumption that a runtime match couldn't move the shared sm0/DMA across arms). The wire order is a runtime red/green swap (embassy stays at `Rgb`), so one binary serves both RGB- and GRB-wired parts. PHY brightness/steady seed the boot defaults that EF_LED_CONF (rsk led) then overrides. New `rsk hw` command (--led-pin / --led-driver / --led-order / --get) does a read-modify-write of only the LED fields (any USB identity is preserved) over the rescue applet and warm-reboots to apply. led_order round-trips the firmware parse/serialize; PicoForge skips it as an unknown tag. HW-verified on a TenStar RP2350-USB (grb, GP22): clean boot at bcdDevice 0x077A -> 0x077B, and a runtime order swap flipped idle green<->red via the phy tag with no reflash. Full scripts/check.sh green; rescue + new hw unit tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… U2F 55/0) A new "FIDO conformance" section in testing.md records the self-run pass of the FIDO Alliance Conformance Tools — CTAP2.3 235/0 (strictest profile_featureful) and U2F 1.1/1.2 55/0 — with what the run exercises and two honest caveats: it is a self-run result, NOT a paid "FIDO Certified" mark (cross-linked to the AAGUID / metadata non-goal), and the full enterprise-attestation suite needs the conformance-only `ea-conformance-rpid` build flag that the shipping build omits. A one-line pointer in the FIDO2 guide links to it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restore the [0.2.4] heading (a prior develop commit had collapsed the released v0.2.4 section back into [Unreleased]) and cut a [0.2.5] — 2026-06-20 section for this cycle: runtime LED via EF_PHY + the rsk hw CLI, the FIDO Conformance Tools v1.8.5.1 pass (CTAP2.3 235/0, U2F 55/0) and its fixes, alwaysUv, the five informational getInfo members, and the hybrid P-256 + ML-KEM-768 seed-backup channel. Consolidate the split [0.2.5] "Added" block. README "latest tagged release" -> v0.2.5. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cuts v0.2.5 (develop → main).
Highlights
EF_PHY— LED pin / driver / wire order are configurable at runtime (rsk hw/ PicoForge), no reflash; HW-verified on a TenStar RP2350-USB (runtime order swap green↔red).bcdDevice→0x077B.alwaysUv, and five informationalgetInfomembers.actions/checkout→ v7.Full notes in CHANGELOG
[0.2.5]. Merge as a merge commit (preserve history); tagv0.2.5afterwards triggers the SLSA-L3 release pipeline.