Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Started by Michael Paquierover 2 years ago121 messages
#1Michael Paquier
michael@paquier.xyz
2 attachment(s)

Hi all,

$Subject says it all. Based on an analysis of the code, I can note
the following when it comes to the removal of 1.0.1:
- A lot of code related to channel binding is now simplified as
X509_get_signature_nid() always exists, mostly around its CFLAGS.
- This removes the comments related to 1.0.1e introduced by 74242c2.

Then for 1.0.2, the following flags can be gone:
HAVE_ASN1_STRING_GET0_DATA
HAVE_BIO_GET_DATA
HAVE_BIO_METH_NEW
HAVE_HMAC_CTX_FREE
HAVE_HMAC_CTX_NEW

It would be nice to remove CRYPTO_lock(), but from what I can see the
function still exists in LibreSSL, meaning that libpq locking wouldn't
be thread-safe if these function's paths are removed.

Another related question is how much do we care about builds with
LibreSSL with MSVC? This patch sets takes the simple path of assuming
that this has never been really tested, and if you look at the MSVC
scripts on HEAD we rely on a version number from OpenSSL, which is not
something LibreSSL copes nicely with already, as documented in
configure.ac.

OpenSSL 1.0.2 has been EOLd at the end of 2019, and 1.0.1 had its last
minor release in September 2019, so with Postgres 17 targetted in
September/October 2024, we would be five years behind that.

Last comes the buildfarm, and I suspect that a few animals are
building with 1.0.2. Among what I have spotted:
- wobbegong and vulpes, on Fedora 27, though I could not find
references about the version used there.
- bonito, on Fedora 29.
- SUSE 12 SP{4,5} have 1.0.2 as their newer version.
- butterflyfish may not like that, if I recall correctly, as it should
have 1.0.2.

So, it seems to me that 1.0.1 would be a rather silent move for the
buildfarm, and 1.0.2 could lead to some noise. Note as well that
1.1.0 support has been stopped by upstream at the same time as 1.0.1,
with a last minor release in September 2019, though that feels like a
huge jump at this stage. On a code basis, removing 1.0.1 leads to the
most cleanup. The removal of 1.0.2 would be nice, but the tweaks
needed for LibreSSL make it less appealing.

Attached are two patches to remove support for 1.0.1 and 1.0.2 for
now, kept separated for clarity, to be considered as something to do
at the beginning of the v17 cycle. 0001 is in a rather good shape
seen from here.

Now, for 0002 and the removal of 1.0.2, I am seeing two things once
OPENSSL_API_COMPAT is bumped from 0x10002000L to 0x10100000L:
- be-secure-openssl.c requires an extra openssl/bn.h, which is not a
big deal, from what I get.
- Much more interesting: OpenSSL_add_all_algorithms() has two macros
that get removed, see include/openssl/evp.h:
# ifdef OPENSSL_LOAD_CONF
# define OpenSSL_add_all_algorithms() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS \
| OPENSSL_INIT_LOAD_CONFIG, NULL)
# else
# define OpenSSL_add_all_algorithms() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
# endif

The part where I am not quite sure of what to do is about
OPENSSL_LOAD_CONF. We could call directly OPENSSL_init_crypto() and
add OPENSSL_INIT_LOAD_CONFIG if building with OPENSSL_LOAD_CONF, but
it feels a bit ugly to copy-paste this code from OpenSSL itself.
Note that patch 0002 still has OPENSSL_API_COMPAT at 0x10002000L.
OPENSSL_init_crypto() looks to be in LibreSSL, and it is new in
OpenSSL 1.1.0, so switching the minimum to OpenSSL 1.1.0 should not
require a new cflags on this one.

Thoughts?
--
Michael

Attachments:

v1-0001-Remove-support-for-OpenSSL-1.0.1.patchtext/x-diff; charset=us-asciiDownload
From 553b9eb7e24250a92d7551cb28a301d9e63ba7ad Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Wed, 24 May 2023 16:22:02 +0900
Subject: [PATCH v1 1/2] Remove support for OpenSSL 1.0.1

A few notes about that:
- This simplifies a lot of code areas related to channel binding, as
X509_get_signature_nid() always exists.
- This removes the comments related to 1.0.1e introduced by 74242c2.
- Do we need to care about the case of building the Postgres code with
LibreSSL on Windows for the MSVC scripts, leading to the removal of the
check with HAVE_SSL_CTX_SET_CERT_CB?
---
 src/include/libpq/libpq-be.h             |  6 +---
 src/include/pg_config.h.in               |  3 --
 src/backend/libpq/auth-scram.c           | 20 ++++++------
 src/backend/libpq/be-secure-openssl.c    |  4 ---
 src/interfaces/libpq/fe-auth-scram.c     |  8 ++---
 src/interfaces/libpq/fe-auth.c           |  2 +-
 src/interfaces/libpq/fe-secure-openssl.c |  4 ---
 src/interfaces/libpq/libpq-int.h         |  6 +---
 src/test/ssl/t/002_scram.pl              | 41 ++++--------------------
 doc/src/sgml/installation.sgml           |  2 +-
 configure                                | 16 ++++-----
 configure.ac                             |  9 +++---
 meson.build                              |  5 ++-
 src/tools/msvc/Solution.pm               | 10 +-----
 14 files changed, 38 insertions(+), 98 deletions(-)

diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index 3b2ce9908f..b80757eabf 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -305,12 +305,8 @@ extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len);
  *
  * The result is a palloc'd hash of the server certificate with its
  * size, and NULL if there is no certificate available.
- *
- * This is not supported with old versions of OpenSSL that don't have
- * the X509_get_signature_nid() function.
  */
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 extern char *be_tls_get_certificate_hash(Port *port, size_t *len);
 #endif
 
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 6d572c3820..ca3a49c552 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -529,9 +529,6 @@
 /* Define to 1 if you have the `X509_get_signature_info' function. */
 #undef HAVE_X509_GET_SIGNATURE_INFO
 
-/* Define to 1 if you have the `X509_get_signature_nid' function. */
-#undef HAVE_X509_GET_SIGNATURE_NID
-
 /* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
 #undef HAVE_X86_64_POPCNTQ
 
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 9b286aa4d7..2729a9d60c 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -209,10 +209,9 @@ scram_get_mechanisms(Port *port, StringInfo buf)
 	/*
 	 * Advertise the mechanisms in decreasing order of importance.  So the
 	 * channel-binding variants go first, if they are supported.  Channel
-	 * binding is only supported with SSL, and only if the SSL implementation
-	 * has a function to get the certificate's hash.
+	 * binding is only supported with SSL.
 	 */
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	if (port->ssl_in_use)
 	{
 		appendStringInfoString(buf, SCRAM_SHA_256_PLUS_NAME);
@@ -251,13 +250,12 @@ scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
 	/*
 	 * Parse the selected mechanism.
 	 *
-	 * Note that if we don't support channel binding, either because the SSL
-	 * implementation doesn't support it or we're not using SSL at all, we
-	 * would not have advertised the PLUS variant in the first place.  If the
-	 * client nevertheless tries to select it, it's a protocol violation like
-	 * selecting any other SASL mechanism we don't support.
+	 * Note that if we don't support channel binding if we're not using SSL at
+	 * all, we would not have advertised the PLUS variant in the first place.
+	 * If the client nevertheless tries to select it, it's a protocol
+	 * violation like selecting any other SASL mechanism we don't support.
 	 */
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
 		state->channel_binding_in_use = true;
 	else
@@ -1010,7 +1008,7 @@ read_client_first_message(scram_state *state, const char *input)
 						 errmsg("malformed SCRAM message"),
 						 errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
 
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 			if (state->port->ssl_in_use)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
@@ -1306,7 +1304,7 @@ read_client_final_message(scram_state *state, const char *input)
 	channel_binding = read_attr_value(&p, 'c');
 	if (state->channel_binding_in_use)
 	{
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 		const char *cbind_data = NULL;
 		size_t		cbind_data_len = 0;
 		size_t		cbind_header_len;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 05276ab95c..658b09988d 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -831,8 +831,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
  *
  * These functions are closely modelled on the standard socket BIO in OpenSSL;
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
- * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
- * to retry; do we need to adopt their logic for that?
  */
 
 #ifndef HAVE_BIO_GET_DATA
@@ -1429,7 +1427,6 @@ be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
 		ptr[0] = '\0';
 }
 
-#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
 char *
 be_tls_get_certificate_hash(Port *port, size_t *len)
 {
@@ -1488,7 +1485,6 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 
 	return cert_hash;
 }
-#endif
 
 /*
  * Convert an X509 subject name to a cstring.
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 6b779ec7ff..441b776330 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -401,7 +401,7 @@ build_client_first_message(fe_scram_state *state)
 		Assert(conn->ssl_in_use);
 		appendPQExpBufferStr(&buf, "p=tls-server-end-point");
 	}
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	else if (conn->channel_binding[0] != 'd' && /* disable */
 			 conn->ssl_in_use)
 	{
@@ -474,7 +474,7 @@ build_client_final_message(fe_scram_state *state)
 	 */
 	if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
 	{
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 		char	   *cbind_data = NULL;
 		size_t		cbind_data_len = 0;
 		size_t		cbind_header_len;
@@ -540,9 +540,9 @@ build_client_final_message(fe_scram_state *state)
 		appendPQExpBufferStr(&conn->errorMessage,
 							 "channel binding not supported by this build\n");
 		return NULL;
-#endif							/* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
+#endif							/* USE_OPENSSL */
 	}
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	else if (conn->channel_binding[0] != 'd' && /* disable */
 			 conn->ssl_in_use)
 		appendPQExpBufferStr(&buf, "c=eSws");	/* base64 of "y,," */
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index de0e13e50d..e730c1a34a 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -478,7 +478,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
 			{
 				/* The server has offered SCRAM-SHA-256-PLUS. */
 
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 				/*
 				 * The client supports channel binding, which is chosen if
 				 * channel_binding is not disabled.
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 390c888c96..bea71660ab 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -364,7 +364,6 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
 	return n;
 }
 
-#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
 char *
 pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 {
@@ -439,7 +438,6 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 
 	return cert_hash;
 }
-#endif							/* HAVE_X509_GET_SIGNATURE_NID */
 
 /* ------------------------------------------------------------ */
 /*						OpenSSL specific code					*/
@@ -1826,8 +1824,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
  *
  * These functions are closely modelled on the standard socket BIO in OpenSSL;
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
- * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
- * to retry; do we need to adopt their logic for that?
  */
 
 #ifndef HAVE_BIO_GET_DATA
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index f1854f9919..33bacd8e65 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -833,12 +833,8 @@ extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);
  *
  * NULL is sent back to the caller in the event of an error, with an
  * error message for the caller to consume.
- *
- * This is not supported with old versions of OpenSSL that don't have
- * the X509_get_signature_nid() function.
  */
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
 #endif
 
diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl
index 28c54bdb09..3a798e1a56 100644
--- a/src/test/ssl/t/002_scram.pl
+++ b/src/test/ssl/t/002_scram.pl
@@ -44,9 +44,6 @@ my $SERVERHOSTADDR = '127.0.0.1';
 # This is the pattern to use in pg_hba.conf to match incoming connections.
 my $SERVERHOSTCIDR = '127.0.0.1/32';
 
-# Determine whether build supports tls-server-end-point.
-my $supports_tls_server_end_point =
-  check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1");
 # Determine whether build supports detection of hash algorithms for
 # RSA-PSS certificates.
 my $supports_rsapss_certs =
@@ -90,21 +87,9 @@ $node->connect_fails(
 	expected_stderr => qr/invalid channel_binding value: "invalid_value"/);
 $node->connect_ok("$common_connstr user=ssltestuser channel_binding=disable",
 	"SCRAM with SSL and channel_binding=disable");
-if ($supports_tls_server_end_point)
-{
-	$node->connect_ok(
-		"$common_connstr user=ssltestuser channel_binding=require",
-		"SCRAM with SSL and channel_binding=require");
-}
-else
-{
-	$node->connect_fails(
-		"$common_connstr user=ssltestuser channel_binding=require",
-		"SCRAM with SSL and channel_binding=require",
-		expected_stderr =>
-		  qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
-	);
-}
+$node->connect_ok(
+	"$common_connstr user=ssltestuser channel_binding=require",
+	"SCRAM with SSL and channel_binding=require");
 
 # Now test when the user has an MD5-encrypted password; should fail
 $node->connect_fails(
@@ -152,22 +137,10 @@ $node->connect_fails(
 	expected_stderr =>
 	  qr/channel binding required but not supported by server's authentication request/
 );
-if ($supports_tls_server_end_point)
-{
-	$node->connect_ok(
-		"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
-		"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256"
-	);
-}
-else
-{
-	$node->connect_fails(
-		"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
-		"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256",
-		expected_stderr =>
-		  qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
-	);
-}
+$node->connect_ok(
+	"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
+	"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256"
+);
 
 # Now test with a server certificate that uses the RSA-PSS algorithm.
 # This checks that the certificate can be loaded and that channel binding
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 75dc81a0a9..e9d797417a 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -275,7 +275,7 @@ documentation.  See standalone-profile.xsl for details.
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.1.
+      required version is 1.0.2.
      </para>
     </listitem>
 
diff --git a/configure b/configure
index 15daccc87f..dbb37f3b83 100755
--- a/configure
+++ b/configure
@@ -12744,9 +12744,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.1
+    # Minimum required OpenSSL version is 1.0.2
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10001000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12961,15 +12961,13 @@ else
 fi
 
   fi
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  for ac_func in X509_get_signature_nid SSL_CTX_set_cert_cb
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  for ac_func in SSL_CTX_set_cert_cb
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
+if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_SSL_CTX_SET_CERT_CB 1
 _ACEOF
 
 fi
diff --git a/configure.ac b/configure.ac
index 97f5be6c73..94ae1d33c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1367,8 +1367,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.1
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10001000L],
+  # Minimum required OpenSSL version is 1.0.2
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1377,9 +1377,8 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([X509_get_signature_nid SSL_CTX_set_cert_cb])
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
   # Functions introduced in OpenSSL 1.1.0. We used to check for
   # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
diff --git a/meson.build b/meson.build
index 096044628c..5cf13e3b36 100644
--- a/meson.build
+++ b/meson.build
@@ -1268,9 +1268,8 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Functions introduced in OpenSSL 1.0.2.
-      ['X509_get_signature_nid'],
-      ['SSL_CTX_set_cert_cb'], # not in LibreSSL
+      # Function not in LibreSSL
+      ['SSL_CTX_set_cert_cb'],
 
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index b6d31c3583..e6d8f9fedc 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -371,7 +371,6 @@ sub GenerateFiles
 		HAVE_UUID_UUID_H => undef,
 		HAVE_WCSTOMBS_L => 1,
 		HAVE_VISIBILITY_ATTRIBUTE => undef,
-		HAVE_X509_GET_SIGNATURE_NID => 1,
 		HAVE_X509_GET_SIGNATURE_INFO => undef,
 		HAVE_X86_64_POPCNTQ => undef,
 		HAVE__BOOL => undef,
@@ -488,6 +487,7 @@ sub GenerateFiles
 	if ($self->{options}->{openssl})
 	{
 		$define{USE_OPENSSL} = 1;
+		$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
 
 		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
 
@@ -509,14 +509,6 @@ sub GenerateFiles
 			$define{HAVE_HMAC_CTX_NEW} = 1;
 			$define{HAVE_OPENSSL_INIT_SSL} = 1;
 		}
-
-		# Symbols needed with OpenSSL 1.0.2 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '0' && $digit3 >= '2'))
-		{
-			$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
-		}
 	}
 
 	$self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
-- 
2.40.1

v1-0002-Remove-support-for-OpenSSL-1.0.2.patchtext/x-diff; charset=us-asciiDownload
From 0bbb001513d07b47223b4dbd8950241c327ca731 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Wed, 24 May 2023 17:08:24 +0900
Subject: [PATCH v1 2/2] Remove support for OpenSSL 1.0.2

This allows the removal of the following flags:
HAVE_ASN1_STRING_GET0_DATA
HAVE_BIO_GET_DATA
HAVE_BIO_METH_NEW
HAVE_HMAC_CTX_FREE
HAVE_HMAC_CTX_NEW

OpenSSL 1.1.0 has removed CRYPTO_lock(), but LibreSSL requires it.  On
the contrary, OPENSSL_init_ssl() is not in OpenSSL.
---
 src/include/pg_config.h.in               | 15 ------------
 src/backend/libpq/be-secure-openssl.c    | 14 ------------
 src/common/hmac_openssl.c                | 17 --------------
 src/interfaces/libpq/fe-secure-openssl.c | 22 ------------------
 src/interfaces/libpq/libpq-int.h         |  5 +---
 doc/src/sgml/installation.sgml           |  2 +-
 configure                                | 29 +++++++-----------------
 configure.ac                             | 21 ++++++++---------
 meson.build                              | 20 ++++++----------
 src/tools/msvc/Solution.pm               | 18 +--------------
 10 files changed, 27 insertions(+), 136 deletions(-)

diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index ca3a49c552..80b6ddec73 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -58,9 +58,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -70,12 +67,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -214,12 +205,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 658b09988d..61ad6b3476 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -833,11 +833,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
  */
 
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
 static BIO_METHOD *my_bio_methods = NULL;
 
 static int
@@ -887,7 +882,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -910,14 +904,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 12be542fa2..068b098da6 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -41,11 +41,7 @@
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -113,14 +109,10 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-#ifdef HAVE_HMAC_CTX_NEW
 #ifndef FRONTEND
 	ResourceOwnerEnlargeHMAC(CurrentResourceOwner);
 #endif
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -134,14 +126,10 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifdef HAVE_HMAC_CTX_NEW
 #ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, PointerGetDatum(ctx));
 #endif
-#else
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif							/* HAVE_HMAC_CTX_NEW */
 
 	return ctx;
 }
@@ -300,15 +288,10 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
 #ifndef FRONTEND
 	ResourceOwnerForgetHMAC(ctx->resowner, PointerGetDatum(ctx));
 #endif
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
 
 	explicit_bzero(ctx, sizeof(pg_hmac_ctx));
 	FREE(ctx);
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index bea71660ab..123ba4d04c 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -511,11 +511,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -546,11 +542,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -1826,11 +1818,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
  */
 
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
 static BIO_METHOD *my_bio_methods;
 
 static int
@@ -1899,7 +1886,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1927,14 +1913,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 33bacd8e65..d3a86876e0 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -564,10 +564,7 @@ struct pg_conn
 								 * OpenSSL version changes */
 #endif
 	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
+								 * been done for this connection */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index e9d797417a..f2dc53dcb5 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -275,7 +275,7 @@ documentation.  See standalone-profile.xsl for details.
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/configure b/configure
index dbb37f3b83..748977c3bb 100755
--- a/configure
+++ b/configure
@@ -12744,7 +12744,8 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0.  API compatibility is kept at
+  # 1.0.2 for OpenSSL_add_all_algorithms().
 
 $as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
 
@@ -12961,24 +12962,11 @@ else
 fi
 
   fi
-  # LibreSSL does not have SSL_CTX_set_cert_cb().
-  for ac_func in SSL_CTX_set_cert_cb
-do :
-  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
-if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SSL_CTX_SET_CERT_CB 1
-_ACEOF
-
-fi
-done
-
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+  # Functions not in LibreSSL.  We used to check for OPENSSL_VERSION_NUMBER,
+  # but that didn't work with OpenSSL 1.1.0, because LibreSSL defines
+  # OPENSSL_VERSION_NUMBER to claim version 2.0.0. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in SSL_CTX_set_cert_cb OPENSSL_init_ssl
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -12990,9 +12978,8 @@ _ACEOF
 fi
 done
 
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
+  # Function included in LibreSSL, not in OpenSSL.  This is required for
+  # thread safety.
   for ac_func in CRYPTO_lock
 do :
   ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
diff --git a/configure.ac b/configure.ac
index 94ae1d33c2..7f723289dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1367,7 +1367,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
+  # Minimum required OpenSSL version is 1.1.0.  API compatibility is kept at
+  # 1.0.2 for OpenSSL_add_all_algorithms().
   AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
@@ -1377,18 +1378,14 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
-  # LibreSSL does not have SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+  # Functions not in LibreSSL.  We used to check for OPENSSL_VERSION_NUMBER,
+  # but that didn't work with OpenSSL 1.1.0, because LibreSSL defines
+  # OPENSSL_VERSION_NUMBER to claim version 2.0.0. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb OPENSSL_init_ssl])
+  # Function included in LibreSSL, not in OpenSSL.  This is required for
+  # thread safety.
+  AC_CHECK_FUNCS(CRYPTO_lock)
   # Function introduced in OpenSSL 1.1.1.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
diff --git a/meson.build b/meson.build
index 5cf13e3b36..c176a0fbea 100644
--- a/meson.build
+++ b/meson.build
@@ -1271,21 +1271,15 @@ if sslopt in ['auto', 'openssl']
       # Function not in LibreSSL
       ['SSL_CTX_set_cert_cb'],
 
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+      # Functions not in LibreSSL. We used to check for OPENSSL_VERSION_NUMBER,
+      # but that didn't work with 1.1.0, because LibreSSL defines
+      # OPENSSL_VERSION_NUMBER to claim version 2.0.0. So check for individual
       # functions.
       ['OPENSSL_init_ssl'],
-      ['BIO_get_data'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
+      ['SSL_CTX_set_cert_cb'],
 
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
+      # Function included in LibreSSL, not in OpenSSL.  This is required for
+      # thread-safety.
       ['CRYPTO_lock'],
 
       # Function introduced in OpenSSL 1.1.1
@@ -1311,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10001000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
                 description: '''Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.''')
       ssl_library = 'openssl'
     else
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index e6d8f9fedc..84e2209e74 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -221,12 +221,9 @@ sub GenerateFiles
 		ENABLE_NLS => $self->{options}->{nls} ? 1 : undef,
 		ENABLE_THREAD_SAFETY => 1,
 		HAVE_APPEND_HISTORY => undef,
-		HAVE_ASN1_STRING_GET0_DATA => undef,
 		HAVE_ATOMICS => 1,
 		HAVE_ATOMIC_H => undef,
 		HAVE_BACKTRACE_SYMBOLS => undef,
-		HAVE_BIO_GET_DATA => undef,
-		HAVE_BIO_METH_NEW => undef,
 		HAVE_COMPUTED_GOTO => undef,
 		HAVE_COPYFILE => undef,
 		HAVE_COPYFILE_H => undef,
@@ -266,8 +263,6 @@ sub GenerateFiles
 		HAVE_GSSAPI_GSSAPI_EXT_H => undef,
 		HAVE_GSSAPI_GSSAPI_H => undef,
 		HAVE_GSSAPI_H => undef,
-		HAVE_HMAC_CTX_FREE => undef,
-		HAVE_HMAC_CTX_NEW => undef,
 		HAVE_HISTORY_H => undef,
 		HAVE_HISTORY_TRUNCATE_FILE => undef,
 		HAVE_IFADDRS_H => undef,
@@ -488,6 +483,7 @@ sub GenerateFiles
 	{
 		$define{USE_OPENSSL} = 1;
 		$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
+		$define{HAVE_OPENSSL_INIT_SSL} = 1;
 
 		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
 
@@ -497,18 +493,6 @@ sub GenerateFiles
 		{
 			$define{HAVE_X509_GET_SIGNATURE_INFO} = 1;
 		}
-
-		# Symbols needed with OpenSSL 1.1.0 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
-		{
-			$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
-			$define{HAVE_BIO_GET_DATA} = 1;
-			$define{HAVE_BIO_METH_NEW} = 1;
-			$define{HAVE_HMAC_CTX_FREE} = 1;
-			$define{HAVE_HMAC_CTX_NEW} = 1;
-			$define{HAVE_OPENSSL_INIT_SSL} = 1;
-		}
 	}
 
 	$self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
-- 
2.40.1

#2Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#1)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 24 May 2023, at 10:22, Michael Paquier <michael@paquier.xyz> wrote:

The removal of 1.0.2 would be nice, but the tweaks
needed for LibreSSL make it less appealing.

1.0.2 is also an LTS version available commercially for premium support
customers of OpenSSL (1.1.1 will become an LTS version as well), with 1.0.2zh
slated for release next week. This raises the likelyhood of Postgres
installations using 1.0.2 in production still, and for some time to come.

--
Daniel Gustafsson

#3Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#2)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, May 24, 2023 at 11:36:56AM +0200, Daniel Gustafsson wrote:

1.0.2 is also an LTS version available commercially for premium support
customers of OpenSSL (1.1.1 will become an LTS version as well), with 1.0.2zh
slated for release next week. This raises the likelyhood of Postgres
installations using 1.0.2 in production still, and for some time to come.

Good point. Indeed, that makes it pretty clear that not dropping
1.0.2 would be the best option for the time being, so 0001 would be
enough.

I am wondering if we should worry about having a buildfarm member that
could test these binaries, though, in case they have compatibility
issues.. But it would be harder to debug without the code at hand, as
well.
--
Michael

#4Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#3)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 24 May 2023, at 11:52, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, May 24, 2023 at 11:36:56AM +0200, Daniel Gustafsson wrote:

1.0.2 is also an LTS version available commercially for premium support
customers of OpenSSL (1.1.1 will become an LTS version as well), with 1.0.2zh
slated for release next week. This raises the likelyhood of Postgres
installations using 1.0.2 in production still, and for some time to come.

Good point. Indeed, that makes it pretty clear that not dropping
1.0.2 would be the best option for the time being, so 0001 would be
enough.

I think thats the right move re 1.0.2 support. 1.0.2 is also the version in
RHEL7 which is in ELS until 2026.

When we moved the goalposts to 1.0.1 (commit 7b283d0e1d1) we referred to RHEL6
using 1.0.1, and RHEL6 goes out of ELS in late June 2024 seems possible to drop
1.0.1 support during v17. I haven't studied the patch yet but I'll have a look
at it.

I am wondering if we should worry about having a buildfarm member that
could test these binaries, though, in case they have compatibility
issues.. But it would be harder to debug without the code at hand, as
well.

It would be nice it the OpenSSL project could grant us an LTS license for a
buildfarm animal to ensure compatibility but I have no idea how realistic that
is (or how much the LTS version of 1.0.2 has diverged from the last available
public 1.0.2 version).

--
Daniel Gustafsson

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Daniel Gustafsson (#4)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Daniel Gustafsson <daniel@yesql.se> writes:

It would be nice it the OpenSSL project could grant us an LTS license for a
buildfarm animal to ensure compatibility but I have no idea how realistic that
is (or how much the LTS version of 1.0.2 has diverged from the last available
public 1.0.2 version).

Surely the answer must be "not much". The entire point of an LTS
version is to not have to change dusty calling applications.

We had definitely better have some animals still using 1.0.2, but
I don't see much reason to think that the last public release
wouldn't be good enough.

regards, tom lane

#6Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#4)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, May 24, 2023 at 01:03:04PM +0200, Daniel Gustafsson wrote:

When we moved the goalposts to 1.0.1 (commit 7b283d0e1d1) we referred to RHEL6
using 1.0.1, and RHEL6 goes out of ELS in late June 2024 seems possible to drop
1.0.1 support during v17. I haven't studied the patch yet but I'll have a look
at it.

Great, thanks for the help.
--
Michael

#7Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#6)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 25 May 2023, at 00:18, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, May 24, 2023 at 01:03:04PM +0200, Daniel Gustafsson wrote:

When we moved the goalposts to 1.0.1 (commit 7b283d0e1d1) we referred to RHEL6
using 1.0.1, and RHEL6 goes out of ELS in late June 2024 seems possible to drop
1.0.1 support during v17. I haven't studied the patch yet but I'll have a look
at it.

Patch looks to be in pretty good shape, just a few minor comments:

-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
Since this is only calling the pgtls abstraction API and not directly into the
SSL implementation we should use USE_SSL here instead. Same for the
corresponding hunks in the frontend code.

+	 * Note that if we don't support channel binding if we're not using SSL at
+	 * all, we would not have advertised the PLUS variant in the first place.
Seems like a word fell off when merging these sentences.  This should probably
be "..support channel binding, or if we're no.." or something similar.
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
 #endif
No need for any guard at all now is there?  All supported SSL implementations
have it, and I doubt we'd accept a new one that doesn't (or which can't
implement the function and error out).
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([X509_get_signature_nid SSL_CTX_set_cert_cb])
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
The comment about when the function was introduced is still interesting and
should remain IMHO.

The changes to the Windows buildsystem worry me a bit, but they don't move the
goalposts in either direction wrt to LibreSSL on Windows so for the purpose of
this patch we don't need to do more. Longer term we should either make
LibreSSL work on Windows builds, or explicitly not support it on Windows.

--
Daniel Gustafsson

#8Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#5)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 24 May 2023, at 16:15, Tom Lane <tgl@sss.pgh.pa.us> wrote:

We had definitely better have some animals still using 1.0.2, but
I don't see much reason to think that the last public release
wouldn't be good enough.

There are still RHEL7 animals like chub who use 1.0.2 so I'm not worried. We
might want to consider displaying the OpenSSL version number during configure
(meson already does it) in all branches to make it easier to figure out which
versions we have coverage for?

--
Daniel Gustafsson

#9Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#8)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, May 25, 2023 at 10:27:02AM +0200, Daniel Gustafsson wrote:

There are still RHEL7 animals like chub who use 1.0.2 so I'm not worried. We
might want to consider displaying the OpenSSL version number during configure
(meson already does it) in all branches to make it easier to figure out which
versions we have coverage for?

+1.
--
Michael
#10Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#7)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, May 25, 2023 at 10:16:27AM +0200, Daniel Gustafsson wrote:

-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
Since this is only calling the pgtls abstraction API and not directly into the
SSL implementation we should use USE_SSL here instead. Same for the
corresponding hunks in the frontend code.

Makes sense, done.

+	 * Note that if we don't support channel binding if we're not using SSL at
+	 * all, we would not have advertised the PLUS variant in the first place.
Seems like a word fell off when merging these sentences.  This should probably
be "..support channel binding, or if we're no.." or something similar.

Indeed, something has been eaten when merging these lines.

-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
#endif
No need for any guard at all now is there?  All supported SSL implementations
have it, and I doubt we'd accept a new one that doesn't (or which can't
implement the function and error out).

Yup. It looks that you are right. A build without SSL is not
complaining once removed in libpq-int.h or libpq-be.h.

-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([X509_get_signature_nid SSL_CTX_set_cert_cb])
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
The comment about when the function was introduced is still interesting and
should remain IMHO.

Okay. Kept as well in meson.build.

The changes to the Windows buildsystem worry me a bit, but they don't move the
goalposts in either direction wrt to LibreSSL on Windows so for the purpose of
this patch we don't need to do more. Longer term we should either make
LibreSSL work on Windows builds, or explicitly not support it on Windows.

Yes, I was wondering what to do about that in the long term. With the
argument that the MSVC scripts may be gone over meson, it is not
really appealing to dig into that.

Something that was missing in 0001 is the bump of OPENSSL_API_COMPAT
in meson.build. This was in 0002.

Please find attached an updated patch only for the removal of 1.0.1.
Thanks for the review.
--
Michael

Attachments:

v2-0001-Remove-support-for-OpenSSL-1.0.1.patchtext/x-diff; charset=us-asciiDownload
From b59a9a192d88bfd6261a3559ace8caced2e25d9a Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Fri, 26 May 2023 10:45:35 +0900
Subject: [PATCH v2] Remove support for OpenSSL 1.0.1

A few notes about that:
- This simplifies a lot of code areas related to channel binding, as
X509_get_signature_nid() always exists.
- This removes the comments related to 1.0.1e introduced by 74242c2.
- Do we need to care about the case of building the Postgres code with
LibreSSL on Windows for the MSVC scripts, leading to the removal of the
check with HAVE_SSL_CTX_SET_CERT_CB?
---
 src/include/libpq/libpq-be.h             |  6 ----
 src/include/pg_config.h.in               |  3 --
 src/backend/libpq/auth-scram.c           | 20 ++++++------
 src/backend/libpq/be-secure-openssl.c    |  4 ---
 src/interfaces/libpq/fe-auth-scram.c     |  8 ++---
 src/interfaces/libpq/fe-auth.c           |  2 +-
 src/interfaces/libpq/fe-secure-openssl.c |  4 ---
 src/interfaces/libpq/libpq-int.h         |  6 ----
 src/test/ssl/t/002_scram.pl              | 41 ++++--------------------
 doc/src/sgml/installation.sgml           |  2 +-
 configure                                | 16 ++++-----
 configure.ac                             |  8 ++---
 meson.build                              |  7 ++--
 src/tools/msvc/Solution.pm               | 10 +-----
 14 files changed, 37 insertions(+), 100 deletions(-)

diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index 3b2ce9908f..a0b74c8095 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -305,14 +305,8 @@ extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len);
  *
  * The result is a palloc'd hash of the server certificate with its
  * size, and NULL if there is no certificate available.
- *
- * This is not supported with old versions of OpenSSL that don't have
- * the X509_get_signature_nid() function.
  */
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_BE_TLS_GET_CERTIFICATE_HASH
 extern char *be_tls_get_certificate_hash(Port *port, size_t *len);
-#endif
 
 /* init hook for SSL, the default sets the password callback if appropriate */
 #ifdef USE_OPENSSL
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 6d572c3820..ca3a49c552 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -529,9 +529,6 @@
 /* Define to 1 if you have the `X509_get_signature_info' function. */
 #undef HAVE_X509_GET_SIGNATURE_INFO
 
