diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1946bb083d..fee83c1496 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -907,6 +907,24 @@ include 'filename'
+
+ ssl_ecdh_curve (string)
+
+ ssl_ecdh_curve> configuration parameter
+
+
+
+ Specifies the name of the curve to use in ECDH key exchanges. The
+ default is prime256p1>.
+
+
+
+ The list of available curves can be shown with the command
+ openssl ecparam -list_curves.
+
+
+
+
password_encryption (boolean)
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index 51f3b12bb9..43633e7a31 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
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH)
+#include
+#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 5c39de5a52..f3bf6e0aa2 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 a0f564bb9c..983cae7fda 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)