From: Hugo Landau Date: Tue, 25 Jul 2023 10:32:25 +0000 (+0100) Subject: QUIC QRX: Don't process 1-RTT packets until handshake is complete X-Git-Tag: openssl-3.2.0-alpha1~282 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2a6f1f2f6e321abe6deb2ce89084ece4aa50b3de;p=thirdparty%2Fopenssl.git QUIC QRX: Don't process 1-RTT packets until handshake is complete Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21547) --- diff --git a/include/internal/quic_record_rx.h b/include/internal/quic_record_rx.h index 19545c3e3a1..ed5cdefb2f9 100644 --- a/include/internal/quic_record_rx.h +++ b/include/internal/quic_record_rx.h @@ -338,6 +338,17 @@ int ossl_qrx_set_late_validation_cb(OSSL_QRX *qrx, */ void ossl_qrx_inject_urxe(OSSL_QRX *qrx, QUIC_URXE *e); +/* + * Decryption of 1-RTT packets must be explicitly enabled by calling this + * function. This is to comply with the requirement that we not process 1-RTT + * packets until the handshake is complete, even if we already have 1-RTT + * secrets. Even if a 1-RTT secret is provisioned for the QRX, incoming 1-RTT + * packets will be handled as though no key is available until this function is + * called. Calling this function will then requeue any such deferred packets for + * processing. + */ +void ossl_qrx_allow_1rtt_processing(OSSL_QRX *qrx); + /* * Key Update (RX) * =============== diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index fa9866bdde2..615fef48a45 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -951,6 +951,9 @@ static int ch_on_handshake_complete(void *arg) OPENSSL_free(ch->local_transport_params); ch->local_transport_params = NULL; + /* Tell the QRX it can now process 1-RTT packets. */ + ossl_qrx_allow_1rtt_processing(ch->qrx); + /* Tell TXP the handshake is complete. */ ossl_quic_tx_packetiser_notify_handshake_complete(ch->txp); diff --git a/ssl/quic/quic_record_rx.c b/ssl/quic/quic_record_rx.c index 74693900cff..feb32d92725 100644 --- a/ssl/quic/quic_record_rx.c +++ b/ssl/quic/quic_record_rx.c @@ -158,6 +158,9 @@ struct ossl_qrx_st { /* Initial key phase. For debugging use only; always 0 in real use. */ unsigned char init_key_phase_bit; + /* Are we allowed to process 1-RTT packets yet? */ + unsigned char allow_1rtt; + /* Message callback related arguments */ ossl_msg_cb msg_callback; void *msg_callback_arg; @@ -883,6 +886,13 @@ static int qrx_process_pkt(OSSL_QRX *qrx, QUIC_URXE *urxe, switch (ossl_qrl_enc_level_set_have_el(&qrx->el_set, enc_level)) { case 1: /* We have keys. */ + if (enc_level == QUIC_ENC_LEVEL_1RTT && !qrx->allow_1rtt) + /* + * But we cannot process 1-RTT packets until the handshake is + * completed (RFC 9000 s. 5.7). + */ + goto cannot_decrypt; + break; case 0: /* No keys yet. */ @@ -1314,6 +1324,15 @@ uint64_t ossl_qrx_get_max_forged_pkt_count(OSSL_QRX *qrx, : ossl_qrl_get_suite_max_forged_pkt(el->suite_id); } +void ossl_qrx_allow_1rtt_processing(OSSL_QRX *qrx) +{ + if (qrx->allow_1rtt) + return; + + qrx->allow_1rtt = 1; + qrx_requeue_deferred(qrx); +} + void ossl_qrx_set_msg_callback(OSSL_QRX *qrx, ossl_msg_cb msg_callback, SSL *msg_callback_ssl) { diff --git a/test/quic_record_test.c b/test/quic_record_test.c index d2b18882c5b..ef0aa9bd623 100644 --- a/test/quic_record_test.c +++ b/test/quic_record_test.c @@ -1744,6 +1744,7 @@ static int rx_state_ensure(struct rx_state *s) && !TEST_ptr(s->qrx = ossl_qrx_new(&s->args))) return 0; + ossl_qrx_allow_1rtt_processing(s->qrx); return 1; }