pub struct HandshakeClient { /* private fields */ }Expand description
Handshake Client State Machine
kem_secret and signing_key are already ZeroizeOnDrop in their own
types. The remaining sensitive field is nonce, which is zeroed via the
derived ZeroizeOnDrop. early_data is application plaintext queued
before the secure channel is up — it lives in user-controlled storage and
is moved out by take_early_data.
Implementations§
Source§impl HandshakeClient
impl HandshakeClient
Sourcepub fn new() -> Result<Self, HandshakeError>
pub fn new() -> Result<Self, HandshakeError>
Construct a client handshake state. Allocates an ephemeral hybrid KEM
keypair, an ephemeral hybrid signing keypair, and a 32-byte client
nonce. Returns Err if the OS RNG cannot be read.
Sourcepub fn create_client_hello(&self) -> ClientHello
pub fn create_client_hello(&self) -> ClientHello
Build the default ClientHello — pinned PROTOCOL_VERSION, no
resumption, no 0-RTT early-data. Downgrade resistance comes from the
transcript signature, which binds both version and the build-side
PROTOCOL_VARIANT; a network rewrite of either aborts the handshake
at the client-side signature check.
Sourcepub fn create_client_hello_with_resume(
&self,
resume_session_id: [u8; 32],
resumption_secret: &[u8; 32],
early_data: Option<&[u8]>,
) -> ClientHello
pub fn create_client_hello_with_resume( &self, resume_session_id: [u8; 32], resumption_secret: &[u8; 32], early_data: Option<&[u8]>, ) -> ClientHello
Build a ClientHello that resumes a prior session, optionally carrying
0-RTT early_data.
resume_session_id and resumption_secret are the two halves of a
prior session’s Session::resumption_hint(). The server checks its
session cache; a known, still-valid ticket bypasses the cookie/PoW DoS
gate. When early_data is Some, it is sealed (AES-256-GCM) under a
key derived from (resumption_secret, self.nonce) and placed in
ClientHello.early_data; the server decrypts it with the matching key
(best-effort — see HandshakeServer::process_client_hello). The
whole hello, early-data included, is transcript-bound (Invariant 7).
The caller MUST ensure early_data.len() <= EARLY_DATA_MAX_LEN;
PhantomSession::connect_with_resumption enforces this and returns an
error for oversized payloads.
Sourcepub fn process_server_hello(
&self,
client_hello: &ClientHello,
server_hello: &ServerHello,
expected_server_key: Option<&HybridVerifyingKey>,
) -> Result<(Session, Option<bool>), HandshakeError>
pub fn process_server_hello( &self, client_hello: &ClientHello, server_hello: &ServerHello, expected_server_key: Option<&HybridVerifyingKey>, ) -> Result<(Session, Option<bool>), HandshakeError>
Verify a ServerHello against the ClientHello we sent and establish
the client-side Session.
Pinning is mandatory in production — expected_server_key is
Some(&key) (Invariant 1). The signature is checked over the whole
transcript, which embeds the entire ClientHello (early-data
ciphertext included) and the build-side PROTOCOL_VARIANT (Invariants
7, 10). Returns the established Session and the 0-RTT verdict:
Some(true/false) when the client sent early-data (accepted / rejected
per server_hello.early_data_accepted), None when it sent none.
Sourcepub fn queue_early_data(&self, data: Vec<u8>)
pub fn queue_early_data(&self, data: Vec<u8>)
Queue a plaintext payload to be sent as early-data once the secure channel is up.
NOTE: Early-data is currently queued at the API layer (see
PhantomSession::send_queue) and the data-pump flushes it through the
regular AEAD path after the handshake completes. This per-handshake
buffer is reserved for the future 0-RTT path (Phase 4.1).
Sourcepub fn take_early_data(&self) -> Vec<Vec<u8>>
pub fn take_early_data(&self) -> Vec<Vec<u8>>
Drain the queued early-data buffer. See Self::queue_early_data — the
production send_queue path is currently used instead; this hook is
reserved for 0-RTT.