]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: ssl/clienthello: ECDSA with ssl-max-ver TLSv1.2 and no ECDSA ciphers
authorWilliam Lallemand <wlallemand@haproxy.com>
Thu, 12 Jun 2025 14:50:08 +0000 (16:50 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Wed, 25 Jun 2025 12:25:14 +0000 (14:25 +0200)
Patch 23093c72 ("BUG/MINOR: ssl: suboptimal certificate selection with TLSv1.3
and dual ECDSA/RSA") introduced a problem when prioritizing the ECDSA
with TLSv1.3.

Indeed, when a client with TLSv1.3 capabilities announce a list of
ECDSA sigalgs, a list of TLSv1.3 ciphersuites compatible with ECDSA,
but only RSA ciphers for TLSv1.2, and haproxy is configured to a
ssl-max-ver TLSv1.2, then haproxy would use the ECDSA keypair, but the
client wouldn't be able to process it because TLSv1.2 was negociated.

HAProxy would be configured like that:

  ssl-default-bind-options ssl-max-ver TLSv1.2

And a client could be used this way:

  openssl s_client -connect localhost:8443 -cipher ECDHE-ECDSA-AES128-GCM-SHA256 \
          -ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

This patch fixes the issue by checking if TLSv1.3 was configured before
allowing ECDSA is an TLSv1.3 ciphersuite is in the list.

This could be backported where 23093c72 ("BUG/MINOR: ssl: suboptimal
certificate selection with TLSv1.3 and dual ECDSA/RSA") was backported.
However this is quite sensible and we should wait a bit before the
backport.

This should fix issue #2988

src/ssl_clienthello.c

index ca0d6fb276958e2c2c8ad10be428261c19bf9751..9d2f4509357c985364d022a621918710dcef72a0 100644 (file)
@@ -396,8 +396,16 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
                        if (cipher_id == SSL3_CK_SCSV || cipher_id == SSL3_CK_FALLBACK_SCSV)
                                continue;
 
-                       if (SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa
-                           || SSL_CIPHER_get_auth_nid(cipher) == NID_auth_any) {
+                       if (SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
+                               has_ecdsa_sig = 1;
+                               break;
+                       }
+                       if (SSL_CIPHER_get_auth_nid(cipher) == NID_auth_any &&
+                           s->ssl_conf.ssl_methods.max >= CONF_TLSV13) {
+                               /* Checking for TLSv1.3 ciphersuites require to check that we allow TLSv1.3, otherwise it would
+                                * chose an ECDSA cipher because of the TLS13 ciphersuites, but the TLS12 ciphers could
+                                * lack ECDSA capabilities.
+                                */
                                has_ecdsa_sig = 1;
                                break;
                        }