-/* Define to 1 if you have the `X509_get_signature_nid' function. */
-#undef HAVE_X509_GET_SIGNATURE_NID
-
 /* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
 #undef HAVE_X86_64_POPCNTQ
 
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 9b286aa4d7..118d15b1a1 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -209,10 +209,9 @@ scram_get_mechanisms(Port *port, StringInfo buf)
 	/*
 	 * Advertise the mechanisms in decreasing order of importance.  So the
 	 * channel-binding variants go first, if they are supported.  Channel
-	 * binding is only supported with SSL, and only if the SSL implementation
-	 * has a function to get the certificate's hash.
+	 * binding is only supported with SSL.
 	 */
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_SSL
 	if (port->ssl_in_use)
 	{
 		appendStringInfoString(buf, SCRAM_SHA_256_PLUS_NAME);
@@ -251,13 +250,12 @@ scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
 	/*
 	 * Parse the selected mechanism.
 	 *
-	 * Note that if we don't support channel binding, either because the SSL
-	 * implementation doesn't support it or we're not using SSL at all, we
-	 * would not have advertised the PLUS variant in the first place.  If the
-	 * client nevertheless tries to select it, it's a protocol violation like
-	 * selecting any other SASL mechanism we don't support.
+	 * Note that if we don't support channel binding, or if we're not using
+	 * SSL at all, we would not have advertised the PLUS variant in the first
+	 * place.  If the client nevertheless tries to select it, it's a protocol
+	 * violation like selecting any other SASL mechanism we don't support.
 	 */
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_SSL
 	if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
 		state->channel_binding_in_use = true;
 	else
@@ -1010,7 +1008,7 @@ read_client_first_message(scram_state *state, const char *input)
 						 errmsg("malformed SCRAM message"),
 						 errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
 
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_SSL
 			if (state->port->ssl_in_use)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
@@ -1306,7 +1304,7 @@ read_client_final_message(scram_state *state, const char *input)
 	channel_binding = read_attr_value(&p, 'c');
 	if (state->channel_binding_in_use)
 	{
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_SSL
 		const char *cbind_data = NULL;
 		size_t		cbind_data_len = 0;
 		size_t		cbind_header_len;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 05276ab95c..658b09988d 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -831,8 +831,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
  *
  * These functions are closely modelled on the standard socket BIO in OpenSSL;
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
- * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
- * to retry; do we need to adopt their logic for that?
  */
 
 #ifndef HAVE_BIO_GET_DATA
@@ -1429,7 +1427,6 @@ be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
 		ptr[0] = '\0';
 }
 
-#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
 char *
 be_tls_get_certificate_hash(Port *port, size_t *len)
 {
@@ -1488,7 +1485,6 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 
 	return cert_hash;
 }
-#endif
 
 /*
  * Convert an X509 subject name to a cstring.
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 6b779ec7ff..61e6cd84d2 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -401,7 +401,7 @@ build_client_first_message(fe_scram_state *state)
 		Assert(conn->ssl_in_use);
 		appendPQExpBufferStr(&buf, "p=tls-server-end-point");
 	}
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_SSL
 	else if (conn->channel_binding[0] != 'd' && /* disable */
 			 conn->ssl_in_use)
 	{
@@ -474,7 +474,7 @@ build_client_final_message(fe_scram_state *state)
 	 */
 	if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
 	{
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_SSL
 		char	   *cbind_data = NULL;
 		size_t		cbind_data_len = 0;
 		size_t		cbind_header_len;
@@ -540,9 +540,9 @@ build_client_final_message(fe_scram_state *state)
 		appendPQExpBufferStr(&conn->errorMessage,
 							 "channel binding not supported by this build\n");
 		return NULL;
-#endif							/* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
+#endif							/* USE_SSL */
 	}
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_SSL
 	else if (conn->channel_binding[0] != 'd' && /* disable */
 			 conn->ssl_in_use)
 		appendPQExpBufferStr(&buf, "c=eSws");	/* base64 of "y,," */
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 88fd0f3d80..f8e09d3b41 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -478,7 +478,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
 			{
 				/* The server has offered SCRAM-SHA-256-PLUS. */
 
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_SSL
 				/*
 				 * The client supports channel binding, which is chosen if
 				 * channel_binding is not disabled.
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 390c888c96..bea71660ab 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -364,7 +364,6 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
 	return n;
 }
 
-#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
 char *
 pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 {
@@ -439,7 +438,6 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 
 	return cert_hash;
 }
-#endif							/* HAVE_X509_GET_SIGNATURE_NID */
 
 /* ------------------------------------------------------------ */
 /*						OpenSSL specific code					*/
@@ -1826,8 +1824,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
  *
  * These functions are closely modelled on the standard socket BIO in OpenSSL;
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
- * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
- * to retry; do we need to adopt their logic for that?
  */
 
 #ifndef HAVE_BIO_GET_DATA
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 0045f83cbf..b70d4aee6a 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -833,14 +833,8 @@ extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);
  *
  * NULL is sent back to the caller in the event of an error, with an
  * error message for the caller to consume.
- *
- * This is not supported with old versions of OpenSSL that don't have
- * the X509_get_signature_nid() function.
  */
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
 extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
-#endif
 
 /*
  * Verify that the server certificate matches the host name we connected to.
diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl
index 28c54bdb09..3a798e1a56 100644
--- a/src/test/ssl/t/002_scram.pl
+++ b/src/test/ssl/t/002_scram.pl
@@ -44,9 +44,6 @@ my $SERVERHOSTADDR = '127.0.0.1';
 # This is the pattern to use in pg_hba.conf to match incoming connections.
 my $SERVERHOSTCIDR = '127.0.0.1/32';
 
-# Determine whether build supports tls-server-end-point.
-my $supports_tls_server_end_point =
-  check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1");
 # Determine whether build supports detection of hash algorithms for
 # RSA-PSS certificates.
 my $supports_rsapss_certs =
@@ -90,21 +87,9 @@ $node->connect_fails(
 	expected_stderr => qr/invalid channel_binding value: "invalid_value"/);
 $node->connect_ok("$common_connstr user=ssltestuser channel_binding=disable",
 	"SCRAM with SSL and channel_binding=disable");
-if ($supports_tls_server_end_point)
-{
-	$node->connect_ok(
-		"$common_connstr user=ssltestuser channel_binding=require",
-		"SCRAM with SSL and channel_binding=require");
-}
-else
-{
-	$node->connect_fails(
-		"$common_connstr user=ssltestuser channel_binding=require",
-		"SCRAM with SSL and channel_binding=require",
-		expected_stderr =>
-		  qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
-	);
-}
+$node->connect_ok(
+	"$common_connstr user=ssltestuser channel_binding=require",
+	"SCRAM with SSL and channel_binding=require");
 
 # Now test when the user has an MD5-encrypted password; should fail
 $node->connect_fails(
@@ -152,22 +137,10 @@ $node->connect_fails(
 	expected_stderr =>
 	  qr/channel binding required but not supported by server's authentication request/
 );
-if ($supports_tls_server_end_point)
-{
-	$node->connect_ok(
-		"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
-		"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256"
-	);
-}
-else
-{
-	$node->connect_fails(
-		"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
-		"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256",
-		expected_stderr =>
-		  qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
-	);
-}
+$node->connect_ok(
+	"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
+	"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256"
+);
 
 # Now test with a server certificate that uses the RSA-PSS algorithm.
 # This checks that the certificate can be loaded and that channel binding
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 75dc81a0a9..e9d797417a 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -275,7 +275,7 @@ documentation.  See standalone-profile.xsl for details.
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.1.
+      required version is 1.0.2.
      </para>
     </listitem>
 
diff --git a/configure b/configure
index 1b415142d1..c25089f2c1 100755
--- a/configure
+++ b/configure
@@ -12744,9 +12744,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.1
+    # Minimum required OpenSSL version is 1.0.2
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10001000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12961,15 +12961,13 @@ else
 fi
 
   fi
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  for ac_func in X509_get_signature_nid SSL_CTX_set_cert_cb
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  for ac_func in SSL_CTX_set_cert_cb
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
+if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_SSL_CTX_SET_CERT_CB 1
 _ACEOF
 
 fi
diff --git a/configure.ac b/configure.ac
index 09558ada0f..093bfad082 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1367,8 +1367,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.1
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10001000L],
+  # Minimum required OpenSSL version is 1.0.2
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1377,9 +1377,9 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
+  # Function introduced in OpenSSL 1.0.2. LibreSSL does not have
   # SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([X509_get_signature_nid SSL_CTX_set_cert_cb])
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
   # Functions introduced in OpenSSL 1.1.0. We used to check for
   # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
diff --git a/meson.build b/meson.build
index 16b2e86646..7d0122ab32 100644
--- a/meson.build
+++ b/meson.build
@@ -1268,9 +1268,8 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Functions introduced in OpenSSL 1.0.2.
-      ['X509_get_signature_nid'],
-      ['SSL_CTX_set_cert_cb'], # not in LibreSSL
+      # Functions introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
 
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
@@ -1312,7 +1311,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10001000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
                 description: '''Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.''')
       ssl_library = 'openssl'
     else
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index b6d31c3583..e6d8f9fedc 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -371,7 +371,6 @@ sub GenerateFiles
 		HAVE_UUID_UUID_H => undef,
 		HAVE_WCSTOMBS_L => 1,
 		HAVE_VISIBILITY_ATTRIBUTE => undef,
-		HAVE_X509_GET_SIGNATURE_NID => 1,
 		HAVE_X509_GET_SIGNATURE_INFO => undef,
 		HAVE_X86_64_POPCNTQ => undef,
 		HAVE__BOOL => undef,
@@ -488,6 +487,7 @@ sub GenerateFiles
 	if ($self->{options}->{openssl})
 	{
 		$define{USE_OPENSSL} = 1;
+		$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
 
 		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
 
@@ -509,14 +509,6 @@ sub GenerateFiles
 			$define{HAVE_HMAC_CTX_NEW} = 1;
 			$define{HAVE_OPENSSL_INIT_SSL} = 1;
 		}
-
-		# Symbols needed with OpenSSL 1.0.2 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '0' && $digit3 >= '2'))
-		{
-			$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
-		}
 	}
 
 	$self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
-- 
2.40.1

#11Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#10)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 26 May 2023, at 04:08, Michael Paquier <michael@paquier.xyz> wrote:
On Thu, May 25, 2023 at 10:16:27AM +0200, Daniel Gustafsson wrote:

The changes to the Windows buildsystem worry me a bit, but they don't move the
goalposts in either direction wrt to LibreSSL on Windows so for the purpose of
this patch we don't need to do more. Longer term we should either make
LibreSSL work on Windows builds, or explicitly not support it on Windows.

Yes, I was wondering what to do about that in the long term. With the
argument that the MSVC scripts may be gone over meson, it is not
really appealing to dig into that.

Yeah, let's revisit this during the v17 cycle when the future of these scripts
will become clearer.

Something that was missing in 0001 is the bump of OPENSSL_API_COMPAT
in meson.build. This was in 0002.

Please find attached an updated patch only for the removal of 1.0.1.
Thanks for the review.

LGTM.

--
Daniel Gustafsson

#12Jacob Champion
jchampion@timescale.com
In reply to: Michael Paquier (#10)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, May 25, 2023 at 7:09 PM Michael Paquier <michael@paquier.xyz> wrote:

Please find attached an updated patch only for the removal of 1.0.1.
Thanks for the review.

Nice! Sorry about the new complications with LibreSSL. :(

-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
+  # Function introduced in OpenSSL 1.0.2. LibreSSL does not have
# SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([X509_get_signature_nid SSL_CTX_set_cert_cb])
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])

Can X509_get_signature_nid be moved to the required section up above?
As it is now, anyone configuring with -Dssl=auto can still pick up a
1.0.1 build, which Meson accepts, and then the build fails downstream.
If we require the function instead, Meson will ignore 1.0.1 (or, for
-Dssl=openssl, complain before we compile).

t/001_ssltests.pl has a reference to 1.0.1 that can probably be
entirely deleted:

# ... (Nor for OpenSSL
# 1.0.1, but that's old enough that accommodating it isn't worth the cost.)

Thanks,
--Jacob

#13Michael Paquier
michael@paquier.xyz
In reply to: Jacob Champion (#12)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, May 26, 2023 at 09:10:17AM -0700, Jacob Champion wrote:

Can X509_get_signature_nid be moved to the required section up above?
As it is now, anyone configuring with -Dssl=auto can still pick up a
1.0.1 build, which Meson accepts, and then the build fails downstream.
If we require the function instead, Meson will ignore 1.0.1 (or, for
-Dssl=openssl, complain before we compile).

Yes, I was wondering a bit if something more should be marked as
required, but just saw more value in removing all references to this
function. Making the build fail straight when setting up things is OK
by me, but I am not convinced that X509_get_signature_nid() would be
the right choice for the job, as it is an OpenSSL artifact originally,
AFAIK.

The same problem exists with OpenSSL 1.0.0 on HEAD when building with
meson? CRYPTO_new_ex_data() and SSL_new() exist there.

t/001_ssltests.pl has a reference to 1.0.1 that can probably be
entirely deleted:

# ... (Nor for OpenSSL
# 1.0.1, but that's old enough that accommodating it isn't worth the cost.)

Not touching that is intentional. It sounded useful to me as an
historic reference for LibreSSL ;)
--
Michael

#14Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#13)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 27 May 2023, at 04:02, Michael Paquier <michael@paquier.xyz> wrote:

Making the build fail straight when setting up things is OK
by me, but I am not convinced that X509_get_signature_nid() would be
the right choice for the job, as it is an OpenSSL artifact originally,
AFAIK.

I think we should avoid the is-defined-in dance and just pull out the version
numbers for comparisons. While it's true that LibreSSL doesn't play well with
OpenSSL versions, they do define their own which can be checked for to
distinguish the libraries.

--
Daniel Gustafsson

#15Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#14)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Jun 02, 2023 at 10:35:43AM +0200, Daniel Gustafsson wrote:

I think we should avoid the is-defined-in dance and just pull out the version
numbers for comparisons. While it's true that LibreSSL doesn't play well with
OpenSSL versions, they do define their own which can be checked for to
distinguish the libraries.

Agreed. How about tackling that in a separate patch? At this stage,
I would like to not care about ./configure and do it only with meson,
but there is value in reporting the version number in ./configure to
see the version coverage in the buildfarm.
--
Michael

#16Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#15)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 2 Jun 2023, at 23:21, Michael Paquier <michael@paquier.xyz> wrote:

On Fri, Jun 02, 2023 at 10:35:43AM +0200, Daniel Gustafsson wrote:

I think we should avoid the is-defined-in dance and just pull out the version
numbers for comparisons. While it's true that LibreSSL doesn't play well with
OpenSSL versions, they do define their own which can be checked for to
distinguish the libraries.

Agreed. How about tackling that in a separate patch?

Absolutely, let's keep these goalposts in place and deal with that separately.

--
Daniel Gustafsson

#17Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#16)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Jun 02, 2023 at 11:23:19PM +0200, Daniel Gustafsson wrote:

Absolutely, let's keep these goalposts in place and deal with that separately.

I have not gone back to this part yet, though I plan to do so. As we
are at the beginning of the development cycle, I have applied the
patch to remove support for 1.0.1 for now on HEAD. Let's see what the
buildfarm tells.
--
Michael

#18Thomas Munro
thomas.munro@gmail.com
In reply to: Michael Paquier (#17)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Mon, Jul 3, 2023 at 4:26 PM Michael Paquier <michael@paquier.xyz> wrote:

I have not gone back to this part yet, though I plan to do so. As we
are at the beginning of the development cycle, I have applied the
patch to remove support for 1.0.1 for now on HEAD. Let's see what the
buildfarm tells.

curculio (OpenBSD 5.9) is failing with "undefined reference to
`X509_get_signature_nid'", but that's OK, Mikael already supplied a
modern OpenBSD system to replace it (schnauzer, which is green) and he
was planning to shut curculio down (see Direct I/O thread where that
came up because its GCC 4.2 compiler doesn't understand our stack
alignment directives; it will also break comprehensively when I push
the nearby all-supported-computers-have-locale_t patch from the
check_strxfrm_bug thread).

#19Daniel Gustafsson
daniel@yesql.se
In reply to: Thomas Munro (#18)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 3 Jul 2023, at 20:40, Thomas Munro <thomas.munro@gmail.com> wrote:

On Mon, Jul 3, 2023 at 4:26 PM Michael Paquier <michael@paquier.xyz> wrote:

I have not gone back to this part yet, though I plan to do so. As we
are at the beginning of the development cycle, I have applied the
patch to remove support for 1.0.1 for now on HEAD. Let's see what the
buildfarm tells.

curculio (OpenBSD 5.9) is failing with "undefined reference to
`X509_get_signature_nid'", but that's OK, Mikael already supplied a
modern OpenBSD system to replace it

Thanks for the report! OpenBSD 5.9 was released in 2016 and is thus well over
5 years EOL, so I agree that it doesn't warrant a code change from us to
support this.

--
Daniel Gustafsson

#20Mikael Kjellström
mikael.kjellstrom@mksoft.nu
In reply to: Daniel Gustafsson (#19)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 2023-07-03 20:53, Daniel Gustafsson wrote:

curculio (OpenBSD 5.9) is failing with "undefined reference to
`X509_get_signature_nid'", but that's OK, Mikael already supplied a
modern OpenBSD system to replace it

Thanks for the report! OpenBSD 5.9 was released in 2016 and is thus well over
5 years EOL, so I agree that it doesn't warrant a code change from us to
support this.

I have retired curculio now. So it will stop reporting in from now on.

/Mikael

#21Michael Paquier
michael@paquier.xyz
In reply to: Mikael Kjellström (#20)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Mon, Jul 03, 2023 at 10:23:02PM +0200, Mikael Kjellström wrote:

On 2023-07-03 20:53, Daniel Gustafsson wrote:

curculio (OpenBSD 5.9) is failing with "undefined reference to
`X509_get_signature_nid'", but that's OK, Mikael already supplied a
modern OpenBSD system to replace it

Thanks for the report! OpenBSD 5.9 was released in 2016 and is thus well over
5 years EOL, so I agree that it doesn't warrant a code change from us to
support this.

OpenBSD 5.9 was EOL in 2017 as far as I know.

I have retired curculio now. So it will stop reporting in from now on.

Thanks Mikael!
--
Michael

#22Michael Paquier
michael@paquier.xyz
In reply to: Thomas Munro (#18)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, Jul 04, 2023 at 06:40:49AM +1200, Thomas Munro wrote:

curculio (OpenBSD 5.9) is failing with "undefined reference to
`X509_get_signature_nid'", but that's OK, Mikael already supplied a
modern OpenBSD system to replace it (schnauzer, which is green) and he
was planning to shut curculio down (see Direct I/O thread where that
came up because its GCC 4.2 compiler doesn't understand our stack
alignment directives; it will also break comprehensively when I push
the nearby all-supported-computers-have-locale_t patch from the
check_strxfrm_bug thread).

The second and third animals to fail are skate and snapper, both using
Debian 7 Wheezy. As far as I know, it was an LTS supported until
2018. The owner of both machines is added in CC. I guess that we
this stuff could just remove --with-openssl from the configure
switches.
--
Michael

#23Michael Paquier
michael@paquier.xyz
In reply to: Michael Paquier (#22)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, Jul 04, 2023 at 07:16:47AM +0900, Michael Paquier wrote:

The second and third animals to fail are skate and snapper, both using
Debian 7 Wheezy. As far as I know, it was an LTS supported until
2018. The owner of both machines is added in CC. I guess that we
this stuff could just remove --with-openssl from the configure
switches.

lapwing has reported a failure and runs a Debian 7, so adding Julien
in CC about the removal of --with-openssl or similar in this animal.
--
Michael

#24Julien Rouhaud
rjuju123@gmail.com
In reply to: Michael Paquier (#23)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Hi,

On Tue, Jul 04, 2023 at 03:03:01PM +0900, Michael Paquier wrote:

On Tue, Jul 04, 2023 at 07:16:47AM +0900, Michael Paquier wrote:

The second and third animals to fail are skate and snapper, both using
Debian 7 Wheezy. As far as I know, it was an LTS supported until
2018. The owner of both machines is added in CC. I guess that we
this stuff could just remove --with-openssl from the configure
switches.

lapwing has reported a failure and runs a Debian 7, so adding Julien
in CC about the removal of --with-openssl or similar in this animal.

Thanks, I actually saw that and already took care of removing openssl support a
couple of hours ago, and also added a new note on the animal to remember when
it was removed. It should come back to green at the next scheduled run.

#25Michael Paquier
michael@paquier.xyz
In reply to: Julien Rouhaud (#24)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, Jul 04, 2023 at 02:15:18PM +0800, Julien Rouhaud wrote:

Thanks, I actually saw that and already took care of removing openssl support a
couple of hours ago, and also added a new note on the animal to remember when
it was removed. It should come back to green at the next scheduled run.

Thanks!
--
Michael

#26Thomas Munro
thomas.munro@gmail.com
In reply to: Daniel Gustafsson (#4)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, May 24, 2023 at 11:03 PM Daniel Gustafsson <daniel@yesql.se> wrote:

On 24 May 2023, at 11:52, Michael Paquier <michael@paquier.xyz> wrote:
On Wed, May 24, 2023 at 11:36:56AM +0200, Daniel Gustafsson wrote:

1.0.2 is also an LTS version available commercially for premium support
customers of OpenSSL (1.1.1 will become an LTS version as well), with 1.0.2zh
slated for release next week. This raises the likelyhood of Postgres
installations using 1.0.2 in production still, and for some time to come.

Good point. Indeed, that makes it pretty clear that not dropping
1.0.2 would be the best option for the time being, so 0001 would be
enough.

I think thats the right move re 1.0.2 support. 1.0.2 is also the version in
RHEL7 which is in ELS until 2026.

I don't mind either way if we rip out OpenSSL 1.0.2 support now or
later, other than a general feeling that cryptography must be about
the worst possible category of software to keep supporting for years
after it has been declared EOL.

But.. I don't like the idea that our *next* release's library version
horizon is controlled by Red Hat's "ELS" phase. The
yum.postgresql.org team aren't packaging 17 for RHEL7 AFAICS, which is
as it should be if you ask me, because the 10 year maintenance phase
ends before 17 will ship. These hypothetical users that want to run
an OS even older than that and don't know how to get modern crypto
libraries on it but insist on a shiny new PostgreSQL release and build
it from source because there are no packages available... don't exist?

#27Daniel Gustafsson
daniel@yesql.se
In reply to: Thomas Munro (#26)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 7 Sep 2023, at 13:30, Thomas Munro <thomas.munro@gmail.com> wrote:

I don't like the idea that our *next* release's library version
horizon is controlled by Red Hat's "ELS" phase.

Agreed. If we instead fence it by "only non-EOL version" then 1.1.1 is also on
the chopping block for v17 as it goes EOL in 4 days from now with 1.1.1w (which
contains a CVE, going out with a bang). Not sure what the best strategy is,
but whichever we opt for I think the most important point is to document it
clearly.

These hypothetical users that want to run
an OS even older than that and don't know how to get modern crypto
libraries on it but insist on a shiny new PostgreSQL release and build
it from source because there are no packages available... don't exist?

Sadly I wouldn't be the least bit surprised if there are 1.0.2 users on modern
operating systems, especially given its LTS status (which OpenSSL hasn't even
capped but sells by "for as long as it remains commercially viable to do so"
basis). That being said, my gut feeling is that 3.x has gotten pretty good
market penetration.

--
Daniel Gustafsson

#28Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#27)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, Sep 07, 2023 at 01:44:11PM +0200, Daniel Gustafsson wrote:

Sadly I wouldn't be the least bit surprised if there are 1.0.2 users on modern
operating systems, especially given its LTS status (which OpenSSL hasn't even
capped but sells by "for as long as it remains commercially viable to do so"
basis).

Yes, I would not be surprised by that either. TBH, I don't like much
the fact that we rely on OpenSSL to decide when we should cut it.
Particularly since all the changes given to it after it got EOL'd are
close source at this point.

That being said, my gut feeling is that 3.x has gotten pretty good
market penetration.

Perhaps.
--
Michael

#29Thomas Munro
thomas.munro@gmail.com
In reply to: Michael Paquier (#28)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Sep 8, 2023 at 11:48 AM Michael Paquier <michael@paquier.xyz> wrote:

On Thu, Sep 07, 2023 at 01:44:11PM +0200, Daniel Gustafsson wrote:

Sadly I wouldn't be the least bit surprised if there are 1.0.2 users on modern
operating systems, especially given its LTS status (which OpenSSL hasn't even
capped but sells by "for as long as it remains commercially viable to do so"
basis).

Yes, I would not be surprised by that either. TBH, I don't like much
the fact that we rely on OpenSSL to decide when we should cut it.
Particularly since all the changes given to it after it got EOL'd are
close source at this point.

Right, just like there are people running ancient PostgreSQL and
buying support. That's not relevant to PostgreSQL 17 IMHO, which
should target contemporary distributions.

BTW I'm not asking anyone to do anything here, I just didn't want to
allow the "RHEL ELS" and "closed source OpenSSL [sic]" theories
mentioned on this thread to go unchallenged. Next time I'm trying to
clean up some other cruft in our tree, I don't want this thread to be
cited as evidence that that is our policy, because I don't buy it, it
doesn't make any sense. Of course there is someone, somewhere selling
support for anything you can think of. There are companies that
support VAXen. There's a company in Irvine, California selling and
supporting modern drop-in replacements for PDP 11s for production use.

#30Thomas Munro
thomas.munro@gmail.com
In reply to: Daniel Gustafsson (#27)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, Sep 7, 2023 at 11:44 PM Daniel Gustafsson <daniel@yesql.se> wrote:

On 7 Sep 2023, at 13:30, Thomas Munro <thomas.munro@gmail.com> wrote:
I don't like the idea that our *next* release's library version
horizon is controlled by Red Hat's "ELS" phase.

Agreed. If we instead fence it by "only non-EOL version" then 1.1.1 is also on
the chopping block for v17 as it goes EOL in 4 days from now with 1.1.1w (which
contains a CVE, going out with a bang). Not sure what the best strategy is,
but whichever we opt for I think the most important point is to document it
clearly.

I was reminded of this thread by ambient security paranoia. As it
stands, we require 1.0.2 (but we very much hope that package
maintainers and others in control of builds don't decide to use it).
Should we skip 1.1.1 and move to requiring 3 for v17?

Upstream says:

"The latest stable version is the 3.2 series supported until 23rd
November 2025. Also available is the 3.1 series supported until 14th
March 2025, and the 3.0 series which is a Long Term Support (LTS)
version and is supported until 7th September 2026. All older versions
(including 1.1.1, 1.1.0, 1.0.2, 1.0.0 and 0.9.8) are now out of
support and should not be used."

I understand that some distros eg RHEL8 will continue to ship and
presumably patch 1.1.1 until some date later than upstream's EOL, for
stability and the benefit of people that really need it for a bit
longer, but that's in parallel with their package for 3, right? New
things should surely be able to require new things. I think we'd have
to reject the argument that we should support it just because they
ship it until the year 2030, or that upstream will support anything
for $50,000/year. I mean, they only do that because some old apps
need it, to which I say 40P01 DEADLOCK DETECTED.

#31Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#30)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Thomas Munro <thomas.munro@gmail.com> writes:

I was reminded of this thread by ambient security paranoia. As it
stands, we require 1.0.2 (but we very much hope that package
maintainers and others in control of builds don't decide to use it).
Should we skip 1.1.1 and move to requiring 3 for v17?

I'd be kind of sad if I couldn't test SSL stuff anymore on my
primary workstation, which has

$ rpm -q openssl
openssl-1.1.1k-12.el8_9.x86_64

I think it's probably true that <=1.0.2 is not in any distro that
we still need to pay attention to, but I reject the contention
that RHEL8 is not in that set.

regards, tom lane

#32Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#31)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Sun, Mar 31, 2024 at 9:59 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

I was reminded of this thread by ambient security paranoia. As it
stands, we require 1.0.2 (but we very much hope that package
maintainers and others in control of builds don't decide to use it).
Should we skip 1.1.1 and move to requiring 3 for v17?

I'd be kind of sad if I couldn't test SSL stuff anymore on my
primary workstation, which has

$ rpm -q openssl
openssl-1.1.1k-12.el8_9.x86_64

I think it's probably true that <=1.0.2 is not in any distro that
we still need to pay attention to, but I reject the contention
that RHEL8 is not in that set.

Hmm, OK so it doesn't have 3 available in parallel from base repos.
But it's also about to reach end of "full support" in 2 months[1]https://access.redhat.com/product-life-cycles?product=Red%20Hat%20Enterprise%20Linux, so
if we applied the policies we discussed in the LLVM-vacuuming thread
(to wit: build farm - EOL'd OSes), then... One question I'm unclear
on is whether v17 will be packaged for RHEL8.

[1]: https://access.redhat.com/product-life-cycles?product=Red%20Hat%20Enterprise%20Linux

#33Daniel Gustafsson
daniel@yesql.se
In reply to: Thomas Munro (#32)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 30 Mar 2024, at 22:27, Thomas Munro <thomas.munro@gmail.com> wrote:
On Sun, Mar 31, 2024 at 9:59 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thanks a lot for bringing this up again Thomas, 1.0.2 has bitten me so many
times and I'd be thrilled to get rid of it.

I think it's probably true that <=1.0.2 is not in any distro that
we still need to pay attention to, but I reject the contention
that RHEL8 is not in that set.

Hmm, OK so it doesn't have 3 available in parallel from base repos.
But it's also about to reach end of "full support" in 2 months[1], so
if we applied the policies we discussed in the LLVM-vacuuming thread
(to wit: build farm - EOL'd OSes), then... One question I'm unclear
on is whether v17 will be packaged for RHEL8.

While 1.1.1 is EOL in upstream, it won't buy us much to deprecate past it since
we don't really make use of 3.x specific functionality. I wouldn't mind not
being on the hook to support an EOL version of OpenSSL for another 5 years, but
it also won't shift the needle too much. For v18 I'd like to work on modernize
our OpenSSL code to make more use of 3+ features/API's and that could be a good
point to cull 1.1.1 support.

Settling for removing support for 1.0.2, which is antiques roadshow material at
this point (no TLSv1.3 support for example), removes most of the compatibility
mess we have in libpq. 1.1.1 was not a deprecation point in OpenSSL but we can
define 1.1.0 as our compatibility level to build warning-free.

The attached removes 1.0.2 support (meson build parts untested yet) with a few
small touch ups of related documentation. I haven't yet done the research on
where that leaves LibreSSL since we don't really define anywhere what we
support (so for we've gotten by assuming it's kind of sort 1.0.2 for the parts
we care about which is skating on fairly thin ice).

--
Daniel Gustafsson

Attachments:

v1-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patchapplication/octet-stream; name=v1-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patch; x-unix-mode=0644Download
From 30ca8928a0a6bd901105529fe664e989122ed6ae Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Tue, 2 Apr 2024 20:46:41 +0200
Subject: [PATCH v1] Remove support for OpenSSL 1.0.2 and 1.1.0

This sets the required version of OpenSSL at 1.1.1.
---
 configure                                |  40 +----
 configure.ac                             |  19 +--
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |   4 +-
 meson.build                              |  21 +--
 src/backend/libpq/be-secure-openssl.c    |  33 +---
 src/common/hmac_openssl.c                |  13 --
 src/include/pg_config.h.in               |  21 ---
 src/interfaces/libpq/fe-secure-openssl.c | 205 +----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 10 files changed, 20 insertions(+), 343 deletions(-)

diff --git a/configure b/configure
index 36feeafbb2..16b7b1fef9 100755
--- a/configure
+++ b/configure
@@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as he deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12556,36 +12557,8 @@ _ACEOF
 fi
 done
 
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
 
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
-_ACEOF
-
-fi
-done
+$as_echo "#define USE_OPENSSL 1" >>confdefs.h
 
   # Function introduced in OpenSSL 1.1.1.
   for ac_func in X509_get_signature_info
@@ -12596,12 +12569,11 @@ if test "x$ac_cv_func_X509_get_signature_info" = xyes; then :
 #define HAVE_X509_GET_SIGNATURE_INFO 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL, version 1.1.1 or newer, is required for SSL support" "$LINENO" 5
 fi
 done
 
-
-$as_echo "#define USE_OPENSSL 1" >>confdefs.h
-
 elif test "$with_ssl" != no ; then
   as_fn_error $? "--with-ssl must specify openssl" "$LINENO" 5
 fi
diff --git a/configure.ac b/configure.ac
index 57f734879e..9d9e976de5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,9 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as he deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1347,19 +1348,9 @@ if test "$with_ssl" = openssl ; then
   fi
   # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
   AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
-  AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
+  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([X509_get_signature_info], [], [AC_MSG_ERROR([OpenSSL, version 1.1.1 or newer, is required for SSL support])])
 elif test "$with_ssl" != no ; then
   AC_MSG_ERROR([--with-ssl must specify openssl])
 fi
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..1d5578d935 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.1.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index d3e87056f2..e718d355bb 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1741,9 +1741,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
         <productname>PostgreSQL</productname> 14 disables compression
         completely in the backend.
diff --git a/meson.build b/meson.build
index 18b5be842e..119f9c9405 100644
--- a/meson.build
+++ b/meson.build
@@ -1274,25 +1274,8 @@ if sslopt in ['auto', 'openssl']
 
       # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
       ['SSL_CTX_set_cert_cb'],
-
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-      # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
       # Function introduced in OpenSSL 1.1.1
-      ['X509_get_signature_info'],
+      ['X509_get_signature_info', {'required': true}]
     ]
 
     are_openssl_funcs_complete = true
@@ -1314,7 +1297,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 72e43af353..c0227f6239 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -98,13 +98,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -261,15 +255,11 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
 	 */
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
-#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
@@ -531,10 +521,8 @@ aloop:
 					case SSL_R_WRONG_SSL_VERSION:
 					case SSL_R_WRONG_VERSION_NUMBER:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
-#ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
 					case SSL_R_VERSION_TOO_LOW:
-#endif
 						give_proto_hint = true;
 						break;
 					default:
@@ -898,7 +886,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -921,14 +908,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
@@ -1468,15 +1447,9 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 
 	/*
 	 * Get the signature algorithm of the certificate to determine the hash
-	 * algorithm to use for the result.  Prefer X509_get_signature_info(),
-	 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
+	 * algorithm to use for the result.
 	 */
-#if HAVE_X509_GET_SIGNATURE_INFO
 	if (!X509_get_signature_info(server_cert, &algo_nid, NULL, NULL, NULL))
-#else
-	if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert),
-							 &algo_nid, NULL))
-#endif
 		elog(ERROR, "could not determine server certificate signature algorithm");
 
 	/*
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index d10f7e5af7..89d71a819e 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -138,14 +138,10 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-#ifdef HAVE_HMAC_CTX_NEW
 #ifndef FRONTEND
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -159,14 +155,10 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifdef HAVE_HMAC_CTX_NEW
 #ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
 #endif
-#else
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif							/* HAVE_HMAC_CTX_NEW */
 
 	return ctx;
 }
@@ -325,16 +317,11 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
 #ifndef FRONTEND
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
 #endif
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
 
 	explicit_bzero(ctx, sizeof(pg_hmac_ctx));
 	FREE(ctx);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 591e1ca3df..d2286e0b44 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
@@ -303,9 +288,6 @@
 /* Define to 1 if you have the `mkdtemp' function. */
 #undef HAVE_MKDTEMP
 
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
-#undef HAVE_OPENSSL_INIT_SSL
-
 /* Define to 1 if you have the <ossp/uuid.h> header file. */
 #undef HAVE_OSSP_UUID_H
 
@@ -507,9 +489,6 @@
 /* Define to 1 if you have the `wcstombs_l' function. */
 #undef HAVE_WCSTOMBS_L
 
-/* Define to 1 if you have the `X509_get_signature_info' function. */
-#undef HAVE_X509_GET_SIGNATURE_INFO
-
 /* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
 #undef HAVE_X86_64_POPCNTQ
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0c8c9f8dcb..dd9dfe963c 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -377,15 +376,9 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 
 	/*
 	 * Get the signature algorithm of the certificate to determine the hash
-	 * algorithm to use for the result.  Prefer X509_get_signature_info(),
-	 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
+	 * algorithm to use for the result.
 	 */
-#if HAVE_X509_GET_SIGNATURE_INFO
 	if (!X509_get_signature_info(peer_cert, &algo_nid, NULL, NULL, NULL))
