Skip to main content

Module envelope

Module envelope 

Source
Expand description

SecureEnvelope — AEAD-wrapped session payloads (fn-129.T7).

Every body the daemon POSTs under a pairing session gets wrapped in this envelope. The envelope binds:

  • Ciphertext + tag to a session-specific AEAD key derived from the TransportKey via HKDF with ENVELOPE_INFO domain separation.
  • Request context (session id, path, monotonic counter) as AAD, in a length-prefixed layout that defeats AAD-confusion attacks.

§Committed design decisions

  • Nonce scheme: deterministic counter XOR’d with a per-session 96-bit IV (RFC 8446 §5.3). Doubles as the monotonic-counter replay defense — one value, not two.
  • AEAD primitive: ChaCha20-Poly1305 for the default build; AES-256-GCM under --features cnsa. Dispatched through CryptoProvider::aead_{encrypt,decrypt} (fn-128.T2) so the swap is automatic.
  • AAD layout (length-prefixed): u32_be(len(session_id)) || session_id || u32_be(len(path)) || path || u32_be(len(channel_binding)) || channel_binding || u32_be(counter). Naive concatenation is forbidden (USENIX’23 AEAD-confusion).
  • Channel binding (anti-relay): the session is pinned to the TLS connection it runs on via the RFC 9266 tls-exporter keying material (see crate::channel_binding). The exporter is folded into BOTH the envelope key derivation (so two channels derive different keys) AND the AAD (so a cross-channel open is rejected explicitly). An envelope sealed on channel A therefore cannot be opened on channel B — a relayed proof is refused. This is the load-bearing negative property; without it the envelope is transport-agnostic and a captured proof replays.
  • Max messages per session: 1024. More than any pairing flow needs; abort with EnvelopeError::SessionExhausted at the cap.
  • API is async to match CryptoProvider’s async trait surface; this avoids a sync-over-async executor inside the crate.

§Typestate

Envelope<Sealed> (carries ciphertext) and Envelope<Open> (carries plaintext) are separate types; seal and open can’t be swapped.

Structs§

Envelope
AEAD envelope. State parameter distinguishes sealed-for-transport from opened-for-use. Never deriving Clone / Copy — a sealed envelope is single-use (counter is one-shot).
EnvelopeSession
Session-local envelope state. Holds the envelope key (HKDF-derived from the TransportKey), the per-session IV, the last-seen counter, and a message budget. Consumed via &mut self so nonce reuse within a session is structurally prevented.
Open
Phantom type: envelope has been opened (contains plaintext).
Sealed
Phantom type: envelope has been sealed (contains ciphertext).

Enums§

EnvelopeError
Errors produced by envelope open/seal.

Constants§

MAX_MESSAGES_PER_SESSION
Hard cap on messages per envelope session. Well above any pairing flow’s natural message count.