From e0edd7d0ec2149fd069cec48ff0ba38be3f99a69 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 18 Dec 2024 22:41:12 +0000 Subject: [PATCH] ssl: enforce TLS v1.2 (or better) Enforce TLS v1.2 or better, and ensure that we use the recommended ciphers (intermediate compatibility) from Mozilla. https://wiki.mozilla.org/Security/Server_Side_TLS --- src/libgit2/streams/mbedtls.c | 14 +++++++++----- src/libgit2/streams/openssl.c | 10 +++++++--- src/libgit2/streams/openssl_dynamic.h | 2 ++ src/libgit2/streams/stransport.c | 3 +-- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/libgit2/streams/mbedtls.c b/src/libgit2/streams/mbedtls.c index 37abcdab5..a3839c2ce 100644 --- a/src/libgit2/streams/mbedtls.c +++ b/src/libgit2/streams/mbedtls.c @@ -39,8 +39,8 @@ #undef inline -#define GIT_SSL_DEFAULT_CIPHERS "TLS1-3-AES-128-GCM-SHA256:TLS1-3-AES-256-GCM-SHA384:TLS1-3-CHACHA20-POLY1305-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-128-GCM-SHA256:TLS-RSA-WITH-AES-256-GCM-SHA384:TLS-RSA-WITH-AES-128-CBC-SHA256:TLS-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-128-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA" -#define GIT_SSL_DEFAULT_CIPHERS_COUNT 28 +#define GIT_SSL_DEFAULT_CIPHERS "TLS1-3-AES-128-GCM-SHA256:TLS1-3-AES-256-GCM-SHA384:TLS1-3-CHACHA20-POLY1305-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256" +#define GIT_SSL_DEFAULT_CIPHERS_COUNT 12 static int ciphers_list[GIT_SSL_DEFAULT_CIPHERS_COUNT]; @@ -94,9 +94,13 @@ int git_mbedtls_stream_global_init(void) goto cleanup; } - /* configure TLSv1.1 or better */ -#ifdef MBEDTLS_SSL_MINOR_VERSION_2 - mbedtls_ssl_conf_min_version(&mbedtls_config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); + /* + * Configure TLSv1.2 or better; if the minor version constant isn't + * defined then this version of mbedTLS doesn't support such an old + * version, so we need not do anything. + */ +#ifdef MBEDTLS_SSL_MINOR_VERSION_3 + mbedtls_ssl_conf_min_version(&mbedtls_config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); #endif /* verify_server_cert is responsible for making the check. diff --git a/src/libgit2/streams/openssl.c b/src/libgit2/streams/openssl.c index e5641e0e2..ca64e460b 100644 --- a/src/libgit2/streams/openssl.c +++ b/src/libgit2/streams/openssl.c @@ -40,7 +40,8 @@ extern char *git__ssl_ciphers; SSL_CTX *git__ssl_ctx; -#define GIT_SSL_DEFAULT_CIPHERS "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA" +#define GIT_SSL_DEFAULT_CIPHERS "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305" + static BIO_METHOD *git_stream_bio_method; static int init_bio_method(void); @@ -105,7 +106,10 @@ static void git_openssl_free(void *mem) static int openssl_init(void) { - long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + long ssl_opts = SSL_OP_NO_SSLv2 | + SSL_OP_NO_SSLv3 | + SSL_OP_NO_TLSv1 | + SSL_OP_NO_TLSv1_1; const char *ciphers = git__ssl_ciphers; #ifdef VALGRIND static bool allocators_initialized = false; @@ -136,7 +140,7 @@ static int openssl_init(void) /* * Despite the name SSLv23_method, this is actually a version- * flexible context, which honors the protocol versions - * specified in `ssl_opts`. So we only support TLSv1.0 and + * specified in `ssl_opts`. So we only support TLSv1.2 and * higher. */ if (!(git__ssl_ctx = SSL_CTX_new(SSLv23_method()))) diff --git a/src/libgit2/streams/openssl_dynamic.h b/src/libgit2/streams/openssl_dynamic.h index e59f1f93b..0d7ef0f2a 100644 --- a/src/libgit2/streams/openssl_dynamic.h +++ b/src/libgit2/streams/openssl_dynamic.h @@ -182,6 +182,8 @@ # define SSL_OP_NO_COMPRESSION 0x00020000L # define SSL_OP_NO_SSLv2 0x01000000L # define SSL_OP_NO_SSLv3 0x02000000L +# define SSL_OP_NO_TLSv1 0x04000000L +# define SSL_OP_NO_TLSv1_1 0x10000000L # define SSL_MODE_AUTO_RETRY 0x00000004L diff --git a/src/libgit2/streams/stransport.c b/src/libgit2/streams/stransport.c index 863616dcc..2d4cc55b5 100644 --- a/src/libgit2/streams/stransport.c +++ b/src/libgit2/streams/stransport.c @@ -331,8 +331,7 @@ static int stransport_wrap( if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr || (ret = SSLSetConnection(st->ctx, st)) != noErr || (ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr || - (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr || - (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr || + (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol12)) != noErr || (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) { CFRelease(st->ctx); git__free(st);