mirror of
https://github.com/openssl/openssl.git
synced 2026-01-18 17:11:31 +01:00
Persist QUIC transport parameters in SSL_SESSION
Adds storage for currently understood remote QUIC transport parameters in the SSL_SESSION struct, including serialization and deserialization support. Sets defaults for these values on SSL_SESSION creation. This enables clients to remember and reuse required QUIC transport parameters for 0-RTT. Reviewed-by: Saša Nedvědický <sashan@openssl.org> Reviewed-by: Neil Horman <nhorman@openssl.org> (Merged from https://github.com/openssl/openssl/pull/28301)
This commit is contained in:
@@ -108,6 +108,8 @@ int ossl_quic_gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len,
|
||||
|
||||
# define QUIC_STATELESS_RESET_TOKEN_LEN 16
|
||||
|
||||
# define QUIC_DEFAULT_MAX_STREAM_DATA (512 * 1024)
|
||||
|
||||
typedef struct {
|
||||
unsigned char token[QUIC_STATELESS_RESET_TOKEN_LEN];
|
||||
} QUIC_STATELESS_RESET_TOKEN;
|
||||
|
||||
@@ -151,7 +151,6 @@ static QLOG *ch_get_qlog_cb(void *arg)
|
||||
#define DEFAULT_INIT_CONN_RXFC_WND (768 * 1024)
|
||||
#define DEFAULT_CONN_RXFC_MAX_WND_MUL 20
|
||||
|
||||
#define DEFAULT_INIT_STREAM_RXFC_WND (512 * 1024)
|
||||
#define DEFAULT_STREAM_RXFC_MAX_WND_MUL 12
|
||||
|
||||
#define DEFAULT_INIT_CONN_MAX_STREAMS 100
|
||||
@@ -206,9 +205,9 @@ static int ch_init(QUIC_CHANNEL *ch)
|
||||
* Note: The TP we transmit governs what the peer can transmit and thus
|
||||
* applies to the RXFC.
|
||||
*/
|
||||
ch->tx_init_max_stream_data_bidi_local = DEFAULT_INIT_STREAM_RXFC_WND;
|
||||
ch->tx_init_max_stream_data_bidi_remote = DEFAULT_INIT_STREAM_RXFC_WND;
|
||||
ch->tx_init_max_stream_data_uni = DEFAULT_INIT_STREAM_RXFC_WND;
|
||||
ch->tx_init_max_stream_data_bidi_local = QUIC_DEFAULT_MAX_STREAM_DATA;
|
||||
ch->tx_init_max_stream_data_bidi_remote = QUIC_DEFAULT_MAX_STREAM_DATA;
|
||||
ch->tx_init_max_stream_data_uni = QUIC_DEFAULT_MAX_STREAM_DATA;
|
||||
|
||||
if (!ossl_quic_rxfc_init(&ch->conn_rxfc, NULL,
|
||||
DEFAULT_INIT_CONN_RXFC_WND,
|
||||
@@ -1812,6 +1811,53 @@ static int ch_on_transport_params(const unsigned char *params,
|
||||
reason = TP_REASON_REQUIRED("RETRY_SCID");
|
||||
goto malformed;
|
||||
}
|
||||
|
||||
/* Store params in SSL_SESSION struct */
|
||||
if (got_initial_max_data)
|
||||
sc->session->quic_params.init_max_data = ch->conn_txfc.cwm;
|
||||
|
||||
if (got_initial_max_stream_data_bidi_local)
|
||||
/*
|
||||
* This is correct; the BIDI_LOCAL TP governs streams created by
|
||||
* the endpoint which sends the TP, i.e., our peer.
|
||||
*/
|
||||
sc->session->quic_params.init_max_stream_data_bidi_local =
|
||||
ch->rx_init_max_stream_data_bidi_remote;
|
||||
|
||||
if (got_initial_max_stream_data_bidi_remote)
|
||||
/*
|
||||
* This is correct; the BIDI_REMOTE TP governs streams created
|
||||
* by the endpoint which receives the TP, i.e., us.
|
||||
*/
|
||||
sc->session->quic_params.init_max_stream_data_bidi_remote =
|
||||
ch->rx_init_max_stream_data_bidi_local;
|
||||
|
||||
if (got_initial_max_stream_data_uni)
|
||||
sc->session->quic_params.init_max_stream_data_uni = ch->rx_init_max_stream_data_uni;
|
||||
|
||||
if (got_initial_max_streams_bidi)
|
||||
sc->session->quic_params.max_local_streams_bidi = ch->max_local_streams_bidi;
|
||||
|
||||
if (got_initial_max_streams_uni)
|
||||
sc->session->quic_params.max_local_streams_uni = ch->max_local_streams_uni;
|
||||
|
||||
if (got_max_idle_timeout)
|
||||
/* Use value for max idle timeout that server requested */
|
||||
sc->session->quic_params.max_idle_timeout = ch->max_idle_timeout_remote_req;
|
||||
|
||||
if (got_max_udp_payload_size)
|
||||
sc->session->quic_params.max_udp_payload_size = ch->rx_max_udp_payload_size;
|
||||
|
||||
if (got_active_conn_id_limit)
|
||||
sc->session->quic_params.active_conn_id_limit = ch->rx_active_conn_id_limit;
|
||||
|
||||
/*
|
||||
* RFC 9000 7.4.1: A client MUST NOT use remembered values for the
|
||||
* following parameters: ack_delay_exponent, max_ack_delay,
|
||||
* initial_source_connection_id, original_destination_connection_id,
|
||||
* preferred_address, retry_source_connection_id, and
|
||||
* stateless_reset_token.
|
||||
*/
|
||||
}
|
||||
|
||||
ch->got_remote_transport_params = 1;
|
||||
|
||||
@@ -46,6 +46,17 @@ typedef struct {
|
||||
ASN1_OCTET_STRING *ticket_appdata;
|
||||
uint32_t kex_group;
|
||||
ASN1_OCTET_STRING *peer_rpk;
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
uint64_t init_max_data;
|
||||
uint64_t init_max_stream_data_bidi_local;
|
||||
uint64_t init_max_stream_data_bidi_remote;
|
||||
uint64_t init_max_stream_data_uni;
|
||||
uint64_t max_local_streams_bidi;
|
||||
uint64_t max_local_streams_uni;
|
||||
uint64_t max_idle_timeout;
|
||||
uint64_t max_udp_payload_size;
|
||||
uint64_t active_conn_id_limit;
|
||||
#endif
|
||||
} SSL_SESSION_ASN1;
|
||||
|
||||
ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
|
||||
@@ -78,7 +89,18 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 17),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, kex_group, UINT32, 19),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, peer_rpk, ASN1_OCTET_STRING, 20)
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, peer_rpk, ASN1_OCTET_STRING, 20),
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, init_max_data, ZUINT64, 21),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, init_max_stream_data_bidi_local, ZUINT64, 22),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, init_max_stream_data_bidi_remote, ZUINT64, 23),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, init_max_stream_data_uni, ZUINT64, 24),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_local_streams_bidi, ZUINT64, 25),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_local_streams_uni, ZUINT64, 26),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_idle_timeout, ZUINT64, 27),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_udp_payload_size, ZUINT64, 28),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, active_conn_id_limit, ZUINT64, 29),
|
||||
#endif
|
||||
} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
|
||||
|
||||
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
|
||||
@@ -217,6 +239,18 @@ int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
|
||||
ssl_session_oinit(&as.ticket_appdata, &ticket_appdata,
|
||||
in->ticket_appdata, in->ticket_appdata_len);
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
as.init_max_data = in->quic_params.init_max_data;
|
||||
as.init_max_stream_data_bidi_local = in->quic_params.init_max_stream_data_bidi_local;
|
||||
as.init_max_stream_data_bidi_remote = in->quic_params.init_max_stream_data_bidi_remote;
|
||||
as.init_max_stream_data_uni = in->quic_params.init_max_stream_data_uni;
|
||||
as.max_local_streams_bidi = in->quic_params.max_local_streams_bidi;
|
||||
as.max_local_streams_uni = in->quic_params.max_local_streams_uni;
|
||||
as.max_idle_timeout = in->quic_params.max_idle_timeout;
|
||||
as.max_udp_payload_size = in->quic_params.max_udp_payload_size;
|
||||
as.active_conn_id_limit = in->quic_params.active_conn_id_limit;
|
||||
#endif
|
||||
|
||||
ret = i2d_SSL_SESSION_ASN1(&as, pp);
|
||||
OPENSSL_free(peer_rpk.data);
|
||||
return ret;
|
||||
@@ -418,6 +452,18 @@ SSL_SESSION *d2i_SSL_SESSION_ex(SSL_SESSION **a, const unsigned char **pp,
|
||||
ret->ticket_appdata_len = 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
ret->quic_params.init_max_data = as->init_max_data;
|
||||
ret->quic_params.init_max_stream_data_bidi_local = as->init_max_stream_data_bidi_local;
|
||||
ret->quic_params.init_max_stream_data_bidi_remote = as->init_max_stream_data_bidi_remote;
|
||||
ret->quic_params.init_max_stream_data_uni = as->init_max_stream_data_uni;
|
||||
ret->quic_params.max_local_streams_bidi = as->max_local_streams_bidi;
|
||||
ret->quic_params.max_local_streams_uni = as->max_local_streams_uni;
|
||||
ret->quic_params.max_idle_timeout = as->max_idle_timeout;
|
||||
ret->quic_params.max_udp_payload_size = as->max_udp_payload_size;
|
||||
ret->quic_params.active_conn_id_limit = as->active_conn_id_limit;
|
||||
#endif
|
||||
|
||||
M_ASN1_free_of(as, SSL_SESSION_ASN1);
|
||||
|
||||
if ((a != NULL) && (*a == NULL))
|
||||
|
||||
@@ -556,6 +556,21 @@ struct ssl_session_st {
|
||||
uint32_t flags;
|
||||
SSL_CTX *owner;
|
||||
|
||||
# ifndef OPENSSL_NO_QUIC
|
||||
/* Remote QUIC transport parameters for 0-RTT, for client only */
|
||||
struct {
|
||||
uint64_t init_max_data;
|
||||
uint64_t init_max_stream_data_bidi_local;
|
||||
uint64_t init_max_stream_data_bidi_remote;
|
||||
uint64_t init_max_stream_data_uni;
|
||||
uint64_t max_local_streams_bidi;
|
||||
uint64_t max_local_streams_uni;
|
||||
uint64_t max_idle_timeout;
|
||||
uint64_t max_udp_payload_size;
|
||||
uint64_t active_conn_id_limit;
|
||||
} quic_params;
|
||||
# endif
|
||||
|
||||
/*
|
||||
* These are used to make removal of session-ids more efficient and to
|
||||
* implement a maximum cache size. Access requires protection of ctx->lock.
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include "internal/ssl_unwrap.h"
|
||||
#include "ssl_local.h"
|
||||
#include "statem/statem_local.h"
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
# include "internal/quic_types.h"
|
||||
#endif
|
||||
|
||||
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
|
||||
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
|
||||
@@ -121,6 +124,19 @@ SSL_SESSION *SSL_SESSION_new(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* Set QUIC params to default values */
|
||||
ss->quic_params.init_max_data = 0;
|
||||
ss->quic_params.init_max_stream_data_bidi_local = QUIC_DEFAULT_MAX_STREAM_DATA;
|
||||
ss->quic_params.init_max_stream_data_bidi_remote = QUIC_DEFAULT_MAX_STREAM_DATA;
|
||||
ss->quic_params.init_max_stream_data_uni = QUIC_DEFAULT_MAX_STREAM_DATA;
|
||||
ss->quic_params.max_local_streams_bidi = 0;
|
||||
ss->quic_params.max_local_streams_uni = 0;
|
||||
ss->quic_params.max_idle_timeout = QUIC_DEFAULT_IDLE_TIMEOUT;
|
||||
ss->quic_params.max_udp_payload_size = QUIC_MIN_INITIAL_DGRAM_LEN;
|
||||
ss->quic_params.active_conn_id_limit = QUIC_MIN_ACTIVE_CONN_ID_LIMIT;
|
||||
#endif
|
||||
|
||||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) {
|
||||
CRYPTO_FREE_REF(&ss->references);
|
||||
OPENSSL_free(ss);
|
||||
@@ -261,6 +277,20 @@ static SSL_SESSION *ssl_session_dup_intern(const SSL_SESSION *src, int ticket)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
dest->quic_params.init_max_data = src->quic_params.init_max_data;
|
||||
dest->quic_params.init_max_stream_data_bidi_local =
|
||||
src->quic_params.init_max_stream_data_bidi_local;
|
||||
dest->quic_params.init_max_stream_data_bidi_remote =
|
||||
src->quic_params.init_max_stream_data_bidi_remote;
|
||||
dest->quic_params.init_max_stream_data_uni = src->quic_params.init_max_stream_data_uni;
|
||||
dest->quic_params.max_local_streams_bidi = src->quic_params.max_local_streams_bidi;
|
||||
dest->quic_params.max_local_streams_uni = src->quic_params.max_local_streams_uni;
|
||||
dest->quic_params.max_idle_timeout = src->quic_params.max_idle_timeout;
|
||||
dest->quic_params.max_udp_payload_size = src->quic_params.max_udp_payload_size;
|
||||
dest->quic_params.active_conn_id_limit = src->quic_params.active_conn_id_limit;
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
err:
|
||||
SSL_SESSION_free(dest);
|
||||
|
||||
Reference in New Issue
Block a user