-#else
-	if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
-							 &algo_nid, NULL))
-#endif
 	{
 		libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
 		return NULL;
@@ -505,11 +498,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +529,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +697,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +713,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +724,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -1596,8 +1435,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1612,8 +1449,6 @@ pgtls_close(PGconn *conn)
 			SSL_free(conn->ssl);
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1631,30 +1466,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1895,7 +1706,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1921,14 +1731,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1936,13 +1738,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9c05f11a6e..d049087301 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -565,11 +565,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.32.1 (Apple Git-133)

#34Daniel Gustafsson
daniel@yesql.se
In reply to: Daniel Gustafsson (#33)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 2 Apr 2024, at 20:55, Daniel Gustafsson <daniel@yesql.se> wrote:

The attached removes 1.0.2 support (meson build parts untested yet)

And a rebased version which applies over the hmac_openssl.c changes earlier
today that I hadn't pulled in.

--
Daniel Gustafsson

Attachments:

v2-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patchapplication/octet-stream; name=v2-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patch; x-unix-mode=0644Download
From 1c9b9a13f8ae5fdab0d71d572eea6b572ba10751 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Tue, 2 Apr 2024 20:46:41 +0200
Subject: [PATCH v2] Remove support for OpenSSL 1.0.2 and 1.1.0

This sets the required version of OpenSSL at 1.1.1.
---
 configure                                |  40 +----
 configure.ac                             |  19 +--
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |   4 +-
 meson.build                              |  21 +--
 src/backend/libpq/be-secure-openssl.c    |  33 +---
 src/common/hmac_openssl.c                |  34 +---
 src/include/pg_config.h.in               |  21 ---
 src/interfaces/libpq/fe-secure-openssl.c | 205 +----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 10 files changed, 27 insertions(+), 357 deletions(-)

diff --git a/configure b/configure
index 36feeafbb2..16b7b1fef9 100755
--- a/configure
+++ b/configure
@@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as he deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12556,36 +12557,8 @@ _ACEOF
 fi
 done
 
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
 
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
-_ACEOF
-
-fi
-done
+$as_echo "#define USE_OPENSSL 1" >>confdefs.h
 
   # Function introduced in OpenSSL 1.1.1.
   for ac_func in X509_get_signature_info
@@ -12596,12 +12569,11 @@ if test "x$ac_cv_func_X509_get_signature_info" = xyes; then :
 #define HAVE_X509_GET_SIGNATURE_INFO 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL, version 1.1.1 or newer, is required for SSL support" "$LINENO" 5
 fi
 done
 
-
-$as_echo "#define USE_OPENSSL 1" >>confdefs.h
-
 elif test "$with_ssl" != no ; then
   as_fn_error $? "--with-ssl must specify openssl" "$LINENO" 5
 fi
diff --git a/configure.ac b/configure.ac
index 57f734879e..9d9e976de5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,9 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as he deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1347,19 +1348,9 @@ if test "$with_ssl" = openssl ; then
   fi
   # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
   AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
-  AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
+  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([X509_get_signature_info], [], [AC_MSG_ERROR([OpenSSL, version 1.1.1 or newer, is required for SSL support])])
 elif test "$with_ssl" != no ; then
   AC_MSG_ERROR([--with-ssl must specify openssl])
 fi
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..1d5578d935 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.1.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index e69feacfe6..c4a3804254 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1779,9 +1779,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
         <productname>PostgreSQL</productname> 14 disables compression
         completely in the backend.
diff --git a/meson.build b/meson.build
index 18b5be842e..119f9c9405 100644
--- a/meson.build
+++ b/meson.build
@@ -1274,25 +1274,8 @@ if sslopt in ['auto', 'openssl']
 
       # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
       ['SSL_CTX_set_cert_cb'],
-
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-      # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
       # Function introduced in OpenSSL 1.1.1
-      ['X509_get_signature_info'],
+      ['X509_get_signature_info', {'required': true}]
     ]
 
     are_openssl_funcs_complete = true
@@ -1314,7 +1297,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 72e43af353..c0227f6239 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -98,13 +98,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -261,15 +255,11 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
 	 */
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
-#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
@@ -531,10 +521,8 @@ aloop:
 					case SSL_R_WRONG_SSL_VERSION:
 					case SSL_R_WRONG_VERSION_NUMBER:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
-#ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
 					case SSL_R_VERSION_TOO_LOW:
-#endif
 						give_proto_hint = true;
 						break;
 					default:
@@ -898,7 +886,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -921,14 +908,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
@@ -1468,15 +1447,9 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 
 	/*
 	 * Get the signature algorithm of the certificate to determine the hash
-	 * algorithm to use for the result.  Prefer X509_get_signature_info(),
-	 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
+	 * algorithm to use for the result.
 	 */
-#if HAVE_X509_GET_SIGNATURE_INFO
 	if (!X509_get_signature_info(server_cert, &algo_nid, NULL, NULL, NULL))
-#else
-	if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert),
-							 &algo_nid, NULL))
-#endif
 		elog(ERROR, "could not determine server certificate signature algorithm");
 
 	/*
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..c2506de7c5 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,11 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
-#define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -68,13 +62,13 @@ struct pg_hmac_ctx
 	pg_hmac_errno error;
 	const char *errreason;
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwner resowner;
 #endif
 };
 
 /* ResourceOwner callbacks to hold HMAC contexts */
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void ResOwnerReleaseHMAC(Datum res);
 
 static const ResourceOwnerDesc hmac_resowner_desc =
@@ -139,16 +133,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,11 +151,8 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
 #endif
@@ -328,14 +314,8 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
 #endif
