From fc47df5b3333e23c16b8c5cc5e6a49079022512f Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Wed, 3 Jul 2024 17:49:12 +0200
Subject: [PATCH v4 1/2] Support multiple ECDH curves

---
 doc/src/sgml/config.sgml              |  1 +
 src/backend/libpq/be-secure-openssl.c | 22 +++-------------------
 src/backend/utils/misc/guc_tables.c   |  4 ++--
 src/test/ssl/t/SSL/Server.pm          |  3 +++
 4 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index b14c5d81a1..65b4d38470 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1462,6 +1462,7 @@ include_dir 'conf.d'
        <para>
         Specifies the name of the curve to use in <acronym>ECDH</acronym> key
         exchange.  It needs to be supported by all clients that connect.
+        Multiple curves can be specified by using a colon-separated list.
         It does not need to be the same curve used by the server's Elliptic
         Curve key.
         This parameter can only be set in the <filename>postgresql.conf</filename>
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 387f30cdaa..5c80739fd1 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -1403,30 +1403,14 @@ static bool
 initialize_ecdh(SSL_CTX *context, bool isServerStart)
 {
 #ifndef OPENSSL_NO_ECDH
-	EC_KEY	   *ecdh;
-	int			nid;
-
-	nid = OBJ_sn2nid(SSLECDHCurve);
-	if (!nid)
+	if (SSL_CTX_set1_groups_list(context, SSLECDHCurve) != 1)
 	{
 		ereport(isServerStart ? FATAL : LOG,
 				(errcode(ERRCODE_CONFIG_FILE_ERROR),
-				 errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
-		return false;
-	}
-
-	ecdh = EC_KEY_new_by_curve_name(nid);
-	if (!ecdh)
-	{
-		ereport(isServerStart ? FATAL : LOG,
-				(errcode(ERRCODE_CONFIG_FILE_ERROR),
-				 errmsg("ECDH: could not create key")));
+				 errmsg("ECDH: failed to set curve names: %s",
+						SSLerrmessage(ERR_get_error()))));
 		return false;
 	}
-
-	SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
-	SSL_CTX_set_tmp_ecdh(context, ecdh);
-	EC_KEY_free(ecdh);
 #endif
 
 	return true;
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 630ed0f162..682c67e567 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4592,8 +4592,8 @@ struct config_string ConfigureNamesString[] =
 
 	{
 		{"ssl_ecdh_curve", PGC_SIGHUP, CONN_AUTH_SSL,
-			gettext_noop("Sets the curve to use for ECDH."),
-			NULL,
+			gettext_noop("Sets the curve(s) to use for ECDH."),
+			gettext_noop("Multiple curves can be specified using colon-separated list."),
 			GUC_SUPERUSER_ONLY
 		},
 		&SSLECDHCurve,
diff --git a/src/test/ssl/t/SSL/Server.pm b/src/test/ssl/t/SSL/Server.pm
index 021eec74ab..b55b7599c8 100644
--- a/src/test/ssl/t/SSL/Server.pm
+++ b/src/test/ssl/t/SSL/Server.pm
@@ -204,6 +204,9 @@ sub configure_test_server_for_ssl
 	print $conf "listen_addresses='$serverhost'\n";
 	print $conf "log_statement=all\n";
 
+	# use lists of ECDH curves for syntax testing
+	print $conf "ssl_ecdh_curve=prime256v1:secp521r1\n";
+
 	# enable SSL and set up server key
 	print $conf "include 'sslconfig.conf'\n";
 
-- 
2.39.3 (Apple Git-146)

