wired
libc-free QUIC/HTTP3 SDK in C for x86_64-linux
Loading...
Searching...
No Matches
server.h File Reference

RFC 9001 4 / 4.1.2, RFC 8446 4 / 4.4.4, RFC 9000 7: server-side handshake orchestrator, the symmetric peer of client. More...

Go to the source code of this file.

Data Structures

struct  wired_server
 Server-side handshake orchestrator state, initialized by wired_server_init. More...
struct  wired_server_init_in
 server_priv_x25519/server_pub_x25519 are the static ECDHE pair; cert_seed is the ECDSA P-256 signing scalar (big-endian). More...

Macros

#define WIRED_SERVER_FLIGHT_MAX   2048
 Capacity of a server flight buffer in octets.
#define WIRED_SERVER_TRANSCRIPT_MAX   16384
 Capacity of the raw handshake transcript buffer in octets: ClientHello + ServerHello + the server Handshake flight, sized past quic-interop-runner's deliberately inflated 9-cert amplificationlimit chain (~10KB flight) with headroom.
#define WIRED_SERVER_DATAGRAM_MAX   1500
 Capacity of one received UDP datagram in octets.

Enumerations

enum  { WIRED_SERVER_HS_INITIAL = 0 , WIRED_SERVER_HS_CH_RECVD , WIRED_SERVER_HS_FLIGHT_SENT , WIRED_SERVER_HS_CONFIRMED }
 Handshake phases of the orchestrator (wired_server.phase). More...

Functions

void wired_server_init (wired_server *s, const wired_server_init_in *in)
 Initialize the orchestrator with the server key material.
int wired_server_set_cids (wired_server *s, wired_span odcid, wired_span iscid)
 RFC 9000 7.3: record the DCID of the client's first Initial (the ODCID the server echoes) and the server's source connection id (ISCID) so the EncryptedExtensions transport parameters carry the real connection ids.
void wired_server_set_limits (wired_server *s, u64 max_data, u64 max_streams_bidi, u64 max_streams_uni, u64 max_datagram_frame_size)
 Override the advertised transport-parameter limits (RFC 9000 18.2); a zero field keeps its built-in default.
void wired_server_set_reset_token (wired_server *s, const u8 token[16])
 Advertise this 16-byte stateless_reset_token (RFC 9000 10.3.1/18.2) for the server's handshake SCID in the transport parameters.
void wired_server_set_keylog_path (wired_server *s, const char *path)
 Set the NSS key log file path (SSLKEYLOGFILE format); 0 disables (the default).
int wired_server_recv_initial (wired_server *s, const u8 *ch_msg, usz ch_len)
 RFC 8446 4.4.1: fold a received ClientHello (TLS handshake message bytes) into the transcript, recording ClientHello.random (bytes [4,36) of ch_msg: legacy_version(2) precedes it, RFC 8446 4.1.2) for later keylog lines.
int wired_server_build_hrr (wired_server *s, wired_obuf *out)
 RFC 8446 4.1.4: emit the HelloRetryRequest a just-received ClientHello1 without a usable (x25519) key_share owes, and restart the raw transcript as message_hash(ClientHello1) || HRR (RFC 8446 4.4.1).
int wired_server_build_flight (wired_server *s, const u8 *server_random, const sdrv_flight_out *out)
 RFC 8446 4.4 / RFC 9001 4: build the server flight (ServerHello into out->sh, EncryptedExtensions||Certificate||CertificateVerify||Finished into out->hs) and derive the Handshake key.
int wired_server_feed (wired_server *s, const u8 *crypto_payload, usz len)
 RFC 8446 4.4.4 / RFC 9001 4.1.2: drive the handshake with one received Handshake-packet CRYPTO payload (socket-free injection).
int wired_server_handshake_done (wired_server *s, wired_obuf *out)
 RFC 9001 4.1.2 / RFC 9000 19.20: write the HANDSHAKE_DONE frame, at most once and only after confirmation.
int wired_server_is_confirmed (const wired_server *s)
 1 once the client Finished verified and the handshake is confirmed.
