From acdc90072ac0c78fe598522bd079f4456fb1ce3f Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Tue, 21 Oct 2025 16:25:23 -0700 Subject: [PATCH v2 1/2] Add configure-time selection of strong 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-strong-random option for the configure script or the -Dstrong_random option for meson. The selected random source can be viewed through the read-only GUC parameter strong_random_source. Reviewed-by: Discussion: https://postgr.es/m/ --- configure | 82 ++++++++++++++++++----- configure.ac | 50 ++++++++++---- doc/src/sgml/config.sgml | 19 ++++++ doc/src/sgml/installation.sgml | 40 +++++++++++ meson.build | 22 ++++++ meson_options.txt | 4 ++ src/backend/utils/misc/guc_parameters.dat | 7 ++ src/backend/utils/misc/guc_tables.c | 7 ++ src/include/pg_config.h.in | 6 ++ src/port/pg_strong_random.c | 6 +- 10 files changed, 213 insertions(+), 30 deletions(-) diff --git a/configure b/configure index f7c24c8f576..c591f8d8fbd 100755 --- a/configure +++ b/configure @@ -886,6 +886,7 @@ with_zstd with_ssl with_openssl enable_largefile +with_strong_random ' 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-strong-random=NAME + set strong random number source (system,openssl) Some influential environment variables: PG_TEST_EXTRA @@ -15000,8 +15003,8 @@ fi # Even though restrict is in C99 and should be supported by all -# supported compilers, but this macro is useful because it will prefer -# a spelling that also works in C++ (often __restrict). (restrict is +# supported compilers, this test is useful because it will prefer a +# spelling that also works in C++ (often __restrict). (restrict is # not part of the C++ standard.) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 $as_echo_n "checking for C/C++ restrict keyword... " >&6; } @@ -18267,24 +18270,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 strong random number source. +# + + + + +# Check whether --with-strong-random was given. +if test "${with_strong_random+set}" = set; then : + withval=$with_strong_random; + case $withval in + yes) + as_fn_error $? "argument required for --with-strong-random option" "$LINENO" 5 + ;; + no) + as_fn_error $? "argument required for --with-strong-random option" "$LINENO" 5 + ;; + *) + strong_random=$withval + ;; + esac + +fi + + + +# If nothing is specified to --with-strong-random, the default value is chosen depends +# on OpenSSL availability. +if test x"$strong_random" = x"" ; then + if test x"$with_ssl" = x"openssl" ; then + strong_random=openssl + else + strong_random=system + fi +elif test x"$strong_random" != x"openssl" -a x"$strong_random" != x"system" ; then + as_fn_error $? "--with-strong-random must sepcify one of system or openssl" "$LINENO" 5 +fi + +if test "$strong_random" = 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 "$strong_random" = 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 STRONG_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 @@ -18304,11 +18352,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 STRONG_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 6c802deaacb..bfdb764f059 100644 --- a/configure.ac +++ b/configure.ac @@ -2289,25 +2289,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 strong random number source. +# + +PGAC_ARG_REQ(with, strong-random, [NAME], [set strong random number source (system,openssl)], + [strong_random=$withval]) + +# If nothing is specified to --with-strong-random, the default value is chosen depends +# on OpenSSL availability. +if test x"$strong_random" = x"" ; then + if test x"$with_ssl" = x"openssl" ; then + strong_random=openssl + else + strong_random=system + fi +elif test x"$strong_random" != x"openssl" -a x"$strong_random" != x"system" ; then + AC_MSG_ERROR([--with-strong-random must sepcify one of system or openssl]) +fi + +if test "$strong_random" = 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 "$strong_random" = 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([STRONG_RANDOM_SOURCE_OPENSSL], 1, [Define to 1 to use OpenSSL libary for strong 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([STRONG_RANDOM_SOURCE_SYSTEM], 1, [Define to 1 to use system native source for strong random number generation]) fi # If not set in template file, set bytes to use libc memset() diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 06d1e4403b5..d839f78e2db 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -12047,6 +12047,25 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir' + + strong_random_source (string) + + strong_random_source configuration parameter + + + + + Reports the name of implementation used to generate cryptographically secure + random data: system or openssl. It + is determined when building the server. See more information see + for installation with Autoconf or + + for installation with Meson. + + + + wal_block_size (integer) diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 593202f4fb2..3ff2f3fb5a1 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -1531,6 +1531,26 @@ build-postgresql: + + + + + Specifies the imlementation used to generate cryptographically secure random + data. Valid values are system and openssl. + + + PostgreSQL relies on strong random numbers in + security-sensitive operations. For example, random values are used when generating + salts for SCRAM-SHA-256 password storage and when creating + UUIDs. By default, the implementation is chosen based on the + option: if PostgreSQL + is built with OpenSSL support, + OpenSSL's random generator is used; otherwise, the + operating system native secure random facility is used. This option overrides + that behavior and forces use of the specified source. + + + @@ -3054,6 +3074,26 @@ ninja install + + + + + + Specifies the imlementation used to generate cryptographically secure random + data. + + + PostgreSQL relies on strong random numbers in + security-sensitive operations. For example, random values are used when generating + salts for SCRAM-SHA-256 password storage and when creating + UUIDs. Default to auto and the implementation will be chosen based on the + option: if PostgreSQL + is built with OpenSSL support, + OpenSSL's random generator is used; otherwise, the + operating system native secure random facility is used. + + + diff --git a/meson.build b/meson.build index 0f61ff6a700..90918fc12da 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 strong random number source. +############################################################### +rand_src_opt = get_option('strong_random') +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 strong random number generation') +endif +if rand_src_opt == 'system' + cdata.set('STRONG_RANDOM_SOURCE_SYSTEM', 1, + description: 'Define to 1 to use system native source for strong random number generation') +else + cdata.set('STRONG_RANDOM_SOURCE_OPENSSL', 1, + description: 'Define to 1 to use OpenSSL libary for strong random number generation') +endif ############################################################### # Other CPU specific stuff diff --git a/meson_options.txt b/meson_options.txt index 06bf5627d3c..46850404c18 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('strong_random', type: 'combo', choices: ['auto', 'system', 'openssl'], + value: 'auto', + description: 'Select strong 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..b70f00cfcc1 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 => 'strong_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 => 'strong_random_source', + boot_val => 'DEFAULT_STRONG_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', diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 00c8376cf4d..1a58d0d19c1 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 STRONG_RANDOM_SOURCE_OPENSSL +#define DEFAULT_STRONG_RANDOM_SOURCE "openssl" +#else +#define DEFAULT_STRONG_RANDOM_SOURCE "system" +#endif +static char *strong_random_source = DEFAULT_STRONG_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 f52f14cc566..4aeceb53eb4 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -666,6 +666,12 @@ /* Define to 1 if strerror_r() returns int. */ #undef STRERROR_R_INT +/* Define to 1 to use system's native source for strong random number generation */ +#undef STRONG_RANDOM_SOURCE_SYSTEM + +/* Define to 1 to use OpenSSL libary for strong random number generation */ +#undef STRONG_RANDOM_SOURCE_OPENSSL + /* Define to 1 to use ARMv8 CRC Extension. */ #undef USE_ARMV8_CRC32C diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index ea6780dcc9f..0d3f00f588f 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -50,7 +50,7 @@ -#ifdef USE_OPENSSL +#ifdef STRONG_RANDOM_SOURCE_OPENSSL #include @@ -92,7 +92,7 @@ pg_strong_random(void *buf, size_t len) return false; } -#elif WIN32 +#elif WIN32 /* STRONG_RANDOM_SOURCE_SYSTEM and WIN32 */ #include /* @@ -134,7 +134,7 @@ pg_strong_random(void *buf, size_t len) return false; } -#else /* not USE_OPENSSL or WIN32 */ +#else /* STRONG_RANDOM_SOURCE_SYSTEM and not WIN32 */ /* * Without OpenSSL or Win32 support, just read /dev/urandom ourselves. -- 2.47.3