From: William Lallemand Date: Thu, 13 Jun 2024 17:11:52 +0000 (+0200) Subject: MEDIUM: ssl: support for ECDA+RSA certificate selection with AWS-LC X-Git-Tag: v3.1-dev1~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7120c77b14133d5d9eb94c35bff9ccca45586a6b;p=thirdparty%2Fhaproxy.git MEDIUM: ssl: support for ECDA+RSA certificate selection with AWS-LC AWS-LC does not support the SSL_CTX_set_client_hello_cb() function from OpenSSL which allows to analyze ciphers and signatures algorithm of the ClientHello. However it supports the SSL_CTX_set_select_certificate_cb() which allows the same thing but was the implementation from the boringSSL side. This patch uses the SSL_CTX_set_select_certificate_cb() as well as the SSL_early_callback_ctx_extension_get() function to get the signature algorithms. This was successfully tested with openssl s_client as well as testssl.sh. This should allow to enable more reg-tests that depend on certificate selection. Require at least AWS-LC 1.22.0. --- diff --git a/include/haproxy/openssl-compat.h b/include/haproxy/openssl-compat.h index d145fb4852..66c30ff091 100644 --- a/include/haproxy/openssl-compat.h +++ b/include/haproxy/openssl-compat.h @@ -79,7 +79,7 @@ #define HAVE_ASN1_TIME_TO_TM #endif -#if (defined(SSL_CLIENT_HELLO_CB) || defined(OPENSSL_IS_BORINGSSL)) +#if (defined(SSL_CLIENT_HELLO_CB) || defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC)) #define HAVE_SSL_CLIENT_HELLO_CB #endif diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h index 6f9d439726..c846fe0342 100644 --- a/include/haproxy/ssl_sock.h +++ b/include/haproxy/ssl_sock.h @@ -104,7 +104,7 @@ void ssl_unload_providers(void); #ifdef HAVE_SSL_CLIENT_HELLO_CB int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv); -# ifdef OPENSSL_IS_BORINGSSL +# if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx); # else /* ! OPENSSL_IS_BORINGSSL */ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg); diff --git a/src/quic_ssl.c b/src/quic_ssl.c index 66eb68eb2b..0b27c7403b 100644 --- a/src/quic_ssl.c +++ b/src/quic_ssl.c @@ -459,7 +459,10 @@ int ssl_quic_initial_ctx(struct bind_conf *bind_conf) } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -# if defined(HAVE_SSL_CLIENT_HELLO_CB) +# if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) + SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); +# elif defined(HAVE_SSL_CLIENT_HELLO_CB) SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); # else /* ! HAVE_SSL_CLIENT_HELLO_CB */ diff --git a/src/ssl_clienthello.c b/src/ssl_clienthello.c index 23719558e9..4044a67204 100644 --- a/src/ssl_clienthello.c +++ b/src/ssl_clienthello.c @@ -131,7 +131,7 @@ int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv) return SSL_TLSEXT_ERR_NOACK; } -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx) { SSL *ssl = ctx->ssl; @@ -170,7 +170,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) #ifdef USE_QUIC if (qc) { /* Look for the QUIC transport parameters. */ -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) if (!SSL_early_callback_ctx_extension_get(ctx, qc->tps_tls_ext, &extension_data, &extension_len)) #else @@ -182,7 +182,9 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) * <*al>, this has as side effect to generate another TLS alert * which would be set after calling quic_set_tls_alert(). */ +#if !defined(OPENSSL_IS_BORINGSSL) && !defined(USE_OPENSSL_AWSLC) *al = SSL_AD_MISSING_EXTENSION; +#endif quic_set_tls_alert(qc, SSL_AD_MISSING_EXTENSION); return 0; } @@ -197,7 +199,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) if (s->ssl_conf.early_data) allow_early = 1; -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) { #else @@ -251,7 +253,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) } /* extract/check clientHello information */ -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) { #else if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) { @@ -296,7 +298,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) ha_ciphers = SSL_get_ciphers(ssl); has_ecdsa_sig = 0; -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) len = ctx->cipher_suites_len; cipher_suites = ctx->cipher_suites; #else @@ -305,7 +307,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) if (len % 2 != 0) goto abort; for (; len != 0; len -= 2, cipher_suites += 2) { -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1]; cipher = SSL_get_cipher_by_value(cipher_suite); #else @@ -392,7 +394,7 @@ sni_lookup: /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */ if (conn) conn->err_code = CO_ER_SSL_HANDSHAKE; -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) return ssl_select_cert_error; #else *al = SSL_AD_UNRECOGNIZED_NAME; @@ -400,7 +402,7 @@ sni_lookup: #endif allow_early: -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) if (allow_early) SSL_set_early_data_enabled(ssl, 1); #else diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 87ee42f1a7..e5eb746cf5 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -3440,7 +3440,7 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) SSL_CTX_set_timeout(ctx, global_ssl.life_time); #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -# ifdef OPENSSL_IS_BORINGSSL +# if defined(OPENSSL_IS_BORINGSSL) || defined(USE_OPENSSL_AWSLC) SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); # elif defined(HAVE_SSL_CLIENT_HELLO_CB)