int wired_server_early_data_used (const wired_server *s)
 RFC 9001 4.6.1 / 9.2: whether the client's 0-RTT early data was accepted on this connection (the ticket was on its first use and its binder verified).
int wired_server_early_send_keys (wired_server *s)
 Derive and install the server's 1-RTT send keys before the client Finished arrives (0.5-RTT, RFC 9001 4.9 / RFC 8446 7.1): the application traffic secrets depend only on the transcript through the server Finished, so they are available the moment the flight is built.
int wired_server_resumption_secret (const wired_server *s, u8 *out)
 RFC 8446 4.6.1/7.1: resumption_master_secret = Derive-Secret(Master Secret, "res master", ClientHello..client Finished) – the secret a NewSessionTicket must actually carry (RFC 8446 4.6.1: "The ticket itself is an opaque label... the PSK associated with the ticket is computed as... resumption_master_secret").
int wired_server_listen (wired_server *s, u16 port)
 Open a UDP socket bound to port and wait for the ClientHello.
int wired_server_pump (wired_server *s)
 One receive iteration: pull a datagram off the socket and feed it.
int wired_server_run_handshake (wired_server *s, int max_iterations)
 Pump until confirmed or max_iterations is reached (bounded so a silent or hostile peer cannot wedge the server).
void wired_server_close (wired_server *s)
 Close the UDP socket and wipe the key schedule's retained secrets (RFC 8446 E.1.4: the exporter_master_secret is erased at teardown).

Detailed Description

RFC 9001 4 / 4.1.2, RFC 8446 4 / 4.4.4, RFC 9000 7: server-side handshake orchestrator, the symmetric peer of client.

Drives the verified parts (sdrv folds the ClientHello and emits the server flight; srvfin verifies the client Finished and, only on success, advances to Master, installs the 1-RTT key set and confirms) to handshake confirmation and HANDSHAKE_DONE.

All policy lives in those layers; the server wires them and gates 1-RTT promotion on a verified client Finished. The data path (wired_server_feed) is socket-free so it can be driven by buffer injection without a socket; only wired_server_pump enters the kernel via io/udp.

Macro Definition Documentation

◆ WIRED_SERVER_TRANSCRIPT_MAX

#define WIRED_SERVER_TRANSCRIPT_MAX   16384

Capacity of the raw handshake transcript buffer in octets: ClientHello + ServerHello + the server Handshake flight, sized past quic-interop-runner's deliberately inflated 9-cert amplificationlimit chain (~10KB flight) with headroom.

A truncated transcript silently desyncs srv_verify_finished's hash from the client's real one, so every client Finished fails and the server goes silent (RFC 8446 4.4.1/4.4.4).

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Handshake phases of the orchestrator (wired_server.phase).

Enumerator
WIRED_SERVER_HS_INITIAL 

awaiting the ClientHello

WIRED_SERVER_HS_CH_RECVD 

ClientHello folded, flight not sent.

WIRED_SERVER_HS_FLIGHT_SENT 

server flight sent, Handshake key ready

WIRED_SERVER_HS_CONFIRMED 

client Finished verified, 1-RTT armed

Function Documentation

◆ wired_server_build_flight()

int wired_server_build_flight ( wired_server * s,
const u8 * server_random,
const sdrv_flight_out * out )

RFC 8446 4.4 / RFC 9001 4: build the server flight (ServerHello into out->sh, EncryptedExtensions||Certificate||CertificateVerify||Finished into out->hs) and derive the Handshake key.

Only valid after the ClientHello was received. Advances CH_RECVD -> FLIGHT_SENT.

Parameters
sthe orchestrator to advance
server_randomthe ServerHello.random, 32 bytes
outreceives the ServerHello and the Handshake-level flight
Returns
1 on success, 0 otherwise.

◆ wired_server_build_hrr()

int wired_server_build_hrr ( wired_server * s,
wired_obuf * out )

RFC 8446 4.1.4: emit the HelloRetryRequest a just-received ClientHello1 without a usable (x25519) key_share owes, and restart the raw transcript as message_hash(ClientHello1) || HRR (RFC 8446 4.4.1).

