Skip to content

refactor: extract root-key custody into a seismic-key-custodian crate#202

Merged
samlaf merged 1 commit into
seismicfrom
extract-key-custodian-crate
Jul 7, 2026
Merged

refactor: extract root-key custody into a seismic-key-custodian crate#202
samlaf merged 1 commit into
seismicfrom
extract-key-custodian-crate

Conversation

@samlaf

@samlaf samlaf commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Move KeyManager out of enclave-server into a new seismic-key-custodian crate (renamed Custodian) that owns root_key and everything derived from it. The crate never sees remote attestation evidence, JSON-RPC, or any network input: releasing root_key to a peer requires a VerifiedPeerAuthorization, built by the caller at the point where it has just verified the peer's evidence. The verified transcript digest (root_key_request_binding) rides along and becomes the AEAD AAD, so a wrapped key cannot be lifted onto a different handshake. enclave-server keeps the untrusted-input surface (evidence verification, RPC) and calls into the custodian through this typed API.

Beyond the code motion, the custody boundary is now enforced by the API:

  • KeyManager::get_root_key() is gone. Raw root-key bytes are unreachable outside the crate; root_key only leaves AEAD-wrapped via wrap_root_key_for_peer.
  • The Clone derive is gone: exactly one Custodian per process, zeroized on drop.
  • The responder-side ephemeral ECDH keypair is now generated inside wrap_root_key_for_peer, so its secret also never exists outside the custodian.
  • answer_root_key_request takes &Custodian instead of &[u8; 32]: bootstrap.rs orchestrates verify -> authorize -> attest without ever holding key material.

The crate's modules are organized by how key material can leave the process: custodian.rs (it doesn't — RAM-only derivation of root_key and purpose keys), luks_keyfile.rs (ephemeral tmpfs handoff to setup-persistent-luks), root_key_wrap.rs (over the network, AEAD-wrapped to an attested peer).

No behavior change: the wire format (nonce || ciphertext+tag, request-binding AAD), HKDF derivations (salts, domain separators), and epoch handling are byte-identical to before.

This is groundwork for splitting enclave-server into a network-facing attestation service and a minimal key-custodian process with no network listener.

Move KeyManager out of enclave-server into a new seismic-key-custodian
crate (renamed Custodian) that owns root_key and everything derived from
it. The crate never sees remote attestation evidence, JSON-RPC, or any
network input: releasing root_key to a peer requires a
VerifiedPeerAuthorization, built by the caller at the point where it has
just verified the peer's evidence. The verified transcript digest
(root_key_request_binding) rides along and becomes the AEAD AAD, so a
wrapped key cannot be lifted onto a different handshake. enclave-server
keeps the untrusted-input surface (evidence verification, RPC) and calls
into the custodian through this typed API.

Beyond the code motion, the custody boundary is now enforced by the API:

- KeyManager::get_root_key() is gone. Raw root-key bytes are unreachable
  outside the crate; root_key only leaves AEAD-wrapped via
  wrap_root_key_for_peer.
- The Clone derive is gone: exactly one Custodian per process, zeroized
  on drop.
- The responder-side ephemeral ECDH keypair is now generated inside
  wrap_root_key_for_peer, so its secret also never exists outside the
  custodian.
- answer_root_key_request takes &Custodian instead of &[u8; 32]:
  bootstrap.rs orchestrates verify -> authorize -> attest without ever
  holding key material.

The crate's modules are organized by how key material can leave the
process: custodian.rs (it doesn't — RAM-only derivation of root_key and
purpose keys), luks_keyfile.rs (ephemeral tmpfs handoff to
setup-persistent-luks), root_key_wrap.rs (over the network, AEAD-wrapped
to an attested peer).

No behavior change: the wire format (nonce || ciphertext+tag,
request-binding AAD), HKDF derivations (salts, domain separators), and
epoch handling are byte-identical to before.

This is groundwork for splitting enclave-server into a network-facing
attestation service and a minimal key-custodian process with no network
listener.
@samlaf samlaf requested a review from cdrappi as a code owner July 7, 2026 17:41
@samlaf samlaf merged commit cf41466 into seismic Jul 7, 2026
5 of 6 checks passed
@samlaf samlaf deleted the extract-key-custodian-crate branch July 7, 2026 17:45
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