// The TLS 1.3 server handshake runner (RFC 8446 ยง4): it drives the server state machine
// over the CRYPTO byte stream. `feed` appends received CRYPTO bytes, splits off every
// complete handshake message, adds each to the running transcript, and advances the
// state machine; a trailing partial message is buffered for the next feed. The server's
// own flight is folded in with `record_sent` (so the transcript stays in message order)
// and `sent_flight` (advancing the state past the send). This ties the handshake-message
// framing, the transcript hash, and the state machine into the driver a QUIC/TLS server
// keeps as it processes the handshake โ a pure core; the keys and socket wrap it.
///|
/// A server-side TLS 1.3 handshake in progress.
pub struct TlsServerHandshake {
mut state : TlsServerState
transcript : TranscriptHash
mut buffer : Bytes
mut client_hello : Bytes
}
///|
/// A fresh handshake, awaiting the ClientHello.
pub fn TlsServerHandshake::new() -> TlsServerHandshake {
{
state: Start,
transcript: TranscriptHash::new(),
buffer: b"",
client_hello: b"",
}
}
///|
/// The current handshake state.
pub fn TlsServerHandshake::state(self : TlsServerHandshake) -> TlsServerState {
self.state
}
///|
/// The running transcript hash over every message seen so far, in order.
pub fn TlsServerHandshake::transcript_hash(self : TlsServerHandshake) -> Bytes {
self.transcript.hash()
}
///|
/// Whether the handshake has completed.
pub fn TlsServerHandshake::is_connected(self : TlsServerHandshake) -> Bool {
self.state == Connected
}
///|
/// The raw ClientHello message the handshake received (empty until one arrives). A server
/// needs it to pull the client's key_share and run the ECDHE that derives the handshake
/// secrets.
pub fn TlsServerHandshake::client_hello(self : TlsServerHandshake) -> Bytes {
self.client_hello
}
///|
/// Feed received CRYPTO bytes: process every complete handshake message now available โ
/// add it to the transcript and drive the state machine โ buffering any trailing partial
/// message. Returns the handshake types processed, in order.
pub fn TlsServerHandshake::feed(
self : TlsServerHandshake,
bytes : Bytes,
) -> Array[Int] raise {
self.buffer = bytes_concat(self.buffer, bytes)
let processed : Array[Int] = []
let view = self.buffer[:]
let mut off = 0
for ;; {
match tls_parse_handshake(view[off:]) {
Some((msg_type, body)) => {
let consumed = 4 + body.length()
let message = view[off:off + consumed].to_owned()
if msg_type == tls_client_hello {
self.client_hello = message
}
self.transcript.add(message)
self.state = tls_server_recv(self.state, msg_type)
processed.push(msg_type)
off = off + consumed
}
None => break
}
}
self.buffer = view[off:view.length()].to_owned()
processed
}
///|
/// Fold a handshake message the server sends (ServerHello, EncryptedExtensions,
/// Certificate, ...) into the transcript, keeping it in message order.
pub fn TlsServerHandshake::record_sent(
self : TlsServerHandshake,
message : Bytes,
) -> Unit {
self.transcript.add(message)
}
///|
/// Advance the state machine past the server's own flight (after the ClientHello),
/// waiting for a client certificate when `request_client_cert` is set.
pub fn TlsServerHandshake::sent_flight(
self : TlsServerHandshake,
request_client_cert : Bool,
) -> Unit raise {
self.state = tls_server_send_flight(self.state, request_client_cert)
}