The phase stays HS_INITIAL: the retried ClientHello2 re-enters wired_server_recv_initial. Only valid while sdrv_hrr_pending; a second HRR is never produced (ClientHello2 still without a share is rejected instead).

Parameters
sthe orchestrator holding the HRR-bound ClientHello1
outreceives the HelloRetryRequest handshake message bytes
Returns
1 on success, 0 when no HRR is pending or building failed.

◆ wired_server_close()

void wired_server_close ( wired_server * s)

Close the UDP socket and wipe the key schedule's retained secrets (RFC 8446 E.1.4: the exporter_master_secret is erased at teardown).

Parameters
sthe orchestrator whose socket to close

◆ wired_server_early_data_used()

int wired_server_early_data_used ( const wired_server * s)

RFC 9001 4.6.1 / 9.2: whether the client's 0-RTT early data was accepted on this connection (the ticket was on its first use and its binder verified).

Stays 1 after the 0-RTT keys are discarded at confirmation, so the application can apply its replay policy to what arrived early.

Parameters
sthe orchestrator to inspect
Returns
1 if early data was accepted, 0 otherwise.

◆ wired_server_early_send_keys()

int wired_server_early_send_keys ( wired_server * s)

Derive and install the server's 1-RTT send keys before the client Finished arrives (0.5-RTT, RFC 9001 4.9 / RFC 8446 7.1): the application traffic secrets depend only on the transcript through the server Finished, so they are available the moment the flight is built.

Does not confirm the handshake; the confirm-time derivation over the same transcript is unaffected. Idempotent.

Parameters
sthe orchestrator whose flight has been built
Returns
1 with the 1-RTT send keys available, 0 before the flight (no transcript to derive from).

◆ wired_server_feed()

int wired_server_feed ( wired_server * s,
const u8 * crypto_payload,
usz len )

RFC 8446 4.4.4 / RFC 9001 4.1.2: drive the handshake with one received Handshake-packet CRYPTO payload (socket-free injection).

Reassembles the client Finished, verifies its verify_data, and ONLY on a match advances to Master, installs the 1-RTT key set and confirms (CH_RECVD/FLIGHT_SENT -> CONFIRMED). A forged Finished promotes nothing.

Parameters
sthe orchestrator to advance
crypto_payloadone Handshake-packet CRYPTO payload
lenlength of crypto_payload in octets
Returns
1 if it advanced the handshake, 0 otherwise.

◆ wired_server_handshake_done()

int wired_server_handshake_done ( wired_server * s,
wired_obuf * out )

RFC 9001 4.1.2 / RFC 9000 19.20: write the HANDSHAKE_DONE frame, at most once and only after confirmation.

Parameters
sthe orchestrator to emit from
outreceives the HANDSHAKE_DONE frame
Returns
1 and sets out->len, or 0 if not confirmed, already sent, or out->cap is 0.

◆ wired_server_init()

void wired_server_init ( wired_server * s,
const wired_server_init_in * in )

Initialize the orchestrator with the server key material.

No socket is opened.

Parameters
sthe orchestrator to initialize
inthe server key material

◆ wired_server_is_confirmed()

int wired_server_is_confirmed ( const wired_server * s)

1 once the client Finished verified and the handshake is confirmed.

Parameters
sthe orchestrator to inspect
Returns
1 once the client Finished verified and the handshake is confirmed.

◆ wired_server_listen()

int wired_server_listen ( wired_server * s,
u16 port )

Open a UDP socket bound to port and wait for the ClientHello.

Parameters
sthe orchestrator that will own the socket
portUDP port to bind
Returns
1 on success, 0 on socket/bind failure.

◆ wired_server_pump()

int wired_server_pump ( wired_server * s)

One receive iteration: pull a datagram off the socket and feed it.

Parameters
sthe orchestrator to pump
Returns
1 if the handshake advanced, 0 otherwise.

◆ wired_server_recv_initial()

int wired_server_recv_initial ( wired_server * s,
const u8 * ch_msg,
usz ch_len )