@@ -379,7 +359,7 @@ pg_hmac_error(pg_hmac_ctx *ctx)
 
 /* ResourceOwner callbacks */
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void
 ResOwnerReleaseHMAC(Datum res)
 {
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 591e1ca3df..d2286e0b44 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
@@ -303,9 +288,6 @@
 /* Define to 1 if you have the `mkdtemp' function. */
 #undef HAVE_MKDTEMP
 
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
-#undef HAVE_OPENSSL_INIT_SSL
-
 /* Define to 1 if you have the <ossp/uuid.h> header file. */
 #undef HAVE_OSSP_UUID_H
 
@@ -507,9 +489,6 @@
 /* Define to 1 if you have the `wcstombs_l' function. */
 #undef HAVE_WCSTOMBS_L
 
-/* Define to 1 if you have the `X509_get_signature_info' function. */
-#undef HAVE_X509_GET_SIGNATURE_INFO
-
 /* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
 #undef HAVE_X86_64_POPCNTQ
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0c8c9f8dcb..dd9dfe963c 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -377,15 +376,9 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 
 	/*
 	 * Get the signature algorithm of the certificate to determine the hash
-	 * algorithm to use for the result.  Prefer X509_get_signature_info(),
-	 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
+	 * algorithm to use for the result.
 	 */
-#if HAVE_X509_GET_SIGNATURE_INFO
 	if (!X509_get_signature_info(peer_cert, &algo_nid, NULL, NULL, NULL))
-#else
-	if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
-							 &algo_nid, NULL))
-#endif
 	{
 		libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
 		return NULL;
@@ -505,11 +498,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +529,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +697,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +713,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +724,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -1596,8 +1435,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1612,8 +1449,6 @@ pgtls_close(PGconn *conn)
 			SSL_free(conn->ssl);
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1631,30 +1466,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1895,7 +1706,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1921,14 +1731,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1936,13 +1738,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9c05f11a6e..d049087301 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -565,11 +565,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.32.1 (Apple Git-133)

#35Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Daniel Gustafsson (#33)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, Apr 2, 2024 at 11:55 AM Daniel Gustafsson <daniel@yesql.se> wrote:

The attached removes 1.0.2 support (meson build parts untested yet) with a few
small touch ups of related documentation. I haven't yet done the research on
where that leaves LibreSSL since we don't really define anywhere what we
support (so for we've gotten by assuming it's kind of sort 1.0.2 for the parts
we care about which is skating on fairly thin ice).

As far as I can tell, no versions of LibreSSL so far provide
X509_get_signature_info(), so this patch is probably a bit too
aggressive.

--Jacob

#36Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jacob Champion (#35)
2 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Jacob Champion <jacob.champion@enterprisedb.com> writes:

As far as I can tell, no versions of LibreSSL so far provide
X509_get_signature_info(), so this patch is probably a bit too
aggressive.

Another problem with cutting support is how many buildfarm members
will we lose. I scraped recent configure logs and got the attached
results. I count 3 machines running 1.0.1, 18 running some flavor
of 1.0.2, and 7 running various LibreSSL versions. We could
probably retire or update the 1.0.1 installations, but the rest
would represent a heavier lift. Notably, it seems that what macOS
is shipping is LibreSSL.

regards, tom lane

Attachments:

opensslversionstext/plain; charset=us-ascii; name=opensslversionsDownload
opensslmesontext/plain; charset=us-ascii; name=opensslmesonDownload
#37Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Tom Lane (#36)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 3, 2024 at 8:29 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

I count 3 machines running 1.0.1, 18 running some flavor
of 1.0.2, and 7 running various LibreSSL versions.

I don't know all the tradeoffs with buildfarm wrangling, but IMO all
those 1.0.2 installations are the most problematic, so I dug in a bit:

arowana CentOS 7
batfish Ubuntu 16.04.3
boa RHEL 7
buri CentOS 7
butterflyfish Photon 2.0
clam RHEL 7.1
cuon Ubuntu 16.04
dhole CentOS 7.4
hake OpenIndiana hipster
mantid CentOS 7.9
margay Solaris 11.4.42
massasauga Amazon Linux 2
myna Photon 3.0
parula Amazon Linux 2
rhinoceros CentOS 7.1
shelduck SUSE 12SP5
siskin RHEL 7.9
snakefly Amazon Linux 2

The RHEL7-alikes are the biggest set, but that's already discussed
above. Looks like SUSE 12 goes EOL later this year (October 2024), and
it ships OpenSSL 1.1.1 as an option. Already-dead distros are Ubuntu
16.04 (April 2021), Photon 2 (January 2023), and Photon 3 (March
2024). That leaves AL2, OpenIndiana Hipster, and Solaris 11.4, all of
which appear to have newer versions of OpenSSL shipped and selectable.

--Jacob

#38Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jacob Champion (#37)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Jacob Champion <jacob.champion@enterprisedb.com> writes:

The RHEL7-alikes are the biggest set, but that's already discussed
above. Looks like SUSE 12 goes EOL later this year (October 2024), and
it ships OpenSSL 1.1.1 as an option. Already-dead distros are Ubuntu
16.04 (April 2021), Photon 2 (January 2023), and Photon 3 (March
2024). That leaves AL2, OpenIndiana Hipster, and Solaris 11.4, all of
which appear to have newer versions of OpenSSL shipped and selectable.

The discussion we had last year concluded that we were OK with
dropping 1.0.1 support when RHEL6 goes out of extended support
(June 2024 per this thread, I didn't check it). Seems like we
should have the same policy for RHEL7. Also, calling Photon 3
dead because it went EOL three days ago seems over-hasty.

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

regards, tom lane

#39Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Tom Lane (#38)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 3, 2024 at 10:38 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Also, calling Photon 3
dead because it went EOL three days ago seems over-hasty.

Well, March 1, but either way I thought "dead" for the purposes of
this thread meant "you can't build the very latest version of Postgres
on it", not "we've forgotten it exists". Back branches will continue
to need support and testing.

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

Okay, but IIUC, waiting for it to drop out of extended support means
we deal with it for four more years. That seems excessive.

--Jacob

#40Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jacob Champion (#39)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Jacob Champion <jacob.champion@enterprisedb.com> writes:

On Wed, Apr 3, 2024 at 10:38 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

Okay, but IIUC, waiting for it to drop out of extended support means
we deal with it for four more years. That seems excessive.

wikipedia says that RHEL7 ends ELS as of June 2026 [1]https://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux#Product_life_cycle.

regards, tom lane

[1]: https://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux#Product_life_cycle

#41Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Tom Lane (#40)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 3, 2024 at 11:13 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

wikipedia says that RHEL7 ends ELS as of June 2026 [1].

I may have misunderstood something in here then:

https://www.redhat.com/en/blog/announcing-4-years-extended-life-cycle-support-els-red-hat-enterprise-linux-7

ELS for RHEL 7 is now available for 4 years, starting on July 1, 2024.

Am I missing something?

--Jacob

#42Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#38)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 3 Apr 2024, at 19:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Jacob Champion <jacob.champion@enterprisedb.com> writes:

The RHEL7-alikes are the biggest set, but that's already discussed
above. Looks like SUSE 12 goes EOL later this year (October 2024), and
it ships OpenSSL 1.1.1 as an option. Already-dead distros are Ubuntu
16.04 (April 2021), Photon 2 (January 2023), and Photon 3 (March
2024). That leaves AL2, OpenIndiana Hipster, and Solaris 11.4, all of
which appear to have newer versions of OpenSSL shipped and selectable.

The discussion we had last year concluded that we were OK with
dropping 1.0.1 support when RHEL6 goes out of extended support
(June 2024 per this thread, I didn't check it). Seems like we
should have the same policy for RHEL7. Also, calling Photon 3
dead because it went EOL three days ago seems over-hasty.

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

Is Red Hat building and and shipping v17 packages for RHEL7 ELS customers? If
not then it seems mostly academical to tie our dependencies to RHEL ELS unless
I'm missing something.

--
Daniel Gustafsson

#43Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#36)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 3 Apr 2024, at 17:29, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Jacob Champion <jacob.champion@enterprisedb.com> writes:

As far as I can tell, no versions of LibreSSL so far provide
X509_get_signature_info(), so this patch is probably a bit too
aggressive.

Another problem with cutting support is how many buildfarm members
will we lose. I scraped recent configure logs and got the attached
results. I count 3 machines running 1.0.1,

Support for 1.0.1 was removed with 8e278b657664 in July 2023 so those are not
building with OpenSSL enabled already.

18 running some flavor of 1.0.2,

massasauga and snakefly run the ssl_passphrase_callback-check test but none of
these run the ssl-check tests AFAICT, so we have very low coverage as is. The
fact that very few animals run the ssl tests is a pet peeve of mine, it would
be nice if we could get broader coverage there.

Worth noting is that the OpenSSL check in configure.ac only reports what the
version of the OpenSSL binary in $PATH is, not which version of the library
that we build against (using --with-libs/--with-includes etc).

--
Daniel Gustafsson

#44Andrew Dunstan
andrew@dunslane.net
In reply to: Daniel Gustafsson (#43)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 2024-04-03 We 15:12, Daniel Gustafsson wrote:

The
fact that very few animals run the ssl tests is a pet peeve of mine, it would
be nice if we could get broader coverage there.

Well, the only reason for that is that the SSL tests need to be listed
in PG_TEST_EXTRA, and the only reason for that is that there's a
possible hazard on multi-user servers. But I bet precious few buildfarm
animals run in such an environment. Mine don't - I'm the only user.

Maybe we could send out an email to the buildfarm-owners list asking
people to consider allowing the ssl tests.

cheers

andrew

--
Andrew Dunstan
EDB:https://www.enterprisedb.com

#45Tom Lane
tgl@sss.pgh.pa.us
In reply to: Daniel Gustafsson (#42)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Daniel Gustafsson <daniel@yesql.se> writes:

On 3 Apr 2024, at 19:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

Is Red Hat building and and shipping v17 packages for RHEL7 ELS customers? If
not then it seems mostly academical to tie our dependencies to RHEL ELS unless
I'm missing something.

True, they won't be doing that, and neither will Devrim. So maybe
we can leave RHEL7 out of the discussion, in which case there's
not a lot of reason to keep 1.0.2 support. We'll need to notify
buildfarm owners to adjust their configurations.

regards, tom lane

#46Daniel Gustafsson
daniel@yesql.se
In reply to: Andrew Dunstan (#44)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 3 Apr 2024, at 21:48, Andrew Dunstan <andrew@dunslane.net> wrote:
On 2024-04-03 We 15:12, Daniel Gustafsson wrote:

The
fact that very few animals run the ssl tests is a pet peeve of mine, it would
be nice if we could get broader coverage there.

Well, the only reason for that is that the SSL tests need to be listed in PG_TEST_EXTRA, and the only reason for that is that there's a possible hazard on multi-user servers. But I bet precious few buildfarm animals run in such an environment. Mine don't - I'm the only user.

Maybe we could send out an email to the buildfarm-owners list asking people to consider allowing the ssl tests.

I think that sounds like a good idea.

--
Daniel Gustafsson

#47Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#45)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 4 Apr 2024, at 00:06, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Daniel Gustafsson <daniel@yesql.se> writes:

On 3 Apr 2024, at 19:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

Is Red Hat building and and shipping v17 packages for RHEL7 ELS customers? If
not then it seems mostly academical to tie our dependencies to RHEL ELS unless
I'm missing something.

True, they won't be doing that, and neither will Devrim. So maybe
we can leave RHEL7 out of the discussion, in which case there's
not a lot of reason to keep 1.0.2 support. We'll need to notify
buildfarm owners to adjust their configurations.

The patch will also need to be adjusted to work with LibreSSL, but I know Jacob
was looking into that so ideally we should have something to review before
the weekend.

--
Daniel Gustafsson

#48Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#32)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 30.03.24 22:27, Thomas Munro wrote:

On Sun, Mar 31, 2024 at 9:59 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

I was reminded of this thread by ambient security paranoia. As it
stands, we require 1.0.2 (but we very much hope that package
maintainers and others in control of builds don't decide to use it).
Should we skip 1.1.1 and move to requiring 3 for v17?

I'd be kind of sad if I couldn't test SSL stuff anymore on my
primary workstation, which has

$ rpm -q openssl
openssl-1.1.1k-12.el8_9.x86_64

I think it's probably true that <=1.0.2 is not in any distro that
we still need to pay attention to, but I reject the contention
that RHEL8 is not in that set.

Hmm, OK so it doesn't have 3 available in parallel from base repos.
But it's also about to reach end of "full support" in 2 months[1], so
if we applied the policies we discussed in the LLVM-vacuuming thread
(to wit: build farm - EOL'd OSes), then... One question I'm unclear
on is whether v17 will be packaged for RHEL8.

The rest of the thread talks about the end of support of RHEL 7, but you
are here talking about RHEL 8. It is true that "full support" for RHEL
8 ended in May 2024, but that is the not the one we are tracking. We
are tracking the 10-year one, which I suppose is now called "maintenance
support".

So if the above package list is correct, then we ought to keep
supporting openssl 1.1.* until 2029.

#49Michael Paquier
michael@paquier.xyz
In reply to: Tom Lane (#38)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 03, 2024 at 01:38:50PM -0400, Tom Lane wrote:

The discussion we had last year concluded that we were OK with
dropping 1.0.1 support when RHEL6 goes out of extended support
(June 2024 per this thread, I didn't check it). Seems like we
should have the same policy for RHEL7. Also, calling Photon 3
dead because it went EOL three days ago seems over-hasty.

Yeah. A bunch of users of Photon are VMware (or you could say
Broadcom) product appliances, and I'd suspect that quite a lot of them
rely on Photon 3 for their base OS image. Upgrading that stuff is not
easy work in my experience because they need to cope with a bunch of
embedded services.

Bottom line for me is that pulling 1.0.1 support now is OK,
but I think pulling 1.0.2 is premature.

Yeah, I guess so. At least that seems like the safest conclusion
currently here. The build-time check on X509_get_signature_info()
would still be required.

I'd love being able to rip out the internal locking logic currently in
libpq as LibreSSL has traces of CRYPTO_lock(), as far as I've checked,
and we rely on its existence.
--
Michael

#50Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#48)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, Apr 4, 2024 at 11:51 AM Peter Eisentraut <peter@eisentraut.org> wrote:

On 30.03.24 22:27, Thomas Munro wrote:

Hmm, OK so it doesn't have 3 available in parallel from base repos.
But it's also about to reach end of "full support" in 2 months[1], so
if we applied the policies we discussed in the LLVM-vacuuming thread
(to wit: build farm - EOL'd OSes), then... One question I'm unclear
on is whether v17 will be packaged for RHEL8.

The rest of the thread talks about the end of support of RHEL 7, but you
are here talking about RHEL 8. It is true that "full support" for RHEL
8 ended in May 2024, but that is the not the one we are tracking. We
are tracking the 10-year one, which I suppose is now called "maintenance
support".

I might have confused myself with the two EOLs and some wishful
thinking. I am a lot less worked up about this general topic now that
RHEL has moved to "rolling" LLVM updates in minor releases, removing a
physical-pain-inducing 10-year vacuuming horizon (that's 20 LLVM major
releases and they only fix bugs in one...). I will leave openssl
discussions to those more knowledgeable about that.

So if the above package list is correct, then we ought to keep
supporting openssl 1.1.* until 2029.

That's a shame. But it sounds like the developer burden isn't so
different from 1.1.1 to 3.x, so maybe it's not such a big deal from
our point of view. (I have no opinion on the security ramifications
of upstream's EOL, but as a layman it sounds completely bonkers to use
it. I wonder why the packaging community wouldn't just arrange to
have a supported-by-upstream 3.x package in their RPM repo when they
supply the newest PostgreSQL versions for the oldest RHEL, but again
not my area so I'll shut up).

#51Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#48)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 4 Apr 2024, at 00:51, Peter Eisentraut <peter@eisentraut.org> wrote:

On 30.03.24 22:27, Thomas Munro wrote:

On Sun, Mar 31, 2024 at 9:59 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

I was reminded of this thread by ambient security paranoia. As it
stands, we require 1.0.2 (but we very much hope that package
maintainers and others in control of builds don't decide to use it).
Should we skip 1.1.1 and move to requiring 3 for v17?

I'd be kind of sad if I couldn't test SSL stuff anymore on my
primary workstation, which has

$ rpm -q openssl
openssl-1.1.1k-12.el8_9.x86_64

I think it's probably true that <=1.0.2 is not in any distro that
we still need to pay attention to, but I reject the contention
that RHEL8 is not in that set.

Hmm, OK so it doesn't have 3 available in parallel from base repos.
But it's also about to reach end of "full support" in 2 months[1], so
if we applied the policies we discussed in the LLVM-vacuuming thread
(to wit: build farm - EOL'd OSes), then... One question I'm unclear
on is whether v17 will be packaged for RHEL8.

The rest of the thread talks about the end of support of RHEL 7, but you are here talking about RHEL 8. It is true that "full support" for RHEL 8 ended in May 2024, but that is the not the one we are tracking. We are tracking the 10-year one, which I suppose is now called "maintenance support".

So if the above package list is correct, then we ought to keep supporting openssl 1.1.* until 2029.

Not 1.1.* but 1.1.1+. In the old OpenSSL version numbering scheme, releases
changing the last digit would contain new features and releases that updated
the appended letter only fixed bugs.
--
Daniel Gustafsson

#52Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#49)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 4 Apr 2024, at 01:24, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, Apr 03, 2024 at 01:38:50PM -0400, Tom Lane wrote:

The discussion we had last year concluded that we were OK with
dropping 1.0.1 support when RHEL6 goes out of extended support
(June 2024 per this thread, I didn't check it). Seems like we
should have the same policy for RHEL7. Also, calling Photon 3
dead because it went EOL three days ago seems over-hasty.

Yeah. A bunch of users of Photon are VMware (or you could say
Broadcom) product appliances, and I'd suspect that quite a lot of them
rely on Photon 3 for their base OS image. Upgrading that stuff is not
easy work in my experience because they need to cope with a bunch of
embedded services.

That's true, but Photon3 won't package new major versions of PostgreSQL (the
latest RPM is 13.14). Anyone who builds v17 on Photon 3 on their own can just
as well be expected to build an updated OpenSSL no? This is equivalent to
RHEL7 which was discussed elsewhere in this thread.

If we are going to pin version dependencies for postgres X to available OS
release packages then it, IMHO, is reasonable to be for OS's that realistically
will package X (either by the vendor or a trusted external packager like PGDG).

It's possible, but not guaranteed, that RHEL8 ships v17 packages in ther
Application Streams Life Cycle model, they have packaged v15 so far with
retirement in 2028 so it seems likely there will be another package to retire
in 2029 when RHEL8 finally goes away (whether that will be v16 or v17 is also
speculation). Thus, pinning on 1.1.1 is grounded in packaging reality, even
though I sincerely hope that noone who isn't paying for support is running
1.1.1 now, let alone in 4 years from now.

--
Daniel Gustafsson

#53Daniel Gustafsson
daniel@yesql.se
In reply to: Thomas Munro (#50)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 4 Apr 2024, at 01:50, Thomas Munro <thomas.munro@gmail.com> wrote:

That's a shame. But it sounds like the developer burden isn't so
different from 1.1.1 to 3.x, so maybe it's not such a big deal from
our point of view.

It isn't as of now since OpenSSL still supply the deprecated API's we use, but
there is no guarantee that they will do that for 5 more years.

--
Daniel Gustafsson

#54Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Daniel Gustafsson (#47)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 3, 2024 at 3:27 PM Daniel Gustafsson <daniel@yesql.se> wrote:

The patch will also need to be adjusted to work with LibreSSL, but I know Jacob
was looking into that so ideally we should have something to review before
the weekend.

v3 does that by putting back checks for symbols that aren't part of
LibreSSL (tested back to 2.7, which is where the 1.1.x APIs started to
arrive). It also makes adjustments for the new OPENSSL_API_COMPAT
version, getting rid of OpenSSL_add_all_algorithms() and adding a
missing header.

This patch has a deficiency where 1.1.0 itself isn't actually rejected
at configure time; Daniel's working on an explicit check for the
OPENSSL/LIBRESSL_VERSION_NUMBER that should fix that up. There's an
open question about which version we should pin for LibreSSL, which
should ultimately come down to which versions of OpenBSD we want PG17
to support.

Thanks,
--Jacob

Attachments:

v3-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patchapplication/octet-stream; name=v3-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patchDownload
From a8ae675062df2681fd31db093ef284edc5900b48 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Tue, 2 Apr 2024 20:46:41 +0200
Subject: [PATCH v3] Remove support for OpenSSL 1.0.2 and 1.1.0

This sets the required version of OpenSSL at 1.1.1.
---
 configure                                |  30 +---
 configure.ac                             |  20 +--
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |   4 +-
 meson.build                              |  28 ++--
 src/backend/libpq/be-secure-openssl.c    |  16 +-
 src/common/hmac_openssl.c                |  34 +---
 src/include/pg_config.h.in               |   3 -
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 11 files changed, 36 insertions(+), 311 deletions(-)

diff --git a/configure b/configure
index 36feeafbb2..0411eaedd2 100755
--- a/configure
+++ b/configure
@@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as he deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12556,11 +12557,7 @@ _ACEOF
 fi
 done
 
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
+  # Functions introduced in OpenSSL 1.1.0/LibreSSL 2.7.0.
   for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -12570,24 +12567,13 @@ if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
 #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL, version 1.1.1 or newer, is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
-_ACEOF
-
-fi
-done
-
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1. This is our minimum version, but we
+  # can't require it because it's not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 57f734879e..73a55bd3c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,9 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as he deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1347,17 +1348,10 @@ if test "$with_ssl" = openssl ; then
   fi
   # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
   AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  # Functions introduced in OpenSSL 1.1.0/LibreSSL 2.7.0.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free], [], [AC_MSG_ERROR([OpenSSL, version 1.1.1 or newer, is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1. This is our minimum version, but we
+  # can't require it because it's not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..1d5578d935 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.1.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index e69feacfe6..c4a3804254 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1779,9 +1779,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
         <productname>PostgreSQL</productname> 14 disables compression
         completely in the backend.
diff --git a/meson.build b/meson.build
index 18b5be842e..3eeb5635c2 100644
--- a/meson.build
+++ b/meson.build
@@ -1275,23 +1275,15 @@ if sslopt in ['auto', 'openssl']
       # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
       ['SSL_CTX_set_cert_cb'],
 
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-      # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      # Functions introduced in OpenSSL 1.1.0/LibreSSL 2.7.0.
+      ['OPENSSL_init_ssl', {'required': true}],
+      ['BIO_meth_new', {'required': true}],
+      ['ASN1_STRING_get0_data', {'required': true}],
+      ['HMAC_CTX_new', {'required': true}],
+      ['HMAC_CTX_free', {'required': true}],
+
+      # Function introduced in OpenSSL 1.1.1. This is our minimum version, but
+      # we can't require it because it's not in LibreSSL.
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1306,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 72e43af353..769e9eb2b7 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -98,13 +99,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -898,7 +893,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -921,14 +915,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..c2506de7c5 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,11 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
-#define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -68,13 +62,13 @@ struct pg_hmac_ctx
 	pg_hmac_errno error;
 	const char *errreason;
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwner resowner;
 #endif
 };
 
 /* ResourceOwner callbacks to hold HMAC contexts */
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void ResOwnerReleaseHMAC(Datum res);
 
 static const ResourceOwnerDesc hmac_resowner_desc =
@@ -139,16 +133,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,11 +151,8 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
 #endif
@@ -328,14 +314,8 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
 #endif
@@ -379,7 +359,7 @@ pg_hmac_error(pg_hmac_ctx *ctx)
 
 /* ResourceOwner callbacks */
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void
 ResOwnerReleaseHMAC(Datum res)
 {
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 591e1ca3df..27989dff25 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -84,9 +84,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0c8c9f8dcb..96f91938ef 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -1596,8 +1441,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1612,8 +1455,6 @@ pgtls_close(PGconn *conn)
 			SSL_free(conn->ssl);
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1631,30 +1472,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1895,7 +1712,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1921,14 +1737,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1936,13 +1744,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9c05f11a6e..d049087301 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -565,11 +565,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.34.1

#55Michael Paquier
michael@paquier.xyz
In reply to: Jacob Champion (#54)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

(Adding Mikael Kjellstrom in CC as OpenBSD owner)

On Thu, Apr 04, 2024 at 11:03:35AM -0700, Jacob Champion wrote:

v3 does that by putting back checks for symbols that aren't part of
LibreSSL (tested back to 2.7, which is where the 1.1.x APIs started to
arrive).

From where did you pull the LibreSSL sources? Directly from the
OpenBSD tree?

It also makes adjustments for the new OPENSSL_API_COMPAT
version, getting rid of OpenSSL_add_all_algorithms() and adding a
missing header.

Ah, right. OpenSSL_add_all_algorithms() is documented as having no
effect in 1.1.0.

This patch has a deficiency where 1.1.0 itself isn't actually rejected
at configure time; Daniel's working on an explicit check for the
OPENSSL/LIBRESSL_VERSION_NUMBER that should fix that up. There's an
open question about which version we should pin for LibreSSL, which
should ultimately come down to which versions of OpenBSD we want PG17
to support.

I would be OK to draw a line to what we test in the buildfarm if it
comes to that, down to OpenBSD 6.9. This version is already not
supported, and we had a number of issues with older versions and
timestamps going backwards.

-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK

I'm happy to see that gone for good.

+      # Functions introduced in OpenSSL 1.1.0/LibreSSL 2.7.0.
+      ['OPENSSL_init_ssl', {'required': true}],
+      ['BIO_meth_new', {'required': true}],
+      ['ASN1_STRING_get0_data', {'required': true}],
+      ['HMAC_CTX_new', {'required': true}],
+      ['HMAC_CTX_free', {'required': true}],

These should be removed to save cycles in ./configure and meson, no?
We don't have any more of their HAVE_* flags in the tree with this
patch applied.

-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',

Seems to me that this should also document in meson.build why 1.1.0 is
chosen, same as ./configure.

It seems to me that src/common/protocol_openssl.c could be cleaned up;
I see SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version
listed in LibreSSL (looking at some past version of
https://github.com/libressl/libressl.git that I still have around).

There is an extra thing in pg_strong_random.c once we cut OpenSSL <
1.1.1.. Do we still need pg_strong_random_init() and its RAND_poll()
when it comes to LibreSSL? This is a sensitive area, so we should be
careful.
--
Michael

#56Mikael Kjellström
mikael.kjellstrom@mksoft.nu
In reply to: Michael Paquier (#55)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 2024-04-05 03:37, Michael Paquier wrote:

(Adding Mikael Kjellstrom in CC as OpenBSD owner)

My 2 OpenBSD animals (morepork
<https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=morepork&amp;br=HEAD&gt;
OpenBSD 6.9, schnauzer
<https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=schnauzer&amp;br=HEAD&gt;
OpenBSD 7.3) is using OpenSSL and not LibreSSL.

The versions are:

OpenBSD 6.9 - openssl-1.1.1k
OpenBSD 7.3 - openssl-3.1.0p1

and that is what I installed them with when I setup both animals.

Is there anything you need me change or do?

/Mikael

#57Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Michael Paquier (#55)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, Apr 4, 2024 at 6:37 PM Michael Paquier <michael@paquier.xyz> wrote:

From where did you pull the LibreSSL sources? Directly from the
OpenBSD tree?

I've been building LibreSSL Portable: https://github.com/libressl/portable

Ah, right. OpenSSL_add_all_algorithms() is documented as having no
effect in 1.1.0.

I think it still has an effect, but it's unnecessary unless you need
some specific initialization other than the defaults -- for which we
now have OPENSSL_init_crypto(). Best I could tell, pgcrypto had no
such requirements (but extra eyes on that would be appreciated).

I would be OK to draw a line to what we test in the buildfarm if it
comes to that, down to OpenBSD 6.9.

That would correspond to LibreSSL 3.3 if I'm not mistaken. Any
particular reason for 6.9 as the dividing line, and not something
later? And by "test in the buildfarm", do you mean across all
versions, or just what we support for PG17? (For the record, I don't
think there's any reason to drop older LibreSSL testing for earlier
branches.)

This version is already not
supported, and we had a number of issues with older versions and
timestamps going backwards.

Speaking of which: for completeness I should note that LibreSSL 3.2
(OpenBSD 6.8) is failing src/test/ssl because of alternate error
messages. That failure exists on HEAD and is not introduced in this
patchset. LibreSSL 3.3, which passes, has the following changelog
note:

* If x509_verify() fails, ensure that the error is set on both
the x509_verify_ctx() and its store context to make some failures
visible from SSL_get_verify_result().

So that would explain that. If we drop support for 3.2 and earlier
then there's nothing to be done anyway.

-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK

I'm happy to see that gone for good.

+1

+      # Functions introduced in OpenSSL 1.1.0/LibreSSL 2.7.0.
+      ['OPENSSL_init_ssl', {'required': true}],
+      ['BIO_meth_new', {'required': true}],
+      ['ASN1_STRING_get0_data', {'required': true}],
+      ['HMAC_CTX_new', {'required': true}],
+      ['HMAC_CTX_free', {'required': true}],

These should be removed to save cycles in ./configure and meson, no?
We don't have any more of their HAVE_* flags in the tree with this
patch applied.

True, but they are required, and I needed something in there to reject
earlier builds. Daniel's suggested approach with _VERSION_NUMBER
should be able to replace this I think.

-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',

Seems to me that this should also document in meson.build why 1.1.0 is
chosen, same as ./configure.

Good point.

It seems to me that src/common/protocol_openssl.c could be cleaned up;
I see SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version
listed in LibreSSL (looking at some past version of
https://github.com/libressl/libressl.git that I still have around).

There is an extra thing in pg_strong_random.c once we cut OpenSSL <
1.1.1.. Do we still need pg_strong_random_init() and its RAND_poll()
when it comes to LibreSSL? This is a sensitive area, so we should be
careful.

It would be cool if there are more cleanups that can happen. I agree
we need to be careful around removal, though, especially now that we
know that LibreSSL testing is spotty... I will look more into these
later today.

Thanks,
--Jacob

#58Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#55)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 5 Apr 2024, at 03:37, Michael Paquier <michael@paquier.xyz> wrote:
On Thu, Apr 04, 2024 at 11:03:35AM -0700, Jacob Champion wrote:

v3 does that by putting back checks for symbols that aren't part of
LibreSSL (tested back to 2.7, which is where the 1.1.x APIs started to
arrive).

From where did you pull the LibreSSL sources? Directly from the
OpenBSD tree?

It also makes adjustments for the new OPENSSL_API_COMPAT
version, getting rid of OpenSSL_add_all_algorithms() and adding a
missing header.

Ah, right. OpenSSL_add_all_algorithms() is documented as having no
effect in 1.1.0.

This API was deprecated and made into a no-op in OpenBSD 6.4 which corresponds
to LibreSSL 2.8.3.

This patch has a deficiency where 1.1.0 itself isn't actually rejected
at configure time; Daniel's working on an explicit check for the
OPENSSL/LIBRESSL_VERSION_NUMBER that should fix that up. There's an
open question about which version we should pin for LibreSSL, which
should ultimately come down to which versions of OpenBSD we want PG17
to support.

I would be OK to draw a line to what we test in the buildfarm if it
comes to that, down to OpenBSD 6.9. This version is already not
supported, and we had a number of issues with older versions and
timestamps going backwards.

There is a member on 6.8 as well, and while 6.8 work fine the tests all fail
due to the error messages being different. Rather than adding alternate output
for an EOL version of OpenBSD (which currently don't even run the ssl checks in
the BF) I think using 6.9 as the minimum makes sense.

+      # Functions introduced in OpenSSL 1.1.0/LibreSSL 2.7.0.
+      ['OPENSSL_init_ssl', {'required': true}],
+      ['BIO_meth_new', {'required': true}],
+      ['ASN1_STRING_get0_data', {'required': true}],
+      ['HMAC_CTX_new', {'required': true}],
+      ['HMAC_CTX_free', {'required': true}],

These should be removed to save cycles in ./configure and meson, no?

Correct, they are removed in favor of a compile test for OpenSSL version.

-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',

Seems to me that this should also document in meson.build why 1.1.0 is
chosen, same as ./configure.

Done.

It seems to me that src/common/protocol_openssl.c could be cleaned up;
I see SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version
listed in LibreSSL (looking at some past version of
https://github.com/libressl/libressl.git that I still have around).

Both SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version are
available in at least OpenBSD 6.3 which is LibreSSL 2.7.5. With this we can
thus remove the whole file.

There is an extra thing in pg_strong_random.c once we cut OpenSSL <
1.1.1.. Do we still need pg_strong_random_init() and its RAND_poll()
when it comes to LibreSSL? This is a sensitive area, so we should be
careful.

Re-reading the thread which added this comment, and the OpenSSL docs and code,
I'm leaning towards leaving this in. The overhead is marginal and fork safety
has been broken at least once in OpenSSL since 1.1.1:

https://github.com/openssl/openssl/issues/12377

That particular bug was thankfully caught before it shipped, but mitigating the
risk is this cheap enough that is seems reasonable to keep this in.

Attached is a WIP patch to get more eyes on it, the Meson test for 1.1.1 fails
on Windows in CI which I will investigate next.

--
Daniel Gustafsson

Attachments:

v4-0001-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v4-0001-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From c288d560c5b24e021b7f313d61f258dba37dc04e Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 5 Apr 2024 14:43:09 +0200
Subject: [PATCH v4] Remove support for OpenSSL 1.0.2

This makes OpenSSL 1.1.1/LibreSSL 3.3.2 the minimally required
versions. Also adjust to past tense in documentation

Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
---
 config/programs.m4                       |  25 +++
 configure                                |  75 +++++----
 configure.ac                             |  20 +--
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |   6 +-
 meson.build                              |  45 +++---
 src/backend/libpq/be-secure-openssl.c    |  33 ++--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  34 +---
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |   3 -
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 src/port/pg_strong_random.c              |   6 +-
 17 files changed, 133 insertions(+), 461 deletions(-)
 delete mode 100644 src/common/protocol_openssl.c

diff --git a/config/programs.m4 b/config/programs.m4
index 490ec9fe9f..230ec21cd7 100644
--- a/config/programs.m4
+++ b/config/programs.m4
@@ -143,6 +143,31 @@ if test "$pgac_cv_ldap_safe" != yes; then
 fi])
 
 
+# PGAC_CHECK_OPENSSL
+# ------------------
+# Check for OpenSSL being at least version 1.1.1 and LibreSSL being at least
+# version 3.3.2 (which shipped in OpenBSD 6.9).  The actual version number
+# found is not recorded, instead we gate functionality based on capabilities to
+# avoid having to check multiple version numbers in the code.
+AC_DEFUN([PGAC_CHECK_OPENSSL],
+[AC_CACHE_CHECK([for compatible OpenSSL installation], [pgac_cv_openssl_safe],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[#include <openssl/opensslv.h>
+#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	LIBRESSL_VERSION_NUMBER < 0x3030200fL))
+choke me
+#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+choke me
+#endif], [])],
+[pgac_cv_openssl_safe=yes],
+[pgac_cv_openssl_safe=no])])
+
+if test "$pgac_cv_openssl_safe" != yes; then
+  AC_MSG_ERROR([OpenSSL 1.1.1 or later is required.])
+fi])
+
 
 # PGAC_CHECK_READLINE
 # -------------------
diff --git a/configure b/configure
index 36feeafbb2..32b0f1bc6d 100755
--- a/configure
+++ b/configure
@@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12544,50 +12545,58 @@ else
 fi
 
   fi
-  # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-  for ac_func in SSL_CTX_set_cert_cb
-do :
-  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
-if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SSL_CTX_SET_CERT_CB 1
-_ACEOF
 
-fi
-done
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compatible OpenSSL installation" >&5
+$as_echo_n "checking for compatible OpenSSL installation... " >&6; }
+if ${pgac_cv_openssl_safe+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <openssl/opensslv.h>
+#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	LIBRESSL_VERSION_NUMBER < 0x3030200fL))
+choke me
+#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+choke me
+#endif
+int
+main ()
+{
 
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+  ;
+  return 0;
+}
 _ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_openssl_safe=yes
+else
+  pgac_cv_openssl_safe=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_openssl_safe" >&5
+$as_echo "$pgac_cv_openssl_safe" >&6; }
 
+if test "$pgac_cv_openssl_safe" != yes; then
+  as_fn_error $? "OpenSSL 1.1.1 or later is required." "$LINENO" 5
 fi
-done
 
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
+  # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+  for ac_func in SSL_CTX_set_cert_cb
 do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
+if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_SSL_CTX_SET_CERT_CB 1
 _ACEOF
 
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 57f734879e..b1e8d7f696 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,9 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1345,19 +1346,12 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
+
+  PGAC_CHECK_OPENSSL
+
   # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
   AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..1d5578d935 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.1.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index e69feacfe6..8987ca5d65 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1779,11 +1779,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
diff --git a/meson.build b/meson.build
index 87437960bc..6fc1417bba 100644
--- a/meson.build
+++ b/meson.build
@@ -1268,6 +1268,28 @@ if sslopt in ['auto', 'openssl']
   endif
 
   if ssl.found()
+	  # Check for OpenSSL being at least version 1.1.1 and LibreSSL being at
+	  # least version 3.3.2 (which shipped in OpenBSD 6.9).  The actual version
+	  # number found is not recorded, instead we gate functionality based on
+	  # capabilities to avoid having to check multiple version numbers in the
+	  # code.
+      compat_test_code = '''
+#include <openssl/opensslv.h>
+#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	LIBRESSL_VERSION_NUMBER < 0x3030200fL))
+choke me
+#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+choke me
+#endif
+'''
+      if not cc.compiles(compat_test_code,
+          name: 'OpenSSL implementation compatible',
+          dependencies: ssl, args: test_c_args)
+        error('OpenSSL 1.1.1 or later is required')
+      endif
+
     check_funcs = [
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
@@ -1275,23 +1297,7 @@ if sslopt in ['auto', 'openssl']
       # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
       ['SSL_CTX_set_cert_cb'],
 
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-      # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1320,10 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+	  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the
+	  # deprecation level since 1.1.1 wasn't defined as a deprecation point by
+	  # OpenSSL
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 72e43af353..0acf4758e4 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -98,13 +99,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -261,15 +256,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
@@ -533,6 +533,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
@@ -898,7 +900,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -921,14 +922,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..c2506de7c5 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,11 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
-#define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -68,13 +62,13 @@ struct pg_hmac_ctx
 	pg_hmac_errno error;
 	const char *errreason;
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwner resowner;
 #endif
 };
 
 /* ResourceOwner callbacks to hold HMAC contexts */
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void ResOwnerReleaseHMAC(Datum res);
 
 static const ResourceOwnerDesc hmac_resowner_desc =
@@ -139,16 +133,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,11 +151,8 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
 #endif
@@ -328,14 +314,8 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
 #endif
@@ -379,7 +359,7 @@ pg_hmac_error(pg_hmac_ctx *ctx)
 
 /* ResourceOwner callbacks */
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void
 ResOwnerReleaseHMAC(Datum res)
 {
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
deleted file mode 100644
index ae378685e1..0000000000
--- a/src/common/protocol_openssl.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 591e1ca3df..27989dff25 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -84,9 +84,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0c8c9f8dcb..96f91938ef 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -1596,8 +1441,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1612,8 +1455,6 @@ pgtls_close(PGconn *conn)
 			SSL_free(conn->ssl);
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1631,30 +1472,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1895,7 +1712,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1921,14 +1737,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1936,13 +1744,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9c05f11a6e..d049087301 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -565,11 +565,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..5df63f99e4 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -56,9 +56,9 @@ void
 pg_strong_random_init(void)
 {
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is in
+	 * theory no longer be required in OpenSSL 1.1.1 and later versions, but
+	 * there is no harm in taking extra precautions.
 	 */
 	RAND_poll();
 }
-- 
2.32.1 (Apple Git-133)

#59Daniel Gustafsson
daniel@yesql.se
In reply to: Jacob Champion (#57)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 5 Apr 2024, at 18:41, Jacob Champion <jacob.champion@enterprisedb.com> wrote:
On Thu, Apr 4, 2024 at 6:37 PM Michael Paquier <michael@paquier.xyz> wrote:

I would be OK to draw a line to what we test in the buildfarm if it
comes to that, down to OpenBSD 6.9.

That would correspond to LibreSSL 3.3 if I'm not mistaken. Any
particular reason for 6.9 as the dividing line, and not something
later? And by "test in the buildfarm", do you mean across all
versions, or just what we support for PG17? (For the record, I don't
think there's any reason to drop older LibreSSL testing for earlier
branches.)

We should draw the line on something we can reliably test, so 6.9 seems fine to
me (unless there is evidence of older versions being common in the wild).
OpenBSD themselves support 2 backbranches so 6.9 is still far beyond the EOL
mark upstream.

--
Daniel Gustafsson

#60Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Daniel Gustafsson (#58)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Apr 5, 2024 at 9:59 AM Daniel Gustafsson <daniel@yesql.se> wrote:

Attached is a WIP patch to get more eyes on it, the Meson test for 1.1.1 fails
on Windows in CI which I will investigate next.

The changes for SSL_OP_NO_CLIENT_RENEGOTIATION and
SSL_R_VERSION_TOO_LOW look good to me.

-    Remove support for OpenSSL 1.0.2 and 1.1.0
+    Remove support for OpenSSL 1.0.2

I modified the commit message while working on v3 and forgot to put it
back before posting, sorry.

+++ b/src/include/pg_config.h.in
@@ -84,9 +84,6 @@
/* Define to 1 if you have the <crtdefs.h> header file. */
#undef HAVE_CRTDEFS_H

-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK

An autoreconf run on my machine pulls in more changes (getting rid of
the symbols we no longer check for).

--Jacob

#61Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#58)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 05.04.24 18:59, Daniel Gustafsson wrote:

Attached is a WIP patch to get more eyes on it, the Meson test for 1.1.1 fails
on Windows in CI which I will investigate next.

I'm not a fan of the new PGAC_CHECK_OPENSSL. It creates a second place
where the OpenSSL version number has to be updated. We had this
carefully constructed so that there is only one place that
OPENSSL_API_COMPAT is defined and that is the only place that needs to
be updated. We put the setting of OPENSSL_API_COMPAT into configure so
that the subsequent OpenSSL tests would use it, and if the API number
higher than what the library supports, the tests should fail. So I
don't understand why the configure changes have to be so expansive.

#62Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#61)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 5 Apr 2024, at 23:26, Peter Eisentraut <peter@eisentraut.org> wrote:

On 05.04.24 18:59, Daniel Gustafsson wrote:

Attached is a WIP patch to get more eyes on it, the Meson test for 1.1.1 fails
on Windows in CI which I will investigate next.

I'm not a fan of the new PGAC_CHECK_OPENSSL. It creates a second place where the OpenSSL version number has to be updated. We had this carefully constructed so that there is only one place that OPENSSL_API_COMPAT is defined and that is the only place that needs to be updated. We put the setting of OPENSSL_API_COMPAT into configure so that the subsequent OpenSSL tests would use it, and if the API number higher than what the library supports, the tests should fail.

But does that actually work? If I change the API_COMPAT to the 1.1.1 version
number and run configure against 1.0.2 it passes just fine. Am I missing some
clever trick here?

The reason to expand the check is to ensure that we have the version we want
for both OpenSSL and LibreSSL, and deprecating OpenSSL versions isn't all that
commonly done so having to change the version in the check didn't seem that
invasive to me.

--
Daniel Gustafsson

#63Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Daniel Gustafsson (#62)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Apr 5, 2024 at 2:48 PM Daniel Gustafsson <daniel@yesql.se> wrote:

But does that actually work? If I change the API_COMPAT to the 1.1.1 version
number and run configure against 1.0.2 it passes just fine. Am I missing some
clever trick here?

Similarly, I changed my API_COMPAT to a nonsense 0x90100000L and
- a 1.1.1 build succeeds
- a 3.0 build fails
- LibreSSL doesn't appear to care or check that #define at all

--Jacob

#64Daniel Gustafsson
daniel@yesql.se
In reply to: Jacob Champion (#60)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 5 Apr 2024, at 22:55, Jacob Champion <jacob.champion@enterprisedb.com> wrote:

On Fri, Apr 5, 2024 at 9:59 AM Daniel Gustafsson <daniel@yesql.se> wrote:

Attached is a WIP patch to get more eyes on it, the Meson test for 1.1.1 fails
on Windows in CI which I will investigate next.

The attached version fixes the Windows 1.1.1 check which was missing the
include directory.

The changes for SSL_OP_NO_CLIENT_RENEGOTIATION and
SSL_R_VERSION_TOO_LOW look good to me.

Thanks!

+++ b/src/include/pg_config.h.in
@@ -84,9 +84,6 @@
/* Define to 1 if you have the <crtdefs.h> header file. */
#undef HAVE_CRTDEFS_H

-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK

An autoreconf run on my machine pulls in more changes (getting rid of
the symbols we no longer check for).

Ah yes, missed updating before formatting the patch. Done in the attached.

--
Daniel Gustafsson

Attachments:

v5-0001-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v5-0001-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From 22bf945e105789767419efd6217e0e172f1a7e9c Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Sat, 6 Apr 2024 00:13:18 +0200
Subject: [PATCH v5] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL for quite some time, and is not the
base OpenSSL library in any distribution which will package 17.
This makes OpenSSL 1.1.1/LibreSSL 3.3.2 the minimum required
versions for compiling PostgreSQL with TLS support.

While updating the documentation, also adjust to past tense for
documenting SSL compression.

Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 config/programs.m4                       |  25 +++
 configure                                |  75 +++++----
 configure.ac                             |  20 +--
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |   6 +-
 meson.build                              |  45 +++---
 src/backend/libpq/be-secure-openssl.c    |  33 ++--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  34 +---
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  18 ---
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 src/port/pg_strong_random.c              |   6 +-
 17 files changed, 133 insertions(+), 476 deletions(-)
 delete mode 100644 src/common/protocol_openssl.c

diff --git a/config/programs.m4 b/config/programs.m4
index 490ec9fe9f..230ec21cd7 100644
--- a/config/programs.m4
+++ b/config/programs.m4
@@ -143,6 +143,31 @@ if test "$pgac_cv_ldap_safe" != yes; then
 fi])
 
 
+# PGAC_CHECK_OPENSSL
+# ------------------
+# Check for OpenSSL being at least version 1.1.1 and LibreSSL being at least
+# version 3.3.2 (which shipped in OpenBSD 6.9).  The actual version number
+# found is not recorded, instead we gate functionality based on capabilities to
+# avoid having to check multiple version numbers in the code.
+AC_DEFUN([PGAC_CHECK_OPENSSL],
+[AC_CACHE_CHECK([for compatible OpenSSL installation], [pgac_cv_openssl_safe],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[#include <openssl/opensslv.h>
+#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	LIBRESSL_VERSION_NUMBER < 0x3030200fL))
+choke me
+#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+choke me
+#endif], [])],
+[pgac_cv_openssl_safe=yes],
+[pgac_cv_openssl_safe=no])])
+
+if test "$pgac_cv_openssl_safe" != yes; then
+  AC_MSG_ERROR([OpenSSL 1.1.1 or later is required.])
+fi])
+
 
 # PGAC_CHECK_READLINE
 # -------------------
diff --git a/configure b/configure
index 36feeafbb2..32b0f1bc6d 100755
--- a/configure
+++ b/configure
@@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12544,50 +12545,58 @@ else
 fi
 
   fi
-  # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-  for ac_func in SSL_CTX_set_cert_cb
-do :
-  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
-if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SSL_CTX_SET_CERT_CB 1
-_ACEOF
 
-fi
-done
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compatible OpenSSL installation" >&5
+$as_echo_n "checking for compatible OpenSSL installation... " >&6; }
+if ${pgac_cv_openssl_safe+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <openssl/opensslv.h>
+#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	LIBRESSL_VERSION_NUMBER < 0x3030200fL))
+choke me
+#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+choke me
+#endif
+int
+main ()
+{
 
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+  ;
+  return 0;
+}
 _ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_openssl_safe=yes
+else
+  pgac_cv_openssl_safe=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_openssl_safe" >&5
+$as_echo "$pgac_cv_openssl_safe" >&6; }
 
+if test "$pgac_cv_openssl_safe" != yes; then
+  as_fn_error $? "OpenSSL 1.1.1 or later is required." "$LINENO" 5
 fi
-done
 
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
+  # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+  for ac_func in SSL_CTX_set_cert_cb
 do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
+if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_SSL_CTX_SET_CERT_CB 1
 _ACEOF
 
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 57f734879e..b1e8d7f696 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,9 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1345,19 +1346,12 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
+
+  PGAC_CHECK_OPENSSL
+
   # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
   AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..1d5578d935 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.1.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index e69feacfe6..8987ca5d65 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1779,11 +1779,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
diff --git a/meson.build b/meson.build
index 87437960bc..720c144bf9 100644
--- a/meson.build
+++ b/meson.build
@@ -1268,6 +1268,28 @@ if sslopt in ['auto', 'openssl']
   endif
 
   if ssl.found()
+	  # Check for OpenSSL being at least version 1.1.1 and LibreSSL being at
+	  # least version 3.3.2 (which shipped in OpenBSD 6.9).  The actual version
+	  # number found is not recorded, instead we gate functionality based on
+	  # capabilities to avoid having to check multiple version numbers in the
+	  # code.
+      compat_test_code = '''
+#include <openssl/opensslv.h>
+#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	LIBRESSL_VERSION_NUMBER < 0x3030200fL))
+choke me
+#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+choke me
+#endif
+'''
+      if not cc.compiles(compat_test_code,
+          name: 'OpenSSL implementation compatible',
+          args: test_c_args, dependencies: ssl_int, include_directories: postgres_inc)
+        error('OpenSSL 1.1.1 or later is required')
+      endif
+
     check_funcs = [
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
@@ -1275,23 +1297,7 @@ if sslopt in ['auto', 'openssl']
       # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
       ['SSL_CTX_set_cert_cb'],
 
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-      # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1320,10 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+	  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the
+	  # deprecation level since 1.1.1 wasn't defined as a deprecation point by
+	  # OpenSSL
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 72e43af353..0acf4758e4 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -98,13 +99,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -261,15 +256,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
@@ -533,6 +533,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
@@ -898,7 +900,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -921,14 +922,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..c2506de7c5 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,11 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
-#define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -68,13 +62,13 @@ struct pg_hmac_ctx
 	pg_hmac_errno error;
 	const char *errreason;
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwner resowner;
 #endif
 };
 
 /* ResourceOwner callbacks to hold HMAC contexts */
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void ResOwnerReleaseHMAC(Datum res);
 
 static const ResourceOwnerDesc hmac_resowner_desc =
@@ -139,16 +133,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,11 +151,8 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
 #endif
@@ -328,14 +314,8 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
 #endif
@@ -379,7 +359,7 @@ pg_hmac_error(pg_hmac_ctx *ctx)
 
 /* ResourceOwner callbacks */
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void
 ResOwnerReleaseHMAC(Datum res)
 {
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
deleted file mode 100644
index ae378685e1..0000000000
--- a/src/common/protocol_openssl.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 591e1ca3df..d7fa014c5a 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
@@ -303,9 +288,6 @@
 /* Define to 1 if you have the `mkdtemp' function. */
 #undef HAVE_MKDTEMP
 
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
-#undef HAVE_OPENSSL_INIT_SSL
-
 /* Define to 1 if you have the <ossp/uuid.h> header file. */
 #undef HAVE_OSSP_UUID_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0c8c9f8dcb..96f91938ef 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -1596,8 +1441,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1612,8 +1455,6 @@ pgtls_close(PGconn *conn)
 			SSL_free(conn->ssl);
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1631,30 +1472,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1895,7 +1712,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1921,14 +1737,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1936,13 +1744,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9c05f11a6e..d049087301 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -565,11 +565,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..5df63f99e4 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -56,9 +56,9 @@ void
 pg_strong_random_init(void)
 {
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is in
+	 * theory no longer be required in OpenSSL 1.1.1 and later versions, but
+	 * there is no harm in taking extra precautions.
 	 */
 	RAND_poll();
 }
-- 
2.32.1 (Apple Git-133)

#65Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Daniel Gustafsson (#64)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Apr 5, 2024 at 3:32 PM Daniel Gustafsson <daniel@yesql.se> wrote:

An autoreconf run on my machine pulls in more changes (getting rid of
the symbols we no longer check for).

Ah yes, missed updating before formatting the patch. Done in the attached.

The commit subject may still need to be reverted to how you had it
originally, unless you are keeping my omission of "1.1.0" on purpose.

I've tested (with Meson) on LibreSSL 3.3 to 3.8, and verified that 2.7
to 3.2 now fail to configure. Similarly, OpenSSL 1.0.2 and 1.1.0 fail
to configure, and I ran tests with 1.1.1 to 3.3. I did a quick smoke
test with autoconf to make sure that old versions are rejected there
too, but I didn't run all the tests again.

Maybe there was a good reason for them to do it, but I'm kind of
amazed that LibreSSL camped on the 2.x version number, then revved to
a 3.x line anyway and camped on those numbers too, so that Meson can't
just rely on pkgconfig to figure out which version we have.

--Jacob

#66Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#62)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 05.04.24 23:48, Daniel Gustafsson wrote:

The reason to expand the check is to ensure that we have the version we want
for both OpenSSL and LibreSSL, and deprecating OpenSSL versions isn't all that
commonly done so having to change the version in the check didn't seem that
invasive to me.

Why do we need to check for the versions at all? We should just check
for the functions we need. At least that's always been the normal
approach in configure.

#67Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#66)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 6 Apr 2024, at 08:02, Peter Eisentraut <peter@eisentraut.org> wrote:

On 05.04.24 23:48, Daniel Gustafsson wrote:

The reason to expand the check is to ensure that we have the version we want
for both OpenSSL and LibreSSL, and deprecating OpenSSL versions isn't all that
commonly done so having to change the version in the check didn't seem that
invasive to me.

Why do we need to check for the versions at all? We should just check for the functions we need. At least that's always been the normal approach in configure.

We could, but finding a stable set of functions which identifies the version of
OpenSSL *and* LibreSSL that we want, and their successors, while not matching
any older versions seemed more opaque than testing two numeric values. The
suggested check is modelled on the LDAP check which tests for an explicit
version in a header file (albeit not for erroring out).

--
Daniel Gustafsson

#68Tom Lane
tgl@sss.pgh.pa.us
In reply to: Daniel Gustafsson (#67)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Daniel Gustafsson <daniel@yesql.se> writes:

On 6 Apr 2024, at 08:02, Peter Eisentraut <peter@eisentraut.org> wrote:
Why do we need to check for the versions at all? We should just check for the functions we need. At least that's always been the normal approach in configure.

We could, but finding a stable set of functions which identifies the version of
OpenSSL *and* LibreSSL that we want, and their successors, while not matching
any older versions seemed more opaque than testing two numeric values.

I don't think you responded to Peter's point at all. The way autoconf
is designed to work is explicitly NOT to try to identify the exact
version of $whatever. Rather, the idea is to probe for the API
features that you want to rely on: functions, macros, struct fields,
or the like. If you can't point to an important API difference
between 1.0.2 and 1.1.1, why drop support for 1.0.2?

regards, tom lane

#69Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#68)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 6 Apr 2024, at 16:04, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Daniel Gustafsson <daniel@yesql.se> writes:

On 6 Apr 2024, at 08:02, Peter Eisentraut <peter@eisentraut.org> wrote:

Why do we need to check for the versions at all? We should just check for the functions we need. At least that's always been the normal approach in configure.

We could, but finding a stable set of functions which identifies the version of
OpenSSL *and* LibreSSL that we want, and their successors, while not matching
any older versions seemed more opaque than testing two numeric values.

I don't think you responded to Peter's point at all. The way autoconf
is designed to work is explicitly NOT to try to identify the exact
version of $whatever. Rather, the idea is to probe for the API
features that you want to rely on: functions, macros, struct fields,
or the like. If you can't point to an important API difference
between 1.0.2 and 1.1.1, why drop support for 1.0.2?

My apologies, I thought I did but clearly failed. My point was that this is a
special/corner case where we try to find one of two different libraries (with
different ideas about backwards compatability etc) for supporting a single
thing. So instead I tested for the explicit versions like how we already test
for the exact Perl version in config/perl.m4 (albeit that a library and a
program are two different things of course).

In bumping we want to move to 1.1.1 since that's the first version with the
rewritten RNG which is fork-safe by design, something PostgreSQL clearly
benefits from. There is no new API for this to gate on though. For LibreSSL
we want 3.3.2 to a) ensure we have coverage in the BF and b) since it's the
first version where the tests pass due to error message alignment with OpenSSL.
The combination of these gets rid of lots of specialcased #ifdef soup. I
wasn't however able to find a specific API call which is unique to the two
version which we rely on.

Testing for the presence of an API provided and introduced by both libraries in
the version we're interested in, but which we don't use, is the alternative but
I thought that would be more frowned upon. EVP_PKEY_new_CMAC_key() was
introduced in 1.1.1 and LibreSSL 3.3.2, so an AC_CHECK_FUNCS for that, as in
the attached, achieves the version check but pollutes pg_config.h with a define
which will never be used which seemed a bit ugly.

--
Daniel Gustafsson

Attachments:

v6-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patchapplication/octet-stream; name=v6-0001-Remove-support-for-OpenSSL-1.0.2-and-1.1.0.patch; x-unix-mode=0644Download
From 0910a7341207b5a7f62a81e439daa24876ad6380 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Sat, 6 Apr 2024 19:41:28 +0200
Subject: [PATCH v6] Remove support for OpenSSL 1.0.2 and 1.1.0

OpenSSL 1.0.2 has been EOL for quite some time, and is not the
base OpenSSL library in any distribution which will package 17.
Bumping the required version to 1.1.1 allows us to remove a lot
of special cased code, and moves us to an OpenSSL version which
has a fork-safe RNG by default.

This makes OpenSSL 1.1.1/LibreSSL 3.3.2 the minimum required
versions for compiling PostgreSQL with TLS support.

While updating the documentation, also adjust to past tense for
documenting SSL compression.

Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  47 ++----
 configure.ac                             |  20 +--
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |   6 +-
 meson.build                              |  27 ++--
 src/backend/libpq/be-secure-openssl.c    |  33 ++--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  34 +---
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  21 +--
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 src/port/pg_strong_random.c              |   6 +-
 16 files changed, 67 insertions(+), 474 deletions(-)
 delete mode 100644 src/common/protocol_openssl.c

diff --git a/configure b/configure
index 36feeafbb2..0ec63ab082 100755
--- a/configure
+++ b/configure
@@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12544,50 +12545,34 @@ else
 fi
 
   fi
-  # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-  for ac_func in SSL_CTX_set_cert_cb
-do :
-  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
-if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SSL_CTX_SET_CERT_CB 1
-_ACEOF
-
-fi
-done
 
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  # Function introduced in OpenSSL 1.1.1 and LibreSSL 3.3.2
+  for ac_func in EVP_PKEY_new_CMAC_key
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "EVP_PKEY_new_CMAC_key" "ac_cv_func_EVP_PKEY_new_CMAC_key"
+if test "x$ac_cv_func_EVP_PKEY_new_CMAC_key" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_EVP_PKEY_NEW_CMAC_KEY 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL 1.1.1 or later is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
+  # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+  for ac_func in SSL_CTX_set_cert_cb
 do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
+if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_SSL_CTX_SET_CERT_CB 1
 _ACEOF
 
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 57f734879e..b19f4775ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,9 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation
+  # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1345,19 +1346,12 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
+
+  # Function introduced in OpenSSL 1.1.1 and LibreSSL 3.3.2
+  AC_CHECK_FUNCS([EVP_PKEY_new_CMAC_key], [], [AC_MSG_ERROR([OpenSSL 1.1.1 or later is required for SSL support])])
   # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
   AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-  # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..1d5578d935 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.1.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index e69feacfe6..8987ca5d65 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1779,11 +1779,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
diff --git a/meson.build b/meson.build
index 87437960bc..19b2efcd3f 100644
--- a/meson.build
+++ b/meson.build
@@ -1268,30 +1268,18 @@ if sslopt in ['auto', 'openssl']
   endif
 
   if ssl.found()
+
     check_funcs = [
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
+      # Function introduced in OpenSSL 1.1.1 and LibreSSL 3.3.2
+      ['EVP_PKEY_new_CMAC_key'],
+
       # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
       ['SSL_CTX_set_cert_cb'],
 
-      # Functions introduced in OpenSSL 1.1.0. We used to check for
-      # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-      # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-      # doesn't have these OpenSSL 1.1.0 functions. So check for individual
-      # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1302,10 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+	  # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the
+	  # deprecation level since 1.1.1 wasn't defined as a deprecation point by
+	  # OpenSSL
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 72e43af353..0acf4758e4 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -98,13 +99,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -261,15 +256,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
@@ -533,6 +533,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
@@ -898,7 +900,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -921,14 +922,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..c2506de7c5 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,11 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
-#define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -68,13 +62,13 @@ struct pg_hmac_ctx
 	pg_hmac_errno error;
 	const char *errreason;
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwner resowner;
 #endif
 };
 
 /* ResourceOwner callbacks to hold HMAC contexts */
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void ResOwnerReleaseHMAC(Datum res);
 
 static const ResourceOwnerDesc hmac_resowner_desc =
@@ -139,16 +133,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,11 +151,8 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
 #endif
@@ -328,14 +314,8 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
 #endif
@@ -379,7 +359,7 @@ pg_hmac_error(pg_hmac_ctx *ctx)
 
 /* ResourceOwner callbacks */
 
-#ifdef USE_RESOWNER_FOR_HMAC
+#ifndef FRONTEND
 static void
 ResOwnerReleaseHMAC(Datum res)
 {
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
deleted file mode 100644
index ae378685e1..0000000000
--- a/src/common/protocol_openssl.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 591e1ca3df..9237984e74 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -133,6 +124,9 @@
 /* Define to 1 if you have the <editline/readline.h> header file. */
 #undef HAVE_EDITLINE_READLINE_H
 
+/* Define to 1 if you have the `EVP_PKEY_new_CMAC_key' function. */
+#undef HAVE_EVP_PKEY_NEW_CMAC_KEY
+
 /* Define to 1 if you have the <execinfo.h> header file. */
 #undef HAVE_EXECINFO_H
 
@@ -198,12 +192,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
@@ -303,9 +291,6 @@
 /* Define to 1 if you have the `mkdtemp' function. */
 #undef HAVE_MKDTEMP
 
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
-#undef HAVE_OPENSSL_INIT_SSL
-
 /* Define to 1 if you have the <ossp/uuid.h> header file. */
 #undef HAVE_OSSP_UUID_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0c8c9f8dcb..96f91938ef 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -1596,8 +1441,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1612,8 +1455,6 @@ pgtls_close(PGconn *conn)
 			SSL_free(conn->ssl);
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1631,30 +1472,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1895,7 +1712,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1921,14 +1737,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1936,13 +1744,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9c05f11a6e..d049087301 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -565,11 +565,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..5df63f99e4 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -56,9 +56,9 @@ void
 pg_strong_random_init(void)
 {
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is in
+	 * theory no longer be required in OpenSSL 1.1.1 and later versions, but
+	 * there is no harm in taking extra precautions.
 	 */
 	RAND_poll();
 }
-- 
2.32.1 (Apple Git-133)

#70Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#69)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Sat, Apr 06, 2024 at 07:47:43PM +0200, Daniel Gustafsson wrote:

My apologies, I thought I did but clearly failed. My point was that this is a
special/corner case where we try to find one of two different libraries (with
different ideas about backwards compatability etc) for supporting a single
thing. So instead I tested for the explicit versions like how we already test
for the exact Perl version in config/perl.m4 (albeit that a library and a
program are two different things of course).

+  # Function introduced in OpenSSL 1.1.1 and LibreSSL 3.3.2
+  AC_CHECK_FUNCS([EVP_PKEY_new_CMAC_key], [], [AC_MSG_ERROR([OpenSSL 1.1.1 or later is required for SSL support])]) 

I can see why you want to do that, but we've always relied on
compilation failures while documenting the versions supported. I
don't disagree to your point of detecting that earlier, but it sounds
like this should be a separate patch separate from the one removing
support for OpenSSL 1.0.2 and 1.1.0, at least, because you are solving
two problems at once.

In bumping we want to move to 1.1.1 since that's the first version with the
rewritten RNG which is fork-safe by design, something PostgreSQL clearly
benefits from. There is no new API for this to gate on though. For LibreSSL
we want 3.3.2 to a) ensure we have coverage in the BF and b) since it's the
first version where the tests pass due to error message alignment with OpenSSL.
The combination of these gets rid of lots of specialcased #ifdef soup. I
wasn't however able to find a specific API call which is unique to the two
version which we rely on.

Based on the state of the patch, all the symbols cleaned up in
pg_config.h.in would be removed only by dropping support for
1.0.2. The routines of protocol_openssl.c exist in 1.1.0. libpq
internal locking can be removed by dropping support for 1.0.2. So
a bunch of ifdefs are removed with 1.0.2 support, but that's much,
much less cleaned once 1.1.0 is removed. And pg_strong_random.c stuff
would still remain around.

Testing for the presence of an API provided and introduced by both libraries in
the version we're interested in, but which we don't use, is the alternative but
I thought that would be more frowned upon. EVP_PKEY_new_CMAC_key() was
introduced in 1.1.1 and LibreSSL 3.3.2, so an AC_CHECK_FUNCS for that, as in
the attached, achieves the version check but pollutes pg_config.h with a define
which will never be used which seemed a bit ugly.

Two lines in pg_config.h is a minimal cost. That does not look like a
big deal to me.

-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is in
+	 * theory no longer be required in OpenSSL 1.1.1 and later versions, but
+	 * there is no harm in taking extra precautions.

I was wondering if this should also document what you've mentioned,
aka that OpenSSL still found ways to break the randomness state and
that this is a cheap insurance against future mistakes that could
happen in this area.
--
Michael

#71Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#70)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 8 Apr 2024, at 00:46, Michael Paquier <michael@paquier.xyz> wrote:

On Sat, Apr 06, 2024 at 07:47:43PM +0200, Daniel Gustafsson wrote:

My apologies, I thought I did but clearly failed. My point was that this is a
special/corner case where we try to find one of two different libraries (with
different ideas about backwards compatability etc) for supporting a single
thing. So instead I tested for the explicit versions like how we already test
for the exact Perl version in config/perl.m4 (albeit that a library and a
program are two different things of course).

+  # Function introduced in OpenSSL 1.1.1 and LibreSSL 3.3.2
+  AC_CHECK_FUNCS([EVP_PKEY_new_CMAC_key], [], [AC_MSG_ERROR([OpenSSL 1.1.1 or later is required for SSL support])]) 

I can see why you want to do that, but we've always relied on
compilation failures while documenting the versions supported. I
don't disagree to your point of detecting that earlier, but it sounds
like this should be a separate patch separate from the one removing
support for OpenSSL 1.0.2 and 1.1.0, at least, because you are solving
two problems at once.

In bumping we want to move to 1.1.1 since that's the first version with the
rewritten RNG which is fork-safe by design, something PostgreSQL clearly
benefits from. There is no new API for this to gate on though. For LibreSSL
we want 3.3.2 to a) ensure we have coverage in the BF and b) since it's the
first version where the tests pass due to error message alignment with OpenSSL.
The combination of these gets rid of lots of specialcased #ifdef soup. I
wasn't however able to find a specific API call which is unique to the two
version which we rely on.

Based on the state of the patch, all the symbols cleaned up in
pg_config.h.in would be removed only by dropping support for
1.0.2. The routines of protocol_openssl.c exist in 1.1.0. libpq
internal locking can be removed by dropping support for 1.0.2. So
a bunch of ifdefs are removed with 1.0.2 support, but that's much,
much less cleaned once 1.1.0 is removed.

If we are settling for removing 1.0.2 we need to make sure there is 1.1.0
buildfarm animals that actually run the sslcheck. 1.1.0 was never an LTS
release so it's presence in distributions is far less widespread. I would
prefer 1.1.1 but, either way, we have ample time to discuss that during the v18
cycle.

And pg_strong_random.c stuff would still remain around.

It stays but as belts-and-suspenders safety against bugs, not as a requirement.

Testing for the presence of an API provided and introduced by both libraries in
the version we're interested in, but which we don't use, is the alternative but
I thought that would be more frowned upon. EVP_PKEY_new_CMAC_key() was
introduced in 1.1.1 and LibreSSL 3.3.2, so an AC_CHECK_FUNCS for that, as in
the attached, achieves the version check but pollutes pg_config.h with a define
which will never be used which seemed a bit ugly.

Two lines in pg_config.h is a minimal cost. That does not look like a
big deal to me.

-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is in
+	 * theory no longer be required in OpenSSL 1.1.1 and later versions, but
+	 * there is no harm in taking extra precautions.

I was wondering if this should also document what you've mentioned,
aka that OpenSSL still found ways to break the randomness state and
that this is a cheap insurance against future mistakes that could
happen in this area.

I'm not quite sure how stable Github links are over time, but I guess we could
post the commit sha for the bug in OpenSSL (as well as the fix) which is a
stable documentation of how it can be subtly broken.

--
Daniel Gustafsson

#72Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#69)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 06.04.24 19:47, Daniel Gustafsson wrote:

In bumping we want to move to 1.1.1 since that's the first version with the
rewritten RNG which is fork-safe by design, something PostgreSQL clearly
benefits from.

I think it might be better to separate this into two steps:

1. Move to 1.1.0. This is an API update. Change OPENSSL_API_COMPAT,
and remove a bunch of code that no longer needs to be conditional. We
could check for a representative function like OPENSSL_init_ssl() in
configure/meson, or we could just let the compilation fail with older
versions.

2. Move to 1.1.1. I understand this has to do with the fork-safety of
pg_strong_random(), and it's not an API change but a behavior change.
Let's make this association clearer in the code. For example, add a
version check or assertion about this into pg_strong_random() itself.

I don't know how LibreSSL interacts with either of these two points.
That's something that could be clearer.

Some more detailed review on the v6 patch:

* doc/src/sgml/libpq.sgml

This small documentation patch could be committed forthwith.

* src/backend/libpq/be-secure-openssl.c

+#include <openssl/bn.h>

This patch doesn't appear to add anything, so why does it need a new
include?

Could the additions of SSL_OP_NO_CLIENT_RENEGOTIATION and
SSL_R_VERSION_TOO_LOW be separate patches?

* src/common/hmac_openssl.c

There appears to be some unrelated refactoring happening here?

* src/include/common/openssl.h

Is the comment no longer applicable to OpenSSL, only to LibreSSL?

* src/port/pg_strong_random.c

I would prefer to remove pg_strong_random_init() if it's no longer
useful. I mean, if we leave it as is, and we are not removing any
callers, then we are effectively continuing to support OpenSSL <1.1.1,
right?

#73Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Peter Eisentraut (#72)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 10, 2024 at 12:31 AM Peter Eisentraut <peter@eisentraut.org> wrote:

* src/backend/libpq/be-secure-openssl.c

+#include <openssl/bn.h>

This patch doesn't appear to add anything, so why does it need a new
include?

This one was mine -- it was an indirect header dependency that was
effectively removed in 1.1.0 and later, due to the bump to
OPENSSL_API_COMPAT [1]https://github.com/openssl/openssl/blob/b372b1f764/include/openssl/dh.h#L20-L22. We have to depend on it directly now.

--Jacob

[1]: https://github.com/openssl/openssl/blob/b372b1f764/include/openssl/dh.h#L20-L22

#74Michael Paquier
michael@paquier.xyz
In reply to: Peter Eisentraut (#72)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 10, 2024 at 09:31:16AM +0200, Peter Eisentraut wrote:

I think it might be better to separate this into two steps:

1. Move to 1.1.0. This is an API update. Change OPENSSL_API_COMPAT, and
remove a bunch of code that no longer needs to be conditional. We could
check for a representative function like OPENSSL_init_ssl() in
configure/meson, or we could just let the compilation fail with older
versions.

2. Move to 1.1.1. I understand this has to do with the fork-safety of
pg_strong_random(), and it's not an API change but a behavior change. Let's
make this association clearer in the code. For example, add a version check
or assertion about this into pg_strong_random() itself.

+1 for a split and a two-step move. The areas cleaned up are not
really dependent.

I don't know how LibreSSL interacts with either of these two points. That's
something that could be clearer.

Not looked at that, unfortunately. Cutting to one specific version of
LibreSSL would help.

I would prefer to remove pg_strong_random_init() if it's no longer useful.
I mean, if we leave it as is, and we are not removing any callers, then we
are effectively continuing to support OpenSSL <1.1.1, right?

I'd rather see it gone too, at the end, but I also get that the
concerns from Daniel are worth keeping in mind.
--
Michael

#75Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#72)
5 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 10 Apr 2024, at 09:31, Peter Eisentraut <peter@eisentraut.org> wrote:

I think it might be better to separate this into two steps:

Fair enough.

1. Move to 1.1.0. This is an API update. Change OPENSSL_API_COMPAT, and remove a bunch of code that no longer needs to be conditional. We could check for a representative function like OPENSSL_init_ssl() in configure/meson, or we could just let the compilation fail with older versions.

The attached 0002 bumps the minimum required version to 1.1.0 with a hard error
in autoconf/meson, and removes all the 1.0.2 support code.

I think the documentation for PQinitOpenSSL should be reworded from "you have
to do this, unless you run 1.1.0 or later" to "If you run 1.1.0, you need to do
this). As it is now the important bit of the paragrapg is at the end rather
than in the beginning. Trying this I didn't find a wording which seemed like
an improvement though, suggestions are welcome.

2. Move to 1.1.1. I understand this has to do with the fork-safety of pg_strong_random(), and it's not an API change but a behavior change. Let's make this association clearer in the code. For example, add a version check or assertion about this into pg_strong_random() itself.

0005 moves the fork safety init inline with calling pg_strong_random, and
removes it for everyone else. This allows 1.1.0 to be supported as we
effectively are at the 1.1.0 API level, at the cost of calls for strong random
being slower on 1.1.0. An unscientific guess based on packaged OpenSSL
versions and the EOL and ELS/LTS status of 1.1.0, is that the number of
production installs of postgres 17 using OpenSSL 1.1.0 is close to zero.

I don't know how LibreSSL interacts with either of these two points. That's something that could be clearer.

The oldest LibreSSL we have in the buildfarm is 3.2 (from OpenBSD 6.8), which
the attached version supports and passes tests with. LibreSSL has been
providing fork safety since 2.0.2 which is well into the past.

* doc/src/sgml/libpq.sgml

This small documentation patch could be committed forthwith.

Agreed, separated into 0001 in the attached and can be committed regardless of
the remaining ones.

* src/backend/libpq/be-secure-openssl.c

+#include <openssl/bn.h>

This patch doesn't appear to add anything, so why does it need a new include?

As mentioned downthread, an indirect inclusion was removed so we need to
explicitly include it.

Could the additions of SSL_OP_NO_CLIENT_RENEGOTIATION and SSL_R_VERSION_TOO_LOW be separate patches?

They can, done in the attached.

SSL_R_VERSION_TOO_LOW was introduced quite recently in LibreSSL 3.6.3 (OpenBSD
7.2), but splitting the check for TOO_LOW and TOO_HIGH into two seems pretty
uncontroversial and a good way to get ever so slightly better error handling on
recent LibreSSL.

SSL renegotiation has been supported for much longer in LibreSSL so adding that
to make OpenSSL and LibreSSL support slightly more on par seems seems like a
good idea regardless of version bump.

* src/common/hmac_openssl.c

There appears to be some unrelated refactoring happening here?

I assume you mean changing back to FRONTEND from USE_RESOWNER_FOR_HMAC, the
latter was added recently in 38698dd38 and have never shipped, so it seemed
more backpatch-friendly to move back. Given the amount of changes it probably
won't move the needle though so reverted.

* src/include/common/openssl.h

Is the comment no longer applicable to OpenSSL, only to LibreSSL?

OpenSSL has since 0.9.8 defined TLS_MAX_VERSION which points highest version
TLS protocol supported, but AFAIK there is no such construction in LibreSSL.
Assuming I didn't totally misunderstand the comment of course.

* src/port/pg_strong_random.c

I would prefer to remove pg_strong_random_init() if it's no longer useful. I mean, if we leave it as is, and we are not removing any callers, then we are effectively continuing to support OpenSSL <1.1.1, right?

The attached removes pg_strong_random_init and instead calls it explicitly for
1.1.0 users by checking the OpenSSL version.

Is the attached split in line with how you were thinking about it?

--
Daniel Gustafsson

Attachments:

v7-0005-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v7-0005-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From 5cbbb027f0537dfb89fe6ac6024e831ca8dfc385 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 13:20:31 +0200
Subject: [PATCH v7 5/5] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.1 is being
increasingly phased out from production use, remove the initialization
and only do it explicitly for anyone running 1.1.0.  This will penalize
1.1.0 installations by doing it per call to pg_strong_random, but the
number of production environments running the latest PostgreSQL combined
with a very out of date OpenSSL (which never was available as LTS/ELS)
is believed to be low.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random which
for the vast majority of users is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/include/port.h          |  1 -
 src/port/pg_strong_random.c | 38 +++++++++++--------------------------
 2 files changed, 11 insertions(+), 28 deletions(-)

diff --git a/src/include/port.h b/src/include/port.h
index ae115d2d97..2a363764f1 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -473,7 +473,6 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits,
 							  char *dst, size_t size);
 
 /* port/pg_strong_random.c */
-extern void pg_strong_random_init(void);
 extern bool pg_strong_random(void *buf, size_t len);
 
 /*
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..99e5e4b66a 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -25,14 +25,11 @@
 #include <sys/time.h>
 
 /*
- * pg_strong_random & pg_strong_random_init
+ * pg_strong_random
  *
  * Generate requested number of random bytes. The returned bytes are
  * cryptographically secure, suitable for use e.g. in authentication.
  *
- * Before pg_strong_random is called in any process, the generator must first
- * be initialized by calling pg_strong_random_init().
- *
  * We rely on system facilities for actually generating the numbers.
  * We support a number of sources:
  *
@@ -51,23 +48,22 @@
 #ifdef USE_OPENSSL
 
 #include <openssl/rand.h>
-
-void
-pg_strong_random_init(void)
-{
-	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
-	 */
-	RAND_poll();
-}
+#include <openssl/opensslv.h>
 
 bool
 pg_strong_random(void *buf, size_t len)
 {
 	int			i;
 
+#if (OPENSSL_VERSION_NUMBER <= 0x10100000L)
+	/*
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * requred on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
+	 */
+	RAND_poll();
+#endif
+
 	/*
 	 * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
 	 * add more seed data using RAND_poll().  With some older versions of
@@ -104,12 +100,6 @@ pg_strong_random(void *buf, size_t len)
  */
 static HCRYPTPROV hProvider = 0;
 
-void
-pg_strong_random_init(void)
-{
-	/* No initialization needed on WIN32 */
-}
-
 bool
 pg_strong_random(void *buf, size_t len)
 {
@@ -143,12 +133,6 @@ pg_strong_random(void *buf, size_t len)
  * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
  */
 
-void
-pg_strong_random_init(void)
-{
-	/* No initialization needed */
-}
-
 bool
 pg_strong_random(void *buf, size_t len)
 {
-- 
2.39.3 (Apple Git-146)

v7-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patchapplication/octet-stream; name=v7-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch; x-unix-mode=0644Download
From 348e8294f73ede569a054c74c467bb492f689e96 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 13:12:17 +0200
Subject: [PATCH v7 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL

The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since
LibreSSL 3.6.3, shipped in OpenSSL 7.2. Previously we only checked for
SSL_R_VERSION_TOO_HIGH and then applied both under that guard since
OpenSSL has only ever supported both at the same time. This breaks the
check into one per reason to allow SSL_R_VERSION_TOO_LOW to work when
using LibreSSL.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index efd49ffca8..59c71b15b5 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -542,6 +542,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
-- 
2.39.3 (Apple Git-146)

v7-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patchapplication/octet-stream; name=v7-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch; x-unix-mode=0644Download
From 8b93bf797cfab09e0f1713bbea9d97e2c2474de4 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 12:44:24 +0200
Subject: [PATCH v7 3/5] Support disallowing SSL renegotiation in LibreSSL

LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is
used by OpenSSL, instead it has invented a similar one for client-
side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been
supported since LibreSSL 2.5.1 which by now can be considered well
below the minimum requirement.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 88153d4bda..efd49ffca8 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -262,15 +262,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
-- 
2.39.3 (Apple Git-146)

v7-0002-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v7-0002-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From da93e9b7fcc57ba39a3c9bd8bf405558eb5469ed Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 11:21:55 +0200
Subject: [PATCH v7 2/5] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 ++--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  16 +-
 src/backend/postmaster/fork_process.c    |   3 -
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  21 +--
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 15 files changed, 28 insertions(+), 440 deletions(-)
 delete mode 100644 src/common/protocol_openssl.c

diff --git a/configure b/configure
index cfbd2a096f..73e76070b0 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 67e738d92b..cf85ad409e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..e35f52a4d0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/meson.build b/meson.build
index 5acf083ce3..02e914e123 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 29c9af1aab..88153d4bda 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -104,13 +105,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -933,7 +928,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -956,14 +950,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c
index 5e42a74ab5..bcff9ef661 100644
--- a/src/backend/postmaster/fork_process.c
+++ b/src/backend/postmaster/fork_process.c
@@ -110,9 +110,6 @@ fork_process(void)
 				close(fd);
 			}
 		}
-
-		/* do post-fork initialization for random number generation */
-		pg_strong_random_init();
 	}
 	else
 	{
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..e55b024159 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +152,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +315,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
deleted file mode 100644
index ae378685e1..0000000000
--- a/src/common/protocol_openssl.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index c98cfa6084..640edebcfe 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1651,30 +1492,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1935,7 +1752,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1961,14 +1777,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1976,13 +1784,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..434d6c449f 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.39.3 (Apple Git-146)

v7-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patchapplication/octet-stream; name=v7-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch; x-unix-mode=0644Download
From e505ee12a13ee245a0d67708a35d43c9ced35c42 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 11:36:08 +0200
Subject: [PATCH v7 1/5] Doc: Use past tense for things which happened in the
 past

The paragraph on SSL compression is largely describing events which
took place many years ago, so reword with past tense.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 doc/src/sgml/libpq.sgml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9199d0d2e5..0db3667fdf 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
-- 
2.39.3 (Apple Git-146)

#76Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#75)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote:

On 10 Apr 2024, at 09:31, Peter Eisentraut <peter@eisentraut.org> wrote:
2. Move to 1.1.1. I understand this has to do with the fork-safety of pg_strong_random(), and it's not an API change but a behavior change. Let's make this association clearer in the code. For example, add a version check or assertion about this into pg_strong_random() itself.

0005 moves the fork safety init inline with calling pg_strong_random, and
removes it for everyone else. This allows 1.1.0 to be supported as we
effectively are at the 1.1.0 API level, at the cost of calls for strong random
being slower on 1.1.0. An unscientific guess based on packaged OpenSSL
versions and the EOL and ELS/LTS status of 1.1.0, is that the number of
production installs of postgres 17 using OpenSSL 1.1.0 is close to zero.

It is only necessary to call RAND_poll once after forking. Wouldn't
it be OK to use a static flag and use the initialization once?

* src/port/pg_strong_random.c

I would prefer to remove pg_strong_random_init() if it's no longer
useful. I mean, if we leave it as is, and we are not removing any
callers, then we are effectively continuing to support OpenSSL
<1.1.1, right?

The attached removes pg_strong_random_init and instead calls it explicitly for
1.1.0 users by checking the OpenSSL version.

Is the attached split in line with how you were thinking about it?

If I may, 0001 looks sensible here. The bits from 0003 and 0004 could
be applied before 0002, as well.

--- a/src/backend/postmaster/fork_process.c
+++ b/src/backend/postmaster/fork_process.c
@@ -110,9 +110,6 @@ fork_process(void)
 				close(fd);
 			}
 		}
-
-		/* do post-fork initialization for random number generation */
-		pg_strong_random_init();

Perhaps you intented this diff to be in 0005 rather than in 0002?
With 0002 applied, only support for 1.0.2 is removed, not 1.1.0 yet.

pg_strong_random(void *buf, size_t len)
{
int i;

+#if (OPENSSL_VERSION_NUMBER <= 0x10100000L)
+	/*
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * requred on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
+	 */
+	RAND_poll();
+#endif

s/requred/required/. Rather than calling always RAND_poll(), this
could use a static flag to call it only once when pg_strong_random is
called for the first time. I would not mind seeing this part entirely
gone with the removal of support for 1.1.0.
--
Michael

#77Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#76)
5 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 15 Apr 2024, at 07:04, Michael Paquier <michael@paquier.xyz> wrote:
On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote:

Is the attached split in line with how you were thinking about it?

If I may, 0001 looks sensible here. The bits from 0003 and 0004 could
be applied before 0002, as well.

Agreed, once we are in post-freeze I think those three are mostly ready to go.

- /* do post-fork initialization for random number generation */
- pg_strong_random_init();

Perhaps you intented this diff to be in 0005 rather than in 0002?
With 0002 applied, only support for 1.0.2 is removed, not 1.1.0 yet.

Yes, nice catch, that was a mistake in splitting up the patch into multiple
pieces, it should be in the 0005 patch for strong random. Fixed.

s/requred/required/.

Fixed.

Rather than calling always RAND_poll(), this
could use a static flag to call it only once when pg_strong_random is
called for the first time.

Agreed, we can good that. Fixed.

I would not mind seeing this part entirely
gone with the removal of support for 1.1.0.

If we want to keep autoconf from checking versions and just check compatibility
(with our code) then we will remain at 1.1.0 compatibility. The only 1.1.1 API
we use is not present in LibreSSL so we can't really place a hard restriction
on that. It might be that keeping it for now, and removing it later during the
v18 cycle as we modernize our OpenSSL code (which I hope to find time to work
on) and make use of newer 1.1.1 API:s. That way we can keep our autoconf/meson
checks consistent across library checks. If we end up with no new API:s to
check for by the time the last commitfest of v18 rolls around, we can revisit
the decision then.

--
Daniel Gustafsson

Attachments:

v8-0005-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v8-0005-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From fb754690b98d87115de6c7c4e6952a67db547a4a Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 13:20:31 +0200
Subject: [PATCH v8 5/5] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.1 is being
increasingly phased out from production use, remove the initialization
and only do it explicitly for anyone running 1.1.0.  This will penalize
1.1.0 installations by doing it per call to pg_strong_random, but the
number of production environments running the latest PostgreSQL combined
with a very out of date OpenSSL (which never was available as LTS/ELS)
is believed to be low.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random which
for the vast majority of users is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/backend/postmaster/fork_process.c |  3 --
 src/include/port.h                    |  1 -
 src/port/pg_strong_random.c           | 43 ++++++++++-----------------
 3 files changed, 16 insertions(+), 31 deletions(-)

diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c
index 5e42a74ab5..bcff9ef661 100644
--- a/src/backend/postmaster/fork_process.c
+++ b/src/backend/postmaster/fork_process.c
@@ -110,9 +110,6 @@ fork_process(void)
 				close(fd);
 			}
 		}
-
-		/* do post-fork initialization for random number generation */
-		pg_strong_random_init();
 	}
 	else
 	{
diff --git a/src/include/port.h b/src/include/port.h
index ae115d2d97..2a363764f1 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -473,7 +473,6 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits,
 							  char *dst, size_t size);
 
 /* port/pg_strong_random.c */
-extern void pg_strong_random_init(void);
 extern bool pg_strong_random(void *buf, size_t len);
 
 /*
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..ac78a93536 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -25,14 +25,11 @@
 #include <sys/time.h>
 
 /*
- * pg_strong_random & pg_strong_random_init
+ * pg_strong_random
  *
  * Generate requested number of random bytes. The returned bytes are
  * cryptographically secure, suitable for use e.g. in authentication.
  *
- * Before pg_strong_random is called in any process, the generator must first
- * be initialized by calling pg_strong_random_init().
- *
  * We rely on system facilities for actually generating the numbers.
  * We support a number of sources:
  *
@@ -51,22 +48,26 @@
 #ifdef USE_OPENSSL
 
 #include <openssl/rand.h>
-
-void
-pg_strong_random_init(void)
-{
-	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
-	 */
-	RAND_poll();
-}
+#include <openssl/opensslv.h>
 
 bool
 pg_strong_random(void *buf, size_t len)
 {
 	int			i;
+#if (OPENSSL_VERSION_NUMBER <= 0x10100000L)
+	static bool rand_initialized = false;
+
+	/*
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
+	 */
+	if (!rand_initialized)
+	{
+		RAND_poll();
+		rand_initialized = true;
+	}
+#endif
 
 	/*
 	 * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
@@ -104,12 +105,6 @@ pg_strong_random(void *buf, size_t len)
  */
 static HCRYPTPROV hProvider = 0;
 
-void
-pg_strong_random_init(void)
-{
-	/* No initialization needed on WIN32 */
-}
-
 bool
 pg_strong_random(void *buf, size_t len)
 {
@@ -143,12 +138,6 @@ pg_strong_random(void *buf, size_t len)
  * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
  */
 
-void
-pg_strong_random_init(void)
-{
-	/* No initialization needed */
-}
-
 bool
 pg_strong_random(void *buf, size_t len)
 {
-- 
2.39.3 (Apple Git-146)

v8-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patchapplication/octet-stream; name=v8-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch; x-unix-mode=0644Download
From 9e09a62f552a15bc280cf88d3ffd880175f7bdf8 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 13:12:17 +0200
Subject: [PATCH v8 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL

The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since
LibreSSL 3.6.3, shipped in OpenSSL 7.2. Previously we only checked for
SSL_R_VERSION_TOO_HIGH and then applied both under that guard since
OpenSSL has only ever supported both at the same time. This breaks the
check into one per reason to allow SSL_R_VERSION_TOO_LOW to work when
using LibreSSL.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index efd49ffca8..59c71b15b5 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -542,6 +542,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
-- 
2.39.3 (Apple Git-146)

v8-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patchapplication/octet-stream; name=v8-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch; x-unix-mode=0644Download
From 4c75bbe0fd09ba69b81db2d2270907f5c604ec24 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 12:44:24 +0200
Subject: [PATCH v8 3/5] Support disallowing SSL renegotiation in LibreSSL

LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is
used by OpenSSL, instead it has invented a similar one for client-
side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been
supported since LibreSSL 2.5.1 which by now can be considered well
below the minimum requirement.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 88153d4bda..efd49ffca8 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -262,15 +262,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
-- 
2.39.3 (Apple Git-146)

v8-0002-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v8-0002-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From 09e807672fb9b8d3f70c522d2aaf616e2dc407d9 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 11:21:55 +0200
Subject: [PATCH v8 2/5] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 ++--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  16 +-
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  21 +--
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 14 files changed, 28 insertions(+), 437 deletions(-)
 delete mode 100644 src/common/protocol_openssl.c

diff --git a/configure b/configure
index cfbd2a096f..73e76070b0 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 67e738d92b..cf85ad409e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..e35f52a4d0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/meson.build b/meson.build
index 43fad5323c..b77dda7c2b 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 29c9af1aab..88153d4bda 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -104,13 +105,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -933,7 +928,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -956,14 +950,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..e55b024159 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +152,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +315,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
deleted file mode 100644
index ae378685e1..0000000000
--- a/src/common/protocol_openssl.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index c98cfa6084..640edebcfe 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1651,30 +1492,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1935,7 +1752,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1961,14 +1777,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1976,13 +1784,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..434d6c449f 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.39.3 (Apple Git-146)

v8-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patchapplication/octet-stream; name=v8-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch; x-unix-mode=0644Download
From 5bba79f12b32b5b9840d16971056cdd3bb7c1ab0 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 11:36:08 +0200
Subject: [PATCH v8 1/5] Doc: Use past tense for things which happened in the
 past

The paragraph on SSL compression is largely describing events which
took place many years ago, so reword with past tense.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 doc/src/sgml/libpq.sgml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9199d0d2e5..0db3667fdf 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
-- 
2.39.3 (Apple Git-146)

#78Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#77)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Mon, Apr 15, 2024 at 11:07:05AM +0200, Daniel Gustafsson wrote:

On 15 Apr 2024, at 07:04, Michael Paquier <michael@paquier.xyz> wrote:

On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote:

Is the attached split in line with how you were thinking about it?

If I may, 0001 looks sensible here. The bits from 0003 and 0004 could
be applied before 0002, as well.

Agreed, once we are in post-freeze I think those three are mostly
ready to go.

Is there a point to wait for 0001, 0003 and 0004, though, and
shouldn't these three be backpatched? 0001 is certainly OK as a
doc-only change to be consistent across the board without waiting 5
more years. 0003 and 0004 are conditional and depend on if
SSL_R_VERSION_TOO_LOW and SSL_OP_NO_CLIENT_RENEGOTIATION are defined
at compile-time. 0003 is much more important, and note that
01e6f1a842f4 has been backpatched all the way down. 0004 is nice,
still not strongly mandatory.

Rather than calling always RAND_poll(), this
could use a static flag to call it only once when pg_strong_random is
called for the first time.

Agreed, we can good that. Fixed.

+#if (OPENSSL_VERSION_NUMBER <= 0x10100000L)
+	static bool rand_initialized = false;

This does not look right. At the top of upstream's branch
OpenSSL_1_1_0-stable, OPENSSL_VERSION_NUMBER is 0x101000d0L, so the
initialization would be missed for any version in the 1.1.0 series
except the GA one without this code being compiled, no?

I would not mind seeing this part entirely
gone with the removal of support for 1.1.0.

If we want to keep autoconf from checking versions and just check compatibility
(with our code) then we will remain at 1.1.0 compatibility. The only 1.1.1 API
we use is not present in LibreSSL so we can't really place a hard restriction
on that. It might be that keeping it for now, and removing it later during the
v18 cycle as we modernize our OpenSSL code (which I hope to find time to work
on) and make use of newer 1.1.1 API:s. That way we can keep our autoconf/meson
checks consistent across library checks. If we end up with no new API:s to
check for by the time the last commitfest of v18 rolls around, we can revisit
the decision then.

Okay, fine by me.
--
Michael

#79Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#78)
5 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 16 Apr 2024, at 01:03, Michael Paquier <michael@paquier.xyz> wrote:

On Mon, Apr 15, 2024 at 11:07:05AM +0200, Daniel Gustafsson wrote:

On 15 Apr 2024, at 07:04, Michael Paquier <michael@paquier.xyz> wrote:

On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote:

Is the attached split in line with how you were thinking about it?

If I may, 0001 looks sensible here. The bits from 0003 and 0004 could
be applied before 0002, as well.

Agreed, once we are in post-freeze I think those three are mostly
ready to go.

Is there a point to wait for 0001, 0003 and 0004, though, and
shouldn't these three be backpatched? 0001 is certainly OK as a
doc-only change to be consistent across the board without waiting 5
more years. 0003 and 0004 are conditional and depend on if
SSL_R_VERSION_TOO_LOW and SSL_OP_NO_CLIENT_RENEGOTIATION are defined
at compile-time. 0003 is much more important, and note that
01e6f1a842f4 has been backpatched all the way down. 0004 is nice,
still not strongly mandatory.

I forgot (and didn't check) that we backpatched 01e6f1a842f4, with that in mind
I agree that we should backpatch 0003 as well to put LibreSSL on par as much as
we can. 0004 is a fix for the LibreSSL support, not adding anything new, so
pushing that to master now makes sense. Unless objections are raised I'll push
0001, 0003 and 0004 shortly. 0002 and 0005 can hopefully be addressed in the
July commitfest.

Rather than calling always RAND_poll(), this
could use a static flag to call it only once when pg_strong_random is
called for the first time.

Agreed, we can good that. Fixed.

+#if (OPENSSL_VERSION_NUMBER <= 0x10100000L)
+ static bool rand_initialized = false;

This does not look right. At the top of upstream's branch
OpenSSL_1_1_0-stable, OPENSSL_VERSION_NUMBER is 0x101000d0L, so the
initialization would be missed for any version in the 1.1.0 series
except the GA one without this code being compiled, no?

Meh, I was clearly not caffeinated as that's a thinko with a typo attached to
it. The check should be "< 0x10101000" to catch any version prior to 1.1.1.
Fixed.

--
Daniel Gustafsson

Attachments:

v9-0005-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v9-0005-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From 88396949018b1e66d94ec9d77f54086fb55fcaa6 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 13:20:31 +0200
Subject: [PATCH v9 5/5] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.1 is being
increasingly phased out from production use, remove the initialization
and only do it explicitly for anyone running 1.1.0.  This will penalize
1.1.0 installations by doing it per call to pg_strong_random, but the
number of production environments running the latest PostgreSQL combined
with a very out of date OpenSSL (which never was available as LTS/ELS)
is believed to be low.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random which
for the vast majority of users is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/backend/postmaster/fork_process.c |  3 --
 src/include/port.h                    |  1 -
 src/port/pg_strong_random.c           | 43 ++++++++++-----------------
 3 files changed, 16 insertions(+), 31 deletions(-)

diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c
index 5e42a74ab5..bcff9ef661 100644
--- a/src/backend/postmaster/fork_process.c
+++ b/src/backend/postmaster/fork_process.c
@@ -110,9 +110,6 @@ fork_process(void)
 				close(fd);
 			}
 		}
-
-		/* do post-fork initialization for random number generation */
-		pg_strong_random_init();
 	}
 	else
 	{
diff --git a/src/include/port.h b/src/include/port.h
index ae115d2d97..2a363764f1 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -473,7 +473,6 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits,
 							  char *dst, size_t size);
 
 /* port/pg_strong_random.c */
-extern void pg_strong_random_init(void);
 extern bool pg_strong_random(void *buf, size_t len);
 
 /*
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..48b8671e68 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -25,14 +25,11 @@
 #include <sys/time.h>
 
 /*
- * pg_strong_random & pg_strong_random_init
+ * pg_strong_random
  *
  * Generate requested number of random bytes. The returned bytes are
  * cryptographically secure, suitable for use e.g. in authentication.
  *
- * Before pg_strong_random is called in any process, the generator must first
- * be initialized by calling pg_strong_random_init().
- *
  * We rely on system facilities for actually generating the numbers.
  * We support a number of sources:
  *
@@ -51,22 +48,26 @@
 #ifdef USE_OPENSSL
 
 #include <openssl/rand.h>
-
-void
-pg_strong_random_init(void)
-{
-	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
-	 */
-	RAND_poll();
-}
+#include <openssl/opensslv.h>
 
 bool
 pg_strong_random(void *buf, size_t len)
 {
 	int			i;
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
+	static bool rand_initialized = false;
+
+	/*
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
+	 */
+	if (!rand_initialized)
+	{
+		RAND_poll();
+		rand_initialized = true;
+	}
+#endif
 
 	/*
 	 * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
@@ -104,12 +105,6 @@ pg_strong_random(void *buf, size_t len)
  */
 static HCRYPTPROV hProvider = 0;
 
-void
-pg_strong_random_init(void)
-{
-	/* No initialization needed on WIN32 */
-}
-
 bool
 pg_strong_random(void *buf, size_t len)
 {
@@ -143,12 +138,6 @@ pg_strong_random(void *buf, size_t len)
  * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
  */
 
-void
-pg_strong_random_init(void)
-{
-	/* No initialization needed */
-}
-
 bool
 pg_strong_random(void *buf, size_t len)
 {
-- 
2.39.3 (Apple Git-146)

v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patchapplication/octet-stream; name=v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch; x-unix-mode=0644Download
From db84b48ed74770bf7f67ed44475f0f52939d772d Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 13:12:17 +0200
Subject: [PATCH v9 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL

The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since
LibreSSL 3.6.3, shipped in OpenSSL 7.2. Previously we only checked for
SSL_R_VERSION_TOO_HIGH and then applied both under that guard since
OpenSSL has only ever supported both at the same time. This breaks the
check into one per reason to allow SSL_R_VERSION_TOO_LOW to work when
using LibreSSL.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index efd49ffca8..59c71b15b5 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -542,6 +542,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
-- 
2.39.3 (Apple Git-146)

v9-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patchapplication/octet-stream; name=v9-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch; x-unix-mode=0644Download
From bf0c8974bbb8ae31c1379b99e4cfc17cf357599c Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 12:44:24 +0200
Subject: [PATCH v9 3/5] Support disallowing SSL renegotiation in LibreSSL

LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is
used by OpenSSL, instead it has invented a similar one for client-
side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been
supported since LibreSSL 2.5.1 which by now can be considered well
below the minimum requirement.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 88153d4bda..efd49ffca8 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -262,15 +262,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
-- 
2.39.3 (Apple Git-146)

v9-0002-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v9-0002-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From d68e4cab94e49e7567093b08ab3dc52f961ec76d Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 11:21:55 +0200
Subject: [PATCH v9 2/5] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 ++--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  16 +-
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  21 +--
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 14 files changed, 28 insertions(+), 437 deletions(-)
 delete mode 100644 src/common/protocol_openssl.c

diff --git a/configure b/configure
index cfbd2a096f..73e76070b0 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 67e738d92b..cf85ad409e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..e35f52a4d0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/meson.build b/meson.build
index 43fad5323c..b77dda7c2b 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 29c9af1aab..88153d4bda 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -104,13 +105,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -933,7 +928,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -956,14 +950,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..e55b024159 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +152,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +315,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
deleted file mode 100644
index ae378685e1..0000000000
--- a/src/common/protocol_openssl.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index c98cfa6084..640edebcfe 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1651,30 +1492,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has then loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1935,7 +1752,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1961,14 +1777,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1976,13 +1784,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..434d6c449f 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.39.3 (Apple Git-146)

v9-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patchapplication/octet-stream; name=v9-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch; x-unix-mode=0644Download
From 9ad9e09523574bf33d8a832e03c31ea539cfe2dc Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Apr 2024 11:36:08 +0200
Subject: [PATCH v9 1/5] Doc: Use past tense for things which happened in the
 past

The paragraph on SSL compression is largely describing events which
took place many years ago, so reword with past tense.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 doc/src/sgml/libpq.sgml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9199d0d2e5..0db3667fdf 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
-- 
2.39.3 (Apple Git-146)

#80Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#79)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 16.04.24 10:17, Daniel Gustafsson wrote:

I forgot (and didn't check) that we backpatched 01e6f1a842f4, with that in mind
I agree that we should backpatch 0003 as well to put LibreSSL on par as much as
we can. 0004 is a fix for the LibreSSL support, not adding anything new, so
pushing that to master now makes sense. Unless objections are raised I'll push
0001, 0003 and 0004 shortly. 0002 and 0005 can hopefully be addressed in the
July commitfest.

Review of the latest batch:

* v9-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch

Ok

8 v9-0002-Remove-support-for-OpenSSL-1.0.2.patch

Ok, but maybe make the punctuation consistent here:

+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL
        ['X509_get_signature_info'],

* v9-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch

ok

* v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch

Seems ok, but the reason isn't clear to me. Are there LibreSSL versions
that have SSL_R_VERSION_TOO_LOW but not SSL_R_VERSION_TOO_HIGH? Maybe
this could be explained better.

Also, "OpenSSL 7.2" in the commit message probably meant "OpenBSD"?

* v9-0005-Remove-pg_strong_random-initialization.patch

I don't understand the reason for this phrase in the commit message:
"1.1.1 is being increasingly phased out from production use". Did you
mean 1.1.0 there?

Conditionally sticking the RAND_poll() into pg_strong_random(), does
that have the effect we want? It wouldn't reinitialize after a fork,
AFAICT.

If everything is addressed, I agree that 0001, 0003, and 0004 can go
into PG17, the rest later.

#81Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#80)
5 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 18 Apr 2024, at 12:53, Peter Eisentraut <peter@eisentraut.org> wrote:

Review of the latest batch:

Thanks for reviewing!

8 v9-0002-Remove-support-for-OpenSSL-1.0.2.patch

Ok, but maybe make the punctuation consistent here:

Fixed.

* v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch

Seems ok, but the reason isn't clear to me. Are there LibreSSL versions that have SSL_R_VERSION_TOO_LOW but not SSL_R_VERSION_TOO_HIGH? Maybe this could be explained better.

LibreSSL doesn't support SSL_R_VERSION_TOO_HIGH at all, they only support
_TOO_LOW starting with the OpenBSD 7.2 release. I've expanded the commit
message to document this.

Also, "OpenSSL 7.2" in the commit message probably meant "OpenBSD"?

Ah yes, fixed.

* v9-0005-Remove-pg_strong_random-initialization.patch

I don't understand the reason for this phrase in the commit message: "1.1.1 is being increasingly phased out from production use". Did you mean 1.1.0 there?

Correct, I got lost among the version numbers it seems. Fixed.

Conditionally sticking the RAND_poll() into pg_strong_random(), does that have the effect we want? It wouldn't reinitialize after a fork, AFAICT.

No I think you're right, my previous version would have worked (but was ugly)
but this doesn't guarantee that. Thinking more about it maybe it's best to
just keep the init function and have a version check for 1.1.0 there, making it
an empty no-op for all other cases. When we move past 1.1.0 due to a new API
requirement we can blow it all away.

If everything is addressed, I agree that 0001, 0003, and 0004 can go into PG17, the rest later.

Agreed, 0002 and 0005 are clearly for the v18 cycle.

--
Daniel Gustafsson

Attachments:

v10-0001-Doc-Use-past-tense-for-things-which-happened-in-.patchapplication/octet-stream; name=v10-0001-Doc-Use-past-tense-for-things-which-happened-in-.patch; x-unix-mode=0644Download
From 82f8a165c651dcdf9b35e208c8aa00fba8696dfe Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:36:52 +0200
Subject: [PATCH v10 1/5] Doc: Use past tense for things which happened in the
 past

The paragraph on SSL compression is largely describing events which
took place many years ago, so reword with past tense.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 doc/src/sgml/libpq.sgml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9199d0d2e5..0db3667fdf 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
 
        <para>
         SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
+        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disabled
         compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
+        disabled it in prior versions as well, so setting this parameter to on
         will not have any effect if the server does not accept compression.
-        <productname>PostgreSQL</productname> 14 disables compression
+        <productname>PostgreSQL</productname> 14 disabled compression
         completely in the backend.
        </para>
 
-- 
2.39.3 (Apple Git-146)

v10-0002-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v10-0002-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From 9f7aff6c60727ed431b638a4d0d4cde3994ae7c5 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:37:00 +0200
Subject: [PATCH v10 2/5] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 ++--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  16 +-
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  21 +--
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 14 files changed, 28 insertions(+), 437 deletions(-)

diff --git a/configure b/configure
index cfbd2a096f..73e76070b0 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 67e738d92b..cf85ad409e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..e35f52a4d0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/meson.build b/meson.build
index cdfd31377d..f9ec8b66a8 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 29c9af1aab..88153d4bda 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -104,13 +105,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -933,7 +928,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -956,14 +950,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..e55b024159 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +152,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +315,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
index ae378685e1..e69de29bb2 100644
--- a/src/common/protocol_openssl.c
+++ b/src/common/protocol_openssl.c
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index e7a4d006e1..640edebcfe 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1651,30 +1492,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has them loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1935,7 +1752,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1961,14 +1777,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1976,13 +1784,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..434d6c449f 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.39.3 (Apple Git-146)

v10-0003-Support-disallowing-SSL-renegotiation-in-LibreSS.patchapplication/octet-stream; name=v10-0003-Support-disallowing-SSL-renegotiation-in-LibreSS.patch; x-unix-mode=0644Download
From 436f9bf6d4bf04eb8b47fea4fede6176be5e29e8 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:37:44 +0200
Subject: [PATCH v10 3/5] Support disallowing SSL renegotiation in LibreSSL

LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is
used by OpenSSL, instead it has invented a similar one for client-
side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been
supported since LibreSSL 2.5.1 which by now can be considered well
below the minimum requirement.

Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 88153d4bda..efd49ffca8 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -262,15 +262,20 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL compression */
 	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
 
-#ifdef SSL_OP_NO_RENEGOTIATION
-
 	/*
-	 * Disallow SSL renegotiation, option available since 1.1.0h.  This
-	 * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
-	 * support for renegotiation.
+	 * Disallow SSL renegotiation.  This concerns only TLSv1.2 and older
+	 * protocol versions, as TLSv1.3 has no support for renegotiation.
+	 * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
+	 * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
+	 * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
+	 * (this is usually on by default).
 	 */
+#ifdef SSL_OP_NO_RENEGOTIATION
 	SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
 #endif
+#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
+	SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
+#endif
 
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
-- 
2.39.3 (Apple Git-146)

v10-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patchapplication/octet-stream; name=v10-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch; x-unix-mode=0644Download
From 909a6c2c9de701931488ab28cc9500ff2326e43e Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:37:57 +0200
Subject: [PATCH v10 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL

The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since
LibreSSL 3.6.3, shipped in OpenBSD 7.2.  SSL_R_VERSION_TOO_HIGH is on
the other hand not supported in any version of LibreSSL.  Previously
we only checked for SSL_R_VERSION_TOO_HIGH and then applied both under
that guard since OpenSSL has only ever supported both at the same time.
This breaks the check into one per reason to allow SSL_R_VERSION_TOO_LOW
to work when using LibreSSL.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/eac70d46-e61c-4d71-a1e1-78e2bfa19485@eisentraut.org
---
 src/backend/libpq/be-secure-openssl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index efd49ffca8..59c71b15b5 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -542,6 +542,8 @@ aloop:
 					case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
 #ifdef SSL_R_VERSION_TOO_HIGH
 					case SSL_R_VERSION_TOO_HIGH:
+#endif
+#ifdef SSL_R_VERSION_TOO_LOW
 					case SSL_R_VERSION_TOO_LOW:
 #endif
 						give_proto_hint = true;
-- 
2.39.3 (Apple Git-146)

v10-0005-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v10-0005-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From 0fc05de568f8699b6265efaf40aad9836b59166a Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:39:33 +0200
Subject: [PATCH v10 5/5] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.0 is being
increasingly phased out from production use, only perform the RAND_poll
initialization for installations running 1.1.0 by checkig the OpenSSL
version number.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random
for the vast majority of users for whom it is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/port/pg_strong_random.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..a8efb2b188 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -50,17 +50,20 @@
 
 #ifdef USE_OPENSSL
 
+#include <openssl/opensslv.h>
 #include <openssl/rand.h>
 
 void
 pg_strong_random_init(void)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
 	 */
 	RAND_poll();
+#endif
 }
 
 bool
-- 
2.39.3 (Apple Git-146)

#82Michael Paquier
michael@paquier.xyz
In reply to: Peter Eisentraut (#80)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote:

If everything is addressed, I agree that 0001, 0003, and 0004 can go into
PG17, the rest later.

About the PG17 bits, would you agree about a backpatch? Or perhaps
you disagree?
--
Michael

#83Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#82)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 19 Apr 2024, at 07:37, Michael Paquier <michael@paquier.xyz> wrote:

On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote:

If everything is addressed, I agree that 0001, 0003, and 0004 can go into
PG17, the rest later.

About the PG17 bits, would you agree about a backpatch? Or perhaps
you disagree?

If we want to 0001 can be baclpatched to v15, 0004 to v13 and 0003 all the way.
I don't have strong opinions either way.

--
Daniel Gustafsson

#84Peter Eisentraut
peter@eisentraut.org
In reply to: Michael Paquier (#82)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 19.04.24 07:37, Michael Paquier wrote:

On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote:

If everything is addressed, I agree that 0001, 0003, and 0004 can go into
PG17, the rest later.

About the PG17 bits, would you agree about a backpatch? Or perhaps
you disagree?

I don't think any of these need to be backpatched, at least right now.

0001 is just a cosmetic documentation tweak, has no reason to be
backpatched.

0003 adds new functionality for LibreSSL. While the code looks
straightforward, we have little knowledge about how it works in
practice. How is the buildfarm coverage of LibreSSL (with SSL tests
enabled!)? If people are keen on this, it might be better to get it
into PG17 and at least let to go through a few months of beta testing.

0004 effectively just enhances an error message for LibreSSL; there is
little reason to backpatch this.

#85Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#84)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 19 Apr 2024, at 10:06, Peter Eisentraut <peter@eisentraut.org> wrote:

On 19.04.24 07:37, Michael Paquier wrote:

On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote:

If everything is addressed, I agree that 0001, 0003, and 0004 can go into
PG17, the rest later.

About the PG17 bits, would you agree about a backpatch? Or perhaps
you disagree?

I don't think any of these need to be backpatched, at least right now.

0001 is just a cosmetic documentation tweak, has no reason to be backpatched.

0003 adds new functionality for LibreSSL. While the code looks straightforward, we have little knowledge about how it works in practice. How is the buildfarm coverage of LibreSSL (with SSL tests enabled!)? If people are keen on this, it might be better to get it into PG17 and at least let to go through a few months of beta testing.

0004 effectively just enhances an error message for LibreSSL; there is little reason to backpatch this.

Hearing no objections to this plan (and the posted v10), I'll go ahead with
0001, 0003 and 0004 into v17 tomorrow.

--
Daniel Gustafsson

#86Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#85)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, Apr 23, 2024 at 10:08:13PM +0200, Daniel Gustafsson wrote:

Hearing no objections to this plan (and the posted v10), I'll go ahead with
0001, 0003 and 0004 into v17 tomorrow.

WFM, thanks.
--
Michael

#87Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#86)
2 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 24 Apr 2024, at 00:20, Michael Paquier <michael@paquier.xyz> wrote:

On Tue, Apr 23, 2024 at 10:08:13PM +0200, Daniel Gustafsson wrote:

Hearing no objections to this plan (and the posted v10), I'll go ahead with
0001, 0003 and 0004 into v17 tomorrow.

WFM, thanks.

Done. Attached are the two remaining patches, rebased over HEAD, for removing
support for OpenSSL 1.0.2 in v18. Parking them in the commitfest for now.

--
Daniel Gustafsson

Attachments:

v11-0002-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v11-0002-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From 331207efef429954265bbb24687d71df91e2c9a9 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:39:33 +0200
Subject: [PATCH v11 2/2] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.0 is being
increasingly phased out from production use, only perform the RAND_poll
initialization for installations running 1.1.0 by checkig the OpenSSL
version number.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random
for the vast majority of users for whom it is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/port/pg_strong_random.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..a8efb2b188 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -50,17 +50,20 @@
 
 #ifdef USE_OPENSSL
 
+#include <openssl/opensslv.h>
 #include <openssl/rand.h>
 
 void
 pg_strong_random_init(void)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
 	 */
 	RAND_poll();
+#endif
 }
 
 bool
-- 
2.39.3 (Apple Git-146)

v11-0001-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v11-0001-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From 626cdc6b1b6a1ed30b44b261c645c8a922360ba4 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:37:00 +0200
Subject: [PATCH v11 1/2] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 ++--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  16 +-
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  21 +--
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 --------------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-secure-openssl.c | 197 -----------------------
 src/interfaces/libpq/libpq-int.h         |   5 -
 14 files changed, 28 insertions(+), 437 deletions(-)

diff --git a/configure b/configure
index cfbd2a096f..73e76070b0 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index 67e738d92b..cf85ad409e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..e35f52a4d0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/meson.build b/meson.build
index cdfd31377d..f9ec8b66a8 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index fc46a33539..59c71b15b5 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -104,13 +105,7 @@ be_tls_init(bool isServerStart)
 	/* This stuff need be done only once. */
 	if (!SSL_initialized)
 	{
-#ifdef HAVE_OPENSSL_INIT_SSL
 		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
 		SSL_initialized = true;
 	}
 
@@ -940,7 +935,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -963,14 +957,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..e55b024159 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +152,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +315,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
index ae378685e1..e69de29bb2 100644
--- a/src/common/protocol_openssl.c
+++ b/src/common/protocol_openssl.c
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index e7a4d006e1..640edebcfe 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 /*
  * Initialize SSL library.
  *
@@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	if (pthread_mutex_lock(&ssl_config_mutex))
 		return -1;
 
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
 	if (!ssl_lib_initialized && do_ssl)
 	{
 		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
 			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
 		ssl_lib_initialized = true;
 	}
 
@@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
 	return 0;
 }
 
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1651,30 +1492,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has them loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1935,7 +1752,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1961,14 +1777,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1976,13 +1784,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..434d6c449f 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
-- 
2.39.3 (Apple Git-146)

#88Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#87)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Apr 24, 2024 at 01:31:12PM +0200, Daniel Gustafsson wrote:

Done. Attached are the two remaining patches, rebased over HEAD, for removing
support for OpenSSL 1.0.2 in v18. Parking them in the commitfest for now.

You have mentioned once upthread the documentation of PQinitOpenSSL():
However, this is unnecessary when using <productname>OpenSSL</productname>
version 1.1.0 or later, as duplicate initializations are no longer problematic.

With 1.0.2's removal in place, this could be simplified more and the
patch does not touch it. This relates also to pq_init_crypto_lib,
which is gone with 0001. Of course, it is not possible to just remove
PQinitOpenSSL() or old application may fail linking. Removing
pq_init_crypto_lib reduces any confusion around this part of the
initialization.

0002 looks OK here.
--
Michael

#89Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#88)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 25 Apr 2024, at 05:49, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, Apr 24, 2024 at 01:31:12PM +0200, Daniel Gustafsson wrote:

Done. Attached are the two remaining patches, rebased over HEAD, for removing
support for OpenSSL 1.0.2 in v18. Parking them in the commitfest for now.

You have mentioned once upthread the documentation of PQinitOpenSSL():
However, this is unnecessary when using <productname>OpenSSL</productname>
version 1.1.0 or later, as duplicate initializations are no longer problematic.

With 1.0.2's removal in place, this could be simplified more and the
patch does not touch it. This relates also to pq_init_crypto_lib,
which is gone with 0001. Of course, it is not possible to just remove
PQinitOpenSSL() or old application may fail linking. Removing
pq_init_crypto_lib reduces any confusion around this part of the
initialization.

That's a good point, there is potential for more code removal here. The
attached 0001 takes a stab at it while it's fresh in mind, I'll revisit before
the July CF to see if there is more that can be done.

--
Daniel Gustafsson

#90Daniel Gustafsson
daniel@yesql.se
In reply to: Daniel Gustafsson (#89)
2 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 27 Apr 2024, at 20:32, Daniel Gustafsson <daniel@yesql.se> wrote:

That's a good point, there is potential for more code removal here. The
attached 0001 takes a stab at it while it's fresh in mind, I'll revisit before
the July CF to see if there is more that can be done.

..and again with the attachment. Not enough coffee.

--
Daniel Gustafsson

Attachments:

v12-0002-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v12-0002-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From 8cdf1101c57917e425feb08f6c26fc35a6be9611 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:39:33 +0200
Subject: [PATCH v12 2/2] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.0 is being
increasingly phased out from production use, only perform the RAND_poll
initialization for installations running 1.1.0 by checkig the OpenSSL
version number.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random
for the vast majority of users for whom it is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/port/pg_strong_random.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..a8efb2b188 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -50,17 +50,20 @@
 
 #ifdef USE_OPENSSL
 
+#include <openssl/opensslv.h>
 #include <openssl/rand.h>
 
 void
 pg_strong_random_init(void)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
 	 */
 	RAND_poll();
+#endif
 }
 
 bool
-- 
2.39.3 (Apple Git-146)

v12-0001-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v12-0001-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From a9f6a2a2db3c12665fb96d01ad22056c4342e604 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:37:00 +0200
Subject: [PATCH v12 1/2] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 +--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  24 +--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  21 +-
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 -----------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-connect.c        |  18 --
 src/interfaces/libpq/fe-secure-openssl.c | 246 -----------------------
 src/interfaces/libpq/fe-secure.c         |  35 +---
 src/interfaces/libpq/libpq-int.h         |  13 +-
 16 files changed, 41 insertions(+), 542 deletions(-)

diff --git a/configure b/configure
index 89644f2249..1181a7347f 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index c7322e292c..2d5e2c2c2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..e35f52a4d0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/meson.build b/meson.build
index cdfd31377d..f9ec8b66a8 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index fc46a33539..3ba85490e5 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -80,7 +81,6 @@ static const char *SSLerrmessage(unsigned long ecode);
 static char *X509_NAME_to_cstring(X509_NAME *name);
 
 static SSL_CTX *SSL_context = NULL;
-static bool SSL_initialized = false;
 static bool dummy_ssl_passwd_cb_called = false;
 static bool ssl_is_server_start;
 
@@ -101,19 +101,6 @@ be_tls_init(bool isServerStart)
 	int			ssl_ver_min = -1;
 	int			ssl_ver_max = -1;
 
-	/* This stuff need be done only once. */
-	if (!SSL_initialized)
-	{
-#ifdef HAVE_OPENSSL_INIT_SSL
-		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
-		SSL_initialized = true;
-	}
-
 	/*
 	 * Create a new SSL context into which we'll load all the configuration
 	 * settings.  If we fail partway through, we can avoid memory leakage by
@@ -940,7 +927,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -963,14 +949,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..e55b024159 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +152,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +315,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
index ae378685e1..e69de29bb2 100644
--- a/src/common/protocol_openssl.c
+++ b/src/common/protocol_openssl.c
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index ec20e3f3a9..f56c0712bb 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -3327,16 +3327,6 @@ keep_going:						/* We will come back to here until there is
 
 #ifdef USE_SSL
 
-				/*
-				 * Enable the libcrypto callbacks before checking if SSL needs
-				 * to be done.  This is done before sending the startup packet
-				 * as depending on the type of authentication done, like MD5
-				 * or SCRAM that use cryptohashes, the callbacks would be
-				 * required even without a SSL connection
-				 */
-				if (pqsecure_initialize(conn, false, true) < 0)
-					goto error_return;
-
 				/*
 				 * If direct SSL is enabled, jump right into SSL handshake. We
 				 * will come back here after SSL encryption has been
@@ -3510,14 +3500,6 @@ keep_going:						/* We will come back to here until there is
 					}
 				}
 
-				/*
-				 * Set up global SSL state if required.  The crypto state has
-				 * already been set if libpq took care of doing that, so there
-				 * is no need to make that happen again.
-				 */
-				if (pqsecure_initialize(conn, true, false) != 0)
-					goto error_return;
-
 				/*
 				 * Begin or continue the SSL negotiation process.
 				 */
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index e7a4d006e1..8927571076 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -83,14 +82,6 @@ static int	my_sock_write(BIO *h, const char *buf, int size);
 static BIO_METHOD *my_BIO_s_socket(void);
 static int	my_SSL_set_fd(PGconn *conn, int fd);
 
-
-static bool pq_init_ssl_lib = true;
-static bool pq_init_crypto_lib = true;
-
-static bool ssl_lib_initialized = false;
-
-static long crypto_open_connections = 0;
-
 static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
@@ -100,20 +91,6 @@ static int	ssl_protocol_version_to_openssl(const char *protocol);
 /*			 Procedures common to all secure sessions			*/
 /* ------------------------------------------------------------ */
 
-void
-pgtls_init_library(bool do_ssl, int do_crypto)
-{
-	/*
-	 * Disallow changing the flags while we have open connections, else we'd
-	 * get completely confused.
-	 */
-	if (crypto_open_connections != 0)
-		return;
-
-	pq_init_ssl_lib = do_ssl;
-	pq_init_crypto_lib = do_crypto;
-}
-
 PostgresPollingStatusType
 pgtls_open_client(PGconn *conn)
 {
@@ -505,11 +482,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +513,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,179 +681,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-/*
- * Initialize SSL library.
- *
- * In threadsafe mode, this includes setting up libcrypto callback functions
- * to do thread locking.
- *
- * If the caller has told us (through PQinitOpenSSL) that he's taking care
- * of libcrypto, we expect that callbacks are already set, and won't try to
- * override it.
- */
-int
-pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return -1;
-
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-	if (!ssl_lib_initialized && do_ssl)
-	{
-		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
-			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
-		ssl_lib_initialized = true;
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-	return 0;
-}
-
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1615,8 +1411,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1632,8 +1426,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1651,30 +1443,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has them loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1935,7 +1703,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -1961,14 +1728,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -1976,13 +1735,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index f628082337..5567be9d39 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -108,42 +108,27 @@ PQsslInUse(PGconn *conn)
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitSSL(int do_init)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_init, do_init);
-#endif
+	/* no-op */
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL and/or libcrypto.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitOpenSSL(int do_ssl, int do_crypto)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_ssl, do_crypto);
-#endif
-}
-
-/*
- *	Initialize global SSL context
- */
-int
-pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	int			r = 0;
-
-#ifdef USE_SSL
-	r = pgtls_init(conn, do_ssl, do_crypto);
-#endif
-
-	return r;
+	/* no-op */
 }
 
 /*
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..21df8623a7 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
@@ -763,7 +758,6 @@ extern int	pqWriteReady(PGconn *conn);
 
 /* === in fe-secure.c === */
 
-extern int	pqsecure_initialize(PGconn *, bool, bool);
 extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
 extern void pqsecure_close(PGconn *);
 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
@@ -786,19 +780,18 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
 /*
  *	Implementation of PQinitSSL().
  */
-extern void pgtls_init_library(bool do_ssl, int do_crypto);
+extern void pgtls_init_library(bool do_ssl);
 
 /*
  * Initialize SSL library.
  *
  * The conn parameter is only used to be able to pass back an error
  * message - no connection-local setup is made here.  do_ssl controls
- * if SSL is initialized, and do_crypto does the same for the crypto
- * part.
+ * if SSL is initialized.
  *
  * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
  */
-extern int	pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto);
+extern int	pgtls_init(PGconn *conn, bool do_ssl);
 
 /*
  *	Begin or continue negotiating a secure session.
-- 
2.39.3 (Apple Git-146)

#91Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#90)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Sat, Apr 27, 2024 at 08:33:55PM +0200, Daniel Gustafsson wrote:

On 27 Apr 2024, at 20:32, Daniel Gustafsson <daniel@yesql.se> wrote:

That's a good point, there is potential for more code removal here. The
attached 0001 takes a stab at it while it's fresh in mind, I'll revisit before
the July CF to see if there is more that can be done.

..and again with the attachment. Not enough coffee.

My remark was originally about pq_init_crypto_lib that does the
locking initialization, and your new patch a bit more, as of:

- /* This stuff need be done only once. */
- if (!SSL_initialized)
- {
-#ifdef HAVE_OPENSSL_INIT_SSL
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
- OPENSSL_config(NULL);
- SSL_library_init();
- SSL_load_error_strings();
-#endif
- SSL_initialized = true;
- }

OPENSSL_init_ssl() has replaced SSL_library_init(), marked as
deprecated, and even this step is mentioned as not required anymore
with 1.1.0~:
https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_init_ssl.html

Same with OPENSSL_init_crypto(), replacing OPENSSL_config(), again not
required in 1.1.0~:
https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_init_crypto.html

SSL_load_error_strings() is recommended as not to use in 1.1.0,
replaced by the others:
https://www.openssl.org/docs/man3.2/man3/SSL_load_error_strings.html

While OpenSSL will be able to cope with that, how much of that applies
to LibreSSL? SSL_load_error_strings(), OPENSSL_init_ssl(),
OPENSSL_CONFIG() are OK based on the docs:
https://man.archlinux.org/man/extra/libressl/libressl-OPENSSL_config.3.en
https://man.archlinux.org/man/extra/libressl/libressl-OPENSSL_init_ssl.3.en
https://man.archlinux.org/man/extra/libressl/libressl-ERR_load_crypto_strings.3.en

So +1 to remove all this code after a closer lookup. I would
recommend to update the documentation of PQinitSSL and PQinitOpenSSL
to tell that these become useless and are deprecated.

ERR_clear_error();
-
#ifdef USE_RESOWNER_FOR_HMAC

Some noise diff.
--
Michael

#92Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#91)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 1 May 2024, at 06:21, Michael Paquier <michael@paquier.xyz> wrote:

My remark was originally about pq_init_crypto_lib that does the
locking initialization, and your new patch a bit more, as of:

...

So +1 to remove all this code after a closer lookup.

Thanks for review.

I would
recommend to update the documentation of PQinitSSL and PQinitOpenSSL
to tell that these become useless and are deprecated.

They are no-ops when linking against v18, but writing an extension which
targets all supported versions of postgres along with their respective
supported OpenSSL versions make them still required, or am I missing something?

ERR_clear_error();
-
#ifdef USE_RESOWNER_FOR_HMAC

Some noise diff.

Will fix with a new rebase when once the tree has settled down from the
post-freeze fixups in this area.

--
Daniel Gustafsson

#93Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#92)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 03.05.24 10:39, Daniel Gustafsson wrote:

I would
recommend to update the documentation of PQinitSSL and PQinitOpenSSL
to tell that these become useless and are deprecated.

They are no-ops when linking against v18, but writing an extension which
targets all supported versions of postgres along with their respective
supported OpenSSL versions make them still required, or am I missing something?

I don't think extensions come into play here, since this is libpq, so
only the shared library interface compatibility matters.

#94Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#93)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Peter Eisentraut <peter@eisentraut.org> writes:

On 03.05.24 10:39, Daniel Gustafsson wrote:

They are no-ops when linking against v18, but writing an extension which
targets all supported versions of postgres along with their respective
supported OpenSSL versions make them still required, or am I missing something?

I don't think extensions come into play here, since this is libpq, so
only the shared library interface compatibility matters.

Yeah, server-side extensions don't really seem to be at hazard,
but doesn't the argument apply to client-side applications and
libraries that want to work across different PG/OpenSSL versions?

regards, tom lane

#95Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#94)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 3 May 2024, at 21:21, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Peter Eisentraut <peter@eisentraut.org> writes:

On 03.05.24 10:39, Daniel Gustafsson wrote:

They are no-ops when linking against v18, but writing an extension which
targets all supported versions of postgres along with their respective
supported OpenSSL versions make them still required, or am I missing something?

I don't think extensions come into play here, since this is libpq, so
only the shared library interface compatibility matters.

Yeah, server-side extensions don't really seem to be at hazard,
but doesn't the argument apply to client-side applications and
libraries that want to work across different PG/OpenSSL versions?

Right, I was using "extension" a bit carelessly, what I meant was client-side
applications using libpq.

--
Daniel Gustafsson

#96Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#92)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Fri, May 03, 2024 at 10:39:15AM +0200, Daniel Gustafsson wrote:

They are no-ops when linking against v18, but writing an extension which
targets all supported versions of postgres along with their respective
supported OpenSSL versions make them still required, or am I missing something?

Yeah, that depends on how much version you expect your application to
work on. Still it seems to me that there's value in mentioning that
if your application does not care about anything older than OpenSSL
1.1.0, like PG 18 assuming that this patch is merged, then these calls
are pointless for HEAD. The routine definitions would be around only
for the .so compatibility.
--
Michael

#97Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#96)
2 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 7 May 2024, at 01:31, Michael Paquier <michael@paquier.xyz> wrote:

On Fri, May 03, 2024 at 10:39:15AM +0200, Daniel Gustafsson wrote:

They are no-ops when linking against v18, but writing an extension which
targets all supported versions of postgres along with their respective
supported OpenSSL versions make them still required, or am I missing something?

Yeah, that depends on how much version you expect your application to
work on. Still it seems to me that there's value in mentioning that
if your application does not care about anything older than OpenSSL
1.1.0, like PG 18 assuming that this patch is merged, then these calls
are pointless for HEAD. The routine definitions would be around only
for the .so compatibility.

Fair enough. I've taken a stab at documenting that the functions are
deprecated, while at the same time documenting when and how they can be used
(and be useful). The attached also removes one additional comment in the
testcode which is now obsolete (since removing 1.0.1 support really), and fixes
the spurious whitespace you detected upthread.

--
Daniel Gustafsson

Attachments:

v13-0002-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v13-0002-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From 07546ae71663b2be824b40f70d583195b10c9708 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:39:33 +0200
Subject: [PATCH v13 2/2] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.0 is being
increasingly phased out from production use, only perform the RAND_poll
initialization for installations running 1.1.0 by checkig the OpenSSL
version number.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random
for the vast majority of users for whom it is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/port/pg_strong_random.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..a8efb2b188 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -50,17 +50,20 @@
 
 #ifdef USE_OPENSSL
 
+#include <openssl/opensslv.h>
 #include <openssl/rand.h>
 
 void
 pg_strong_random_init(void)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
 	 */
 	RAND_poll();
+#endif
 }
 
 bool
-- 
2.39.3 (Apple Git-146)

v13-0001-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v13-0001-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From 5fcf25d268a29022a8e4f1eea299cc01940fd96c Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:37:00 +0200
Subject: [PATCH v13 1/2] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from upstream for some time, and is no
longer the default OpenSSL version with any vendor which package
PostgreSQL.  By retiring support for 1.0.2 we can remove a lot of
complexity from the tree which is no longer required.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 +--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |  36 ++--
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  24 +--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  20 +-
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 -----------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-connect.c        |  18 --
 src/interfaces/libpq/fe-secure-openssl.c | 246 -----------------------
 src/interfaces/libpq/fe-secure.c         |  35 +---
 src/interfaces/libpq/libpq-int.h         |  13 +-
 src/test/ssl/t/001_ssltests.pl           |   3 +-
 18 files changed, 58 insertions(+), 563 deletions(-)

diff --git a/configure b/configure
index 89644f2249..1181a7347f 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index c7322e292c..2d5e2c2c2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 1b32d5ca62..daa7d19b77 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 101c676e08..11c0ae0e3c 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -9830,9 +9830,11 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
   <title>SSL Library Initialization</title>
 
   <para>
-   If your application initializes <literal>libssl</literal> and/or
-   <literal>libcrypto</literal> libraries and <application>libpq</application>
-   is built with <acronym>SSL</acronym> support, you should call
+   Applications which need to be compatible with older versions of
+   <productname>PostgreSQL</productname>, using <productname>OpenSSL</productname>
+   version 1.0.2 or older, need to initialize the SSL library before using it.
+   Applications which initialize <literal>libssl</literal> and/or
+   <literal>libcrypto</literal> libraries should call
    <xref linkend="libpq-PQinitOpenSSL"/> to tell <application>libpq</application>
    that the <literal>libssl</literal> and/or <literal>libcrypto</literal> libraries
    have been initialized by your application, so that
@@ -9840,6 +9842,10 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
    However, this is unnecessary when using <productname>OpenSSL</productname>
    version 1.1.0 or later, as duplicate initializations are no longer problematic.
   </para>
+  <para>
+   Refer to the documentation for the version of <productname>PostgreSQL</productname>
+   that you are targeting for details on their use.
+  </para>
 
   <para>
    <variablelist>
@@ -9855,21 +9861,8 @@ void PQinitOpenSSL(int do_ssl, int do_crypto);
       </para>
 
       <para>
-       When <parameter>do_ssl</parameter> is non-zero, <application>libpq</application>
-       will initialize the <productname>OpenSSL</productname> library before first
-       opening a database connection.  When <parameter>do_crypto</parameter> is
-       non-zero, the <literal>libcrypto</literal> library will be initialized.  By
-       default (if <xref linkend="libpq-PQinitOpenSSL"/> is not called), both libraries
-       are initialized.  When SSL support is not compiled in, this function is
-       present but does nothing.
-      </para>
-
-      <para>
-       If your application uses and initializes either <productname>OpenSSL</productname>
-       or its underlying <literal>libcrypto</literal> library, you <emphasis>must</emphasis>
-       call this function with zeroes for the appropriate parameter(s)
-       before first opening a database connection.  Also be sure that you
-       have done that initialization before opening a database connection.
+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
       </para>
      </listitem>
     </varlistentry>
@@ -9886,11 +9879,14 @@ void PQinitSSL(int do_ssl);
       <para>
        This function is equivalent to
        <literal>PQinitOpenSSL(do_ssl, do_ssl)</literal>.
-       It is sufficient for applications that initialize both or neither
-       of <productname>OpenSSL</productname> and <literal>libcrypto</literal>.
+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
       </para>
 
       <para>
+       <xref linkend="libpq-PQinitSSL"/> and <xref linkend="libpq-PQinitOpenSSL"/>
+       are maintained for backwards compatibility, but are no longer required
+       since <productname>PostgreSQL</productname> 18.
        <xref linkend="libpq-PQinitSSL"/> has been present since
        <productname>PostgreSQL</productname> 8.0, while <xref linkend="libpq-PQinitOpenSSL"/>
        was added in <productname>PostgreSQL</productname> 8.4, so <xref linkend="libpq-PQinitSSL"/>
diff --git a/meson.build b/meson.build
index 1c0579d5a6..12508612a6 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 60cf68aac4..85c700cb05 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -80,7 +81,6 @@ static const char *SSLerrmessage(unsigned long ecode);
 static char *X509_NAME_to_cstring(X509_NAME *name);
 
 static SSL_CTX *SSL_context = NULL;
-static bool SSL_initialized = false;
 static bool dummy_ssl_passwd_cb_called = false;
 static bool ssl_is_server_start;
 
@@ -101,19 +101,6 @@ be_tls_init(bool isServerStart)
 	int			ssl_ver_min = -1;
 	int			ssl_ver_max = -1;
 
-	/* This stuff need be done only once. */
-	if (!SSL_initialized)
-	{
-#ifdef HAVE_OPENSSL_INIT_SSL
-		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
-		SSL_initialized = true;
-	}
-
 	/*
 	 * Create a new SSL context into which we'll load all the configuration
 	 * settings.  If we fail partway through, we can avoid memory leakage by
@@ -940,7 +927,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -963,14 +949,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..da2c93e32a 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -144,11 +139,7 @@ pg_hmac_create(pg_cryptohash_type type)
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +153,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +316,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
index ae378685e1..e69de29bb2 100644
--- a/src/common/protocol_openssl.c
+++ b/src/common/protocol_openssl.c
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 81d278c395..20f1960319 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -3336,16 +3336,6 @@ keep_going:						/* We will come back to here until there is
 
 #ifdef USE_SSL
 
-				/*
-				 * Enable the libcrypto callbacks before checking if SSL needs
-				 * to be done.  This is done before sending the startup packet
-				 * as depending on the type of authentication done, like MD5
-				 * or SCRAM that use cryptohashes, the callbacks would be
-				 * required even without a SSL connection
-				 */
-				if (pqsecure_initialize(conn, false, true) < 0)
-					goto error_return;
-
 				/*
 				 * If direct SSL is enabled, jump right into SSL handshake. We
 				 * will come back here after SSL encryption has been
@@ -3523,14 +3513,6 @@ keep_going:						/* We will come back to here until there is
 					}
 				}
 
-				/*
-				 * Set up global SSL state if required.  The crypto state has
-				 * already been set if libpq took care of doing that, so there
-				 * is no need to make that happen again.
-				 */
-				if (pqsecure_initialize(conn, true, false) != 0)
-					goto error_return;
-
 				/*
 				 * Begin or continue the SSL negotiation process.
 				 */
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index fb6bb911f5..b9bfb8e37e 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -83,14 +82,6 @@ static int	my_sock_write(BIO *h, const char *buf, int size);
 static BIO_METHOD *my_BIO_s_socket(void);
 static int	my_SSL_set_fd(PGconn *conn, int fd);
 
-
-static bool pq_init_ssl_lib = true;
-static bool pq_init_crypto_lib = true;
-
-static bool ssl_lib_initialized = false;
-
-static long crypto_open_connections = 0;
-
 static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
@@ -100,20 +91,6 @@ static int	ssl_protocol_version_to_openssl(const char *protocol);
 /*			 Procedures common to all secure sessions			*/
 /* ------------------------------------------------------------ */
 
-void
-pgtls_init_library(bool do_ssl, int do_crypto)
-{
-	/*
-	 * Disallow changing the flags while we have open connections, else we'd
-	 * get completely confused.
-	 */
-	if (crypto_open_connections != 0)
-		return;
-
-	pq_init_ssl_lib = do_ssl;
-	pq_init_crypto_lib = do_crypto;
-}
-
 PostgresPollingStatusType
 pgtls_open_client(PGconn *conn)
 {
@@ -505,11 +482,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +513,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,179 +681,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-/*
- * Initialize SSL library.
- *
- * In threadsafe mode, this includes setting up libcrypto callback functions
- * to do thread locking.
- *
- * If the caller has told us (through PQinitOpenSSL) that he's taking care
- * of libcrypto, we expect that callbacks are already set, and won't try to
- * override it.
- */
-int
-pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return -1;
-
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-	if (!ssl_lib_initialized && do_ssl)
-	{
-		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
-			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
-		ssl_lib_initialized = true;
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-	return 0;
-}
-
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1643,8 +1439,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1660,8 +1454,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1679,30 +1471,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has them loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1980,7 +1748,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -2006,14 +1773,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -2021,13 +1780,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index f628082337..5567be9d39 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -108,42 +108,27 @@ PQsslInUse(PGconn *conn)
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitSSL(int do_init)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_init, do_init);
-#endif
+	/* no-op */
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL and/or libcrypto.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitOpenSSL(int do_ssl, int do_crypto)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_ssl, do_crypto);
-#endif
-}
-
-/*
- *	Initialize global SSL context
- */
-int
-pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	int			r = 0;
-
-#ifdef USE_SSL
-	r = pgtls_init(conn, do_ssl, do_crypto);
-#endif
-
-	return r;
+	/* no-op */
 }
 
 /*
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3691e5ee96..21df8623a7 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -580,11 +580,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
@@ -763,7 +758,6 @@ extern int	pqWriteReady(PGconn *conn);
 
 /* === in fe-secure.c === */
 
-extern int	pqsecure_initialize(PGconn *, bool, bool);
 extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
 extern void pqsecure_close(PGconn *);
 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
@@ -786,19 +780,18 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
 /*
  *	Implementation of PQinitSSL().
  */
-extern void pgtls_init_library(bool do_ssl, int do_crypto);
+extern void pgtls_init_library(bool do_ssl);
 
 /*
  * Initialize SSL library.
  *
  * The conn parameter is only used to be able to pass back an error
  * message - no connection-local setup is made here.  do_ssl controls
- * if SSL is initialized, and do_crypto does the same for the crypto
- * part.
+ * if SSL is initialized.
  *
  * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
  */
-extern int	pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto);
+extern int	pgtls_init(PGconn *conn, bool do_ssl);
 
 /*
  *	Begin or continue negotiating a secure session.
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index 94ff043c8e..c982aeb361 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -36,8 +36,7 @@ sub switch_server_cert
 }
 
 # Determine whether this build uses OpenSSL or LibreSSL. As a heuristic, the
-# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. (Nor for OpenSSL
-# 1.0.1, but that's old enough that accommodating it isn't worth the cost.)
+# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL.
 my $libressl = not check_pg_config("#define HAVE_SSL_CTX_SET_CERT_CB 1");
 
 #### Some configuration
-- 
2.39.3 (Apple Git-146)

#98Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#97)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, May 07, 2024 at 12:36:24PM +0200, Daniel Gustafsson wrote:

Fair enough. I've taken a stab at documenting that the functions are
deprecated, while at the same time documenting when and how they can be used
(and be useful). The attached also removes one additional comment in the
testcode which is now obsolete (since removing 1.0.1 support really), and fixes
the spurious whitespace you detected upthread.

+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
[...]
+       <xref linkend="libpq-PQinitSSL"/> and <xref linkend="libpq-PQinitOpenSSL"/>
+       are maintained for backwards compatibility, but are no longer required
+       since <productname>PostgreSQL</productname> 18.

LGTM, thanks for doing this!
--
Michael

#99Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#97)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 07.05.24 11:36, Daniel Gustafsson wrote:

Yeah, that depends on how much version you expect your application to
work on. Still it seems to me that there's value in mentioning that
if your application does not care about anything older than OpenSSL
1.1.0, like PG 18 assuming that this patch is merged, then these calls
are pointless for HEAD. The routine definitions would be around only
for the .so compatibility.

Fair enough. I've taken a stab at documenting that the functions are
deprecated, while at the same time documenting when and how they can be used
(and be useful). The attached also removes one additional comment in the
testcode which is now obsolete (since removing 1.0.1 support really), and fixes
the spurious whitespace you detected upthread.

The 0001 patch removes the functions pgtls_init_library() and
pgtls_init() but keeps the declarations in libpq-int.h. This should be
fixed.

#100Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#99)
2 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 11 Jul 2024, at 23:22, Peter Eisentraut <peter@eisentraut.org> wrote:

The 0001 patch removes the functions pgtls_init_library() and pgtls_init() but keeps the declarations in libpq-int.h. This should be fixed.

Ah, nice catch. Done in the attached rebase.

--
Daniel Gustafsson

Attachments:

v14-0002-Remove-pg_strong_random-initialization.patchapplication/octet-stream; name=v14-0002-Remove-pg_strong_random-initialization.patch; x-unix-mode=0644Download
From b0b113cd3af897b0eb31de74100b14b4a04ca29c Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:39:33 +0200
Subject: [PATCH v14 2/2] Remove pg_strong_random initialization.

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.0 is being
increasingly phased out from production use, only perform the RAND_poll
initialization for installations running 1.1.0 by checkig the OpenSSL
version number.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random
for the vast majority of users for whom it is no longer required.

Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/port/pg_strong_random.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..a8efb2b188 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -50,17 +50,20 @@
 
 #ifdef USE_OPENSSL
 
+#include <openssl/opensslv.h>
 #include <openssl/rand.h>
 
 void
 pg_strong_random_init(void)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
 	 */
 	RAND_poll();
+#endif
 }
 
 bool
-- 
2.39.3 (Apple Git-146)

v14-0001-Remove-support-for-OpenSSL-1.0.2.patchapplication/octet-stream; name=v14-0001-Remove-support-for-OpenSSL-1.0.2.patch; x-unix-mode=0644Download
From ed61fbcc6f3a470ebacc4148b2a9e940e8df6ad1 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 12 Jul 2024 22:08:08 +0200
Subject: [PATCH v14 1/2] Remove support for OpenSSL 1.0.2

OpenSSL 1.0.2 has been EOL from the upstream OpenSSL project for
some time, and is no longer the default OpenSSL version with any
vendor which package PostgreSQL. By retiring support for OpenSSL
1.0.2 we can remove a lot of no longer required complexity for
managing state within libcrypto which is now handled by OpenSSL.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 +--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |  36 ++--
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  24 +--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  20 +-
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 -----------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-connect.c        |  18 --
 src/interfaces/libpq/fe-secure-openssl.c | 246 -----------------------
 src/interfaces/libpq/fe-secure.c         |  35 +---
 src/interfaces/libpq/libpq-int.h         |  23 ---
 src/test/ssl/t/001_ssltests.pl           |   3 +-
 18 files changed, 55 insertions(+), 576 deletions(-)

diff --git a/configure b/configure
index 76f06bd8fd..bea2e9f234 100755
--- a/configure
+++ b/configure
@@ -12330,9 +12330,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12564,33 +12564,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info
 do :
   ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info"
diff --git a/configure.ac b/configure.ac
index ab2d51c21c..818f7ee702 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,8 +1335,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1352,12 +1352,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 4784834ab9..5e0e163acb 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 068ee60771..f0e1681987 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -9863,9 +9863,11 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
   <title>SSL Library Initialization</title>
 
   <para>
-   If your application initializes <literal>libssl</literal> and/or
-   <literal>libcrypto</literal> libraries and <application>libpq</application>
-   is built with <acronym>SSL</acronym> support, you should call
+   Applications which need to be compatible with older versions of
+   <productname>PostgreSQL</productname>, using <productname>OpenSSL</productname>
+   version 1.0.2 or older, need to initialize the SSL library before using it.
+   Applications which initialize <literal>libssl</literal> and/or
+   <literal>libcrypto</literal> libraries should call
    <xref linkend="libpq-PQinitOpenSSL"/> to tell <application>libpq</application>
    that the <literal>libssl</literal> and/or <literal>libcrypto</literal> libraries
    have been initialized by your application, so that
@@ -9873,6 +9875,10 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
    However, this is unnecessary when using <productname>OpenSSL</productname>
    version 1.1.0 or later, as duplicate initializations are no longer problematic.
   </para>
+  <para>
+   Refer to the documentation for the version of <productname>PostgreSQL</productname>
+   that you are targeting for details on their use.
+  </para>
 
   <para>
    <variablelist>
@@ -9888,21 +9894,8 @@ void PQinitOpenSSL(int do_ssl, int do_crypto);
       </para>
 
       <para>
-       When <parameter>do_ssl</parameter> is non-zero, <application>libpq</application>
-       will initialize the <productname>OpenSSL</productname> library before first
-       opening a database connection.  When <parameter>do_crypto</parameter> is
-       non-zero, the <literal>libcrypto</literal> library will be initialized.  By
-       default (if <xref linkend="libpq-PQinitOpenSSL"/> is not called), both libraries
-       are initialized.  When SSL support is not compiled in, this function is
-       present but does nothing.
-      </para>
-
-      <para>
-       If your application uses and initializes either <productname>OpenSSL</productname>
-       or its underlying <literal>libcrypto</literal> library, you <emphasis>must</emphasis>
-       call this function with zeroes for the appropriate parameter(s)
-       before first opening a database connection.  Also be sure that you
-       have done that initialization before opening a database connection.
+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
       </para>
      </listitem>
     </varlistentry>
@@ -9919,11 +9912,14 @@ void PQinitSSL(int do_ssl);
       <para>
        This function is equivalent to
        <literal>PQinitOpenSSL(do_ssl, do_ssl)</literal>.
-       It is sufficient for applications that initialize both or neither
-       of <productname>OpenSSL</productname> and <literal>libcrypto</literal>.
+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
       </para>
 
       <para>
+       <xref linkend="libpq-PQinitSSL"/> and <xref linkend="libpq-PQinitOpenSSL"/>
+       are maintained for backwards compatibility, but are no longer required
+       since <productname>PostgreSQL</productname> 18.
        <xref linkend="libpq-PQinitSSL"/> has been present since
        <productname>PostgreSQL</productname> 8.0, while <xref linkend="libpq-PQinitOpenSSL"/>
        was added in <productname>PostgreSQL</productname> 8.4, so <xref linkend="libpq-PQinitSSL"/>
diff --git a/meson.build b/meson.build
index 5387bb6d5f..fd2e09a40e 100644
--- a/meson.build
+++ b/meson.build
@@ -1272,26 +1272,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
       ['X509_get_signature_info'],
     ]
 
@@ -1314,7 +1305,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 387f30cdaa..2ca648fb45 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -80,7 +81,6 @@ static const char *SSLerrmessage(unsigned long ecode);
 static char *X509_NAME_to_cstring(X509_NAME *name);
 
 static SSL_CTX *SSL_context = NULL;
-static bool SSL_initialized = false;
 static bool dummy_ssl_passwd_cb_called = false;
 static bool ssl_is_server_start;
 
@@ -101,19 +101,6 @@ be_tls_init(bool isServerStart)
 	int			ssl_ver_min = -1;
 	int			ssl_ver_max = -1;
 
-	/* This stuff need be done only once. */
-	if (!SSL_initialized)
-	{
-#ifdef HAVE_OPENSSL_INIT_SSL
-		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
-		SSL_initialized = true;
-	}
-
 	/*
 	 * Create a new SSL context into which we'll load all the configuration
 	 * settings.  If we fail partway through, we can avoid memory leakage by
@@ -941,7 +928,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -964,14 +950,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 3d83299432..fdc33ed6d4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..da2c93e32a 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -144,11 +139,7 @@ pg_hmac_create(pg_cryptohash_type type)
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +153,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +316,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index de68e408fa..8cbc46ab81 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
index ae378685e1..e69de29bb2 100644
--- a/src/common/protocol_openssl.c
+++ b/src/common/protocol_openssl.c
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2b5f5cafab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,9 +54,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you want to use atomics if available. */
 #undef HAVE_ATOMICS
 
@@ -66,9 +63,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -84,9 +78,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -198,12 +189,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index e003279fb6..01269a289c 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -3341,16 +3341,6 @@ keep_going:						/* We will come back to here until there is
 
 #ifdef USE_SSL
 
-				/*
-				 * Enable the libcrypto callbacks before checking if SSL needs
-				 * to be done.  This is done before sending the startup packet
-				 * as depending on the type of authentication done, like MD5
-				 * or SCRAM that use cryptohashes, the callbacks would be
-				 * required even without a SSL connection
-				 */
-				if (pqsecure_initialize(conn, false, true) < 0)
-					goto error_return;
-
 				/*
 				 * If SSL is enabled, start the SSL negotiation. We will come
 				 * back here after SSL encryption has been established, with
@@ -3531,14 +3521,6 @@ keep_going:						/* We will come back to here until there is
 					}
 				}
 
-				/*
-				 * Set up global SSL state if required.  The crypto state has
-				 * already been set if libpq took care of doing that, so there
-				 * is no need to make that happen again.
-				 */
-				if (pqsecure_initialize(conn, true, false) != 0)
-					goto error_return;
-
 				/*
 				 * Begin or continue the SSL negotiation process.
 				 */
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 5c867106fb..ec9fd91059 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -83,14 +82,6 @@ static int	my_sock_write(BIO *h, const char *buf, int size);
 static BIO_METHOD *my_BIO_s_socket(void);
 static int	my_SSL_set_fd(PGconn *conn, int fd);
 
-
-static bool pq_init_ssl_lib = true;
-static bool pq_init_crypto_lib = true;
-
-static bool ssl_lib_initialized = false;
-
-static long crypto_open_connections = 0;
-
 static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
@@ -100,20 +91,6 @@ static int	ssl_protocol_version_to_openssl(const char *protocol);
 /*			 Procedures common to all secure sessions			*/
 /* ------------------------------------------------------------ */
 
-void
-pgtls_init_library(bool do_ssl, int do_crypto)
-{
-	/*
-	 * Disallow changing the flags while we have open connections, else we'd
-	 * get completely confused.
-	 */
-	if (crypto_open_connections != 0)
-		return;
-
-	pq_init_ssl_lib = do_ssl;
-	pq_init_crypto_lib = do_crypto;
-}
-
 PostgresPollingStatusType
 pgtls_open_client(PGconn *conn)
 {
@@ -505,11 +482,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +513,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,179 +681,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-/*
- * Initialize SSL library.
- *
- * In threadsafe mode, this includes setting up libcrypto callback functions
- * to do thread locking.
- *
- * If the caller has told us (through PQinitOpenSSL) that he's taking care
- * of libcrypto, we expect that callbacks are already set, and won't try to
- * override it.
- */
-int
-pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return -1;
-
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-	if (!ssl_lib_initialized && do_ssl)
-	{
-		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
-			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
-		ssl_lib_initialized = true;
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-	return 0;
-}
-
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1643,8 +1439,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1660,8 +1454,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1679,30 +1471,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has them loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1980,7 +1748,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -2006,14 +1773,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -2021,13 +1780,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index f628082337..5567be9d39 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -108,42 +108,27 @@ PQsslInUse(PGconn *conn)
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitSSL(int do_init)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_init, do_init);
-#endif
+	/* no-op */
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL and/or libcrypto.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitOpenSSL(int do_ssl, int do_crypto)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_ssl, do_crypto);
-#endif
-}
-
-/*
- *	Initialize global SSL context
- */
-int
-pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	int			r = 0;
-
-#ifdef USE_SSL
-	r = pgtls_init(conn, do_ssl, do_crypto);
-#endif
-
-	return r;
+	/* no-op */
 }
 
 /*
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index f36d76bf3f..e93962867b 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -578,11 +578,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
@@ -761,7 +756,6 @@ extern int	pqWriteReady(PGconn *conn);
 
 /* === in fe-secure.c === */
 
