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)