RFC 8446 4.4.1: fold a received ClientHello (TLS handshake message bytes) into the transcript, recording ClientHello.random (bytes [4,36) of ch_msg: legacy_version(2) precedes it, RFC 8446 4.1.2) for later keylog lines.

Advances INITIAL -> CH_RECVD.

Parameters
sthe orchestrator to advance
ch_msgthe ClientHello handshake message bytes
ch_lenlength of ch_msg in octets
Returns
1 on success, 0 if the message is not a usable ClientHello or out of phase.

◆ wired_server_resumption_secret()

int wired_server_resumption_secret ( const wired_server * s,
u8 * out )

RFC 8446 4.6.1/7.1: resumption_master_secret = Derive-Secret(Master Secret, "res master", ClientHello..client Finished) – the secret a NewSessionTicket must actually carry (RFC 8446 4.6.1: "The ticket itself is an opaque label... the PSK associated with the ticket is computed as... resumption_master_secret").

Only meaningful once wired_server_is_ confirmed (the client Finished must have verified first); returns 0 (leaving out untouched) before that.

Parameters
sthe confirmed orchestrator to derive from
outreceives the Hash.length-byte resumption_master_secret (32, or 48 under TLS_AES_256_GCM_SHA384); size it TICKET_SECRET_LEN
Returns
1 on success, 0 if s is not yet confirmed.

◆ wired_server_run_handshake()

int wired_server_run_handshake ( wired_server * s,
int max_iterations )

Pump until confirmed or max_iterations is reached (bounded so a silent or hostile peer cannot wedge the server).

Parameters
sthe orchestrator to pump
max_iterationsupper bound on receive iterations
Returns
1 if confirmed.

◆ wired_server_set_cids()

int wired_server_set_cids ( wired_server * s,
wired_span odcid,
wired_span iscid )

RFC 9000 7.3: record the DCID of the client's first Initial (the ODCID the server echoes) and the server's source connection id (ISCID) so the EncryptedExtensions transport parameters carry the real connection ids.

Must be called before build_flight.

Parameters
sthe orchestrator to record on
odcidthe DCID of the client's first Initial
iscidthe server's source connection id
Returns
1 ok, 0 if either length exceeds 20.

◆ wired_server_set_keylog_path()

void wired_server_set_keylog_path ( wired_server * s,
const char * path )

Set the NSS key log file path (SSLKEYLOGFILE format); 0 disables (the default).

When set, wired_server_feed appends, once the client Finished verifies, CLIENT_EARLY_TRAFFIC_SECRET (only if 0-RTT was accepted), CLIENT_/SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_/SERVER_TRAFFIC_SECRET_0 and EXPORTER_SECRET lines (RFC 8446 7.1 secrets).

Parameters
sthe orchestrator to configure
pathNUL-terminated key log file path, or 0 to disable

◆ wired_server_set_limits()

void wired_server_set_limits ( wired_server * s,
u64 max_data,
u64 max_streams_bidi,
u64 max_streams_uni,
u64 max_datagram_frame_size )

Override the advertised transport-parameter limits (RFC 9000 18.2); a zero field keeps its built-in default.

Call before the flight is built.

Parameters
sthe server
max_datainitial_max_data in bytes (0 = default)
max_streams_bidiinitial_max_streams_bidi (0 = default)
max_streams_uniinitial_max_streams_uni (0 = default); advertise only what the receive side's slot capacity actually backs (RFC 9000 4.6 lockstep – see stp_limits.max_streams_uni)
max_datagram_frame_sizemax_datagram_frame_size (RFC 9221 3), 0 = not advertised (no default: opt in once DATAGRAM delivery is wired)

◆ wired_server_set_reset_token()

void wired_server_set_reset_token ( wired_server * s,
const u8 token[16] )

Advertise this 16-byte stateless_reset_token (RFC 9000 10.3.1/18.2) for the server's handshake SCID in the transport parameters.

Derive it from a restart-stable secret (sreset_key_derive + sreset_token) so a rebooted server can still produce it. Call before the flight is built; never calling it simply omits the TP.

Parameters
sthe server
tokenthe 16-byte token