From 9c37bd7bfff6da30b556fa0aad2bbb599ba50aec Mon Sep 17 00:00:00 2001 From: McLeodD <124275164+McLeodD@users.noreply.github.com> Date: Wed, 20 Mar 2024 06:24:51 +0100 Subject: [PATCH] UtilitySSL: Add support of TLS 1.3 (#451) --- src/C++/SessionSettings.h | 19 +++++++++++++++++++ src/C++/UtilitySSL.cpp | 35 ++++++++++++++++++++++++++++++++++- src/C++/UtilitySSL.h | 12 +++++++++--- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/C++/SessionSettings.h b/src/C++/SessionSettings.h index c58f11583..4e00d8b68 100644 --- a/src/C++/SessionSettings.h +++ b/src/C++/SessionSettings.h @@ -188,6 +188,9 @@ const char CERTIFICATE_VERIFY_LEVEL[] = "CertificateVerifyLevel"; */ const char SSL_PROTOCOL[] = "SSLProtocol"; /* +# DISCLAIMER: This setting only work for TLSv1.2 and below +# see: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_cipher_list.html +# # This complex directive uses a colon-separated cipher-spec string consisting # of OpenSSL cipher specifications to configure the Cipher Suite the client is # permitted to negotiate in the SSL handshake phase. Notice that this directive @@ -217,6 +220,22 @@ const char SSL_PROTOCOL[] = "SSLProtocol"; # Example: RC4+RSA:+HIGH: */ const char SSL_CIPHER_SUITE[] = "SSLCipherSuite"; +/* +# DISCLAIMER: This setting only work for TLSv1.3 and upper +# see: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_ciphersuites.html +# +# This is a simple colon (":") separated list of TLSv1.3 ciphersuite names in +# order of preference. Valid TLSv1.3 ciphersuite names are: +# TLS_AES_128_GCM_SHA256 +# TLS_AES_256_GCM_SHA384 +# TLS_CHACHA20_POLY1305_SHA256 +# TLS_AES_128_CCM_SHA256 +# TLS_AES_128_CCM_8_SHA256 +# +# An empty list is permissible. The default value for the this setting is: +# "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" +*/ +const char TLS_CIPHER_SUITES[] = "TLSCipherSuites"; /// Container for setting dictionaries mapped to sessions. diff --git a/src/C++/UtilitySSL.cpp b/src/C++/UtilitySSL.cpp index f95adc8b3..ebaa116b4 100644 --- a/src/C++/UtilitySSL.cpp +++ b/src/C++/UtilitySSL.cpp @@ -997,6 +997,13 @@ long protocolOptions(const char *opt) thisopt = SSL_PROTOCOL_TLSV1_2; w += 7 /* strlen("TLSv1_2") */; } +#if (OPENSSL_VERSION_NUMBER >= 0x1010100FL) + else if (!strncasecmp(w, "TLSv1_3", 7 /* strlen("TLSv1_3") */)) + { + thisopt = SSL_PROTOCOL_TLSV1_3; + w += 7 /* strlen("TLSv1_3") */; + } +#endif else if (!strncasecmp(w, "TLSv1", 5 /* strlen("TLSv1") */)) { thisopt = SSL_PROTOCOL_TLSV1; @@ -1041,6 +1048,10 @@ void setCtxOptions(SSL_CTX *ctx, long options) SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1); if (!(options & SSL_PROTOCOL_TLSV1_2)) SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2); +#if (OPENSSL_VERSION_NUMBER >= 0x1010100FL) + if (!(options & SSL_PROTOCOL_TLSV1_3)) + SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_3); +#endif } int enable_DH_ECDH(SSL_CTX *ctx, const char *certFile) @@ -1148,6 +1159,28 @@ SSL_CTX *createSSLContext(bool server, const SessionSettings &settings, } } + if (settings.get().has(TLSCipherSuites)) + { + std::string strCipherSuites = settings.get().getString(TLSCipherSuites); + +#if (OPENSSL_VERSION_NUMBER >= 0x1010100FL) + if (!strCipherSuites.empty() && + !SSL_CTX_set_ciphersuites(ctx, strCipherSuites.c_str())) + { + errStr.append("Unable to configure permitted TLS ciphersuites"); + SSL_CTX_free(ctx); + return 0; + } +#else + if (!strCipherSuites.empty()) + { + errStr.append("Unable to configure TLS ciphersuites (OpenSSl < 1.1.1)"); + SSL_CTX_free(ctx); + return 0; + } +#endif + } + return ctx; } @@ -1309,7 +1342,7 @@ bool loadSSLCert(SSL_CTX *ctx, bool server, const SessionSettings &settings, return false; } break; - + case SSL_ALGO_EC: log->onEvent("Configuring EC client private key"); if (SSL_CTX_use_PrivateKey(ctx, privateKey) <= 0) diff --git a/src/C++/UtilitySSL.h b/src/C++/UtilitySSL.h index 363366123..fda65f6ab 100644 --- a/src/C++/UtilitySSL.h +++ b/src/C++/UtilitySSL.h @@ -225,9 +225,15 @@ int setSocketNonBlocking(socket_handle pSocket); #define SSL_PROTOCOL_TLSV1 (1 << 2) #define SSL_PROTOCOL_TLSV1_1 (1 << 3) #define SSL_PROTOCOL_TLSV1_2 (1 << 4) -#define SSL_PROTOCOL_ALL \ - (SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | \ - SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2) +#if (OPENSSL_VERSION_NUMBER >= 0x1010100FL) +# define SSL_PROTOCOL_TLSV1_3 (1 << 5) +# define SSL_PROTOCOL_ALL \ + (SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | \ + SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | SSL_PROTOCOL_TLSV1_3) +#else +# define SSL_PROTOCOL_ALL \ + (SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | \ + SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2) typedef enum { SSL_CLIENT_VERIFY_NONE = 0,