-extern int	pqsecure_initialize(PGconn *, bool, bool);
 extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
 extern void pqsecure_close(PGconn *);
 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
@@ -781,23 +775,6 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
  * The SSL implementation provides these functions.
  */
 
-/*
- *	Implementation of PQinitSSL().
- */
-extern void pgtls_init_library(bool do_ssl, int do_crypto);
-
-/*
- * Initialize SSL library.
- *
- * The conn parameter is only used to be able to pass back an error
- * message - no connection-local setup is made here.  do_ssl controls
- * if SSL is initialized, and do_crypto does the same for the crypto
- * part.
- *
- * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
- */
-extern int	pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto);
-
 /*
  *	Begin or continue negotiating a secure session.
  */
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index b877327023..4bd868ff65 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -36,8 +36,7 @@ sub switch_server_cert
 }
 
 # Determine whether this build uses OpenSSL or LibreSSL. As a heuristic, the
-# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. (Nor for OpenSSL
-# 1.0.1, but that's old enough that accommodating it isn't worth the cost.)
+# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL.
 my $libressl = not check_pg_config("#define HAVE_SSL_CTX_SET_CERT_CB 1");
 
 #### Some configuration
-- 
2.39.3 (Apple Git-146)

#101Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#100)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 12.07.24 21:42, Daniel Gustafsson wrote:

On 11 Jul 2024, at 23:22, Peter Eisentraut <peter@eisentraut.org> wrote:

The 0001 patch removes the functions pgtls_init_library() and pgtls_init() but keeps the declarations in libpq-int.h. This should be fixed.

Ah, nice catch. Done in the attached rebase.

This patch version looks good to me.

Small comments on the commit message of 0002: Typo "checkig". Also,
maybe the commit message title can be qualified a little, since we're
not really doing "Remove pg_strong_random initialization." but something
like "Remove unnecessary ..."?

#102Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#101)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 14 Jul 2024, at 14:03, Peter Eisentraut <peter@eisentraut.org> wrote:

On 12.07.24 21:42, Daniel Gustafsson wrote:

On 11 Jul 2024, at 23:22, Peter Eisentraut <peter@eisentraut.org> wrote:
The 0001 patch removes the functions pgtls_init_library() and pgtls_init() but keeps the declarations in libpq-int.h. This should be fixed.

Ah, nice catch. Done in the attached rebase.

This patch version looks good to me.

Thanks for review, I will go ahead with this once back from vacation at the
tail end of July when I can properly handle the BF.

Small comments on the commit message of 0002: Typo "checkig". Also, maybe the commit message title can be qualified a little, since we're not really doing "Remove pg_strong_random initialization." but something like "Remove unnecessary ..."?

