DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
quic_tls.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file quic_tls.h
6 * @brief TLS 1.3 server handshake state machine for QUIC (RFC 9001 / RFC 8446).
7 *
8 * Drives the server side of the TLS 1.3 handshake that QUIC carries in CRYPTO frames. It ties the
9 * key schedule (tls13_kdf), the handshake messages (tls13_msg), and the transport parameters
10 * (quic_tp) together: it runs the transcript hash, consumes the client's ClientHello, produces the
11 * server flight (ServerHello at the Initial level; EncryptedExtensions + Certificate +
12 * CertificateVerify + Finished at the Handshake level), derives the Handshake and 1-RTT packet keys
13 * for both directions, and verifies the client's Finished.
14 *
15 * The transport engine (quic_conn) owns CRYPTO stream reassembly and packet protection; this module
16 * is transport-free. It consumes an in-order byte run (quic_tls_recv_crypto returns how many bytes it
17 * used) and exposes the outbound flight per encryption level (quic_tls_flight), so it is fully
18 * host-testable by feeding it a captured ClientHello and inspecting the flight and derived keys.
19 *
20 * Profile: TLS_AES_128_GCM_SHA256, X25519, Ed25519 certificate, no PSK / 0-RTT / HelloRetryRequest /
21 * client authentication. The ephemeral X25519 private key and the ServerHello random are supplied in
22 * the config (the caller draws them from its RNG, or fixes them in a test).
23 *
24 * @author Douglas Quigg (dstroy0)
25 * @date 2026
26 */
27
28#ifndef DETERMINISTICESPASYNCWEBSERVER_QUIC_TLS_H
29#define DETERMINISTICESPASYNCWEBSERVER_QUIC_TLS_H
30
31#include "ServerConfig.h"
32
33#if DETWS_ENABLE_HTTP3
34
39#include <stddef.h>
40#include <stdint.h>
41
42/** @brief QUIC encryption levels (RFC 9001 sec 4). 0-RTT is not supported. */
43struct QuicEnc
44{
45 static constexpr uint8_t QUIC_ENC_INITIAL = 0;
46 static constexpr uint8_t QUIC_ENC_HANDSHAKE = 1;
47 static constexpr uint8_t QUIC_ENC_APP = 2; ///< 1-RTT (application) keys
48};
49
50/** @brief Server handshake configuration (certificate, key, transport params, ephemeral inputs). */
51struct QuicTlsConfig
52{
53 const uint8_t *cert_der; ///< DER X.509 leaf certificate (Ed25519 public key)
54 size_t cert_len;
55 uint8_t ed25519_seed[32]; ///< Ed25519 private seed matching the certificate
56 QuicTransportParams params; ///< the server's transport parameters (caller sets the CIDs)
57 uint8_t ephemeral_priv[32]; ///< server X25519 private key
58 uint8_t random[32]; ///< ServerHello random
59#if DETWS_ENABLE_PQC_KEX
60 uint8_t mlkem_m[32]; ///< ML-KEM Encaps randomness (X25519MLKEM768 hybrid); fresh per handshake
61#endif
62};
63
64/** @brief Handshake state (a mutually-exclusive internal state, not a wire value). */
65enum class QtlsState : uint8_t
66{
67 QTLS_START = 0, ///< awaiting ClientHello
68 QTLS_WAIT_FINISHED, ///< server flight sent; awaiting client Finished
69 QTLS_DONE, ///< client Finished verified
70 QTLS_FAILED, ///< a fatal handshake error (see alert)
71};
72
73/** @brief One server handshake's state (fixed storage, no heap). */
74struct QuicTls
75{
76 QuicTlsConfig cfg;
77 SshSha256Ctx transcript; ///< running Transcript-Hash over the handshake messages
78 Tls13KeySchedule ks;
79
80 QtlsState state;
81 uint8_t alert; ///< TLS alert code (RFC 8446 sec 6) when state == QtlsState::QTLS_FAILED
82 bool hs_keys_ready; ///< Handshake-level keys derived (after ServerHello)
83 bool ap_keys_ready; ///< 1-RTT keys derived (after the server Finished)
84 bool complete; ///< client Finished verified
85
86 QuicPacketKeys hs_client; ///< Handshake: opens client packets
87 QuicPacketKeys hs_server; ///< Handshake: seals server packets
88 QuicPacketKeys ap_client; ///< 1-RTT: opens client packets
89 QuicPacketKeys ap_server; ///< 1-RTT: seals server packets
90
91 uint8_t hs_finished_hash[32]; ///< H(ClientHello..server Finished), to verify client Finished
92
93#if DETWS_ENABLE_PQC_KEX
94 uint8_t flight_initial[1400]; ///< outbound Initial CRYPTO (ServerHello; hybrid key_share is ~1.1 KB)
95#else
96 uint8_t flight_initial[256]; ///< outbound Initial CRYPTO (ServerHello)
97#endif
98 size_t flight_initial_len;
99 uint8_t flight_hs[DETWS_H3_CRYPTO_BUF]; ///< outbound Handshake CRYPTO (EE..Finished)
100 size_t flight_hs_len;
101
102 QuicTransportParams peer; ///< the client's parsed transport parameters
103 bool have_peer;
104};
105
106/** @brief Initialize a server handshake with @p cfg (copied). Resets the transcript and state. */
107void quic_tls_server_init(QuicTls *qt, const QuicTlsConfig *cfg);
108
109/**
110 * @brief Feed in-order CRYPTO stream bytes for encryption level @p level.
111 *
112 * Consumes as many complete handshake messages as @p data holds. At QuicEnc::QUIC_ENC_INITIAL it expects the
113 * ClientHello and, on success, builds the whole server flight and derives the Handshake + 1-RTT keys.
114 * At QuicEnc::QUIC_ENC_HANDSHAKE it expects the client Finished and verifies it. On a fatal error it sets the
115 * state to QtlsState::QTLS_FAILED and an alert. @return the number of leading bytes of @p data consumed (a
116 * partial trailing message is left for the next call).
117 */
118size_t quic_tls_recv_crypto(QuicTls *qt, int level, const uint8_t *data, size_t len);
119
120/**
121 * @brief The pending outbound CRYPTO flight for @p level (QuicEnc::QUIC_ENC_INITIAL / QuicEnc::QUIC_ENC_HANDSHAKE).
122 * @return a pointer to the flight bytes and its length via @p len (0 if none). The transport engine
123 * fragments these into CRYPTO frames and tracks its own send offset / retransmission.
124 */
125const uint8_t *quic_tls_flight(const QuicTls *qt, int level, size_t *len);
126
127/**
128 * @brief The packet-protection keys for @p level (QuicEnc::QUIC_ENC_HANDSHAKE / QuicEnc::QUIC_ENC_APP), @p is_server
129 * picking the seal (server) or open (client) direction. @return NULL if those keys are not ready.
130 */
131const QuicPacketKeys *quic_tls_keys(const QuicTls *qt, int level, bool is_server);
132
133/** @brief The client's parsed transport parameters (valid once the ClientHello is processed). */
134const QuicTransportParams *quic_tls_peer_params(const QuicTls *qt);
135
136#endif // DETWS_ENABLE_HTTP3
137#endif // DETERMINISTICESPASYNCWEBSERVER_QUIC_TLS_H
User-facing configuration for DeterministicESPAsyncWebServer.
#define DETWS_H3_CRYPTO_BUF
Maximum bytes of one QUIC/TLS handshake CRYPTO flight (RFC 9001).
QUIC packet protection: Initial secrets, AEAD payload protection, header protection,...
QUIC transport parameters (RFC 9000 sec 18) carried in the TLS quic_transport_parameters extension (R...
SHA-256 (FIPS 180-4) - streaming context and one-shot API.
Streaming SHA-256 context.
Definition ssh_sha256.h:44
TLS 1.3 key schedule (RFC 8446 sec 7.1) for the QUIC handshake.