From 4510e906e490d934f628cb9d919cf5659542f5a8 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Wed, 3 Jul 2024 17:49:12 +0200 Subject: [PATCH v3 1/2] Support multiple ECDH curves --- doc/src/sgml/config.sgml | 1 + src/backend/libpq/be-secure-openssl.c | 48 ++++++++++++++++++++------- src/backend/utils/misc/guc_tables.c | 4 +-- src/test/ssl/t/SSL/Server.pm | 3 ++ 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 17d84bd321..67a5e3ea3d 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1462,6 +1462,7 @@ include_dir 'conf.d' Specifies the name of the curve to use in ECDH 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 postgresql.conf diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 39b1a66236..55faf5df38 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -1402,30 +1402,54 @@ static bool initialize_ecdh(SSL_CTX *context, bool isServerStart) { #ifndef OPENSSL_NO_ECDH - EC_KEY *ecdh; - int nid; + StringInfoData errstr; + int errors = 0; + char *curve_list = pstrdup(SSLECDHCurve); + char *saveptr; + char *token = strtok_r(curve_list, ":", &saveptr); - nid = OBJ_sn2nid(SSLECDHCurve); - if (!nid) + initStringInfo(&errstr); + + /* + * Parse the colon separated list and test each member for being a known + * curve name in order be able to provide a good errormessage. The full + * list is parsed to catch all incorrect names rather than having the user + * fix one only to error out again in the case of multiple errors. + */ + while (token != NULL) + { + if (OBJ_sn2nid(token) == NID_undef) + { + appendStringInfo(&errstr, "%s%s", errors ? ", " : "", token); + errors++; + } + + token = strtok_r(NULL, ":", &saveptr); + } + + if (errors > 0) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve))); + errmsg_plural("ECDH: unrecognized curve name: %s", + "ECDH: unrecognized curve names: %s", + errors, errstr.data))); + pfree(errstr.data); return false; } - ecdh = EC_KEY_new_by_curve_name(nid); - if (!ecdh) + pfree(errstr.data); + + /* + * No errors were found, apply the entire list. + */ + if (SSL_CTX_set1_groups_list(context, SSLECDHCurve) != 1) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("ECDH: could not create key"))); + errmsg("ECDH: failed to set curve names"))); 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 d28b0bcb40..adf94381fd 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 ca4c7b567b..abc695c6a3 100644 --- a/src/test/ssl/t/SSL/Server.pm +++ b/src/test/ssl/t/SSL/Server.pm @@ -198,6 +198,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)