Skip to content

keychain: Secure Enclave custody fixes — delegation works on SE roots, software keys are never silently discarded - #381

Merged
bordumb merged 2 commits into
mainfrom
fix/se-software-key-custody
Jul 18, 2026
Merged

bordumb merged 2 commits into
mainfrom
fix/se-software-key-custody

Conversation

@bordumb

@bordumb bordumb commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Found by attempting the product's own flagship flow — delegating a headless release agent under a Secure Enclave root — which surfaced a chain of SE custody bugs:

  1. KEL anchoring raw-decrypted the root key (stage_root_anchor_ixn): an SE blob is an opaque handle, so every id agent add on an SE root died with Unknown encryption tag: 4. Anchors now sign through sign_with_key — the same hardware-aware dispatch the commit-signing path trusts — with a curve cross-check. The call site no longer touches seed or passphrase material at all.
  2. SecureEnclaveKeyStorage::store_key discarded provided key material and minted an unrelated hardware key. Every store-existing-material flow (agent delegation, device pairing, key import, rotation persistence) silently lost the only copy of a key the KEL had already anchored — the delegation "succeeded" with its private key gone. Non-empty material is now stored as a real software item (.swkey, 0600) with metadata; the empty-blob convention (identity init) still hardware-generates. load_key/delete_key/list_aliases handle both forms.

Also in this PR: .auths/ci-bundle.json regenerated so the traveling evidence carries the new delegation anchors (14 KEL events, 6 device KELs).

This commit is itself the proof: it is signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp — the claude-release agent delegated under the maintainer's SE root via the fixed ceremony (scopes sign_commit + sign_release, 30-day expiry, revocable with auths id agent revoke) — and auths verify HEAD accepts it through the pinned root. No fingerprint was involved in signing it.

Known follow-ups (intentionally not here): the key export guard refuses per-backend instead of per-key, so software items in an SE backend can't export (worked around via key copy-backend); a mid-ceremony SE auth failure leaves a partially-anchored delegation (keys stored, later seals missing) — the ceremony should be atomic or resumable; auths sign's trailer source (commit-trailers file) and signer resolution don't follow --repo/env overrides cleanly for delegate machines.

🤖 Generated with Claude Code

… hardware-aware signer; software keys stored, never silently replaced

Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
4c018c99 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ✅ 1/1 commits verified

Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EPlN9Y8qKPDEq8gg80D6N_rCN3aANK6xAoMr8OTGJ1tR
Auths-Anchor-Seq: 10
@bordumb
bordumb merged commit 8325b8e into main Jul 18, 2026
17 of 18 checks passed
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
a7c4f52d ❌ Failed Signing key is not the device's current key
4c018c99 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ❌ 1/2 commits verified


How to fix

Commit a7c4f52d failed verification. See the Actions log for details.

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