From 07b2b5de4f89a041bf534cae2e46e49bd9a9d8bd Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Tue, 21 Oct 2025 16:25:23 -0700
Subject: [PATCH v1 1/2] Add configure-time selection of random number source.

Previously, the random number source was automatically selected: OpenSSL
was the first choice, with native platform sources (Windows API or
/dev/urandom) used as fallback options.

This commit adds the ability to specify the random number source at
configure time using either the --with-random-source option for the
configure script or the -Drandom_source option for meson.

The selected random source can be viewed through the read-only GUC
parameter random_source.

XXX doc updates.

Reviewed-by:
Discussion: https://postgr.es/m/
---
 configure                                 | 78 +++++++++++++++++++----
 configure.ac                              | 50 +++++++++++----
 meson.build                               | 22 +++++++
 meson_options.txt                         |  4 ++
 src/backend/utils/misc/guc_parameters.dat |  8 ++-
 src/backend/utils/misc/guc_tables.c       |  7 ++
 src/include/pg_config.h.in                |  6 ++
 7 files changed, 149 insertions(+), 26 deletions(-)

diff --git a/configure b/configure
index 22cd866147b..809691fd61c 100755
--- a/configure
+++ b/configure
@@ -886,6 +886,7 @@ with_zstd
 with_ssl
 with_openssl
 enable_largefile
+with_random_source
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1605,6 +1606,8 @@ Optional Packages:
   --with-zstd             build with ZSTD support
   --with-ssl=LIB          use LIB for SSL/TLS support (openssl)
   --with-openssl          obsolete spelling of --with-ssl=openssl
+  --with-random-source=NAME
+                          set random number source (system,openssl)
 
 Some influential environment variables:
   PG_TEST_EXTRA
@@ -18277,24 +18280,69 @@ $as_echo "#define USE_WIN32_SHARED_MEMORY 1" >>confdefs.h
   SHMEM_IMPLEMENTATION="src/backend/port/win32_shmem.c"
 fi
 
-# Select random number source. If a TLS library is used then it will be the
-# first choice, else the native platform sources (Windows API or /dev/urandom)
-# will be used.
+#
+# Select random number source.
+#
+
+
+
+
+# Check whether --with-random-source was given.
+if test "${with_random_source+set}" = set; then :
+  withval=$with_random_source;
+  case $withval in
+    yes)
+      as_fn_error $? "argument required for --with-random-source option" "$LINENO" 5
+      ;;
+    no)
+      as_fn_error $? "argument required for --with-random-source option" "$LINENO" 5
+      ;;
+    *)
+      random_source=$withval
+      ;;
+  esac
+
+fi
+
+
+
+# If nothing is specified to --with-random-source, the default value is chosen depends
+# on OpenSSL availability.
+if test x"$random_source" = x"" ; then
+  if test x"$with_ssl" = x"openssl" ; then
+    random_source=openssl
+  else
+    random_source=system
+  fi
+elif test x"$random_source" != x"openssl" -a x"$random_source" != x"system" ; then
+  as_fn_error $? "--with-random-source must sepcify one of system or openssl" "$LINENO" 5
+fi
+
+if test "$random_source" = openssl -a x"$with_ssl" != x"openssl" ; then
+  as_fn_error $? "OpenSSL library is required for random number generation" "$LINENO" 5
+fi
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking which random number source to use" >&5
 $as_echo_n "checking which random number source to use... " >&6; }
-if test x"$with_ssl" = x"openssl" ; then
+if test "$random_source" = openssl ; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenSSL" >&5
 $as_echo "OpenSSL" >&6; }
-elif test x"$PORTNAME" = x"win32" ; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows native" >&5
+
+$as_echo "#define USE_RANDOM_SOURCE_OPENSSL  1" >>confdefs.h
+
+else
+  # Select native platform source sources (Windows API or /dev/urandom) will
+  # be used.
+  if test x"$PORTNAME" = x"win32" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows native" >&5
 $as_echo "Windows native" >&6; }
