From 15bd1bc543f0c851c18576d559071a5c5af24ea0 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 11 Aug 2026 15:06:37 +0200 Subject: [PATCH] Let OpenSSL auto-select DH parameters by default Previously, if ssl_dh_params_file was not set, compiled-in default parameters were used. This changes this so that in that case, we call SSL_CTX_set_dh_auto() and have OpenSSL choose appropriate, well-known, and appropriately sized parameters. In particular, the size of the parameters is chosen consistent with the size of the key and certificate, and so it can automatically grow with new standards and best practices. This default behavior is now preferable; it is noted that setting ssl_dh_params_file is obsolescent. There was also some not-very-modern text about this in README.SSL, which is deleted here. Note that if you use a very small certificate/key size, then this could mean that the size of the chosen DH parameters could also end up smaller than the previous hard-coded default. But that could only happen if you disregarded all current security best practices anyway. Note a small behavior change: Previously, if loading the DH file failed during a server reload, the system would then fall back to using the built-in parameters, instead of failing the reload and keeping the old SSL context, which is what it would do if some other aspect of reinitializing SSL would fail. This is now fixed. --- doc/src/sgml/config.sgml | 14 +++-- src/backend/libpq/README.SSL | 24 -------- src/backend/libpq/be-secure-openssl.c | 87 +++++++++------------------ src/include/libpq/libpq-be.h | 20 ------ 4 files changed, 39 insertions(+), 106 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 10b304122ef..b68edafdd8f 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1687,11 +1687,15 @@ SSL Specifies the name of the file containing Diffie-Hellman parameters used for so-called ephemeral DH family of SSL ciphers. The default is - empty, in which case compiled-in default DH parameters used. Using - custom DH parameters reduces the exposure if an attacker manages to - crack the well-known compiled-in DH parameters. You can create your own - DH parameters file with the command - openssl dhparam -out dhparams.pem 2048. + empty, in which case the SSL library selects well-known DH parameters + that are consistent with the size of the key associated with the + server's certificate. The default approach is preferred; this + parameter is obsolescent. + + + + This mechanism only affects TLS 1.2 and below. See for a similar mechanism for TLS 1.3. diff --git a/src/backend/libpq/README.SSL b/src/backend/libpq/README.SSL index d84a434a6ee..c07c156d5d9 100644 --- a/src/backend/libpq/README.SSL +++ b/src/backend/libpq/README.SSL @@ -56,27 +56,3 @@ SSL | Yes | Fail with unknown - ---------------------------------------------------------------------------- - -Ephemeral DH -============ - -Since the server static private key ($DataDir/server.key) will -normally be stored unencrypted so that the database backend can -restart automatically, it is important that we select an algorithm -that continues to provide confidentiality even if the attacker has the -server's private key. Ephemeral DH (EDH) keys provide this and more -(Perfect Forward Secrecy aka PFS). - -N.B., the static private key should still be protected to the largest -extent possible, to minimize the risk of impersonations. - -Another benefit of EDH is that it allows the backend and clients to -use DSA keys. DSA keys can only provide digital signatures, not -encryption, and are often acceptable in jurisdictions where RSA keys -are unacceptable. - -The downside to EDH is that it makes it impossible to use ssldump(1) -if there's a problem establishing an SSL session. In this case you'll -need to temporarily disable EDH (see initialize_dh()). diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 04764700845..88b85537aec 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -83,7 +83,6 @@ static BIO_METHOD *port_bio_method(void); static int ssl_set_port_bio(Port *port); static DH *load_dh_file(char *filename, bool isServerStart); -static DH *load_dh_buffer(const char *buffer, size_t len); static int ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata); static int dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); static int verify_cb(int ok, X509_STORE_CTX *ctx); @@ -1538,32 +1537,6 @@ load_dh_file(char *filename, bool isServerStart) return dh; } -/* - * Load hardcoded DH parameters. - * - * If DH parameters cannot be loaded from a specified file, we can load - * the hardcoded DH parameters supplied with the backend to prevent - * problems. - */ -static DH * -load_dh_buffer(const char *buffer, size_t len) -{ - BIO *bio; - DH *dh = NULL; - - bio = BIO_new_mem_buf(buffer, len); - if (bio == NULL) - return NULL; - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - if (dh == NULL) - ereport(DEBUG2, - (errmsg_internal("DH load buffer: %s", - SSLerrmessage(ERR_get_error())))); - BIO_free(bio); - - return dh; -} - /* * Passphrase collection callback using ssl_passphrase_command */ @@ -2072,48 +2045,48 @@ sni_clienthello_cb(SSL *ssl, int *al, void *arg) #endif /* HAVE_SSL_CTX_SET_CLIENT_HELLO_CB */ /* - * Set DH parameters for generating ephemeral DH keys. The - * DH parameters can take a long time to compute, so they must be - * precomputed. - * - * Since few sites will bother to create a parameter file, we also - * provide a fallback to the parameters provided by the OpenSSL - * project. - * - * These values can be static (once loaded or computed) since the - * OpenSSL library can efficiently generate random keys from the - * information provided. + * Set DH parameters for generating ephemeral DH keys. */ static bool initialize_dh(SSL_CTX *context, bool isServerStart) { - DH *dh = NULL; - SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE); if (ssl_dh_params_file[0]) - dh = load_dh_file(ssl_dh_params_file, isServerStart); - if (!dh) - dh = load_dh_buffer(FILE_DH2048, sizeof(FILE_DH2048)); - if (!dh) { - ereport(isServerStart ? FATAL : LOG, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("DH: could not load DH parameters"))); - return false; - } + DH *dh; + + dh = load_dh_file(ssl_dh_params_file, isServerStart); + + if (!dh) + return false; + + if (SSL_CTX_set_tmp_dh(context, dh) != 1) + { + ereport(isServerStart ? FATAL : LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("DH: could not set DH parameters: %s", + SSLerrmessage(ERR_get_error())))); + DH_free(dh); + return false; + } - if (SSL_CTX_set_tmp_dh(context, dh) != 1) - { - ereport(isServerStart ? FATAL : LOG, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("DH: could not set DH parameters: %s", - SSLerrmessage(ERR_get_error())))); DH_free(dh); - return false; + } + else + { + /* If ssl_dh_params_file is not set, let OpenSSL pick a default. */ + + if (SSL_CTX_set_dh_auto(context, 1) != 1) + { + ereport(isServerStart ? FATAL : LOG, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("DH: could not set DH parameters: %s", + SSLerrmessage(ERR_get_error())))); + return false; + } } - DH_free(dh); return true; } diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index 921b2daa4ff..ad51eb7b058 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -252,26 +252,6 @@ typedef struct ClientSocket } ClientSocket; #ifdef USE_SSL -/* - * Hardcoded DH parameters, used in ephemeral DH keying. (See also - * README.SSL for more details on EDH.) - * - * This is the 2048-bit DH parameter from RFC 3526. The generation of the - * prime is specified in RFC 2412 Appendix E, which also discusses the - * design choice of the generator. Note that when loaded with OpenSSL - * this causes DH_check() to fail on DH_NOT_SUITABLE_GENERATOR, where - * leaking a bit is preferred. - */ -#define FILE_DH2048 \ -"-----BEGIN DH PARAMETERS-----\n\ -MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n\ -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n\ -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n\ -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n\ -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n\ -5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n\ ------END DH PARAMETERS-----\n" - /* * These functions are implemented by the glue code specific to each * SSL implementation (e.g. be-secure-openssl.c) base-commit: d29d469becec1f2ac082d82863ae1c29fca9dd97 -- 2.55.0