Skip to content

piv: let "Enable Anyway" also send the reads the compatibility table skips - #161

Merged
framefilter merged 2 commits into
mainfrom
feat/piv-override-internal-reads
Oct 4, 2026
Merged

framefilter merged 2 commits into
mainfrom
feat/piv-override-internal-reads

Conversation

@framefilter

@framefilter framefilter commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Follow-up to #128's PIV override (@episource, FYI — this reintroduces a transport-level piece you deliberately kept out, so I'd value your view).

Why: #128's "Unlock Anyway" relaxes the PIV pane's controls, but the transport still skips GET METADATA and ATTEST whenever the compatibility table lists them unsupported. If that entry is wrong (newer firmware, a misidentified card), keyroost silently hides algorithm and PIN/touch-policy information, and nothing shows why.

Changes

  • PivSessionState::set_send_unsupported_reads: a per-key choice, kept across a card change (set before the session's first read). The GUI sets it from "Enable Anyway" for that key and re-reads status when toggled. RESET and the reset mechanism choice are never overridden.
  • PivSession::internal_read_allowed: one decision point for GET METADATA and ATTEST. Every read the table skips — or sends anyway under the override — leaves a --debug / activity-log trace line naming the applet fingerprint. GET SLOT KEY STATUS is untouched: it reads through GET METADATA, and its gate in the import mismatch check only ever refuses on a supported verdict.
  • CLI parity: --force on a PIV command (generate-key, change-management-key, reset, delete-key, move-key) also sends those reads for the rest of the command (PivSession::set_send_unsupported_reads, set once in guard_piv_feature), with the same trace lines.
  • Wording: "Unlock Anyway" → "Enable Anyway", "…are unlocked…" → "…are enabled…"; the rest is PIV applet fingerprinting, device specific feature gates #128's.
  • CLAUDE.md's crate table gains the missing keyroost-pivtest row (rsa, p256/p384/p521, ed25519-dalek, x25519-dalek, zeroize), including PIV applet fingerprinting, device specific feature gates #128's new p521.

Verified

  • Unit test for the decision (supported/unverified → send, no trace; unsupported → skip + trace; unsupported + override → send + trace).
  • Gates: fmt, clippy -D warnings, workspace tests (1312), rustdoc -D warnings, docs audit.
  • YubiKey 5.7 in the GUI: "Enable Anyway" / "…are enabled for this key. Undo", ECC P-521 offered with the ⚠ marker, status re-read keeps the GET METADATA–derived PIN/touch policy. The skip path itself can't be exercised on a YubiKey (it supports both reads); the unit test covers it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU

framefilter and others added 2 commits October 3, 2026 20:52
…skips

#128's override relaxes the PIV pane's controls but left the transport's
internal reads (GET METADATA, ATTEST) gated by the table. A wrong entry
there, e.g. for newer firmware, silently hides information (algorithms,
PIN/touch policy) with no way to get it back and no trace of why.

- PivSessionState carries a send-unsupported-reads choice, kept across a
  card change; the GUI sets it from "Enable Anyway" for that key and
  re-reads status when it is toggled. RESET is never overridden.
- Every internal read the table skips, or sends anyway under the
  override, leaves a --debug / activity-log trace line naming the
  applet fingerprint, so a wrong entry can be spotted.
- "Unlock Anyway" is now "Enable Anyway" (and "…are enabled for this
  key"); the rest of the wording is #128's.
- CLAUDE.md lists keyroost-pivtest and its RustCrypto/dalek dependencies,
  including the new p521.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Parity with the GUI's "Enable Anyway": a PIV command run with --force
(generate-key, change-management-key, reset, delete-key, move-key) now
also sends GET METADATA and ATTEST for the rest of that command when the
table lists them unsupported, each with a --debug trace line. Done once
in guard_piv_feature, which every forced command calls first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
@framefilter
framefilter merged commit 53ad6f8 into main Oct 4, 2026
12 checks passed
@framefilter
framefilter deleted the feat/piv-override-internal-reads branch October 4, 2026 02:34
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