Good points, will address before pushing.

--
Daniel Gustafsson

#103Joe Conway
mail@joeconway.com
In reply to: Daniel Gustafsson (#102)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 7/15/24 17:42, Daniel Gustafsson wrote:

On 14 Jul 2024, at 14:03, Peter Eisentraut <peter@eisentraut.org>
wrote:

On 12.07.24 21:42, Daniel Gustafsson wrote:

On 11 Jul 2024, at 23:22, Peter Eisentraut
<peter@eisentraut.org> wrote: The 0001 patch removes the
functions pgtls_init_library() and pgtls_init() but keeps the
declarations in libpq-int.h. This should be fixed.

Ah, nice catch. Done in the attached rebase.

This patch version looks good to me.

Thanks for review, I will go ahead with this once back from vacation
at the tail end of July when I can properly handle the BF.

Small comments on the commit message of 0002: Typo "checkig".
Also, maybe the commit message title can be qualified a little,
since we're not really doing "Remove pg_strong_random
initialization." but something like "Remove unnecessary ..."?

Good points, will address before pushing.

I know I am way late to this thread, and I have only tried a cursory
skim of it given the length, but have we made any kind of announcement
(packagers at least?) that we intend to not support Postgres 18 with ssl
on RHEL 7.9 and derivatives? Yes, RHEL 7 just passed EOL, but there is
commercial extended support available until July 2028[1]https://www.redhat.com/en/blog/announcing-4-years-extended-life-cycle-support-els-red-hat-enterprise-linux-7 -- Joe Conway PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com which means
many people will continue to use it.

Joe

[1]: https://www.redhat.com/en/blog/announcing-4-years-extended-life-cycle-support-els-red-hat-enterprise-linux-7 -- Joe Conway PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
https://www.redhat.com/en/blog/announcing-4-years-extended-life-cycle-support-els-red-hat-enterprise-linux-7
--
Joe Conway
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#104Devrim Gündüz
devrim@gunduz.org
In reply to: Joe Conway (#103)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Hi Joe,

On Mon, 2024-08-05 at 08:38 -0400, Joe Conway wrote:

I know I am way late to this thread, and I have only tried a cursory
skim of it given the length, but have we made any kind of announcement
(packagers at least?) that we intend to not support Postgres 18 with
ssl on RHEL 7.9 and derivatives?

I dropped RHEL 7 support as of PostgreSQL 16:
https://yum.postgresql.org/news/rhel7-postgresql-rpms-end-of-life/

and also recently stopped providing updates except PostgreSQL packages:

https://yum.postgresql.org/news/rhel7-end-of-life/

Min OS version is RHEL 8 / SLES 15.

-HTH

Regards,
--
Devrim Gündüz
Open Source Solution Architect, PostgreSQL Major Contributor
Twitter: @DevrimGunduz , @DevrimGunduzTR

#105Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#103)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Joe Conway <mail@joeconway.com> writes:

I know I am way late to this thread, and I have only tried a cursory
skim of it given the length, but have we made any kind of announcement
(packagers at least?) that we intend to not support Postgres 18 with ssl
on RHEL 7.9 and derivatives? Yes, RHEL 7 just passed EOL, but there is
commercial extended support available until July 2028[1] which means
many people will continue to use it.

PG v16 will be in-support until November 2028, so it's not like
we are leaving RHEL 7 completely in the lurch. I doubt that the
sort of people who are still running an EOL OS are looking to put
a bleeding-edge database on it, so this seems sufficient to me.

As for notifying packagers --- Red Hat themselves will certainly
not be trying to put new major versions of anything on RHEL 7,
and Devrim has stopped packaging newer PG for RHEL 7 altogether,
so who among them is going to care?

regards, tom lane

#106Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#105)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 8/5/24 09:14, Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I know I am way late to this thread, and I have only tried a cursory
skim of it given the length, but have we made any kind of announcement
(packagers at least?) that we intend to not support Postgres 18 with ssl
on RHEL 7.9 and derivatives? Yes, RHEL 7 just passed EOL, but there is
commercial extended support available until July 2028[1] which means
many people will continue to use it.

PG v16 will be in-support until November 2028, so it's not like
we are leaving RHEL 7 completely in the lurch. I doubt that the
sort of people who are still running an EOL OS are looking to put
a bleeding-edge database on it, so this seems sufficient to me.

ok

As for notifying packagers --- Red Hat themselves will certainly
not be trying to put new major versions of anything on RHEL 7,
and Devrim has stopped packaging newer PG for RHEL 7 altogether,
so who among them is going to care?

Perhaps no one on packagers. It would not shock me to see complaints
from others after we rip out support for 1.0.2, but maybe not ¯\_(ツ)_/¯

--
Joe Conway
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#107Daniel Gustafsson
daniel@yesql.se
In reply to: Joe Conway (#106)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 5 Aug 2024, at 15:36, Joe Conway <mail@joeconway.com> wrote:

It would not shock me to see complaints from others after we rip out support
for 1.0.2, but maybe not ¯\_(ツ)_/¯

I think it's highly likely that we will see complaints for any support we
deprecate. OpenSSL 1.0.2 will however still be supported for another 5 years
with v17 (which is ~9years past its EOL date) so I don't feel too bad about it.

--
Daniel Gustafsson

#108Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#107)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Aug 7, 2024, at 22:49, Daniel Gustafsson <daniel@yesql.se> wrote:
I think it's highly likely that we will see complaints for any support we
deprecate. OpenSSL 1.0.2 will however still be supported for another 5 years
with v17 (which is ~9years past its EOL date) so I don't feel too bad about it.

I’ve cut 1.0.1 at least by myself last year, and definitely not regret it while not hearing complains on the matter. 1.0.2 being a LTS matters more in the likeliness to see complaints, but I think it’s time to just let it go. So let’s do it and move on.

I’d seriously consider 1.1.0 as well for this release cycle as something to drop but I’m ok to keep it as the code gains are not really here. The 1.0.2 cut removes a lot of code and concepts particularly with the libcrypto threading and its locks!
--
Michael

#109Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#107)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 07.08.24 15:49, Daniel Gustafsson wrote:

On 5 Aug 2024, at 15:36, Joe Conway <mail@joeconway.com> wrote:

It would not shock me to see complaints from others after we rip out support
for 1.0.2, but maybe not ¯\_(ツ)_/¯

I think it's highly likely that we will see complaints for any support we
deprecate. OpenSSL 1.0.2 will however still be supported for another 5 years
with v17 (which is ~9years past its EOL date) so I don't feel too bad about it.

Is anything -- other than this inquiry -- preventing this patch set from
getting committed?

#110Joe Conway
mail@joeconway.com
In reply to: Peter Eisentraut (#109)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 8/21/24 09:01, Peter Eisentraut wrote:

On 07.08.24 15:49, Daniel Gustafsson wrote:

On 5 Aug 2024, at 15:36, Joe Conway <mail@joeconway.com> wrote:

It would not shock me to see complaints from others after we rip out support
for 1.0.2, but maybe not ¯\_(ツ)_/¯

I think it's highly likely that we will see complaints for any support we
deprecate. OpenSSL 1.0.2 will however still be supported for another 5 years
with v17 (which is ~9years past its EOL date) so I don't feel too bad about it.

Is anything -- other than this inquiry -- preventing this patch set from
getting committed?

The overwhelming consensus seemed to be "just do it", so FWIW consider
my reservations withdrawn ;-)

--
Joe Conway
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#111Michael Paquier
michael@paquier.xyz
In reply to: Joe Conway (#110)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Wed, Aug 21, 2024 at 10:48:38AM -0400, Joe Conway wrote:

On 8/21/24 09:01, Peter Eisentraut wrote:

Is anything -- other than this inquiry -- preventing this patch set from
getting committed?

The overwhelming consensus seemed to be "just do it", so FWIW consider my
reservations withdrawn ;-)

Just do it :)

I am pretty sure that Daniel is just on vacations and that this will
happen sooner than later during the next commit fest, so I'd rather
wait for him for an update on this thread first.
--
Michael

#112Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#111)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 22 Aug 2024, at 02:31, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, Aug 21, 2024 at 10:48:38AM -0400, Joe Conway wrote:

On 8/21/24 09:01, Peter Eisentraut wrote:

Is anything -- other than this inquiry -- preventing this patch set from
getting committed?

That, and available time.

The overwhelming consensus seemed to be "just do it", so FWIW consider my
reservations withdrawn ;-)

Just do it :)

That's my plan, I wanted to wait a bit to see if anyone else chimed in with
concerns.

--
Daniel Gustafsson

#113Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#112)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Thu, Aug 22, 2024 at 11:13:15PM +0200, Daniel Gustafsson wrote:

On 22 Aug 2024, at 02:31, Michael Paquier <michael@paquier.xyz> wrote:

Just do it :)

That's my plan, I wanted to wait a bit to see if anyone else chimed in with
concerns.

Cool, thanks!
--
Michael

#114Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#113)
2 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 23 Aug 2024, at 01:56, Michael Paquier <michael@paquier.xyz> wrote:

On Thu, Aug 22, 2024 at 11:13:15PM +0200, Daniel Gustafsson wrote:

On 22 Aug 2024, at 02:31, Michael Paquier <michael@paquier.xyz> wrote:

Just do it :)

That's my plan, I wanted to wait a bit to see if anyone else chimed in with
concerns.

Cool, thanks!

Attached is a rebased v15 (only changes are commit-message changes noted by
Peter upthread) for the sake of archives, and for a green-check run in the
CFBot. Assuming this builds green I intend to push this.

--
Daniel Gustafsson

Attachments:

v15-0002-Only-perform-pg_strong_random-init-when-required.patchapplication/octet-stream; name=v15-0002-Only-perform-pg_strong_random-init-when-required.patch; x-unix-mode=0644Download
From e73f3e7454ff516a12361346e04d3bcf8309ce4f Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Thu, 18 Apr 2024 21:39:33 +0200
Subject: [PATCH v15 2/2] Only perform pg_strong_random init when required

The random number generator in OpenSSL 1.1.1 was redesigned to provide
fork safety by default, thus removing the need for calling RAND_poll
after forking to ensure that two processes cannot share the same state.
Since we now support 1.1.0 as the minumum version, and 1.1.0 is being
increasingly phased out from production use, only perform the RAND_poll
initialization for installations running 1.1.0 by checking the OpenSSL
version number. This saves the vast majority of installations from the
init function call overhead.

LibreSSL changed random number generator when forking OpenSSL and has
provided fork safety since version 2.0.2.

This removes the overhead of initializing the RNG for strong random
for the vast majority of users for whom it is no longer required.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 src/port/pg_strong_random.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 5f2b248425..a8efb2b188 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -50,17 +50,20 @@
 
 #ifdef USE_OPENSSL
 
+#include <openssl/opensslv.h>
 #include <openssl/rand.h>
 
 void
 pg_strong_random_init(void)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10101000L)
 	/*
-	 * Make sure processes do not share OpenSSL randomness state.  This is no
-	 * longer required in OpenSSL 1.1.1 and later versions, but until we drop
-	 * support for version < 1.1.1 we need to do this.
+	 * Make sure processes do not share OpenSSL randomness state.  This is not
+	 * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later
+	 * versions.
 	 */
 	RAND_poll();
+#endif
 }
 
 bool
-- 
2.39.3 (Apple Git-146)

v15-0001-Remove-support-for-OpenSSL-older-than-1.1.0.patchapplication/octet-stream; name=v15-0001-Remove-support-for-OpenSSL-older-than-1.1.0.patch; x-unix-mode=0644Download
From 014ce6fd56a559d6eadc76260857b816b50a2ebd Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Mon, 2 Sep 2024 09:28:07 +0200
Subject: [PATCH v15 1/2] Remove support for OpenSSL older than 1.1.0

OpenSSL 1.0.2 has been EOL from the upstream OpenSSL project for
some time, and is no longer the default OpenSSL version with any
vendor which package PostgreSQL. By retiring support for OpenSSL
1.0.2 we can remove a lot of no longer required complexity for
managing state within libcrypto which is now handled by OpenSSL.

Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
---
 configure                                |  31 +--
 configure.ac                             |  12 +-
 contrib/pgcrypto/openssl.c               |   8 -
 doc/src/sgml/installation.sgml           |   2 +-
 doc/src/sgml/libpq.sgml                  |  36 ++--
 meson.build                              |  23 +--
 src/backend/libpq/be-secure-openssl.c    |  24 +--
 src/common/Makefile                      |   3 +-
 src/common/hmac_openssl.c                |  20 +-
 src/common/meson.build                   |   1 -
 src/common/protocol_openssl.c            | 117 -----------
 src/include/common/openssl.h             |  14 +-
 src/include/pg_config.h.in               |  15 --
 src/interfaces/libpq/fe-connect.c        |  18 --
 src/interfaces/libpq/fe-secure-openssl.c | 246 -----------------------
 src/interfaces/libpq/fe-secure.c         |  35 +---
 src/interfaces/libpq/libpq-int.h         |  23 ---
 src/test/ssl/t/001_ssltests.pl           |   3 +-
 18 files changed, 55 insertions(+), 576 deletions(-)

