From 2ff0082e3e6d937a7de469811d70791d287a6255 Mon Sep 17 00:00:00 2001 From: Mikhail Koviazin Date: Fri, 20 Mar 2026 14:09:43 +0100 Subject: [PATCH 1/2] restrict TLS 1.3 ciphersuites to FIPS-approved algorithms SSL_CTX_set_cipher_list() only controls TLS 1.2 and below. TLS 1.3 ciphersuites are a separate namespace controlled by SSL_CTX_set_ciphersuites(), which was never called. This meant all TLS 1.3 ciphersuites were allowed by default, including non-FIPS-approved ones like TLS_CHACHA20_POLY1305_SHA256. Add a new "cipherSuites" parameter (mirroring the existing "cipherList") that calls SSL_CTX_set_ciphersuites(). The default is set to "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256", which are the only two FIPS-approved TLS 1.3 ciphersuites. This can be overridden via the XML config element under openSSL.server/client. The parameter is plumbed through all three SSL context creation paths: SSLManager (general), TLSHandler (native TCP), and PostgreSQLHandler (PostgreSQL wire protocol). --- base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h | 5 +++++ base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h | 7 ++++++- base/poco/NetSSL_OpenSSL/src/Context.cpp | 4 +++- base/poco/NetSSL_OpenSSL/src/SSLManager.cpp | 3 +++ src/Server/PostgreSQLHandler.cpp | 1 + src/Server/TLSHandler.cpp | 1 + 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h b/base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h index 2c56875835e7..c44b915a0a10 100644 --- a/base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h +++ b/base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h @@ -148,6 +148,11 @@ namespace Net /// Specifies the supported ciphers in OpenSSL notation. /// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH". + std::string cipherSuites; + /// Specifies the supported TLSv1.3 ciphersuites in OpenSSL notation. + /// Defaults to "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256" + /// (FIPS-approved ciphersuites only). + std::string dhParamsFile; /// Specifies a file containing Diffie-Hellman parameters. /// If empty, the default parameters are used. diff --git a/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h b/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h index 25dc133fb204..606616167c39 100644 --- a/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h +++ b/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h @@ -78,6 +78,7 @@ namespace Net /// 1..9 /// true|false /// ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH + /// TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384 /// true|false /// /// KeyFileHandler @@ -119,7 +120,9 @@ namespace Net /// will fail if a certificate chain larger than this is encountered. /// - loadDefaultCAFile (boolean): Specifies whether the builtin CA certificates from OpenSSL are used. /// - cipherList (string): Specifies the supported ciphers in OpenSSL notation - /// (e.g. "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"). + /// (e.g. "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"). Only applies to TLSv1.2 and below. + /// - cipherSuites (string): Specifies the supported TLSv1.3 ciphersuites in OpenSSL notation + /// (e.g. "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"). If empty, the library default is used. /// - preferServerCiphers (bool): When choosing a cipher, use the server's preferences instead of the /// client preferences. When not called, the SSL server will always follow the clients /// preferences. When called, the SSL/TLS server will choose following its own @@ -278,6 +281,8 @@ namespace Net static const std::string CFG_CIPHER_LIST; static const std::string CFG_CYPHER_LIST; // for backwards compatibility static const std::string VAL_CIPHER_LIST; + static const std::string CFG_CIPHER_SUITES; + static const std::string VAL_CIPHER_SUITES; static const std::string CFG_PREFER_SERVER_CIPHERS; static const std::string CFG_DELEGATE_HANDLER; static const std::string VAL_DELEGATE_HANDLER; diff --git a/base/poco/NetSSL_OpenSSL/src/Context.cpp b/base/poco/NetSSL_OpenSSL/src/Context.cpp index 6a5aa1af48ab..de6ebf373831 100644 --- a/base/poco/NetSSL_OpenSSL/src/Context.cpp +++ b/base/poco/NetSSL_OpenSSL/src/Context.cpp @@ -42,7 +42,8 @@ Context::Params::Params(): verificationMode(VERIFY_RELAXED), verificationDepth(9), loadDefaultCAs(false), - cipherList("ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH") + cipherList("ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH"), + cipherSuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256") { } @@ -322,6 +323,7 @@ void Context::init(const Params& params) SSL_CTX_set_verify(_pSSLContext, params.verificationMode, &SSLManager::verifyClientCallback); SSL_CTX_set_cipher_list(_pSSLContext, params.cipherList.c_str()); + SSL_CTX_set_ciphersuites(_pSSLContext, params.cipherSuites.c_str()); SSL_CTX_set_verify_depth(_pSSLContext, params.verificationDepth); SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY); SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF); diff --git a/base/poco/NetSSL_OpenSSL/src/SSLManager.cpp b/base/poco/NetSSL_OpenSSL/src/SSLManager.cpp index ae04a9947865..3960c37c51f8 100644 --- a/base/poco/NetSSL_OpenSSL/src/SSLManager.cpp +++ b/base/poco/NetSSL_OpenSSL/src/SSLManager.cpp @@ -42,6 +42,8 @@ const bool SSLManager::VAL_ENABLE_DEFAULT_CA(true); const std::string SSLManager::CFG_CIPHER_LIST("cipherList"); const std::string SSLManager::CFG_CYPHER_LIST("cypherList"); const std::string SSLManager::VAL_CIPHER_LIST("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); +const std::string SSLManager::CFG_CIPHER_SUITES("cipherSuites"); +const std::string SSLManager::VAL_CIPHER_SUITES("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256"); const std::string SSLManager::CFG_PREFER_SERVER_CIPHERS("preferServerCiphers"); const std::string SSLManager::CFG_DELEGATE_HANDLER("privateKeyPassphraseHandler.name"); const std::string SSLManager::VAL_DELEGATE_HANDLER("KeyConsoleHandler"); @@ -275,6 +277,7 @@ void SSLManager::initDefaultContext(bool server) params.loadDefaultCAs = config.getBool(prefix + CFG_ENABLE_DEFAULT_CA, VAL_ENABLE_DEFAULT_CA); params.cipherList = config.getString(prefix + CFG_CIPHER_LIST, VAL_CIPHER_LIST); params.cipherList = config.getString(prefix + CFG_CYPHER_LIST, params.cipherList); // for backwards compatibility + params.cipherSuites = config.getString(prefix + CFG_CIPHER_SUITES, VAL_CIPHER_SUITES); bool requireTLSv1 = config.getBool(prefix + CFG_REQUIRE_TLSV1, false); bool requireTLSv1_1 = config.getBool(prefix + CFG_REQUIRE_TLSV1_1, false); bool requireTLSv1_2 = config.getBool(prefix + CFG_REQUIRE_TLSV1_2, false); diff --git a/src/Server/PostgreSQLHandler.cpp b/src/Server/PostgreSQLHandler.cpp index e07ef9db35d0..9b74017d1b81 100644 --- a/src/Server/PostgreSQLHandler.cpp +++ b/src/Server/PostgreSQLHandler.cpp @@ -90,6 +90,7 @@ PostgreSQLHandler::PostgreSQLHandler( params.cipherList = config.getString(prefix + Poco::Net::SSLManager::CFG_CIPHER_LIST, Poco::Net::SSLManager::VAL_CIPHER_LIST); params.cipherList = config.getString(prefix + Poco::Net::SSLManager::CFG_CYPHER_LIST, params.cipherList); // for backwards compatibility + params.cipherSuites = config.getString(prefix + Poco::Net::SSLManager::CFG_CIPHER_SUITES, Poco::Net::SSLManager::VAL_CIPHER_SUITES); bool require_tlsv1 = config.getBool(prefix + Poco::Net::SSLManager::CFG_REQUIRE_TLSV1, false); bool require_tlsv1_1 = config.getBool(prefix + Poco::Net::SSLManager::CFG_REQUIRE_TLSV1_1, false); diff --git a/src/Server/TLSHandler.cpp b/src/Server/TLSHandler.cpp index b0ed342c2512..96f9d2f06933 100644 --- a/src/Server/TLSHandler.cpp +++ b/src/Server/TLSHandler.cpp @@ -51,6 +51,7 @@ DB::TLSHandler::TLSHandler( params.loadDefaultCAs = config.getBool(prefix + SSLManager::CFG_ENABLE_DEFAULT_CA, SSLManager::VAL_ENABLE_DEFAULT_CA); params.cipherList = config.getString(prefix + SSLManager::CFG_CIPHER_LIST, SSLManager::VAL_CIPHER_LIST); params.cipherList = config.getString(prefix + SSLManager::CFG_CYPHER_LIST, params.cipherList); // for backwards compatibility + params.cipherSuites = config.getString(prefix + SSLManager::CFG_CIPHER_SUITES, SSLManager::VAL_CIPHER_SUITES); bool require_tlsv1 = config.getBool(prefix + SSLManager::CFG_REQUIRE_TLSV1, false); bool require_tlsv1_1 = config.getBool(prefix + SSLManager::CFG_REQUIRE_TLSV1_1, false); From f0ceaebd7e3e531b0d3ee9f86026a41555dcf4ff Mon Sep 17 00:00:00 2001 From: Mikhail Koviazin Date: Fri, 20 Mar 2026 14:22:28 +0100 Subject: [PATCH 2/2] fixed a comment --- base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h b/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h index 606616167c39..01d937952847 100644 --- a/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h +++ b/base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h @@ -121,8 +121,8 @@ namespace Net /// - loadDefaultCAFile (boolean): Specifies whether the builtin CA certificates from OpenSSL are used. /// - cipherList (string): Specifies the supported ciphers in OpenSSL notation /// (e.g. "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"). Only applies to TLSv1.2 and below. - /// - cipherSuites (string): Specifies the supported TLSv1.3 ciphersuites in OpenSSL notation - /// (e.g. "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"). If empty, the library default is used. + /// - cipherSuites (string): Specifies the supported TLSv1.3 ciphersuites in OpenSSL notation. + /// Defaults to "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256" (FIPS-approved ciphersuites only). /// - preferServerCiphers (bool): When choosing a cipher, use the server's preferences instead of the /// client preferences. When not called, the SSL server will always follow the clients /// preferences. When called, the SSL/TLS server will choose following its own