diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 1946bb083d92f453e242aedf764747d2dc95ee6d..fee83c1496b0a742bf1dfcfbbca83f662be0daa4 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -907,6 +907,24 @@ include 'filename' </listitem> </varlistentry> + <varlistentry id="guc-ssl-ecdh-curve" xreflabel="ssl_ecdh_curve"> + <term><varname>ssl_ecdh_curve</varname> (<type>string</type>)</term> + <indexterm> + <primary><varname>ssl_ecdh_curve</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Specifies the name of the curve to use in ECDH key exchanges. The + default is <literal>prime256p1</>. + </para> + + <para> + The list of available curves can be shown with the command + <literal>openssl ecparam -list_curves</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-password-encryption" xreflabel="password_encryption"> <term><varname>password_encryption</varname> (<type>boolean</type>)</term> <indexterm> diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 51f3b12bb97e6c4cfc21999fcce276b23ed5f63d..43633e7a316da4c2f7ffba41d98d32e010b1ba86 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -69,6 +69,9 @@ #if SSLEAY_VERSION_NUMBER >= 0x0907000L #include <openssl/conf.h> #endif +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH) +#include <openssl/ec.h> +#endif #endif /* USE_SSL */ #include "libpq/libpq.h" @@ -112,6 +115,9 @@ static bool ssl_loaded_verify_locations = false; /* GUC variable controlling SSL cipher list */ char *SSLCipherSuites = NULL; +/* GUC variable for default ECHD curve. */ +char *SSLECDHCurve; + /* GUC variable: if false, prefer client ciphers */ bool SSLPreferServerCiphers; @@ -774,6 +780,31 @@ info_cb(const SSL *ssl, int type, int args) } } +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH) +static void +initialize_ecdh(void) +{ + EC_KEY *ecdh; + int nid; + + nid = OBJ_sn2nid(SSLECDHCurve); + if (!nid) + ereport(FATAL, + (errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve))); + + ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) + ereport(FATAL, + (errmsg("ECDH: could not create key"))); + + SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_tmp_ecdh(SSL_context, ecdh); + EC_KEY_free(ecdh); +} +#else +#define initialize_ecdh() +#endif + /* * Initialize global SSL context. */ @@ -853,6 +884,9 @@ initialize_SSL(void) SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2); + /* set up ephemeral ECDH keys */ + initialize_ecdh(); + /* set up the allowed cipher list */ if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5c39de5a522e8a87e44a42cc0bbfa61bd3003570..f3bf6e0aa2fce7e66a775beeed8aa0ee15ac291f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -127,6 +127,7 @@ extern char *temp_tablespaces; extern bool ignore_checksum_failure; extern bool synchronize_seqscans; extern char *SSLCipherSuites; +extern char *SSLECDHCurve; extern bool SSLPreferServerCiphers; #ifdef TRACE_SORT @@ -3150,6 +3151,21 @@ static struct config_string ConfigureNamesString[] = NULL, NULL, NULL }, + { + {"ssl_ecdh_curve", PGC_POSTMASTER, CONN_AUTH_SECURITY, + gettext_noop("Sets the curve to use for ECDH."), + NULL, + GUC_SUPERUSER_ONLY + }, + &SSLECDHCurve, +#ifdef USE_SSL + "prime256v1", +#else + "none", +#endif + NULL, NULL, NULL + }, + { {"application_name", PGC_USERSET, LOGGING_WHAT, gettext_noop("Sets the application name to be reported in statistics and logs."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index a0f564bb9cf6634f40a0bbf92344d46c71dbfec4..983cae7fda24c2656937cc6b942ac52abbc12fa5 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -82,6 +82,7 @@ #ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers # (change requires restart) #ssl_prefer_server_ciphers = on # (change requires restart) +#ssl_ecdh_curve = 'prime256v1' # (change requires restart) #ssl_renegotiation_limit = 512MB # amount of data between renegotiations #ssl_cert_file = 'server.crt' # (change requires restart) #ssl_key_file = 'server.key' # (change requires restart)