diff --git a/configure b/configure
index 537366945c..53c8a1f2ba 100755
--- a/configure
+++ b/configure
@@ -12313,9 +12313,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.2
+    # Minimum required OpenSSL version is 1.1.0
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12547,33 +12547,20 @@ done
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in OPENSSL_init_ssl
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  for ac_func in CRYPTO_lock
-do :
-  ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
-if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CRYPTO_LOCK 1
+#define HAVE_OPENSSL_INIT_SSL 1
 _ACEOF
 
+else
+  as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$LINENO" 5
 fi
 done
 
-  # Function introduced in OpenSSL 1.1.1.
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   for ac_func in X509_get_signature_info SSL_CTX_set_num_tickets
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
diff --git a/configure.ac b/configure.ac
index 4e279c4bd6..6a35b2880b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1314,8 +1314,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
+  # Minimum required OpenSSL version is 1.1.0
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
      AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
@@ -1331,12 +1331,8 @@ if test "$with_ssl" = openssl ; then
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
   # doesn't have these OpenSSL 1.1.0 functions. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
-  # OpenSSL versions before 1.1.0 required setting callback functions, for
-  # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-  # function was removed.
-  AC_CHECK_FUNCS([CRYPTO_lock])
-  # Function introduced in OpenSSL 1.1.1.
+  AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])])
+  # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
   AC_CHECK_FUNCS([X509_get_signature_info SSL_CTX_set_num_tickets])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
 elif test "$with_ssl" != no ; then
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 8259de5e39..26454bc3e2 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -154,8 +154,6 @@ digest_free(PX_MD *h)
 	pfree(h);
 }
 
-static int	px_openssl_initialized = 0;
-
 /* PUBLIC functions */
 
 int
@@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res)
 	PX_MD	   *h;
 	OSSLDigest *digest;
 
-	if (!px_openssl_initialized)
-	{
-		px_openssl_initialized = 1;
-		OpenSSL_add_all_algorithms();
-	}
-
 	md = EVP_get_digestbyname(name);
 	if (md == NULL)
 		return PXE_NO_HASH;
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 9e5a35ca3f..ff9abd4649 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -293,7 +293,7 @@
       encrypted client connections.  <productname>OpenSSL</productname> is
       also required for random number generation on platforms that do not
       have <filename>/dev/urandom</filename> (except Windows).  The minimum
-      required version is 1.0.2.
+      required version is 1.1.0.
      </para>
     </listitem>
 
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index f916fce414..25646f6f8e 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -9865,9 +9865,11 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
   <title>SSL Library Initialization</title>
 
   <para>
-   If your application initializes <literal>libssl</literal> and/or
-   <literal>libcrypto</literal> libraries and <application>libpq</application>
-   is built with <acronym>SSL</acronym> support, you should call
+   Applications which need to be compatible with older versions of
+   <productname>PostgreSQL</productname>, using <productname>OpenSSL</productname>
+   version 1.0.2 or older, need to initialize the SSL library before using it.
+   Applications which initialize <literal>libssl</literal> and/or
+   <literal>libcrypto</literal> libraries should call
    <xref linkend="libpq-PQinitOpenSSL"/> to tell <application>libpq</application>
    that the <literal>libssl</literal> and/or <literal>libcrypto</literal> libraries
    have been initialized by your application, so that
@@ -9875,6 +9877,10 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
    However, this is unnecessary when using <productname>OpenSSL</productname>
    version 1.1.0 or later, as duplicate initializations are no longer problematic.
   </para>
+  <para>
+   Refer to the documentation for the version of <productname>PostgreSQL</productname>
+   that you are targeting for details on their use.
+  </para>
 
   <para>
    <variablelist>
@@ -9890,21 +9896,8 @@ void PQinitOpenSSL(int do_ssl, int do_crypto);
       </para>
 
       <para>
-       When <parameter>do_ssl</parameter> is non-zero, <application>libpq</application>
-       will initialize the <productname>OpenSSL</productname> library before first
-       opening a database connection.  When <parameter>do_crypto</parameter> is
-       non-zero, the <literal>libcrypto</literal> library will be initialized.  By
-       default (if <xref linkend="libpq-PQinitOpenSSL"/> is not called), both libraries
-       are initialized.  When SSL support is not compiled in, this function is
-       present but does nothing.
-      </para>
-
-      <para>
-       If your application uses and initializes either <productname>OpenSSL</productname>
-       or its underlying <literal>libcrypto</literal> library, you <emphasis>must</emphasis>
-       call this function with zeroes for the appropriate parameter(s)
-       before first opening a database connection.  Also be sure that you
-       have done that initialization before opening a database connection.
+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
       </para>
      </listitem>
     </varlistentry>
@@ -9921,11 +9914,14 @@ void PQinitSSL(int do_ssl);
       <para>
        This function is equivalent to
        <literal>PQinitOpenSSL(do_ssl, do_ssl)</literal>.
-       It is sufficient for applications that initialize both or neither
-       of <productname>OpenSSL</productname> and <literal>libcrypto</literal>.
+       This function is deprecated and only present for backwards compatibility,
+       it does nothing.
       </para>
 
       <para>
+       <xref linkend="libpq-PQinitSSL"/> and <xref linkend="libpq-PQinitOpenSSL"/>
+       are maintained for backwards compatibility, but are no longer required
+       since <productname>PostgreSQL</productname> 18.
        <xref linkend="libpq-PQinitSSL"/> has been present since
        <productname>PostgreSQL</productname> 8.0, while <xref linkend="libpq-PQinitOpenSSL"/>
        was added in <productname>PostgreSQL</productname> 8.4, so <xref linkend="libpq-PQinitSSL"/>
diff --git a/meson.build b/meson.build
index ea07126f78..4764b09266 100644
--- a/meson.build
+++ b/meson.build
@@ -1359,26 +1359,17 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
-      ['SSL_CTX_set_cert_cb'],
-
       # Functions introduced in OpenSSL 1.1.0. We used to check for
       # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
       # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
       # doesn't have these OpenSSL 1.1.0 functions. So check for individual
       # functions.
-      ['OPENSSL_init_ssl'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
-
-      # OpenSSL versions before 1.1.0 required setting callback functions, for
-      # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
-      # function was removed.
-      ['CRYPTO_lock'],
-
-      # Function introduced in OpenSSL 1.1.1
+      ['OPENSSL_init_ssl', {'required': true}],
+
+      # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
+      ['SSL_CTX_set_cert_cb'],
+
+      # Function introduced in OpenSSL 1.1.1, not in LibreSSL.
       ['X509_get_signature_info'],
       ['SSL_CTX_set_num_tickets'],
     ]
@@ -1402,7 +1393,7 @@ if sslopt in ['auto', 'openssl']
     if are_openssl_funcs_complete
       cdata.set('USE_OPENSSL', 1,
                 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
-      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10100000L',
                 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
       ssl_library = 'openssl'
     else
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 60cf5d16e7..1ebd3f2e6d 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -44,6 +44,7 @@
  * include <wincrypt.h>, but some other Windows headers do.)
  */
 #include "common/openssl.h"
+#include <openssl/bn.h>
 #include <openssl/conf.h>
 #include <openssl/dh.h>
 #ifndef OPENSSL_NO_ECDH
@@ -80,7 +81,6 @@ static const char *SSLerrmessage(unsigned long ecode);
 static char *X509_NAME_to_cstring(X509_NAME *name);
 
 static SSL_CTX *SSL_context = NULL;
-static bool SSL_initialized = false;
 static bool dummy_ssl_passwd_cb_called = false;
 static bool ssl_is_server_start;
 
@@ -101,19 +101,6 @@ be_tls_init(bool isServerStart)
 	int			ssl_ver_min = -1;
 	int			ssl_ver_max = -1;
 
-	/* This stuff need be done only once. */
-	if (!SSL_initialized)
-	{
-#ifdef HAVE_OPENSSL_INIT_SSL
-		OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-		OPENSSL_config(NULL);
-		SSL_library_init();
-		SSL_load_error_strings();
-#endif
-		SSL_initialized = true;
-	}
-
 	/*
 	 * Create a new SSL context into which we'll load all the configuration
 	 * settings.  If we fail partway through, we can avoid memory leakage by
@@ -952,7 +939,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -975,14 +961,6 @@ my_BIO_s_socket(void)
 			my_bio_methods = NULL;
 			return NULL;
 		}
-#else
-		my_bio_methods = malloc(sizeof(BIO_METHOD));
-		if (!my_bio_methods)
-			return NULL;
-		memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
-		my_bio_methods->bread = my_sock_read;
-		my_bio_methods->bwrite = my_sock_write;
-#endif
 	}
 	return my_bio_methods;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index 89ef61c52a..d4f4b573c0 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -88,8 +88,7 @@ OBJS_COMMON = \
 ifeq ($(with_ssl),openssl)
 OBJS_COMMON += \
 	cryptohash_openssl.o \
-	hmac_openssl.o \
-	protocol_openssl.o
+	hmac_openssl.o
 else
 OBJS_COMMON += \
 	cryptohash.o \
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
index 84fcf340d8..da2c93e32a 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -35,17 +35,12 @@
 
 /*
  * In backend, use an allocation in TopMemoryContext to count for resowner
- * cleanup handling if necessary.  For versions of OpenSSL where HMAC_CTX is
- * known, just use palloc().  In frontend, use malloc to be able to return
+ * cleanup handling if necessary.  In frontend, use malloc to be able to return
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #define USE_RESOWNER_FOR_HMAC
 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
-#else
-#define ALLOC(size) palloc(size)
-#endif
 #define FREE(ptr) pfree(ptr)
 #else							/* FRONTEND */
 #define ALLOC(size) malloc(size)
@@ -144,11 +139,7 @@ pg_hmac_create(pg_cryptohash_type type)
 	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
-#ifdef HAVE_HMAC_CTX_NEW
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -162,9 +153,6 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifndef HAVE_HMAC_CTX_NEW
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif
 
 #ifdef USE_RESOWNER_FOR_HMAC
 	ctx->resowner = CurrentResourceOwner;
@@ -328,13 +316,7 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
-
 #ifdef USE_RESOWNER_FOR_HMAC
 	if (ctx->resowner)
 		ResourceOwnerForgetHMAC(ctx->resowner, ctx);
diff --git a/src/common/meson.build b/src/common/meson.build
index 1a564e1dce..d396e11ce9 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -44,7 +44,6 @@ if ssl.found()
   common_sources += files(
     'cryptohash_openssl.c',
     'hmac_openssl.c',
-    'protocol_openssl.c',
   )
 else
   common_sources += files(
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
index ae378685e1..e69de29bb2 100644
--- a/src/common/protocol_openssl.c
+++ b/src/common/protocol_openssl.c
@@ -1,117 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * protocol_openssl.c
- *	  OpenSSL functionality shared between frontend and backend
- *
- * This should only be used if code is compiled with OpenSSL support.
- *
- * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *		  src/common/protocol_openssl.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include "common/openssl.h"
-
-/*
- * Replacements for APIs introduced in OpenSSL 1.1.0.
- */
-#ifndef SSL_CTX_set_min_proto_version
-
-/*
- * OpenSSL versions that support TLS 1.3 shouldn't get here because they
- * already have these functions.  So we don't have to keep updating the below
- * code for every new TLS version, and eventually it can go away.  But let's
- * just check this to make sure ...
- */
-#ifdef TLS1_3_VERSION
-#error OpenSSL version mismatch
-#endif
-
-int
-SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-
-	if (version > TLS1_VERSION)
-		ssl_options |= SSL_OP_NO_TLSv1;
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version > TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version > TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-	int			ssl_options = 0;
-
-	Assert(version != 0);
-
-	/*
-	 * Some OpenSSL versions define TLS*_VERSION macros but not the
-	 * corresponding SSL_OP_NO_* macro, so in those cases we have to return
-	 * unsuccessfully here.
-	 */
-#ifdef TLS1_1_VERSION
-	if (version < TLS1_1_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_1
-		ssl_options |= SSL_OP_NO_TLSv1_1;
-#else
-		return 0;
-#endif
-	}
-#endif
-#ifdef TLS1_2_VERSION
-	if (version < TLS1_2_VERSION)
-	{
-#ifdef SSL_OP_NO_TLSv1_2
-		ssl_options |= SSL_OP_NO_TLSv1_2;
-#else
-		return 0;
-#endif
-	}
-#endif
-
-	SSL_CTX_set_options(ctx, ssl_options);
-
-	return 1;					/* success */
-}
-
-#endif							/* !SSL_CTX_set_min_proto_version */
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 964d691d32..cc54604e6e 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -18,10 +18,10 @@
 #include <openssl/ssl.h>
 
 /*
- * OpenSSL doesn't provide any very nice way to identify the min/max
- * protocol versions the library supports, so we fake it as best we can.
- * Note in particular that this doesn't account for restrictions that
- * might be specified in the installation's openssl.cnf.
+ * LibreSSL doesn't provide any very nice way to identify the max protocol
+ * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so
+ * we define our own.  Note in particular that this doesn't account for
+ * restrictions that might be specified in the installation's openssl.cnf.
  *
  * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
  * protocol version of interest.
@@ -38,12 +38,6 @@
 #define MAX_OPENSSL_TLS_VERSION  "TLSv1"
 #endif
 
-/* src/common/protocol_openssl.c */
-#ifndef SSL_CTX_set_min_proto_version
-extern int	SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-extern int	SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 #endif							/* USE_OPENSSL */
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 979925cc2e..38006367a4 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -54,18 +54,12 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
 /* Define to 1 if you have the <atomic.h> header file. */
 #undef HAVE_ATOMIC_H
 
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
 /* Define to 1 if your compiler handles computed gotos. */
 #undef HAVE_COMPUTED_GOTO
 
@@ -81,9 +75,6 @@
 /* Define to 1 if you have the <crtdefs.h> header file. */
 #undef HAVE_CRTDEFS_H
 
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
    don't. */
 #undef HAVE_DECL_FDATASYNC
@@ -199,12 +190,6 @@
 /* Define to 1 if you have the `history_truncate_file' function. */
 #undef HAVE_HISTORY_TRUNCATE_FILE
 
-/* Define to 1 if you have the `HMAC_CTX_free' function. */
-#undef HAVE_HMAC_CTX_FREE
-
-/* Define to 1 if you have the `HMAC_CTX_new' function. */
-#undef HAVE_HMAC_CTX_NEW
-
 /* Define to 1 if you have the <ifaddrs.h> header file. */
 #undef HAVE_IFADDRS_H
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 4cd7281b6e..3fa2dd864f 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -3342,16 +3342,6 @@ keep_going:						/* We will come back to here until there is
 
 #ifdef USE_SSL
 
-				/*
-				 * Enable the libcrypto callbacks before checking if SSL needs
-				 * to be done.  This is done before sending the startup packet
-				 * as depending on the type of authentication done, like MD5
-				 * or SCRAM that use cryptohashes, the callbacks would be
-				 * required even without a SSL connection
-				 */
-				if (pqsecure_initialize(conn, false, true) < 0)
-					goto error_return;
-
 				/*
 				 * If SSL is enabled, start the SSL negotiation. We will come
 				 * back here after SSL encryption has been established, with
@@ -3544,14 +3534,6 @@ keep_going:						/* We will come back to here until there is
 					}
 				}
 
-				/*
-				 * Set up global SSL state if required.  The crypto state has
-				 * already been set if libpq took care of doing that, so there
-				 * is no need to make that happen again.
-				 */
-				if (pqsecure_initialize(conn, true, false) != 0)
-					goto error_return;
-
 				/*
 				 * Begin or continue the SSL negotiation process.
 				 */
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index b6fffd7b9b..b5749d0292 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -71,7 +71,6 @@ static int	openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
 static int	openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 															ASN1_OCTET_STRING *addr_entry,
 															char **store_name);
-static void destroy_ssl_system(void);
 static int	initialize_SSL(PGconn *conn);
 static PostgresPollingStatusType open_client_SSL(PGconn *conn);
 static char *SSLerrmessage(unsigned long ecode);
@@ -83,14 +82,6 @@ static int	my_sock_write(BIO *h, const char *buf, int size);
 static BIO_METHOD *my_BIO_s_socket(void);
 static int	my_SSL_set_fd(PGconn *conn, int fd);
 
-
-static bool pq_init_ssl_lib = true;
-static bool pq_init_crypto_lib = true;
-
-static bool ssl_lib_initialized = false;
-
-static long crypto_open_connections = 0;
-
 static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
@@ -100,20 +91,6 @@ static int	ssl_protocol_version_to_openssl(const char *protocol);
 /*			 Procedures common to all secure sessions			*/
 /* ------------------------------------------------------------ */
 
-void
-pgtls_init_library(bool do_ssl, int do_crypto)
-{
-	/*
-	 * Disallow changing the flags while we have open connections, else we'd
-	 * get completely confused.
-	 */
-	if (crypto_open_connections != 0)
-		return;
-
-	pq_init_ssl_lib = do_ssl;
-	pq_init_crypto_lib = do_crypto;
-}
-
 PostgresPollingStatusType
 pgtls_open_client(PGconn *conn)
 {
@@ -505,11 +482,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
 	/*
 	 * GEN_DNS can be only IA5String, equivalent to US ASCII.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	namedata = ASN1_STRING_get0_data(name_entry);
-#else
-	namedata = ASN1_STRING_data(name_entry);
-#endif
 	len = ASN1_STRING_length(name_entry);
 
 	/* OK to cast from unsigned to plain char, since it's all ASCII. */
@@ -540,11 +513,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 	 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
 	 * order.
 	 */
-#ifdef HAVE_ASN1_STRING_GET0_DATA
 	addrdata = ASN1_STRING_get0_data(addr_entry);
-#else
-	addrdata = ASN1_STRING_data(addr_entry);
-#endif
 	len = ASN1_STRING_length(addr_entry);
 
 	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
@@ -712,179 +681,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 	return rc;
 }
 
-#if defined(HAVE_CRYPTO_LOCK)
-/*
- *	Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
- *	does its own locking, and doesn't need these anymore.  The
- *	CRYPTO_lock() function was removed in 1.1.0, when the callbacks
- *	were made obsolete, so we assume that if CRYPTO_lock() exists,
- *	the callbacks are still required.)
- */
-
-static unsigned long
-pq_threadidcallback(void)
-{
-	/*
-	 * This is not standards-compliant.  pthread_self() returns pthread_t, and
-	 * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
-	 * it, so we have to do it.
-	 */
-	return (unsigned long) pthread_self();
-}
-
-static pthread_mutex_t *pq_lockarray;
-
-static void
-pq_lockingcallback(int mode, int n, const char *file, int line)
-{
-	/*
-	 * There's no way to report a mutex-primitive failure, so we just Assert
-	 * in development builds, and ignore any errors otherwise.  Fortunately
-	 * this is all obsolete in modern OpenSSL.
-	 */
-	if (mode & CRYPTO_LOCK)
-	{
-		if (pthread_mutex_lock(&pq_lockarray[n]))
-			Assert(false);
-	}
-	else
-	{
-		if (pthread_mutex_unlock(&pq_lockarray[n]))
-			Assert(false);
-	}
-}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-/*
- * Initialize SSL library.
- *
- * In threadsafe mode, this includes setting up libcrypto callback functions
- * to do thread locking.
- *
- * If the caller has told us (through PQinitOpenSSL) that he's taking care
- * of libcrypto, we expect that callbacks are already set, and won't try to
- * override it.
- */
-int
-pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return -1;
-
-#ifdef HAVE_CRYPTO_LOCK
-	if (pq_init_crypto_lib)
-	{
-		/*
-		 * If necessary, set up an array to hold locks for libcrypto.
-		 * libcrypto will tell us how big to make this array.
-		 */
-		if (pq_lockarray == NULL)
-		{
-			int			i;
-
-			pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
-			if (!pq_lockarray)
-			{
-				pthread_mutex_unlock(&ssl_config_mutex);
-				return -1;
-			}
-			for (i = 0; i < CRYPTO_num_locks(); i++)
-			{
-				if (pthread_mutex_init(&pq_lockarray[i], NULL))
-				{
-					free(pq_lockarray);
-					pq_lockarray = NULL;
-					pthread_mutex_unlock(&ssl_config_mutex);
-					return -1;
-				}
-			}
-		}
-
-		if (do_crypto && !conn->crypto_loaded)
-		{
-			if (crypto_open_connections++ == 0)
-			{
-				/*
-				 * These are only required for threaded libcrypto
-				 * applications, but make sure we don't stomp on them if
-				 * they're already set.
-				 */
-				if (CRYPTO_get_id_callback() == NULL)
-					CRYPTO_set_id_callback(pq_threadidcallback);
-				if (CRYPTO_get_locking_callback() == NULL)
-					CRYPTO_set_locking_callback(pq_lockingcallback);
-			}
-
-			conn->crypto_loaded = true;
-		}
-	}
-#endif							/* HAVE_CRYPTO_LOCK */
-
-	if (!ssl_lib_initialized && do_ssl)
-	{
-		if (pq_init_ssl_lib)
-		{
-#ifdef HAVE_OPENSSL_INIT_SSL
-			OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
-#else
-			OPENSSL_config(NULL);
-			SSL_library_init();
-			SSL_load_error_strings();
-#endif
-		}
-		ssl_lib_initialized = true;
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-	return 0;
-}
-
-/*
- *	This function is needed because if the libpq library is unloaded
- *	from the application, the callback functions will no longer exist when
- *	libcrypto is used by other parts of the system.  For this reason,
- *	we unregister the callback functions when the last libpq
- *	connection is closed.  (The same would apply for OpenSSL callbacks
- *	if we had any.)
- *
- *	Callbacks are only set when we're compiled in threadsafe mode, so
- *	we only need to remove them in this case. They are also not needed
- *	with OpenSSL 1.1.0 anymore.
- */
-static void
-destroy_ssl_system(void)
-{
-#if defined(HAVE_CRYPTO_LOCK)
-	if (pthread_mutex_lock(&ssl_config_mutex))
-		return;
-
-	if (pq_init_crypto_lib && crypto_open_connections > 0)
-		--crypto_open_connections;
-
-	if (pq_init_crypto_lib && crypto_open_connections == 0)
-	{
-		/*
-		 * No connections left, unregister libcrypto callbacks, if no one
-		 * registered different ones in the meantime.
-		 */
-		if (CRYPTO_get_locking_callback() == pq_lockingcallback)
-			CRYPTO_set_locking_callback(NULL);
-		if (CRYPTO_get_id_callback() == pq_threadidcallback)
-			CRYPTO_set_id_callback(NULL);
-
-		/*
-		 * We don't free the lock array. If we get another connection in this
-		 * process, we will just re-use them with the existing mutexes.
-		 *
-		 * This means we leak a little memory on repeated load/unload of the
-		 * library.
-		 */
-	}
-
-	pthread_mutex_unlock(&ssl_config_mutex);
-#endif
-}
-
 /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
 static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
 
@@ -1643,8 +1439,6 @@ open_client_SSL(PGconn *conn)
 void
 pgtls_close(PGconn *conn)
 {
-	bool		destroy_needed = false;
-
 	if (conn->ssl_in_use)
 	{
 		if (conn->ssl)
@@ -1660,8 +1454,6 @@ pgtls_close(PGconn *conn)
 			conn->ssl = NULL;
 			conn->ssl_in_use = false;
 			conn->ssl_handshake_started = false;
-
-			destroy_needed = true;
 		}
 
 		if (conn->peer)
@@ -1679,30 +1471,6 @@ pgtls_close(PGconn *conn)
 		}
 #endif
 	}
-	else
-	{
-		/*
-		 * In the non-SSL case, just remove the crypto callbacks if the
-		 * connection has them loaded.  This code path has no dependency on
-		 * any pending SSL calls.
-		 */
-		if (conn->crypto_loaded)
-			destroy_needed = true;
-	}
-
-	/*
-	 * This will remove our crypto locking hooks if this is the last
-	 * connection using libcrypto which means we must wait to call it until
-	 * after all the potential SSL calls have been made, otherwise we can end
-	 * up with a race condition and possible deadlocks.
-	 *
-	 * See comments above destroy_ssl_system().
-	 */
-	if (destroy_needed)
-	{
-		destroy_ssl_system();
-		conn->crypto_loaded = false;
-	}
 }
 
 
@@ -1981,7 +1749,6 @@ my_BIO_s_socket(void)
 	if (!my_bio_methods)
 	{
 		BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
-#ifdef HAVE_BIO_METH_NEW
 		int			my_bio_index;
 
 		my_bio_index = BIO_get_new_index();
@@ -2007,14 +1774,6 @@ my_BIO_s_socket(void)
 		{
 			goto err;
 		}
-#else
-		res = malloc(sizeof(BIO_METHOD));
-		if (!res)
-			goto err;
-		memcpy(res, biom, sizeof(BIO_METHOD));
-		res->bread = my_sock_read;
-		res->bwrite = my_sock_write;
-#endif
 	}
 
 	my_bio_methods = res;
@@ -2022,13 +1781,8 @@ my_BIO_s_socket(void)
 	return res;
 
 err:
-#ifdef HAVE_BIO_METH_NEW
 	if (res)
 		BIO_meth_free(res);
-#else
-	if (res)
-		free(res);
-#endif
 	pthread_mutex_unlock(&ssl_config_mutex);
 	return NULL;
 }
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index f628082337..5567be9d39 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -108,42 +108,27 @@ PQsslInUse(PGconn *conn)
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitSSL(int do_init)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_init, do_init);
-#endif
+	/* no-op */
 }
 
 /*
- *	Exported function to allow application to tell us it's already
- *	initialized OpenSSL and/or libcrypto.
+ *	Exported function to allow application to tell us it's already initialized
+ *	OpenSSL.  Since OpenSSL 1.1.0 it is no longer required to explicitly
+ *	initialize libssl and libcrypto, so this is a no-op.  This function remains
+ *	for backwards API compatibility.
  */
 void
 PQinitOpenSSL(int do_ssl, int do_crypto)
 {
-#ifdef USE_SSL
-	pgtls_init_library(do_ssl, do_crypto);
-#endif
-}
-
-/*
- *	Initialize global SSL context
- */
-int
-pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
-{
-	int			r = 0;
-
-#ifdef USE_SSL
-	r = pgtls_init(conn, do_ssl, do_crypto);
-#endif
-
-	return r;
+	/* no-op */
 }
 
 /*
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 8ed1b28fcc..9579f80353 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -592,11 +592,6 @@ struct pg_conn
 	void	   *engine;			/* dummy field to keep struct the same if
 								 * OpenSSL version changes */
 #endif
-	bool		crypto_loaded;	/* Track if libcrypto locking callbacks have
-								 * been done for this connection. This can be
-								 * removed once support for OpenSSL 1.0.2 is
-								 * removed as this locking is handled
-								 * internally in OpenSSL >= 1.1.0. */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
@@ -776,7 +771,6 @@ extern int	pqWriteReady(PGconn *conn);
 
 /* === in fe-secure.c === */
 
-extern int	pqsecure_initialize(PGconn *, bool, bool);
 extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
 extern void pqsecure_close(PGconn *);
 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
@@ -796,23 +790,6 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
  * The SSL implementation provides these functions.
  */
 
-/*
- *	Implementation of PQinitSSL().
- */
-extern void pgtls_init_library(bool do_ssl, int do_crypto);
-
-/*
- * Initialize SSL library.
- *
- * The conn parameter is only used to be able to pass back an error
- * message - no connection-local setup is made here.  do_ssl controls
- * if SSL is initialized, and do_crypto does the same for the crypto
- * part.
- *
- * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
- */
-extern int	pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto);
-
 /*
  *	Begin or continue negotiating a secure session.
  */
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index b877327023..4bd868ff65 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -36,8 +36,7 @@ sub switch_server_cert
 }
 
 # Determine whether this build uses OpenSSL or LibreSSL. As a heuristic, the
-# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. (Nor for OpenSSL
-# 1.0.1, but that's old enough that accommodating it isn't worth the cost.)
+# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL.
 my $libressl = not check_pg_config("#define HAVE_SSL_CTX_SET_CERT_CB 1");
 
 #### Some configuration
-- 
2.39.3 (Apple Git-146)

#115Daniel Gustafsson
daniel@yesql.se
In reply to: Daniel Gustafsson (#114)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 2 Sep 2024, at 10:03, Daniel Gustafsson <daniel@yesql.se> wrote:

On 23 Aug 2024, at 01:56, Michael Paquier <michael@paquier.xyz> wrote:

On Thu, Aug 22, 2024 at 11:13:15PM +0200, Daniel Gustafsson wrote:

On 22 Aug 2024, at 02:31, Michael Paquier <michael@paquier.xyz> wrote:

Just do it :)

That's my plan, I wanted to wait a bit to see if anyone else chimed in with
concerns.

Cool, thanks!

Attached is a rebased v15 (only changes are commit-message changes noted by
Peter upthread) for the sake of archives, and for a green-check run in the
CFBot. Assuming this builds green I intend to push this.

And pushed. All BF owners with animals using 1.0.2 have been notified but not
all have been updated (or modified to skip SSL) so there will be some failing.

--
Daniel Gustafsson

#116Peter Eisentraut
peter@eisentraut.org
In reply to: Daniel Gustafsson (#115)
1 attachment(s)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 02.09.24 14:26, Daniel Gustafsson wrote:

On 2 Sep 2024, at 10:03, Daniel Gustafsson <daniel@yesql.se> wrote:

On 23 Aug 2024, at 01:56, Michael Paquier <michael@paquier.xyz> wrote:

On Thu, Aug 22, 2024 at 11:13:15PM +0200, Daniel Gustafsson wrote:

On 22 Aug 2024, at 02:31, Michael Paquier <michael@paquier.xyz> wrote:

Just do it :)

That's my plan, I wanted to wait a bit to see if anyone else chimed in with
concerns.

Cool, thanks!

Attached is a rebased v15 (only changes are commit-message changes noted by
Peter upthread) for the sake of archives, and for a green-check run in the
CFBot. Assuming this builds green I intend to push this.

And pushed. All BF owners with animals using 1.0.2 have been notified but not
all have been updated (or modified to skip SSL) so there will be some failing.

A small follow-up for this: With the current minimum OpenSSL version
being 1.1.0, we can remove an unconstify() call; see attached patch.

See this OpenSSL commit:
<https://github.com/openssl/openssl/commit/8ab31975ba&gt;. The analogous
LibreSSL change is here:
<https://cvsweb.openbsd.org/src/lib/libcrypto/bio/bss_mem.c?rev=1.17&amp;content-type=text/x-cvsweb-markup&gt;.
I don't know if we have a concrete minimum LibreSSL version, but the
change is about as old as the OpenSSL change.

Attachments:

0001-Remove-obsolete-unconstify.patchtext/plain; charset=UTF-8; name=0001-Remove-obsolete-unconstify.patchDownload
From 91550eaac4883113b9e85361c5c049a6555cd2f3 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Tue, 10 Sep 2024 09:53:32 +0200
Subject: [PATCH] Remove obsolete unconstify()

This is no longer needed as of OpenSSL 1.1.0 (the current minimum
version).  LibreSSL made the same change around the same time as well.
---
 src/backend/libpq/be-secure-openssl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 1ebd3f2e6d3..8ec78c83304 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -1075,7 +1075,7 @@ load_dh_buffer(const char *buffer, size_t len)
 	BIO		   *bio;
 	DH		   *dh = NULL;
 
-	bio = BIO_new_mem_buf(unconstify(char *, buffer), len);
+	bio = BIO_new_mem_buf(buffer, len);
 	if (bio == NULL)
 		return NULL;
 	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
-- 
2.46.0

#117Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#116)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On 10 Sep 2024, at 10:01, Peter Eisentraut <peter@eisentraut.org> wrote:

And pushed. All BF owners with animals using 1.0.2 have been notified but not
all have been updated (or modified to skip SSL) so there will be some failing.

A small follow-up for this: With the current minimum OpenSSL version being 1.1.0, we can remove an unconstify() call; see attached patch.

Nice catch.

See this OpenSSL commit: <https://github.com/openssl/openssl/commit/8ab31975ba&gt;. The analogous LibreSSL change is here: <https://cvsweb.openbsd.org/src/lib/libcrypto/bio/bss_mem.c?rev=1.17&amp;content-type=text/x-cvsweb-markup&gt;.

I don't know if we have a concrete minimum LibreSSL version, but the change is about as old as the OpenSSL change.

We've never documented the minimum LibreSSL version we support, but given that
we regularly test LibreSSL and fix breakage in our support I think we should.

--
Daniel Gustafsson

#118Robins Tharakan
tharakan@gmail.com
In reply to: Daniel Gustafsson (#43)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Hi,

On Thu, 4 Apr 2024 at 05:42, Daniel Gustafsson <daniel@yesql.se> wrote:

massasauga and snakefly run the ssl_passphrase_callback-check test but
none of
these run the ssl-check tests AFAICT, so we have very low coverage as is.
The
fact that very few animals run the ssl tests is a pet peeve of mine, it
would
be nice if we could get broader coverage there.

I am quite late to this discussion, but I am unable to get snakefly up and
running,
i.e. I see that all versions failed today (most on
ssl_passphrase_callback-check
test [2], but v15/v16 on sslCheck [1] too)

This machine has OpenSSL v1.0.2k so I am not expecting it to work on v17+,
but I was assuming at least the older versions should still be working.
Also despite
adding --without-openssl the older versions still fail [2].

Is upgrading OpenSSL the only way to get snakefly back to green?

Reference:
1.
https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=snakefly&amp;dt=2024-12-16%2014%3A04%3A25
2.
https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=snakefly&amp;dt=2024-12-16%2014%3A01%3A21

-
robins

#119Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robins Tharakan (#118)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

Robins Tharakan <tharakan@gmail.com> writes:

I am quite late to this discussion, but I am unable to get snakefly up and
running,
i.e. I see that all versions failed today (most on
ssl_passphrase_callback-check
test [2], but v15/v16 on sslCheck [1] too)

The failures all seem to be in "checkprep", ie the test setup
stage not the test proper. The log output from that isn't being
captured, making it hard to diagnose. Could we prevail on you
to install a more up-to-date buildfarm client script on that
machine? It looks to be running v11, which is rather old.

regards, tom lane

#120Michael Paquier
michael@paquier.xyz
In reply to: Tom Lane (#119)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Mon, Dec 16, 2024 at 11:17:17PM -0500, Tom Lane wrote:

The failures all seem to be in "checkprep", ie the test setup
stage not the test proper. The log output from that isn't being
captured, making it hard to diagnose. Could we prevail on you
to install a more up-to-date buildfarm client script on that
machine? It looks to be running v11, which is rather old.

+1.  Robins, feel free to ping me directly if you need help with this
host.
--
Michael
#121Robins Tharakan
tharakan@gmail.com
In reply to: Michael Paquier (#120)
Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~?

On Tue, 17 Dec 2024 at 16:59, Michael Paquier <michael@paquier.xyz> wrote:

+1. Robins, feel free to ping me directly if you need help with this
host.

Much appreciated Michael. Thankfully the new client worked without much
hiccup
(once it got the correct config file).

This is an old instance and IIRC gcc 7.3.1 gave me trouble sometime back. So
like alligator, I upgraded gcc recently. That (along with what feels like
cron config)
needs some attention and I should be able to stabilize the results soon.

-
robins