|
wired
libc-free QUIC/HTTP3 SDK in C for x86_64-linux
|
RFC 8446 4 / RFC 9001 4: server-side handshake driver. More...
#include "common/bytes/span/span.h"#include "crypto/kdf/hkdf/hkdf.h"#include "tls/ext/salpn/negotiate.h"#include "tls/ext/salpn/sni_check.h"#include "tls/ext/stp/server_tp.h"#include "tls/handshake/core/tls/cert.h"#include "tls/handshake/core/tls/initial.h"#include "tls/handshake/core/tls/transcript.h"#include "tls/keys/ticket/ticket.h"Go to the source code of this file.
Data Structures | |
| struct | quic_sdrv |
| Server-side handshake driver state. More... | |
| struct | quic_sdrv_init_in |
| Inputs to quic_sdrv_init. More... | |
| struct | quic_sdrv_flight_out |
| Destination for quic_sdrv_build_server_flight: sh receives the ServerHello, hs the EncryptedExtensions || Certificate || CertificateVerify || Finished flight. More... | |
Functions | |
| void | quic_sdrv_init (quic_sdrv *s, const quic_sdrv_init_in *in) |
| Hold the server key material. | |
| int | quic_sdrv_set_cids (quic_sdrv *s, quic_span odcid, quic_span iscid) |
| RFC 9000 7.3: record the ODCID (the DCID of the client's first Initial) and the ISCID (the server's source connection id) to advertise in the EncryptedExtensions transport parameters. | |
| void | quic_sdrv_set_group (quic_sdrv *s, u16 group) |
| RFC 8446 4.2.7: select the NamedGroup for the ECDHE key_share (QUIC_GROUP_X25519 or QUIC_GROUP_SECP256R1). | |
| int | quic_sdrv_set_cids_retried (quic_sdrv *s, quic_span odcid, quic_span iscid, quic_span true_odcid) |
| RFC 9000 7.3, post-Retry accept: odcid is the Initial-key derivation input (the Retry's own SCID – the client's second Initial is keyed off it, RFC 9001 5.2), iscid the server's own source connection id as usual, and true_odcid the ORIGINAL first Initial's DCID recovered from the Retry token – advertised as original_destination_connection_id instead of odcid, which has already moved on. | |
| int | quic_sdrv_set_retry_scid (quic_sdrv *s, quic_span rscid) |
| Record the Retry packet's SCID for the retry_source_connection_id transport parameter (RFC 9000 7.3) – only after a Retry actually happened; never call it on the direct-accept path. | |
| int | quic_sdrv_recv_client_hello (quic_sdrv *s, const u8 *ch_msg, usz ch_len) |
| RFC 8446 4.4.1: fold the ClientHello into the transcript and take the client's x25519 key_share. | |
| quic_salpn_sni_outcome | quic_sdrv_sni_outcome (const quic_sdrv *s) |
| RFC 6066 3: the outcome of checking the last ClientHello's server_name against this driver's own certificate (set by quic_sdrv_recv_client_hello via quic_salpn_sni_check). | |
| int | quic_sdrv_enforce_sni (quic_sdrv *s) |
| RFC 6066 3: opt-in enforcement of the last checked SNI outcome. | |
| int | quic_sdrv_hrr_pending (const quic_sdrv *s) |
| RFC 8446 4.1.4: 1 when the last quic_sdrv_recv_client_hello call found no x25519 key_share and a HelloRetryRequest must be sent before anything else – the caller must call quic_sdrv_build_hrr instead of proceeding to quic_sdrv_build_server_flight. | |
| int | quic_sdrv_build_hrr (quic_sdrv *s, quic_obuf *out) |
| RFC 8446 4.1.4 / 4.4.1: build the HelloRetryRequest (requesting x25519, this driver's only supported group) into out, fold it into the transcript, and arm ClientHello2 handling: quic_sdrv_recv_client_hello. | |
| u64 | quic_sdrv_last_error (const quic_sdrv *s) |
| RFC 9001 8.2 / RFC 9000 20.1: the CRYPTO_ERROR recorded by the last quic_sdrv_recv_client_hello call, or 0 if it succeeded. | |
| int | quic_sdrv_build_server_flight (quic_sdrv *s, const u8 *server_random, const quic_sdrv_flight_out *out) |
| RFC 8446 4.4: build the full server flight into out->sh / out->hs. | |
| int | quic_sdrv_handshake_secret (const quic_sdrv *s, const u8 **secret) |
| Point *secret at the derived Handshake Secret (verification aid). | |
| int | quic_sdrv_early_keys (const quic_sdrv *s, quic_initial_keys *out) |
| RFC 8446 4.2.10 / RFC 9001 4.6.1: the 0-RTT packet-protection keys (client_early_traffic_secret's key/iv/hp), derived by quic_sdrv_recv_client_hello over the accepted PSK and the raw ClientHello bytes when early_data_accepted is 1. | |
RFC 8446 4 / RFC 9001 4: server-side handshake driver.
Receives the client ClientHello and emits the real TLS bytes of the server flight (ServerHello + EncryptedExtensions + Certificate + CertificateVerify + Finished). Pure orchestration over the existing build/sign/key-schedule parts.
RFC 8446 4.1.4 / 4.4.1: build the HelloRetryRequest (requesting x25519, this driver's only supported group) into out, fold it into the transcript, and arm ClientHello2 handling: quic_sdrv_recv_client_hello.
Must only be called when quic_sdrv_hrr_pending is 1 (right after the ClientHello1 that triggered it, before anything else touches the transcript).
| s | driver state |
| out | receives the HelloRetryRequest message bytes |
| int quic_sdrv_build_server_flight | ( | quic_sdrv * | s, |
| const u8 * | server_random, | ||
| const quic_sdrv_flight_out * | out ) |
RFC 8446 4.4: build the full server flight into out->sh / out->hs.
Derives the handshake secret over the real ECDHE.
| s | driver state |
| server_random | the 32-byte ServerHello.random |
| out | destination buffers for the ServerHello and handshake flight |
| int quic_sdrv_early_keys | ( | const quic_sdrv * | s, |
| quic_initial_keys * | out ) |
RFC 8446 4.2.10 / RFC 9001 4.6.1: the 0-RTT packet-protection keys (client_early_traffic_secret's key/iv/hp), derived by quic_sdrv_recv_client_hello over the accepted PSK and the raw ClientHello bytes when early_data_accepted is 1.
| s | driver state (quic_sdrv_recv_client_hello must have run) |
| out | receives the 0-RTT key/iv/hp |
| int quic_sdrv_enforce_sni | ( | quic_sdrv * | s | ) |
RFC 6066 3: opt-in enforcement of the last checked SNI outcome.
A QUIC_SALPN_SNI_MISMATCH sets s->last_error to quic_err_crypto(QUIC_TLS_ALERT_UNRECOGNIZED_NAME) and fails; MATCH and ABSENT are no-ops. Call right after a successful quic_sdrv_recv_client_hello when the caller wants unrecognized_name enforced instead of RFC 6066 3's silent-continue default.
| s | driver state |
Point *secret at the derived Handshake Secret (verification aid).
| s | driver state |
| secret | receives a pointer to the internal Handshake Secret |
| int quic_sdrv_hrr_pending | ( | const quic_sdrv * | s | ) |
RFC 8446 4.1.4: 1 when the last quic_sdrv_recv_client_hello call found no x25519 key_share and a HelloRetryRequest must be sent before anything else – the caller must call quic_sdrv_build_hrr instead of proceeding to quic_sdrv_build_server_flight.
| s | driver state |
| void quic_sdrv_init | ( | quic_sdrv * | s, |
| const quic_sdrv_init_in * | in ) |
Hold the server key material.
If in->chain is NULL/empty, build the self-signed P-256 certificate from in->sign_priv; otherwise copy the chain views (leaf first) as the certificate_list to send. Init transcript/key schedule.
| s | driver state to initialize |
| in | key material and optional external certificate chain |
RFC 9001 8.2 / RFC 9000 20.1: the CRYPTO_ERROR recorded by the last quic_sdrv_recv_client_hello call, or 0 if it succeeded.
| s | driver state |
RFC 8446 4.4.1: fold the ClientHello into the transcript and take the client's x25519 key_share.
RFC 8446 4.2.11/4.2.11.2 session resumption, only when has_ticket_key: if the ClientHello carries no pre_shared_key extension, behavior is exactly the full-handshake path above (psk_accepted stays 0). If it does, this opens the offered ticket (its identity bytes) under ticket_key; a ticket that fails to open (wrong key, malformed, tampered) is a silent MAY- degrade to a full handshake (psk_accepted stays 0, no error). A ticket that opens has its PSK binder verified against the resumption secret and the truncated ClientHello; a binder mismatch instead makes this whole call fail (0) – RFC 8446 4.2.11.2 MUST abort the handshake, never fall back silently. On a verified binder, psk_accepted is set to 1 and psk_secret holds the opened ticket's resumption secret, for quic_sdrv_build_server_flight's key schedule.
RFC 9001 8.2: a ClientHello missing the quic_transport_parameters extension (0x39) is rejected before any other field is taken; s->last_error is set to the missing_extension CRYPTO_ERROR (0x016d) in that case.
| s | driver state |
| ch_msg | the ClientHello handshake message bytes |
| ch_len | length of ch_msg in bytes |
RFC 9000 7.3: record the ODCID (the DCID of the client's first Initial) and the ISCID (the server's source connection id) to advertise in the EncryptedExtensions transport parameters.
Must be called before build_server_flight.
| s | driver state |
| odcid | DCID of the client's first Initial packet |
| iscid | the server's source connection id |
| int quic_sdrv_set_cids_retried | ( | quic_sdrv * | s, |
| quic_span | odcid, | ||
| quic_span | iscid, | ||
| quic_span | true_odcid ) |
RFC 9000 7.3, post-Retry accept: odcid is the Initial-key derivation input (the Retry's own SCID – the client's second Initial is keyed off it, RFC 9001 5.2), iscid the server's own source connection id as usual, and true_odcid the ORIGINAL first Initial's DCID recovered from the Retry token – advertised as original_destination_connection_id instead of odcid, which has already moved on.
RFC 8446 4.2.7: select the NamedGroup for the ECDHE key_share (QUIC_GROUP_X25519 or QUIC_GROUP_SECP256R1).
quic_sdrv_init defaults to QUIC_GROUP_X25519; call this right after init, before receiving any ClientHello, to use secp256r1 instead. server_priv/server_pub must already hold the matching key pair (32-byte P-256 scalar + 65-byte SEC1 uncompressed public, in place of the x25519 pair quic_sdrv_init took).
| s | driver state |
| group | the NamedGroup to require/advertise. |
Record the Retry packet's SCID for the retry_source_connection_id transport parameter (RFC 9000 7.3) – only after a Retry actually happened; never call it on the direct-accept path.
| s | the server driver |
| rscid | the Retry's source connection id (at most 20 bytes) |
| quic_salpn_sni_outcome quic_sdrv_sni_outcome | ( | const quic_sdrv * | s | ) |
RFC 6066 3: the outcome of checking the last ClientHello's server_name against this driver's own certificate (set by quic_sdrv_recv_client_hello via quic_salpn_sni_check).
QUIC_SALPN_SNI_ABSENT if the client sent no server_name (or it was malformed) or no certificate was available yet to check against. A QUIC_SALPN_SNI_MISMATCH never fails the handshake on its own (RFC 6066 3 permits continuing); a caller that wants to enforce unrecognized_name checks this and closes with quic_err_crypto(QUIC_TLS_ALERT_UNRECOGNIZED_NAME) itself.
| s | driver state |