Support configuring TLSv1.3 cipher suites

The ssl_ciphers GUC can only set cipher suites for TLSv1.2, and lower,
connections. For TLSv1.3 connections a different OpenSSL API must be
used.  This adds a new GUC, ssl_tls13_ciphers, which can be used to
configure a colon separated list of cipher suites to support when
performing a TLSv1.3 handshake.

Original patch by Erica Zhang with additional hacking by me.

Author: Erica Zhang <ericazhangy2021@qq.com>
Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://postgr.es/m/tencent_063F89FA72CCF2E48A0DF5338841988E9809@qq.com
This commit is contained in:
Daniel Gustafsson 2024-10-24 15:20:32 +02:00
parent 3d1ef3a15c
commit 45188c2ea2
7 changed files with 66 additions and 15 deletions

View File

@ -1340,6 +1340,28 @@ include_dir 'conf.d'
</listitem>
</varlistentry>
<varlistentry id="guc-ssl-tls13-ciphers" xreflabel="ssl_tls13_ciphers">
<term><varname>ssl_tls13_ciphers</varname> (<type>string</type>)
<indexterm>
<primary><varname>ssl_tls13_ciphers</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Specifies a list of cipher suites that are allowed by connections using
<acronym>TLS</acronym> version 1.3. Multiple cipher suites can be
specified by using a colon separated list. If left blank, the default
set of cipher suites in <productname>OpenSSL</productname> will be used.
</para>
<para>
This parameter can only be set in the
<filename>postgresql.conf</filename> file or on the server command
line.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-ssl-ciphers" xreflabel="ssl_ciphers">
<term><varname>ssl_ciphers</varname> (<type>string</type>)
<indexterm>
@ -1348,15 +1370,13 @@ include_dir 'conf.d'
</term>
<listitem>
<para>
Specifies a list of <acronym>SSL</acronym> cipher suites that are
allowed to be used by SSL connections. See the
<citerefentry><refentrytitle>ciphers</refentrytitle></citerefentry>
Specifies a list of <acronym>SSL</acronym> ciphers that are allowed by
connections using TLS version 1.2 and lower, see
<xref linkend="guc-ssl-tls13-ciphers"/> for TLS version 1.3 connections. See
the <citerefentry><refentrytitle>ciphers</refentrytitle></citerefentry>
manual page in the <productname>OpenSSL</productname> package for the
syntax of this setting and a list of supported values. Only
connections using TLS version 1.2 and lower are affected. There is
currently no setting that controls the cipher choices used by TLS
version 1.3 connections. The default value is
<literal>HIGH:MEDIUM:+3DES:!aNULL</literal>. The default is usually a
syntax of this setting and a list of supported values. The default value
is <literal>HIGH:MEDIUM:+3DES:!aNULL</literal>. The default is usually a
reasonable choice unless you have specific security requirements.
</para>

View File

@ -288,15 +288,31 @@ be_tls_init(bool isServerStart)
if (!initialize_ecdh(context, isServerStart))
goto error;
/* set up the allowed cipher list */
if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1)
/* set up the allowed cipher list for TLSv1.2 and below */
if (SSL_CTX_set_cipher_list(context, SSLCipherList) != 1)
{
ereport(isServerStart ? FATAL : LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("could not set the cipher list (no valid ciphers available)")));
errmsg("could not set the TLSv1.2 cipher list (no valid ciphers available)")));
goto error;
}
/*
* Set up the allowed cipher suites for TLSv1.3. If the GUC is an empty
* string we leave the allowed suites to be the OpenSSL default value.
*/
if (SSLCipherSuites[0])
{
/* set up the allowed cipher suites */
if (SSL_CTX_set_ciphersuites(context, SSLCipherSuites) != 1)
{
ereport(isServerStart ? FATAL : LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("could not set the TLSv1.3 cipher suites (no valid ciphers available)")));
goto error;
}
}
/* Let server choose order */
if (SSLPreferServerCiphers)
SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);

View File

@ -49,6 +49,7 @@ bool ssl_loaded_verify_locations = false;
/* GUC variable controlling SSL cipher list */
char *SSLCipherSuites = NULL;
char *SSLCipherList = NULL;
/* GUC variable for default ECHD curve. */
char *SSLECDHCurve;

View File

@ -4641,12 +4641,23 @@ struct config_string ConfigureNamesString[] =
},
{
{"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
gettext_noop("Sets the list of allowed SSL ciphers."),
{"ssl_tls13_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
gettext_noop("Sets the list of allowed TLSv1.3 cipher suites (leave blank for default)."),
NULL,
GUC_SUPERUSER_ONLY
},
&SSLCipherSuites,
"",
NULL, NULL, NULL
},
{
{"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
gettext_noop("Sets the list of allowed TLSv1.2 (and lower) ciphers."),
NULL,
GUC_SUPERUSER_ONLY
},
&SSLCipherList,
#ifdef USE_OPENSSL
"HIGH:MEDIUM:+3DES:!aNULL",
#else

View File

@ -110,7 +110,8 @@
#ssl_crl_file = ''
#ssl_crl_dir = ''
#ssl_key_file = 'server.key'
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed TLSv1.2 ciphers
#ssl_tls13_ciphers = '' # allowed TLSv1.3 cipher suites, blank for default
#ssl_prefer_server_ciphers = on
#ssl_groups = 'prime256v1'
#ssl_min_protocol_version = 'TLSv1.2'

View File

@ -118,6 +118,7 @@ extern ssize_t secure_open_gssapi(Port *port);
/* GUCs */
extern PGDLLIMPORT char *SSLCipherSuites;
extern PGDLLIMPORT char *SSLCipherList;
extern PGDLLIMPORT char *SSLECDHCurve;
extern PGDLLIMPORT bool SSLPreferServerCiphers;
extern PGDLLIMPORT int ssl_min_protocol_version;

View File

@ -300,8 +300,9 @@ sub switch_server_cert
ok(unlink($node->data_dir . '/sslconfig.conf'));
$node->append_conf('sslconfig.conf', "ssl=on");
$node->append_conf('sslconfig.conf', $backend->set_server_cert(\%params));
# use lists of ECDH curves for syntax testing
# use lists of ECDH curves and cipher suites for syntax testing
$node->append_conf('sslconfig.conf', 'ssl_groups=prime256v1:secp521r1');
$node->append_conf('sslconfig.conf', 'ssl_tls13_ciphers=TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256');
$node->append_conf('sslconfig.conf',
"ssl_passphrase_command='" . $params{passphrase_cmd} . "'")