15#if DETWS_ENABLE_PQC_KEX
23 static constexpr uint8_t TLS_ALERT_UNEXPECTED_MESSAGE = 10;
24 static constexpr uint8_t TLS_ALERT_HANDSHAKE_FAILURE = 40;
25 static constexpr uint8_t TLS_ALERT_ILLEGAL_PARAMETER = 47;
26 static constexpr uint8_t TLS_ALERT_DECODE_ERROR = 50;
27 static constexpr uint8_t TLS_ALERT_DECRYPT_ERROR = 51;
28 static constexpr uint8_t TLS_ALERT_PROTOCOL_VERSION = 70;
29 static constexpr uint8_t TLS_ALERT_INTERNAL_ERROR = 80;
30 static constexpr uint8_t TLS_ALERT_MISSING_EXTENSION = 109;
31 static constexpr uint8_t TLS_ALERT_NO_APPLICATION_PROTOCOL = 120;
36void fail(QuicTls *qt, uint8_t alert)
38 qt->state = QtlsState::QTLS_FAILED;
43void snapshot_hash(
const SshSha256Ctx *ctx, uint8_t out[32])
50bool emit(QuicTls *qt, uint8_t *flight,
size_t cap,
size_t *plen,
size_t written)
55 if (!written || written > cap - *plen)
57 fail(qt, TlsAlert::TLS_ALERT_INTERNAL_ERROR);
65bool process_client_hello(QuicTls *qt,
const uint8_t *msg,
size_t msg_len)
68 if (!tls13_parse_client_hello(msg, msg_len, &ch))
70 fail(qt, TlsAlert::TLS_ALERT_DECODE_ERROR);
75 fail(qt, TlsAlert::TLS_ALERT_PROTOCOL_VERSION);
78 bool use_hybrid =
false;
79#if DETWS_ENABLE_PQC_KEX
81 use_hybrid = ch.has_hybrid_share && ch.offers_x25519mlkem768;
83 if (!ch.offers_ed25519 || (!use_hybrid && (!ch.has_key_share || !ch.offers_x25519)))
85 fail(qt, TlsAlert::TLS_ALERT_HANDSHAKE_FAILURE);
88 if (!ch.offers_h3_alpn)
90 fail(qt, TlsAlert::TLS_ALERT_NO_APPLICATION_PROTOCOL);
95 fail(qt, TlsAlert::TLS_ALERT_MISSING_EXTENSION);
98 if (!quic_tp_parse(ch.quic_tp, ch.quic_tp_len, &qt->peer))
100 fail(qt, TlsAlert::TLS_ALERT_ILLEGAL_PARAMETER);
103 qt->have_peer =
true;
111#if DETWS_ENABLE_PQC_KEX
112 uint8_t server_share[MLKEM768_CT_BYTES + 32];
116 if (!mlkem768_encaps(ch.client_mlkem_ek, qt->cfg.mlkem_m, server_share, ml_ss))
118 fail(qt, TlsAlert::TLS_ALERT_HANDSHAKE_FAILURE);
122 uint8_t server_pub[32];
123 ssh_x25519(x_ss, qt->cfg.ephemeral_priv, ch.client_x25519);
125 memcpy(server_share + MLKEM768_CT_BYTES, server_pub, 32);
126 memcpy(ecdhe, ml_ss, 32);
127 memcpy(ecdhe + 32, x_ss, 32);
129 share_len = MLKEM768_CT_BYTES + 32;
130 group = TLS_GROUP_X25519MLKEM768;
134 uint8_t server_share[32];
137 ssh_x25519(ecdhe, qt->cfg.ephemeral_priv, ch.client_x25519);
141 group = TLS_GROUP_X25519;
148 size_t n = tls13_build_server_hello(qt->flight_initial,
sizeof(qt->flight_initial), qt->cfg.random, ch.session_id,
149 ch.session_id_len, server_share, share_len, group);
150 qt->flight_initial_len = 0;
151 if (!emit(qt, qt->flight_initial,
sizeof(qt->flight_initial), &qt->flight_initial_len, n))
157 snapshot_hash(&qt->transcript, hash);
158 tls13_ks_early(&TLS13_KDF, &qt->ks);
159 tls13_ks_handshake(&qt->ks, ecdhe, hash, ecdhe_len);
160 quic_keys_from_secret(qt->ks.client_hs_traffic, &qt->hs_client);
161 quic_keys_from_secret(qt->ks.server_hs_traffic, &qt->hs_server);
162 qt->hs_keys_ready =
true;
165 qt->flight_hs_len = 0;
167 size_t tp_len = quic_tp_encode(&qt->cfg.params, tp_enc,
sizeof(tp_enc));
169 n = tls13_build_encrypted_extensions(qt->flight_hs + qt->flight_hs_len,
sizeof(qt->flight_hs) - qt->flight_hs_len,
171 if (!emit(qt, qt->flight_hs,
sizeof(qt->flight_hs), &qt->flight_hs_len, n))
174 n = tls13_build_certificate(qt->flight_hs + qt->flight_hs_len,
sizeof(qt->flight_hs) - qt->flight_hs_len,
175 qt->cfg.cert_der, qt->cfg.cert_len);
176 if (!emit(qt, qt->flight_hs,
sizeof(qt->flight_hs), &qt->flight_hs_len, n))
180 snapshot_hash(&qt->transcript, hash);
181 n = tls13_build_cert_verify(qt->flight_hs + qt->flight_hs_len,
sizeof(qt->flight_hs) - qt->flight_hs_len, hash,
182 qt->cfg.ed25519_seed);
183 if (!emit(qt, qt->flight_hs,
sizeof(qt->flight_hs), &qt->flight_hs_len, n))
187 snapshot_hash(&qt->transcript, hash);
189 tls13_finished_mac(&TLS13_KDF, qt->ks.server_hs_traffic, hash, verify);
190 n = tls13_build_finished(qt->flight_hs + qt->flight_hs_len,
sizeof(qt->flight_hs) - qt->flight_hs_len, verify);
191 if (!emit(qt, qt->flight_hs,
sizeof(qt->flight_hs), &qt->flight_hs_len, n))
196 snapshot_hash(&qt->transcript, qt->hs_finished_hash);
197 tls13_ks_master(&qt->ks, qt->hs_finished_hash);
198 quic_keys_from_secret(qt->ks.client_ap_traffic, &qt->ap_client);
199 quic_keys_from_secret(qt->ks.server_ap_traffic, &qt->ap_server);
200 qt->ap_keys_ready =
true;
202 qt->state = QtlsState::QTLS_WAIT_FINISHED;
206bool process_client_finished(QuicTls *qt,
const uint8_t *msg,
size_t msg_len)
208 if (msg[0] != TlsHs::TLS_HS_FINISHED || msg_len != 4 + 32)
210 fail(qt, TlsAlert::TLS_ALERT_DECODE_ERROR);
213 uint8_t expected[32];
214 tls13_finished_mac(&TLS13_KDF, qt->ks.client_hs_traffic, qt->hs_finished_hash, expected);
216 for (
int i = 0; i < 32; i++)
217 diff |= (uint8_t)(expected[i] ^ msg[4 + i]);
220 fail(qt, TlsAlert::TLS_ALERT_DECRYPT_ERROR);
225 qt->state = QtlsState::QTLS_DONE;
229bool process_message(QuicTls *qt,
int level,
const uint8_t *msg,
size_t msg_len)
231 if (level == QuicEnc::QUIC_ENC_INITIAL && qt->state == QtlsState::QTLS_START &&
232 msg[0] == TlsHs::TLS_HS_CLIENT_HELLO)
233 return process_client_hello(qt, msg, msg_len);
234 if (level == QuicEnc::QUIC_ENC_HANDSHAKE && qt->state == QtlsState::QTLS_WAIT_FINISHED &&
235 msg[0] == TlsHs::TLS_HS_FINISHED)
236 return process_client_finished(qt, msg, msg_len);
237 fail(qt, TlsAlert::TLS_ALERT_UNEXPECTED_MESSAGE);
242void quic_tls_server_init(QuicTls *qt,
const QuicTlsConfig *cfg)
244 memset(qt, 0,
sizeof(*qt));
247 qt->state = QtlsState::QTLS_START;
250size_t quic_tls_recv_crypto(QuicTls *qt,
int level,
const uint8_t *data,
size_t len)
252 if (qt->state == QtlsState::QTLS_FAILED)
255 while (off + 4 <= len)
257 uint32_t mlen = (uint32_t)((data[off + 1] << 16) | (data[off + 2] << 8) | data[off + 3]);
258 size_t total = 4 + mlen;
259 if (off + total > len)
261 if (!process_message(qt, level, data + off, total))
264 if (qt->state == QtlsState::QTLS_DONE)
270const uint8_t *quic_tls_flight(
const QuicTls *qt,
int level,
size_t *len)
272 if (level == QuicEnc::QUIC_ENC_INITIAL)
274 *len = qt->flight_initial_len;
275 return qt->flight_initial;
277 if (level == QuicEnc::QUIC_ENC_HANDSHAKE)
279 *len = qt->flight_hs_len;
280 return qt->flight_hs;
286const QuicPacketKeys *quic_tls_keys(
const QuicTls *qt,
int level,
bool is_server)
288 if (level == QuicEnc::QUIC_ENC_HANDSHAKE && qt->hs_keys_ready)
289 return is_server ? &qt->hs_server : &qt->hs_client;
290 if (level == QuicEnc::QUIC_ENC_APP && qt->ap_keys_ready)
291 return is_server ? &qt->ap_server : &qt->ap_client;
295const QuicTransportParams *quic_tls_peer_params(
const QuicTls *qt)
297 return qt->have_peer ? &qt->peer :
nullptr;
ML-KEM-768 encapsulation (FIPS 203), responder side only.
TLS 1.3 server handshake state machine for QUIC (RFC 9001 / RFC 8446).
void ssh_x25519_base(uint8_t out[32], const uint8_t scalar[32])
X25519 with the standard base point u=9: out = scalar * G.
void ssh_x25519(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32])
X25519 scalar multiplication: out = scalar * point (RFC 7748 §5).
Curve25519 field arithmetic + X25519 (RFC 7748) for the curve25519-sha256 KEX.
void ssh_sha256_init(SshSha256Ctx *ctx)
Initialize a streaming SHA-256 context.
void ssh_sha256_update(SshSha256Ctx *ctx, const uint8_t *data, size_t len)
Feed len bytes of data into the running hash.
void ssh_sha256_final(SshSha256Ctx *ctx, uint8_t digest[SSH_SHA256_DIGEST_LEN])
Finalize the hash and write the 32-byte digest.
Streaming SHA-256 context.
TLS 1.3 handshake messages for the QUIC handshake (RFC 8446 sec 4).