-elif test x"$cross_compiling" = x"yes"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming /dev/urandom" >&5
+  elif test x"$cross_compiling" = x"yes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming /dev/urandom" >&5
 $as_echo "assuming /dev/urandom" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5
 $as_echo "/dev/urandom" >&6; }
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/urandom" >&5
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/urandom" >&5
 $as_echo_n "checking for /dev/urandom... " >&6; }
 if ${ac_cv_file__dev_urandom+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -18314,11 +18362,15 @@ if test "x$ac_cv_file__dev_urandom" = xyes; then :
 fi
 
 
-  if test x"$ac_cv_file__dev_urandom" = x"no" ; then
-    as_fn_error $? "
+    if test x"$ac_cv_file__dev_urandom" = x"no" ; then
+      as_fn_error $? "
 no source of strong random numbers was found
 PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers." "$LINENO" 5
+    fi
   fi
+
+$as_echo "#define USE_RANDOM_SOURCE_SYSTEM  1" >>confdefs.h
+
 fi
 
 # If not set in template file, set bytes to use libc memset()
diff --git a/configure.ac b/configure.ac
index e44943aa6fe..2690b71527b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2296,25 +2296,51 @@ else
   SHMEM_IMPLEMENTATION="src/backend/port/win32_shmem.c"
 fi
 
-# Select random number source. If a TLS library is used then it will be the
-# first choice, else the native platform sources (Windows API or /dev/urandom)
-# will be used.
+#
+# Select random number source.
+#
+
+PGAC_ARG_REQ(with, random-source, [NAME], [set random number source (system,openssl)],
+             [random_source=$withval])
+
+# If nothing is specified to --with-random-source, the default value is chosen depends
+# on OpenSSL availability.
+if test x"$random_source" = x"" ; then
+  if test x"$with_ssl" = x"openssl" ; then
+    random_source=openssl
+  else
+    random_source=system
+  fi
+elif test x"$random_source" != x"openssl" -a x"$random_source" != x"system" ; then
+  AC_MSG_ERROR([--with-random-source must sepcify one of system or openssl])
+fi
+
+if test "$random_source" = openssl -a x"$with_ssl" != x"openssl" ; then
+  AC_MSG_ERROR([OpenSSL library is required for random number generation])
+fi
+
 AC_MSG_CHECKING([which random number source to use])
-if test x"$with_ssl" = x"openssl" ; then
+if test "$random_source" = openssl ; then
   AC_MSG_RESULT([OpenSSL])
-elif test x"$PORTNAME" = x"win32" ; then
-  AC_MSG_RESULT([Windows native])
-elif test x"$cross_compiling" = x"yes"; then
-  AC_MSG_RESULT([assuming /dev/urandom])
+  AC_DEFINE([USE_RANDOM_SOURCE_OPENSSL] , 1, [Define to 1 to use OpenSSL libary for random number generation])
 else
-  AC_MSG_RESULT([/dev/urandom])
-  AC_CHECK_FILE([/dev/urandom], [], [])
+  # Select native platform source sources (Windows API or /dev/urandom) will
+  # be used.
+  if test x"$PORTNAME" = x"win32" ; then
+    AC_MSG_RESULT([Windows native])
+  elif test x"$cross_compiling" = x"yes"; then
+    AC_MSG_RESULT([assuming /dev/urandom])
+  else
+    AC_MSG_RESULT([/dev/urandom])
+    AC_CHECK_FILE([/dev/urandom], [], [])
 
-  if test x"$ac_cv_file__dev_urandom" = x"no" ; then
-    AC_MSG_ERROR([
+    if test x"$ac_cv_file__dev_urandom" = x"no" ; then
+      AC_MSG_ERROR([
 no source of strong random numbers was found
 PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers.])
+    fi
   fi
+  AC_DEFINE([USE_RANDOM_SOURCE_SYSTEM] , 1, [Define to 1 to use system native source for random number generation])
 fi
 
 # If not set in template file, set bytes to use libc memset()
diff --git a/meson.build b/meson.build
index 395416a6060..fce1e1436e7 100644
--- a/meson.build
+++ b/meson.build
@@ -2547,7 +2547,29 @@ if not have_optimized_crc
   cdata.set('USE_SLICING_BY_8_CRC32C', 1)
 endif
 
+###############################################################
+# Select random number source.
+###############################################################
+rand_src_opt = get_option('random_source')
+if rand_src_opt == 'auto'
+  if ssl.found()
+    rand_src_opt = 'openssl'
+  else
+    rand_src_opt = 'system'
+  endif
+endif
+
+if rand_src_opt == 'openssl' and not ssl.found()
+  error('OpenSSL library must be enabled for random number generation')
+endif
 
+if rand_src_opt == 'system'
+  cdata.set('USE_RANDOM_SOURCE_SYSTEM', 1,
+            description: 'Define to 1 to use system native source for random number generation')
+else
+  cdata.set('USE_RANDOM_SOURCE_OPENSSL', 1,
+            description: 'Define to 1 to use OpenSSL libary for random number generation')
+endif
 
 ###############################################################
 # Other CPU specific stuff
diff --git a/meson_options.txt b/meson_options.txt
index 06bf5627d3c..55f0f202c60 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -142,6 +142,10 @@ option('pltcl', type: 'feature', value: 'auto',
 option('tcl_version', type: 'string', value: 'tcl',
   description: 'Tcl version')
 
+option('random_source', type: 'combo', choices: ['auto', 'system', 'openssl'],
+  value: 'auto',
+  description: 'Select random number source')
+
 option('readline', type: 'feature', value: 'auto',
   description: 'Use GNU Readline or BSD Libedit for editing')
 
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index d6fc8333850..e3059c36b7d 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -3195,6 +3195,13 @@
   assign_hook => 'assign_log_connections',
 },
 
+{ name => 'random_source', type => 'string', context => 'PGC_INTERNAL', group => 'PRESET_OPTIONS',
+  short_desc => 'Shows implementation used for generating strong random number.',
+  flags => 'GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE',
+  variable => 'random_source',
+  boot_val => 'DEFAULT_RANDOM_SOURCE',
+},
+
 { name => 'backslash_quote', type => 'enum', context => 'PGC_USERSET', group => 'COMPAT_OPTIONS_PREVIOUS',
   short_desc => 'Sets whether "\\\\\'" is allowed in string literals.',
   variable => 'backslash_quote',
@@ -3500,5 +3507,4 @@
   options => 'io_method_options',
   assign_hook => 'assign_io_method',
 },
-
 ]
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 00c8376cf4d..52630ada573 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -620,6 +620,13 @@ static int	num_os_semaphores;
 static bool data_checksums;
 static bool integer_datetimes;
 
+#ifdef USE_RANDOM_SOURCE_OPENSSL
+#define DEFAULT_RANDOM_SOURCE "openssl"
+#else
+#define DEFAULT_RANDOM_SOURCE "system"
+#endif
+static char *random_source = DEFAULT_RANDOM_SOURCE;
+
 #ifdef USE_ASSERT_CHECKING
 #define DEFAULT_ASSERT_ENABLED true
 #else
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index c4dc5d72bdb..35543a3e3c6 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -727,6 +727,12 @@
 /* Define to 1 to build with PAM support. (--with-pam) */
 #undef USE_PAM
 
+/* Define to 1 to use system's native source for random number generation  */
+#undef USE_RANDOM_SOURCE_SYSTEM
+
+/* Define to 1 to use OpenSSL libary for random number generation */
+#undef USE_RANDOM_SOURCE_OPENSSL
+
 /* Define to 1 to use software CRC-32C implementation (slicing-by-8). */
 #undef USE_SLICING_BY_8_CRC32C
 
-- 
2.47.3

