From 9c30a4debcdef47fdb056b0bd1cff29882f372d9 Mon Sep 17 00:00:00 2001 From: Vadim Zhestikov Date: Wed, 12 Aug 2026 12:41:54 -0700 Subject: [PATCH] QUIC: rejected CRYPTO frames received in 1-RTT packets If a CRYPTO frame was received after the handshake, ngx_quic_handshake() ran the handshake completion for the second time. With the check added in 6f8c520f4, this is limited to short header packets. Since a client has nothing to send in a CRYPTO frame once the handshake is complete, such frames are now rejected with the "unexpected_message" connection error, as does TLS 1.3 for handshake messages received out of order, and QUIC requires for KeyUpdate. --- src/event/quic/ngx_event_quic_ssl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c index 705f39f6c..259f5525c 100644 --- a/src/event/quic/ngx_event_quic_ssl.c +++ b/src/event/quic/ngx_event_quic_ssl.c @@ -638,6 +638,15 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, return NGX_OK; } + if (c->ssl->handshaked) { + /* QUIC doesn't define post-handshake messages for a client */ + + qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_UNEXPECTED_MESSAGE); + qc->error_reason = "unexpected CRYPTO frame"; + + return NGX_ERROR; + } + ctx = ngx_quic_get_send_ctx(qc, pkt->level); f = &frame->u.crypto;