MEDIUM: quic: Dynamic allocations of QUIC TLS encryption levels

Replace ->els static array of encryption levels by 4 pointers into the QUIC
connection object, quic_conn struct.
    ->iel denotes the Initial encryption level,
    ->eel the Early-Data encryption level,
    ->hel the Handshaske encryption level and
    ->ael the Application Data encryption level.

Add ->qel_list to this structure to list the encryption levels after having been
allocated. Modify consequently the encryption level object itself (quic_enc_level
struct) so that it might be added to ->qel_list QUIC connection list of
encryption levels.

Implement qc_enc_level_alloc() to initialize the value of a pointer to an encryption
level object. It is used to initialized the pointer newly added to the quic_conn
structure. It also takes a packet number space pointer address as argument to
initialize it if not already initialized.

Modify quic_tls_ctx_reset() to call it from quic_conn_enc_level_init() which is
called by qc_enc_level_alloc() to allocate an encryption level object.

Implement 2 new helper functions:
  - ssl_to_qel_addr() to match and pointer address to a quic_encryption level
    attached to a quic_conn object with a TLS encryption level enum value;
  - qc_quic_enc_level() to match a pointer to a quic_encryption level attached
    to a quic_conn object with an internal encryption level enum value.
This functions are useful to be called from ->set_encryption_secrets() and
->add_handshake_data() TLS stack called which takes a TLS encryption enum
as argument (enum ssl_encryption_level_t).

Replace all the use of the qc->els[] array element values by one of the newly
added ->[ieha]el quic_conn struct member values.
This commit is contained in:
Frédéric Lécaille 2023-06-22 07:19:03 +02:00 committed by Amaury Denoyelle
parent 25a7b15144
commit 3097be92f1
6 changed files with 241 additions and 171 deletions

View File

