From 647fdf65c9ab20886fdd01040bc4ab2afa4ac68f Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 24 Jan 2025 19:51:01 -0500 Subject: [PATCH] Schedule new token frame after handshake complete MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We don't want to schedule the NEW_TOKEN frame until such time as the handshake is complete, otherwise we risk giving a token to validate a future connection to a peer we haven't decided to trust yet Reviewed-by: Matt Caswell Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/26517) --- ssl/quic/quic_channel.c | 10 ++++++++++ ssl/quic/quic_channel_local.h | 6 ++++++ ssl/quic/quic_impl.c | 14 ++++---------- ssl/quic/quic_port.c | 14 +++++++++++--- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index a9b453e69f2..bfefa272c34 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -405,6 +405,7 @@ static void ch_cleanup(QUIC_CHANNEL *ch) OPENSSL_free((char *)ch->terminate_cause.reason); OSSL_ERR_STATE_free(ch->err_state); OPENSSL_free(ch->ack_range_scratch); + OPENSSL_free(ch->pending_new_token); if (ch->on_port_list) { ossl_list_ch_remove(&ch->port->channel_list, ch); @@ -1126,6 +1127,15 @@ static int ch_on_handshake_complete(void *arg) ch->handshake_complete = 1; + if (ch->pending_new_token != NULL) { + ossl_quic_channel_schedule_new_token(ch, + ch->pending_new_token, + ch->pending_new_token_len); + OPENSSL_free(ch->pending_new_token); + ch->pending_new_token = NULL; + ch->pending_new_token_len = 0; + } + if (ch->is_server) { /* * On the server, the handshake is confirmed as soon as it is complete. diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index 63f10412189..6ba6366f4b5 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -60,6 +60,12 @@ struct quic_channel_st { */ unsigned char *local_transport_params; + /* + * Pending new token to send once handshake is complete + */ + uint8_t *pending_new_token; + size_t pending_new_token_len; + /* Our current L4 peer address, if any. */ BIO_ADDR cur_peer_addr; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 1afa4f27a8e..4f99a68934b 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -4815,7 +4815,6 @@ static QUIC_TOKEN *ossl_quic_build_new_token(BIO_ADDR *peer, uint8_t *token, BIO_ADDR_rawaddress(peer, addrptr, NULL); if (token != NULL) memcpy(new_token->token, token, token_len); - return new_token; } @@ -4836,12 +4835,13 @@ int ossl_quic_update_peer_token(SSL_CTX *ctx, BIO_ADDR *peer, ossl_crypto_mutex_lock(c->mutex); old = lh_QUIC_TOKEN_retrieve(c->cache, tok); - if (old != NULL) - lh_QUIC_TOKEN_delete(c->cache, tok); + if (old != NULL) { + lh_QUIC_TOKEN_delete(c->cache, old); + free_quic_token(old); + } lh_QUIC_TOKEN_insert(c->cache, tok); ossl_crypto_mutex_unlock(c->mutex); - free_quic_token(old); return 1; } @@ -4861,11 +4861,6 @@ int ossl_quic_get_peer_token(SSL_CTX *ctx, BIO_ADDR *peer, ossl_crypto_mutex_lock(c->mutex); tok = lh_QUIC_TOKEN_retrieve(c->cache, key); if (tok != NULL) { - if (tok->token_len > *token_len) { - /* allow reuse here */ - tok = NULL; - goto out; - } *token = tok->token; *token_len = tok->token_len; *token_free_ptr = tok; @@ -4873,7 +4868,6 @@ int ossl_quic_get_peer_token(SSL_CTX *ctx, BIO_ADDR *peer, rc = 1; } -out: ossl_crypto_mutex_unlock(c->mutex); free_quic_token(key); return rc; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index f85c5579ef6..e6e2762463f 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -1348,7 +1348,7 @@ static void generate_new_token(QUIC_CHANNEL *ch, BIO_ADDR *peer) QUIC_CONN_ID rscid = { 0 }; QUIC_VALIDATION_TOKEN token; unsigned char buffer[ENCRYPTED_TOKEN_MAX_LEN]; - unsigned char ct_buf[ENCRYPTED_TOKEN_MAX_LEN]; + unsigned char *ct_buf; size_t ct_len; size_t token_buf_len = 0; @@ -1356,6 +1356,10 @@ static void generate_new_token(QUIC_CHANNEL *ch, BIO_ADDR *peer) if (!ch->is_server) return; + ct_buf = OPENSSL_zalloc(ENCRYPTED_TOKEN_MAX_LEN); + if (ct_buf == NULL) + return; + if (!ossl_quic_lcidm_get_unused_cid(ch->port->lcidm, &rscid)) return; @@ -1366,10 +1370,14 @@ static void generate_new_token(QUIC_CHANNEL *ch, BIO_ADDR *peer) || ct_len > ENCRYPTED_TOKEN_MAX_LEN || !encrypt_validation_token(ch->port, buffer, token_buf_len, ct_buf, &ct_len) - || !ossl_assert(ct_len >= QUIC_RETRY_INTEGRITY_TAG_LEN)) + || !ossl_assert(ct_len >= QUIC_RETRY_INTEGRITY_TAG_LEN)) { + OPENSSL_free(ct_buf); return; + } + + ch->pending_new_token = ct_buf; + ch->pending_new_token_len = ct_len; - ossl_quic_channel_schedule_new_token(ch, ct_buf, ct_len); cleanup_validation_token(&token); } -- 2.47.2