]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: OpenSSL 3.5 trick to support 0-RTT
authorFrederic Lecaille <flecaille@haproxy.com>
Mon, 19 May 2025 15:39:58 +0000 (17:39 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Tue, 20 May 2025 13:00:06 +0000 (15:00 +0200)
For an unidentified reason, SSL_do_hanshake() succeeds at its first call when 0-RTT
is enabled for the connection. This behavior looks very similar by the one encountered
by AWS-LC stack. That said, it was documented by AWS-LC. This issue leads the
connection to stop sending handshake packets after having release the handshake
encryption level. In fact, no handshake packets could even been sent leading
the handshake to always fail.

To fix this, this patch simulates a "handshake in progress" state waiting
for the application level read secret to be established by the TLS stack.
This may happen only after the QUIC listener has completed/confirmed the handshake
upon handshake CRYPTO data receipt from the peer.

src/quic_ssl.c

index 17d8493a3d297139b509c5928136a7b9754b101c..06075ef312802e6533fe97de91bfcfc3b9f5aba3 100644 (file)
@@ -874,7 +874,27 @@ static int qc_ssl_provide_quic_data(struct ncbuf *ncbuf,
                }
 #endif
 
+#ifndef HAVE_OPENSSL_QUIC
                TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
+#else
+               /* Hack to support O-RTT with the OpenSSL 3.5 QUIC API.
+                * SSL_do_handshake() succeeds at the first call. Why? |-(
+                * This prevents the handshake CRYPTO data to be sent.
+                * To overcome this, ensure one does not consider the handshake is
+                * successful if the read application level secrets have not been
+                * provided by the stack. This happens after having received the peer
+                * handshake level CRYPTO data which are validated by the TLS stack.
+                */
+               if (qc->li->bind_conf->ssl_conf.early_data &&
+                   (!qc->ael || !qc->ael->tls_ctx.rx.secret)) {
+                       TRACE_PROTO("SSL handshake in progress",
+                                   QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
+                       goto out;
+               }
+               else {
+                       TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
+               }
+#endif
 
                /* Check the alpn could be negotiated */
                if (!qc->app_ops) {