[PATCH 3 of 8] QUIC: prevented output of ACK frame when discarding handshake keys

Sergey Kandaurov pluknet at nginx.com
Thu Sep 7 15:13:55 UTC 2023


# HG changeset patch
# User Sergey Kandaurov <pluknet at nginx.com>
# Date 1694041354 -14400
#      Thu Sep 07 03:02:34 2023 +0400
# Node ID b05feba278a8b766cddd4cc35d73ff43e8d77092
# Parent  02c86eac80c907adb7790c79ac6892afabcee5f4
QUIC: prevented output of ACK frame when discarding handshake keys.

Previously, ACK frames were generated to acknowledge the Handshake packet
that carries remaining CRYPTO payload used to complete the TLS handshake.
At the server, when the handshake is complete, it is considered confirmed,
and to meet the RFC 9001 specification, handshake keys must be discarded.
This includes cleaning up all stale frames from the send queue that might
be generated prior to discarding the keys, but this doesn't apply to ACK
frames: ACK generation happens late in packet processing, after the keys
could have been discarded, so this needs a special treatment.

diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c
--- a/src/event/quic/ngx_event_quic_ssl.c
+++ b/src/event/quic/ngx_event_quic_ssl.c
@@ -44,7 +44,7 @@ static int ngx_quic_flush_flight(ngx_ssl
 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
     enum ssl_encryption_level_t level, uint8_t alert);
 static ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
-    enum ssl_encryption_level_t level);
+    ngx_quic_header_t *pkt);
 
 
 #if (NGX_QUIC_BORINGSSL_API)
@@ -355,7 +355,7 @@ ngx_quic_handle_crypto_frame(ngx_connect
     }
 
     if (f->offset == ctx->crypto.offset) {
-        if (ngx_quic_crypto_input(c, frame->data, pkt->level) != NGX_OK) {
+        if (ngx_quic_crypto_input(c, frame->data, pkt) != NGX_OK) {
             return NGX_ERROR;
         }
 
@@ -373,7 +373,7 @@ ngx_quic_handle_crypto_frame(ngx_connect
     cl = ngx_quic_read_buffer(c, &ctx->crypto, (uint64_t) -1);
 
     if (cl) {
-        if (ngx_quic_crypto_input(c, cl, pkt->level) != NGX_OK) {
+        if (ngx_quic_crypto_input(c, cl, pkt) != NGX_OK) {
             return NGX_ERROR;
         }
 
@@ -386,7 +386,7 @@ ngx_quic_handle_crypto_frame(ngx_connect
 
 static ngx_int_t
 ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
-    enum ssl_encryption_level_t level)
+    ngx_quic_header_t *pkt)
 {
     int                     n, sslerr;
     ngx_buf_t              *b;
@@ -402,7 +402,9 @@ ngx_quic_crypto_input(ngx_connection_t *
     for (cl = data; cl; cl = cl->next) {
         b = cl->buf;
 
-        if (!SSL_provide_quic_data(ssl_conn, level, b->pos, b->last - b->pos)) {
+        if (!SSL_provide_quic_data(ssl_conn, pkt->level,
+                                   b->pos, b->last - b->pos))
+        {
             ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
                           "SSL_provide_quic_data() failed");
             return NGX_ERROR;
@@ -482,6 +484,9 @@ ngx_quic_crypto_input(ngx_connection_t *
      */
     ngx_quic_discard_ctx(c, ssl_encryption_handshake);
 
+    /* no need to ack the Handshake packet that brought us there */
+    pkt->need_ack = 0;
+
     ngx_quic_discover_path_mtu(c, qc->path);
 
     /* start accepting clients on negotiated number of server ids */


More information about the nginx-devel mailing list