@ -597,7 +597,17 @@ struct quic_conn {
struct eb_root cids; /* tree of quic_connection_id - used to match a received packet DCID with a connection */ struct eb_root cids; /* tree of quic_connection_id - used to match a received packet DCID with a connection */
uint64_t next_cid_seq_num; uint64_t next_cid_seq_num;
struct quic_enc_level els[QUIC_TLS_ENC_LEVEL_MAX]; /* Initial encryption level */
struct quic_enc_level *iel;
/* 0-RTT encryption level */
struct quic_enc_level *eel;
/* Handshake encryption level */
struct quic_enc_level *hel;
/* 1-RTT encryption level */
struct quic_enc_level *ael;
/* List of allocated QUIC TLS encryption level */
struct list qel_list;
struct quic_pktns *ipktns; struct quic_pktns *ipktns;
struct quic_pktns *hpktns; struct quic_pktns *hpktns;
struct quic_pktns *apktns; struct quic_pktns *apktns;

View File

@ -54,6 +54,7 @@ int ssl_quic_initial_ctx(struct bind_conf *bind_conf);
struct quic_cstream *quic_cstream_new(struct quic_conn *qc); struct quic_cstream *quic_cstream_new(struct quic_conn *qc);
void quic_cstream_free(struct quic_cstream *cs); void quic_cstream_free(struct quic_cstream *cs);
void quic_free_arngs(struct quic_conn *qc, struct quic_arngs *arngs); void quic_free_arngs(struct quic_conn *qc, struct quic_arngs *arngs);
struct quic_cstream *quic_cstream_new(struct quic_conn *qc);
/* Return the long packet type matching with <qv> version and <type> */ /* Return the long packet type matching with <qv> version and <type> */
static inline int quic_pkt_type(int type, uint32_t version) static inline int quic_pkt_type(int type, uint32_t version)

View File

@ -217,6 +217,7 @@ struct quic_tls_ctx {
}; };
struct quic_enc_level { struct quic_enc_level {
struct list list;
/* Encryption level, as defined by the TLS stack. */ /* Encryption level, as defined by the TLS stack. */
enum ssl_encryption_level_t level; enum ssl_encryption_level_t level;
/* TLS encryption context (AEAD only) */ /* TLS encryption context (AEAD only) */

View File

@ -31,13 +31,15 @@
#include <haproxy/trace.h> #include <haproxy/trace.h>
void quic_pktns_release(struct quic_conn *qc, struct quic_pktns **pktns); void quic_pktns_release(struct quic_conn *qc, struct quic_pktns **pktns);
int qc_enc_level_alloc(struct quic_conn *qc, struct quic_pktns **pktns,
struct quic_enc_level **qel, enum ssl_encryption_level_t level);
void qc_enc_level_free(struct quic_conn *qc, struct quic_enc_level **qel);
void quic_tls_keys_hexdump(struct buffer *buf, void quic_tls_keys_hexdump(struct buffer *buf,
const struct quic_tls_secrets *secs); const struct quic_tls_secrets *secs);
void quic_tls_kp_keys_hexdump(struct buffer *buf, void quic_tls_kp_keys_hexdump(struct buffer *buf,
const struct quic_tls_kp *kp); const struct quic_tls_kp *kp);
int quic_conn_enc_level_init(struct quic_conn *qc,
enum quic_tls_enc_level level);
void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel); void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel);
void quic_tls_secret_hexdump(struct buffer *buf, void quic_tls_secret_hexdump(struct buffer *buf,
const unsigned char *secret, size_t secret_len); const unsigned char *secret, size_t secret_len);
@ -181,7 +183,10 @@ static inline struct quic_pktns **ssl_to_quic_pktns(struct quic_conn *qc,
return NULL; return NULL;
} }
} }
/* These following functions map TLS implementation encryption level to ours */
/* Map <level> TLS stack encryption level to our internal QUIC TLS encryption level
* if succeded, or -1 if failed.
*/
static inline enum quic_tls_enc_level ssl_to_quic_enc_level(enum ssl_encryption_level_t level) static inline enum quic_tls_enc_level ssl_to_quic_enc_level(enum ssl_encryption_level_t level)
{ {
switch (level) { switch (level) {
@ -198,6 +203,47 @@ static inline enum quic_tls_enc_level ssl_to_quic_enc_level(enum ssl_encryption_
} }
} }
/* Return the address of the QUIC TLS encryption level associated to <level> TLS
* stack encryption level and attached to <qc> QUIC connection if succeeded, or
* NULL if failed.
*/
static inline struct quic_enc_level **ssl_to_qel_addr(struct quic_conn *qc,
enum ssl_encryption_level_t level)
{
switch (level) {
case ssl_encryption_initial:
return &qc->iel;
case ssl_encryption_early_data:
return &qc->eel;
case ssl_encryption_handshake:
return &qc->hel;
case ssl_encryption_application:
return &qc->ael;
default:
return NULL;
}
}
/* Return the QUIC TLS encryption level associated to <level> internal encryption
* level attached to <qc> QUIC connection if succeeded, or NULL if failed.
*/
static inline struct quic_enc_level *qc_quic_enc_level(const struct quic_conn *qc,
enum quic_tls_enc_level level)
{
switch (level) {
case QUIC_TLS_ENC_LEVEL_INITIAL:
return qc->iel;
case QUIC_TLS_ENC_LEVEL_EARLY_DATA:
return qc->eel;
case QUIC_TLS_ENC_LEVEL_HANDSHAKE:
return qc->hel;
case QUIC_TLS_ENC_LEVEL_APP:
return qc->ael;
default:
return NULL;
}
}
/* These two following functions map our encryption level to the TLS implementation ones. */ /* These two following functions map our encryption level to the TLS implementation ones. */
static inline enum ssl_encryption_level_t quic_to_ssl_enc_level(enum quic_tls_enc_level level) static inline enum ssl_encryption_level_t quic_to_ssl_enc_level(enum quic_tls_enc_level level)
{ {
@ -309,13 +355,13 @@ static inline char quic_enc_level_char(enum quic_tls_enc_level level)
static inline char quic_enc_level_char_from_qel(const struct quic_enc_level *qel, static inline char quic_enc_level_char_from_qel(const struct quic_enc_level *qel,
const struct quic_conn *qc) const struct quic_conn *qc)
{ {
if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]) if (qel == qc->iel)
return 'I'; return 'I';
else if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA]) else if (qel == qc->eel)
return 'E'; return 'E';
else if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]) else if (qel == qc->hel)
return 'H'; return 'H';
else if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_APP]) else if (qel == qc->ael)
return 'A'; return 'A';
return '-'; return '-';
} }
@ -499,17 +545,25 @@ static inline enum quic_tls_pktns quic_tls_pktns(enum quic_tls_enc_level level)
} }
} }
/* Reset all members of <ctx> to default values. */ /* Reset all members of <ctx> to default values, ->hp_key[] excepted */
static inline void quic_tls_ctx_reset(struct quic_tls_ctx *ctx) static inline void quic_tls_ctx_reset(struct quic_tls_ctx *ctx)
{ {
ctx->rx.ctx = NULL; ctx->rx.ctx = NULL;
ctx->rx.aead = NULL;
ctx->rx.md = NULL;
ctx->rx.hp_ctx = NULL; ctx->rx.hp_ctx = NULL;
ctx->rx.hp = NULL;
ctx->rx.secret = NULL;
ctx->rx.iv = NULL; ctx->rx.iv = NULL;
ctx->rx.key = NULL; ctx->rx.key = NULL;
ctx->rx.pn = 0; ctx->rx.pn = 0;
ctx->tx.ctx = NULL; ctx->tx.ctx = NULL;
ctx->tx.aead = NULL;
ctx->tx.md = NULL;
ctx->tx.hp_ctx = NULL; ctx->tx.hp_ctx = NULL;
ctx->tx.hp = NULL;
ctx->tx.secret = NULL;
ctx->tx.iv = NULL; ctx->tx.iv = NULL;
ctx->tx.key = NULL; ctx->tx.key = NULL;
/* Not used on the TX path. */ /* Not used on the TX path. */
@ -850,13 +904,13 @@ static inline int quic_tls_ku_init(struct quic_conn *qc)
/* Return 1 if <qel> has RX secrets, 0 if not. */ /* Return 1 if <qel> has RX secrets, 0 if not. */
static inline int quic_tls_has_rx_sec(const struct quic_enc_level *qel) static inline int quic_tls_has_rx_sec(const struct quic_enc_level *qel)
{ {
return !!qel->tls_ctx.rx.key; return qel && !!qel->tls_ctx.rx.key;
} }
/* Return 1 if <qel> has TX secrets, 0 if not. */ /* Return 1 if <qel> has TX secrets, 0 if not. */
static inline int quic_tls_has_tx_sec(const struct quic_enc_level *qel) static inline int quic_tls_has_tx_sec(const struct quic_enc_level *qel)
{ {
return !!qel->tls_ctx.tx.key; return qel && !!qel->tls_ctx.tx.key;
} }
#endif /* USE_QUIC */ #endif /* USE_QUIC */

View File

@ -227,9 +227,6 @@ DECLARE_STATIC_POOL(pool_head_quic_cstream, "quic_cstream", sizeof(struct quic_c
DECLARE_POOL(pool_head_quic_frame, "quic_frame", sizeof(struct quic_frame)); DECLARE_POOL(pool_head_quic_frame, "quic_frame", sizeof(struct quic_frame));
DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng", sizeof(struct quic_arng_node)); DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng", sizeof(struct quic_arng_node));
static int quic_conn_enc_level_init(struct quic_conn *qc,
struct quic_pktns *pktns,
enum quic_tls_enc_level level);
static struct quic_connection_id *new_quic_cid(struct eb_root *root, static struct quic_connection_id *new_quic_cid(struct eb_root *root,
struct quic_conn *qc, struct quic_conn *qc,
const struct quic_cid *odcid, const struct quic_cid *odcid,
@ -320,16 +317,15 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
} }
if ((mask & QUIC_EV_CONN_ISEC) && qc) { if ((mask & QUIC_EV_CONN_ISEC) && qc) {
/* Initial read & write secrets. */ /* Initial read & write secrets. */
enum quic_tls_enc_level level = QUIC_TLS_ENC_LEVEL_INITIAL;
const unsigned char *rx_sec = a2; const unsigned char *rx_sec = a2;
const unsigned char *tx_sec = a3; const unsigned char *tx_sec = a3;
tls_ctx = &qc->els[level].tls_ctx; tls_ctx = &qc->iel->tls_ctx;
chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(level)); chunk_appendf(&trace_buf, "\n RX el=I");
if (rx_sec) if (rx_sec)
quic_tls_secret_hexdump(&trace_buf, rx_sec, 32); quic_tls_secret_hexdump(&trace_buf, rx_sec, 32);
quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx); quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx);
chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(level)); chunk_appendf(&trace_buf, "\n TX el=I");
if (tx_sec) if (tx_sec)
quic_tls_secret_hexdump(&trace_buf, tx_sec, 32); quic_tls_secret_hexdump(&trace_buf, tx_sec, 32);
quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx); quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx);
@ -360,12 +356,11 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
if (level) { if (level) {
enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level); enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
struct quic_enc_level *qel = qc_quic_enc_level(qc, lvl);
chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(lvl)); chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(lvl));
if (quic_tls_has_rx_sec(&qc->els[lvl])) { if (quic_tls_has_rx_sec(qel))
tls_ctx = &qc->els[lvl].tls_ctx; quic_tls_keys_hexdump(&trace_buf, &qel->tls_ctx.rx);
quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx);
}
else else
chunk_appendf(&trace_buf, " (none)"); chunk_appendf(&trace_buf, " (none)");
} }
@ -376,11 +371,11 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
if (level) { if (level) {
enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level); enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
struct quic_enc_level *qel = qc_quic_enc_level(qc, lvl);
chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(lvl)); chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(lvl));
if (quic_tls_has_tx_sec(&qc->els[lvl])) { if (quic_tls_has_tx_sec(qel)) {
tls_ctx = &qc->els[lvl].tls_ctx; quic_tls_keys_hexdump(&trace_buf, &qel->tls_ctx.tx);
quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx);
} }
else else
chunk_appendf(&trace_buf, " (none)"); chunk_appendf(&trace_buf, " (none)");
@ -908,7 +903,7 @@ static inline void qc_set_timer(struct quic_conn *qc)
*/ */
static int quic_tls_key_update(struct quic_conn *qc) static int quic_tls_key_update(struct quic_conn *qc)
{ {
struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx; struct quic_tls_ctx *tls_ctx = &qc->ael->tls_ctx;
struct quic_tls_secrets *rx = &tls_ctx->rx; struct quic_tls_secrets *rx = &tls_ctx->rx;
struct quic_tls_secrets *tx = &tls_ctx->tx; struct quic_tls_secrets *tx = &tls_ctx->tx;
/* Used only for the traces */ /* Used only for the traces */
@ -998,7 +993,7 @@ static int quic_tls_key_update(struct quic_conn *qc)
*/ */
static void quic_tls_rotate_keys(struct quic_conn *qc) static void quic_tls_rotate_keys(struct quic_conn *qc)
{ {
struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx; struct quic_tls_ctx *tls_ctx = &qc->ael->tls_ctx;
unsigned char *curr_secret, *curr_iv, *curr_key; unsigned char *curr_secret, *curr_iv, *curr_key;
EVP_CIPHER_CTX *curr_ctx; EVP_CIPHER_CTX *curr_ctx;
@ -1050,29 +1045,25 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
const uint8_t *read_secret, const uint8_t *read_secret,
const uint8_t *write_secret, size_t secret_len) const uint8_t *write_secret, size_t secret_len)
{ {
int ret = 0;
struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
enum quic_tls_enc_level tel = ssl_to_quic_enc_level(level); struct quic_enc_level **qel = ssl_to_qel_addr(qc, level);
struct quic_enc_level *qel = &qc->els[tel]; struct quic_pktns **pktns = ssl_to_quic_pktns(qc, level);
struct quic_tls_ctx *tls_ctx = &qel->tls_ctx; struct quic_tls_ctx *tls_ctx;
const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
struct quic_tls_secrets *rx = NULL, *tx = NULL; struct quic_tls_secrets *rx = NULL, *tx = NULL;
const struct quic_version *ver = const struct quic_version *ver =
qc->negotiated_version ? qc->negotiated_version : qc->original_version; qc->negotiated_version ? qc->negotiated_version : qc->original_version;
int ret = 0;
TRACE_ENTER(QUIC_EV_CONN_RWSEC, qc); TRACE_ENTER(QUIC_EV_CONN_RWSEC, qc);
BUG_ON(secret_len > QUIC_TLS_SECRET_LEN); BUG_ON(secret_len > QUIC_TLS_SECRET_LEN);
if (!qel->pktns) { if (!*qel && !qc_enc_level_alloc(qc, pktns, qel, level)) {
struct quic_pktns **pktns = ssl_to_quic_pktns(qc, level); TRACE_PROTO("Could not allocated an encryption level", QUIC_EV_CONN_ADDDATA, qc);
goto out;
}
if (pktns == NULL || tls_ctx = &(*qel)->tls_ctx;
!quic_pktns_init(qc, pktns) ||
!quic_conn_enc_level_init(qc, *pktns, tel)) {
TRACE_ERROR("Could not initialized the packet number space", QUIC_EV_CONN_ADDDATA, qc);
goto leave;
}
}
if (qc->flags & QUIC_FL_CONN_TO_KILL) { if (qc->flags & QUIC_FL_CONN_TO_KILL) {
TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc); TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc);
@ -1366,12 +1357,11 @@ int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alp
int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level, int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level,
const uint8_t *data, size_t len) const uint8_t *data, size_t len)
{ {
struct quic_conn *qc;
enum quic_tls_enc_level tel;
struct quic_enc_level *qel;
int ret = 0; int ret = 0;
struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
struct quic_enc_level **qel = ssl_to_qel_addr(qc, level);
struct quic_pktns **pktns = ssl_to_quic_pktns(qc, level);
qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc); TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc);
if (qc->flags & QUIC_FL_CONN_TO_KILL) { if (qc->flags & QUIC_FL_CONN_TO_KILL) {
@ -1384,25 +1374,10 @@ int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level,
goto out; goto out;
} }
tel = ssl_to_quic_enc_level(level); if (!*qel && !qc_enc_level_alloc(qc, pktns, qel, level))
if (tel == -1) {
TRACE_ERROR("Wrong encryption level", QUIC_EV_CONN_ADDDATA, qc);
goto leave; goto leave;
}
qel = &qc->els[tel]; if (!quic_crypto_data_cpy(qc, *qel, data, len)) {
if (!qel->pktns) {
struct quic_pktns **pktns = ssl_to_quic_pktns(qc, level);
if (pktns == NULL ||
!quic_pktns_init(qc, pktns) ||
!quic_conn_enc_level_init(qc, *pktns, tel)) {
TRACE_ERROR("Could not initialized the packet number space", QUIC_EV_CONN_ADDDATA, qc);
goto leave;
}
}
if (!quic_crypto_data_cpy(qc, qel, data, len)) {
TRACE_ERROR("Could not bufferize", QUIC_EV_CONN_ADDDATA, qc); TRACE_ERROR("Could not bufferize", QUIC_EV_CONN_ADDDATA, qc);
goto leave; goto leave;
} }
@ -2767,8 +2742,8 @@ static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc,
struct list itmp = LIST_HEAD_INIT(itmp); struct list itmp = LIST_HEAD_INIT(itmp);
struct list htmp = LIST_HEAD_INIT(htmp); struct list htmp = LIST_HEAD_INIT(htmp);
struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]; struct quic_enc_level *iqel = qc->iel;
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; struct quic_enc_level *hqel = qc->hel;
struct quic_enc_level *qel = iqel; struct quic_enc_level *qel = iqel;
struct eb_root *pkts; struct eb_root *pkts;
struct eb64_node *node; struct eb64_node *node;
@ -2869,7 +2844,7 @@ static int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
{ {
int ret = 0; int ret = 0;
struct quic_frame *ss, *rs; struct quic_frame *ss, *rs;
struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; struct quic_enc_level *qel = qc->ael;
const uint64_t app_error_code = H3_REQUEST_REJECTED; const uint64_t app_error_code = H3_REQUEST_REJECTED;
TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc); TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
@ -2976,7 +2951,7 @@ static int qc_handle_crypto_frm(struct quic_conn *qc,
/* Nothing to do */ /* Nothing to do */
TRACE_PROTO("Already received CRYPTO data", TRACE_PROTO("Already received CRYPTO data",
QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug); QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
if (qc_is_listener(qc) && qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] && if (qc_is_listener(qc) && qel == qc->iel &&
!(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP)) !(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP))
*fast_retrans = 1; *fast_retrans = 1;
goto done; goto done;
@ -3045,7 +3020,7 @@ static int qc_build_new_connection_id_frm(struct quic_conn *qc,
TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc); TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; qel = qc->ael;
frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID); frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
if (!frm) { if (!frm) {
TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc); TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
@ -3361,8 +3336,8 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED; qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
if (fast_retrans) { if (fast_retrans) {
struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]; struct quic_enc_level *iqel = qc->iel;
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; struct quic_enc_level *hqel = qc->hel;
TRACE_PROTO("speeding up handshake completion", QUIC_EV_CONN_PRSHPKT, qc); TRACE_PROTO("speeding up handshake completion", QUIC_EV_CONN_PRSHPKT, qc);
qc_prep_hdshk_fast_retrans(qc, &iqel->pktns->tx.frms, &hqel->pktns->tx.frms); qc_prep_hdshk_fast_retrans(qc, &iqel->pktns->tx.frms, &hqel->pktns->tx.frms);
@ -3375,14 +3350,14 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
*/ */
if (pkt->type == QUIC_PACKET_TYPE_HANDSHAKE && qc_is_listener(qc)) { if (pkt->type == QUIC_PACKET_TYPE_HANDSHAKE && qc_is_listener(qc)) {
if (qc->state >= QUIC_HS_ST_SERVER_INITIAL) { if (qc->state >= QUIC_HS_ST_SERVER_INITIAL) {
if (!(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx.flags & if (!(qc->iel->tls_ctx.flags &
QUIC_FL_TLS_SECRETS_DCD)) { QUIC_FL_TLS_SECRETS_DCD)) {
quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]); quic_tls_discard_keys(qc->iel);
TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PRSHPKT, qc); TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PRSHPKT, qc);
quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc); quic_pktns_discard(qc->iel->pktns, qc);
qc_set_timer(qc); qc_set_timer(qc);
qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]); qc_el_rx_pkts_del(qc->iel);
qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns); qc_release_pktns_frms(qc, qc->iel->pktns);
} }
if (qc->state < QUIC_HS_ST_SERVER_HANDSHAKE) if (qc->state < QUIC_HS_ST_SERVER_HANDSHAKE)
qc->state = QUIC_HS_ST_SERVER_HANDSHAKE; qc->state = QUIC_HS_ST_SERVER_HANDSHAKE;
@ -3454,9 +3429,7 @@ static int qc_may_build_pkt(struct quic_conn *qc, struct list *frms,
struct quic_enc_level *qel, int cc, int probe, struct quic_enc_level *qel, int cc, int probe,
int *must_ack) int *must_ack)
{ {
int force_ack = int force_ack = qel == qc->iel || qel == qc->hel;
qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] ||
qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
int nb_aepkts_since_last_ack = qel->pktns->rx.nb_aepkts_since_last_ack; int nb_aepkts_since_last_ack = qel->pktns->rx.nb_aepkts_since_last_ack;
/* An acknowledgement must be sent if this has been forced by the caller, /* An acknowledgement must be sent if this has been forced by the caller,
@ -3507,7 +3480,7 @@ static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf,
TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc); TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; qel = qc->ael;
total = 0; total = 0;
pos = (unsigned char *)b_tail(buf); pos = (unsigned char *)b_tail(buf);
while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen) { while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen) {
@ -3603,7 +3576,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
BUG_ON_HOT(buf->head || buf->data); BUG_ON_HOT(buf->head || buf->data);
total = 0; total = 0;
qel = &qc->els[tel]; qel = qc_quic_enc_level(qc, tel);
frms = tel_frms; frms = tel_frms;
dglen = 0; dglen = 0;
padding = 0; padding = 0;
@ -3629,7 +3602,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
if (tel != next_tel && next_tel != QUIC_TLS_ENC_LEVEL_NONE) { if (tel != next_tel && next_tel != QUIC_TLS_ENC_LEVEL_NONE) {
tel = next_tel; tel = next_tel;
frms = next_tel_frms; frms = next_tel_frms;
qel = &qc->els[tel]; qel = qc_quic_enc_level(qc, tel);
/* Build a new datagram */ /* Build a new datagram */
prv_pkt = NULL; prv_pkt = NULL;
TRACE_DEVEL("next encryption level selected", QUIC_EV_CONN_PHPKTS, qc); TRACE_DEVEL("next encryption level selected", QUIC_EV_CONN_PHPKTS, qc);
@ -3673,7 +3646,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
if (qc->negotiated_version) { if (qc->negotiated_version) {
ver = qc->negotiated_version; ver = qc->negotiated_version;
if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]) if (qel == qc->iel)
tls_ctx = &qc->negotiated_ictx; tls_ctx = &qc->negotiated_ictx;
else else
tls_ctx = &qel->tls_ctx; tls_ctx = &qel->tls_ctx;
@ -3726,12 +3699,12 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
*/ */
if (qc->state == QUIC_HS_ST_CLIENT_INITIAL && if (qc->state == QUIC_HS_ST_CLIENT_INITIAL &&
pkt_type == QUIC_PACKET_TYPE_HANDSHAKE) { pkt_type == QUIC_PACKET_TYPE_HANDSHAKE) {
quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]); quic_tls_discard_keys(qc->iel);
TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PHPKTS, qc); TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PHPKTS, qc);
quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc); quic_pktns_discard(qc->iel->pktns, qc);
qc_set_timer(qc); qc_set_timer(qc);
qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]); qc_el_rx_pkts_del(qc->iel);
qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns); qc_release_pktns_frms(qc, qc->iel->pktns);
qc->state = QUIC_HS_ST_CLIENT_HANDSHAKE; qc->state = QUIC_HS_ST_CLIENT_HANDSHAKE;
} }
/* If the data for the current encryption level have all been sent, /* If the data for the current encryption level have all been sent,
@ -3743,11 +3716,11 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel) if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel)
next_tel = QUIC_TLS_ENC_LEVEL_APP; next_tel = QUIC_TLS_ENC_LEVEL_APP;
tel = next_tel; tel = next_tel;
qel = qc_quic_enc_level(qc, tel);
if (tel == QUIC_TLS_ENC_LEVEL_APP) if (tel == QUIC_TLS_ENC_LEVEL_APP)
frms = &qc->els[tel].pktns->tx.frms; frms = &qel->pktns->tx.frms;
else else
frms = next_tel_frms; frms = next_tel_frms;
qel = &qc->els[tel];
if (!LIST_ISEMPTY(frms)) { if (!LIST_ISEMPTY(frms)) {
/* If there is data for the next level, do not /* If there is data for the next level, do not
* consume a datagram. * consume a datagram.
@ -4188,7 +4161,7 @@ static int quic_build_post_handshake_frames(struct quic_conn *qc)
TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; qel = qc->ael;
/* Only servers must send a HANDSHAKE_DONE frame. */ /* Only servers must send a HANDSHAKE_DONE frame. */
if (qc_is_listener(qc)) { if (qc_is_listener(qc)) {
frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE); frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE);
@ -4473,7 +4446,7 @@ static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packe
{ {
uint64_t largest_pn = qel->pktns->rx.largest_pn; uint64_t largest_pn = qel->pktns->rx.largest_pn;
if (qel != &qc->els[QUIC_TLS_ENC_LEVEL_APP] || largest_pn == -1 || if (qel != qc->ael || largest_pn == -1 ||
pkt->pn <= largest_pn) pkt->pn <= largest_pn)
return; return;
@ -4497,12 +4470,10 @@ static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packe
static inline void qc_rm_hp_pkts(struct quic_conn *qc, struct quic_enc_level *el) static inline void qc_rm_hp_pkts(struct quic_conn *qc, struct quic_enc_level *el)
{ {
struct quic_rx_packet *pqpkt, *pkttmp; struct quic_rx_packet *pqpkt, *pkttmp;
struct quic_enc_level *app_qel;
TRACE_ENTER(QUIC_EV_CONN_ELRMHP, qc); TRACE_ENTER(QUIC_EV_CONN_ELRMHP, qc);
app_qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
/* A server must not process incoming 1-RTT packets before the handshake is complete. */ /* A server must not process incoming 1-RTT packets before the handshake is complete. */
if (el == app_qel && qc_is_listener(qc) && qc->state < QUIC_HS_ST_COMPLETE) { if (el == qc->ael && qc_is_listener(qc) && qc->state < QUIC_HS_ST_COMPLETE) {
TRACE_PROTO("RX hp not removed (handshake not completed)", TRACE_PROTO("RX hp not removed (handshake not completed)",
QUIC_EV_CONN_ELRMHP, qc); QUIC_EV_CONN_ELRMHP, qc);
goto out; goto out;
@ -4679,15 +4650,12 @@ int qc_treat_rx_pkts(struct quic_conn *qc, struct quic_enc_level *cur_el,
static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel) static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel)
{ {
int ret = 0; int ret = 0;
enum quic_tls_enc_level tel;
TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc); TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc);
if (!qel) if (!qel)
goto cant_rm_hp; goto cant_rm_hp;
tel = ssl_to_quic_enc_level(qel->level);
/* check if tls secrets are available */ /* check if tls secrets are available */
if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) { if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) {
TRACE_PROTO("Discarded keys", QUIC_EV_CONN_TRMHP, qc); TRACE_PROTO("Discarded keys", QUIC_EV_CONN_TRMHP, qc);
@ -4699,13 +4667,13 @@ static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel)
goto cant_rm_hp; goto cant_rm_hp;
} }
if (tel == QUIC_TLS_ENC_LEVEL_APP && qc->state < QUIC_HS_ST_COMPLETE) { if (qel == qc->ael && qc->state < QUIC_HS_ST_COMPLETE) {
TRACE_PROTO("handshake not complete", QUIC_EV_CONN_TRMHP, qc); TRACE_PROTO("handshake not complete", QUIC_EV_CONN_TRMHP, qc);
goto cant_rm_hp; goto cant_rm_hp;
} }
/* check if the connection layer is ready before using app level */ /* check if the connection layer is ready before using app level */
if ((tel == QUIC_TLS_ENC_LEVEL_APP || tel == QUIC_TLS_ENC_LEVEL_EARLY_DATA) && if ((qel == qc->ael || qel == qc->eel) &&
qc->mux_state == QC_MUX_NULL) { qc->mux_state == QC_MUX_NULL) {
TRACE_PROTO("connection layer not ready", QUIC_EV_CONN_TRMHP, qc); TRACE_PROTO("connection layer not ready", QUIC_EV_CONN_TRMHP, qc);
goto cant_rm_hp; goto cant_rm_hp;
@ -4847,9 +4815,8 @@ int qc_send_mux(struct quic_conn *qc, struct list *frms)
/* Try to send post handshake frames first unless on 0-RTT. */ /* Try to send post handshake frames first unless on 0-RTT. */
if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) && if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) &&
qc->state >= QUIC_HS_ST_COMPLETE) { qc->state >= QUIC_HS_ST_COMPLETE) {
struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
quic_build_post_handshake_frames(qc); quic_build_post_handshake_frames(qc);
qc_send_app_pkts(qc, &qel->pktns->tx.frms); qc_send_app_pkts(qc, &qc->ael->pktns->tx.frms);
} }
TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc); TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc);
@ -4925,9 +4892,9 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
static int qc_dgrams_retransmit(struct quic_conn *qc) static int qc_dgrams_retransmit(struct quic_conn *qc)
{ {
int ret = 0; int ret = 0;
struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]; struct quic_enc_level *iqel = qc->iel;
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; struct quic_enc_level *hqel = qc->hel;
struct quic_enc_level *aqel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; struct quic_enc_level *aqel = qc->ael;
TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc); TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
@ -5035,7 +5002,7 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta
TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; qel = qc->ael;
TRACE_STATE("connection handshake state", QUIC_EV_CONN_IO_CB, qc, &qc->state); TRACE_STATE("connection handshake state", QUIC_EV_CONN_IO_CB, qc, &qc->state);
if (qc_test_fd(qc)) if (qc_test_fd(qc))
@ -5097,6 +5064,19 @@ static int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel)
!LIST_ISEMPTY(&qel->pktns->tx.frms); !LIST_ISEMPTY(&qel->pktns->tx.frms);
} }
static int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf,
struct quic_enc_level *qel, struct quic_enc_level *next_qel)
{
enum quic_tls_enc_level next_tel =
next_qel ? ssl_to_quic_enc_level(next_qel->level) : QUIC_TLS_ENC_LEVEL_NONE;
struct list *next_frms =
next_qel ? &next_qel->pktns->tx.frms : NULL;
return qc_prep_pkts(qc, buf,
ssl_to_quic_enc_level(qel->level), &qel->pktns->tx.frms,
next_tel, next_frms);
}
/* QUIC connection packet handler task. */ /* QUIC connection packet handler task. */
struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
{ {
@ -5111,7 +5091,7 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
eqel = &qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA]; eqel = qc->eel;
st = qc->state; st = qc->state;
TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st); TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st);
@ -5132,7 +5112,7 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
qc_rcv_buf(qc); qc_rcv_buf(qc);
if (st >= QUIC_HS_ST_COMPLETE && if (st >= QUIC_HS_ST_COMPLETE &&
qc_el_rx_pkts(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) { qc_el_rx_pkts(qc->hel)) {
TRACE_DEVEL("remaining Handshake packets", QUIC_EV_CONN_PHPKTS, qc); TRACE_DEVEL("remaining Handshake packets", QUIC_EV_CONN_PHPKTS, qc);
/* There may be remaining Handshake packets to treat and acknowledge. */ /* There may be remaining Handshake packets to treat and acknowledge. */
tel = QUIC_TLS_ENC_LEVEL_HANDSHAKE; tel = QUIC_TLS_ENC_LEVEL_HANDSHAKE;
@ -5141,8 +5121,8 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
else if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, zero_rtt)) else if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, zero_rtt))
goto out; goto out;
qel = &qc->els[tel]; qel = qc_quic_enc_level(qc, tel);
next_qel = next_tel == QUIC_TLS_ENC_LEVEL_NONE ? NULL : &qc->els[next_tel]; next_qel = next_tel == QUIC_TLS_ENC_LEVEL_NONE ? NULL : qc_quic_enc_level(qc, next_tel);
next_level: next_level:
/* Treat packets waiting for header packet protection decryption */ /* Treat packets waiting for header packet protection decryption */
@ -5174,18 +5154,17 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
st = qc->state; st = qc->state;
if (st >= QUIC_HS_ST_COMPLETE) { if (st >= QUIC_HS_ST_COMPLETE) {
if (!(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].tls_ctx.flags & if (!(qc->hel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD)) {
QUIC_FL_TLS_SECRETS_DCD)) {
/* Discard the Handshake keys. */ /* Discard the Handshake keys. */
quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]); quic_tls_discard_keys(qc->hel);
TRACE_PROTO("discarding Handshake pktns", QUIC_EV_CONN_PHPKTS, qc); TRACE_PROTO("discarding Handshake pktns", QUIC_EV_CONN_PHPKTS, qc);
quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns, qc); quic_pktns_discard(qc->hel->pktns, qc);
qc_set_timer(qc); qc_set_timer(qc);
qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]); qc_el_rx_pkts_del(qc->hel);
qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns); qc_release_pktns_frms(qc, qc->hel->pktns);
} }
if (qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) { if (qc->hel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) {
/* There may be remaining handshake to build (acks) */ /* There may be remaining handshake to build (acks) */
st = QUIC_HS_ST_SERVER_HANDSHAKE; st = QUIC_HS_ST_SERVER_HANDSHAKE;
} }
@ -5216,8 +5195,9 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
BUG_ON_HOT(b_data(buf)); BUG_ON_HOT(b_data(buf));
b_reset(buf); b_reset(buf);
ret = qc_prep_pkts(qc, buf, tel, &qc->els[tel].pktns->tx.frms, ret = qc_prep_hpkts(qc, buf,
next_tel, &qc->els[next_tel].pktns->tx.frms); qc_quic_enc_level(qc, tel),
qc_quic_enc_level(qc, next_tel));
if (ret == -1) { if (ret == -1) {
qc_txb_release(qc); qc_txb_release(qc);
goto out; goto out;
@ -5386,13 +5366,10 @@ struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
} }
} }
else if (!qc_is_listener(qc) && qc->state <= QUIC_HS_ST_COMPLETE) { else if (!qc_is_listener(qc) && qc->state <= QUIC_HS_ST_COMPLETE) {
struct quic_enc_level *iel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]; if (quic_tls_has_tx_sec(qc->hel))
struct quic_enc_level *hel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; qc->hel->pktns->tx.pto_probe = 1;
if (quic_tls_has_tx_sec(qc->iel))
if (quic_tls_has_tx_sec(hel)) qc->iel->pktns->tx.pto_probe = 1;
hel->pktns->tx.pto_probe = 1;
if (quic_tls_has_tx_sec(iel))
iel->pktns->tx.pto_probe = 1;
} }
tasklet_wakeup(qc->wait_event.tasklet); tasklet_wakeup(qc->wait_event.tasklet);
@ -5480,7 +5457,6 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
struct quic_conn *qc; struct quic_conn *qc;
struct listener *l = NULL; struct listener *l = NULL;
struct quic_cc_algo *cc_algo = NULL; struct quic_cc_algo *cc_algo = NULL;
struct quic_tls_ctx *ictx, *app_ctx;
TRACE_ENTER(QUIC_EV_CONN_INIT); TRACE_ENTER(QUIC_EV_CONN_INIT);
@ -5526,30 +5502,15 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
quic_tls_ku_reset(&qc->ku.nxt_rx); quic_tls_ku_reset(&qc->ku.nxt_rx);
quic_tls_ku_reset(&qc->ku.nxt_tx); quic_tls_ku_reset(&qc->ku.nxt_tx);
/* Encryption level: required to safely call quic_conn_enc_level_uninit() /* Encryption levels */
* from quic_conn_release(). qc->iel = qc->eel = qc->hel = qc->ael = NULL;
*/ LIST_INIT(&qc->qel_list);
for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
struct quic_enc_level *qel = &qc->els[i];
struct quic_tls_ctx *ctx = &qel->tls_ctx;
quic_tls_ctx_reset(ctx);
qel->tx.crypto.nb_buf = 0;
qel->tx.crypto.bufs = NULL;
qel->cstream = NULL;
qel->pktns = NULL;
}
/* Packet number spaces */ /* Packet number spaces */
qc->ipktns = qc->hpktns = qc->apktns = NULL; qc->ipktns = qc->hpktns = qc->apktns = NULL;
LIST_INIT(&qc->pktns_list); LIST_INIT(&qc->pktns_list);
quic_tls_ctx_reset(&qc->negotiated_ictx); quic_tls_ctx_reset(&qc->negotiated_ictx);
app_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
app_ctx->rx.secret = NULL;
app_ctx->tx.secret = NULL;
/* Required to safely call quic_conn_prx_cntrs_update() from quic_conn_release(). */ /* Required to safely call quic_conn_prx_cntrs_update() from quic_conn_release(). */
qc->prx_counters = NULL; qc->prx_counters = NULL;
@ -5607,12 +5568,7 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
/* Select our SCID which is the first CID with 0 as sequence number. */ /* Select our SCID which is the first CID with 0 as sequence number. */
qc->scid = conn_id->cid; qc->scid = conn_id->cid;
/* Initial packet number spaces initialization. */ if (!qc_enc_level_alloc(qc, &qc->ipktns, &qc->iel, ssl_encryption_initial)) {
if (!quic_pktns_init(qc, &qc->ipktns))
goto err;
/* Initial encryption level initialization */
if (!quic_conn_enc_level_init(qc, qc->ipktns, QUIC_TLS_ENC_LEVEL_INITIAL)) {
TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc); TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc);
goto err; goto err;
} }
@ -5678,8 +5634,7 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
!quic_conn_init_idle_timer_task(qc)) !quic_conn_init_idle_timer_task(qc))
goto err; goto err;
ictx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx; if (!qc_new_isecs(qc, &qc->iel->tls_ctx, qc->original_version, dcid->data, dcid->len, 1))
if (!qc_new_isecs(qc, ictx,qc->original_version, dcid->data, dcid->len, 1))
goto err; goto err;
/* Counters initialization */ /* Counters initialization */
@ -5728,10 +5683,8 @@ static inline void quic_conn_prx_cntrs_update(struct quic_conn *qc)
*/ */
void quic_conn_release(struct quic_conn *qc) void quic_conn_release(struct quic_conn *qc)
{ {
int i;
struct ssl_sock_ctx *conn_ctx; struct ssl_sock_ctx *conn_ctx;
struct eb64_node *node; struct eb64_node *node;
struct quic_tls_ctx *app_tls_ctx;
struct quic_rx_packet *pkt, *pktback; struct quic_rx_packet *pkt, *pktback;
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc); TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
@ -5792,15 +5745,20 @@ void quic_conn_release(struct quic_conn *qc)
} }
quic_tls_ku_free(qc); quic_tls_ku_free(qc);
for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) { if (qc->ael) {
quic_tls_ctx_secs_free(&qc->els[i].tls_ctx); struct quic_tls_ctx *actx = &qc->ael->tls_ctx;
quic_conn_enc_level_uninit(qc, &qc->els[i]);
}
quic_tls_ctx_secs_free(&qc->negotiated_ictx);
app_tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx; /* Secrets used by keyupdate */
pool_free(pool_head_quic_tls_secret, app_tls_ctx->rx.secret); pool_free(pool_head_quic_tls_secret, actx->rx.secret);
pool_free(pool_head_quic_tls_secret, app_tls_ctx->tx.secret); pool_free(pool_head_quic_tls_secret, actx->tx.secret);
}
qc_enc_level_free(qc, &qc->iel);
qc_enc_level_free(qc, &qc->eel);
qc_enc_level_free(qc, &qc->hel);
qc_enc_level_free(qc, &qc->ael);
quic_tls_ctx_secs_free(&qc->negotiated_ictx);
quic_pktns_release(qc, &qc->ipktns); quic_pktns_release(qc, &qc->ipktns);
quic_pktns_release(qc, &qc->hpktns); quic_pktns_release(qc, &qc->hpktns);
@ -6092,7 +6050,7 @@ static inline int qc_try_rm_hp(struct quic_conn *qc,
pn = beg + pkt->pn_offset; pn = beg + pkt->pn_offset;
tel = quic_packet_type_enc_level(pkt->type); tel = quic_packet_type_enc_level(pkt->type);
qel = &qc->els[tel]; qel = qc_quic_enc_level(qc, tel);
if (qc_qel_may_rm_hp(qc, qel)) { if (qc_qel_may_rm_hp(qc, qel)) {
struct quic_tls_ctx *tls_ctx = qc_select_tls_ctx(qc, qel, pkt); struct quic_tls_ctx *tls_ctx = qc_select_tls_ctx(qc, qel, pkt);
@ -7802,8 +7760,7 @@ static void qc_build_cc_frm(struct quic_conn *qc, struct quic_enc_level *qel,
if (qc->err.app) { if (qc->err.app) {
if (unlikely(qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] || if (unlikely(qel == qc->iel || qel == qc->hel)) {
qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) {
/* RFC 9000 10.2.3. Immediate Close during the Handshake /* RFC 9000 10.2.3. Immediate Close during the Handshake
* *
* Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake * Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake

View File

@ -106,20 +106,23 @@ void quic_tls_secret_hexdump(struct buffer *buf,
* Returns 1 if succeeded, 0 if not. On error the caller is responsible to use * Returns 1 if succeeded, 0 if not. On error the caller is responsible to use
* quic_conn_enc_level_uninit() to cleanup partially allocated content. * quic_conn_enc_level_uninit() to cleanup partially allocated content.
*/ */
int quic_conn_enc_level_init(struct quic_conn *qc, static int quic_conn_enc_level_init(struct quic_conn *qc,
enum quic_tls_enc_level level) struct quic_enc_level **el,
struct quic_pktns *pktns,
enum ssl_encryption_level_t level)
{ {
int ret = 0; int ret = 0;
struct quic_enc_level *qel; struct quic_enc_level *qel;
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc); TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
qel = &qc->els[level]; qel = pool_alloc(pool_head_quic_enc_level);
qel->level = quic_to_ssl_enc_level(level); if (!qel)
qel->tls_ctx.rx.aead = qel->tls_ctx.tx.aead = NULL; goto leave;
qel->tls_ctx.rx.md = qel->tls_ctx.tx.md = NULL;
qel->tls_ctx.rx.hp = qel->tls_ctx.tx.hp = NULL; qel->pktns = pktns;
qel->tls_ctx.flags = 0; qel->level = level;
quic_tls_ctx_reset(&qel->tls_ctx);
qel->rx.pkts = EB_ROOT; qel->rx.pkts = EB_ROOT;
LIST_INIT(&qel->rx.pqpkts); LIST_INIT(&qel->rx.pqpkts);
@ -140,7 +143,7 @@ int quic_conn_enc_level_init(struct quic_conn *qc,
qel->tx.crypto.sz = 0; qel->tx.crypto.sz = 0;
qel->tx.crypto.offset = 0; qel->tx.crypto.offset = 0;
/* No CRYPTO data for early data TLS encryption level */ /* No CRYPTO data for early data TLS encryption level */
if (level == QUIC_TLS_ENC_LEVEL_EARLY_DATA) if (level == ssl_encryption_early_data)
qel->cstream = NULL; qel->cstream = NULL;
else { else {
qel->cstream = quic_cstream_new(qc); qel->cstream = quic_cstream_new(qc);
@ -148,6 +151,8 @@ int quic_conn_enc_level_init(struct quic_conn *qc,
goto leave; goto leave;
} }
LIST_APPEND(&qc->qel_list, &qel->list);
*el = qel;
ret = 1; ret = 1;
leave: leave:
TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc); TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
@ -173,6 +178,48 @@ void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel
TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc); TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
} }
/* Allocate a QUIC TLS encryption with <level> as TLS stack encryption to be
* attached to <qc> QUIC connection. Also allocate the associated packet number
* space object with <pktns> as address to be attached to <qc> if not already
* allocated.
* Return 1 if succeeded, 0 if not.
*/
int qc_enc_level_alloc(struct quic_conn *qc, struct quic_pktns **pktns,
struct quic_enc_level **qel, enum ssl_encryption_level_t level)
{
int ret = 0;
BUG_ON(!qel || !pktns);
BUG_ON(*qel && !*pktns);
if (!*pktns && !quic_pktns_init(qc, pktns))
goto leave;
if (!*qel && !quic_conn_enc_level_init(qc, qel, *pktns, level))
goto leave;
ret = 1;
leave:
return ret;
}
/* Free the memory allocated to the encryption level attached to <qc> connection
* with <qel> as pointer address. Also remove it from the list of the encryption
* levels attached to this connection and reset its value to NULL.
* Never fails.
*/
void qc_enc_level_free(struct quic_conn *qc, struct quic_enc_level **qel)
{
if (!*qel)
return;
quic_tls_ctx_secs_free(&(*qel)->tls_ctx);
quic_conn_enc_level_uninit(qc, *qel);
LIST_DEL_INIT(&(*qel)->list);
pool_free(pool_head_quic_enc_level, *qel);
*qel = NULL;
}
int quic_hkdf_extract(const EVP_MD *md, int quic_hkdf_extract(const EVP_MD *md,
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *key, size_t keylen, const unsigned char *key, size_t keylen,