From 2e1f3ef7233f9ecafc0f4bfccdb1195bdebbf256 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Mon, 22 Sep 2025 23:20:06 -0700
Subject: [PATCH 1/2] PoC: Select random source type.

---
 src/backend/utils/misc/Makefile               |  1 +
 src/backend/utils/misc/guc_parameters.dat     |  8 +++
 src/backend/utils/misc/guc_tables.c           |  1 +
 src/backend/utils/misc/meson.build            |  1 +
 src/backend/utils/misc/postgresql.conf.sample |  1 +
 src/backend/utils/misc/random_source.c        | 59 +++++++++++++++++++
 src/bin/initdb/initdb.c                       | 13 ++++
 src/include/port.h                            | 31 +++++++++-
 src/include/utils/guc.h                       |  1 +
 src/include/utils/guc_hooks.h                 |  1 +
 src/include/utils/random_source.h             | 32 ++++++++++
 src/port/pg_strong_random.c                   | 37 ++++++++----
 12 files changed, 174 insertions(+), 12 deletions(-)
 create mode 100644 src/backend/utils/misc/random_source.c
 create mode 100644 src/include/utils/random_source.h

diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index b362ae43771..96686c50e5f 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -27,6 +27,7 @@ OBJS = \
 	pg_rusage.o \
 	ps_status.o \
 	queryenvironment.o \
+	random_source.o \
 	rls.o \
 	sampling.o \
 	stack_depth.o \
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index 6bc6be13d2a..22e9aa7dbab 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -3475,4 +3475,12 @@
   assign_hook => 'assign_io_method',
 },
 
+{ name => 'random_source_type', type => 'enum', context => 'PGC_BACKEND', group => 'RESOURCES_KERNEL',
+  short_desc => 'Selects the random data generation function.',
+  variable => 'random_source_type',
+  boot_val => 'DEFAULT_RANDOM_SOURCE_TYPE',
+  options => 'random_source_type_options',
+  assign_hook => 'assign_random_source_type',
+},
+
 ]
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 00c8376cf4d..0bdc144a155 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -99,6 +99,7 @@
 #include "utils/pg_locale.h"
 #include "utils/plancache.h"
 #include "utils/ps_status.h"
+#include "utils/random_source.h"
 #include "utils/rls.h"
 #include "utils/xml.h"
 
diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build
index 9e389a00d05..6b03998b942 100644
--- a/src/backend/utils/misc/meson.build
+++ b/src/backend/utils/misc/meson.build
@@ -12,6 +12,7 @@ backend_sources += files(
   'pg_rusage.c',
   'ps_status.c',
   'queryenvironment.c',
+  'random_source.c',
   'rls.c',
   'sampling.c',
   'stack_depth.c',
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index c36fcb9ab61..c148b06bd27 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -772,6 +772,7 @@ autovacuum_worker_slots = 16	# autovacuum worker slots to allocate
 #gin_pending_list_limit = 4MB
 #createrole_self_grant = ''		# set and/or inherit
 #event_triggers = on
+#random_source_type = 'system'
 
 # - Locale and Formatting -
 
diff --git a/src/backend/utils/misc/random_source.c b/src/backend/utils/misc/random_source.c
new file mode 100644
index 00000000000..8ae67cf8d85
--- /dev/null
+++ b/src/backend/utils/misc/random_source.c
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * random_source.c
+ *
+ * Dynamically setup random generation function based on random_source_type
+ * GUC parameter.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994-5, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/utils/misc/random_source.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "port.h"
+#include "utils/random_source.h"
+#include "utils/guc.h"
+#include "utils/guc_hooks.h"
+
+const struct config_enum_entry random_source_type_options[] = {
+	{"system", RANDOM_SOURCE_TYPE_SYSTEM, false},
+#ifdef USE_OPENSSL
+	{"openssl", RANDOM_SOURCE_TYPE_OSSL, false},
+#endif
+	{NULL, 0, false}
+};
+
+static const struct
+{
+	pg_strong_random_init_fn initfn;
+	pg_strong_random_fn genfn;
+}			random_source_type_table[] = {
+
+	[RANDOM_SOURCE_TYPE_SYSTEM] = {
+		.initfn = pg_strong_random_init_system,
+		.genfn = pg_strong_random_system,
+	},
+#ifdef USE_OPENSSL
+	[RANDOM_SOURCE_TYPE_OSSL] = {
+		.initfn = pg_strong_random_init_openssl,
+		.genfn = pg_strong_random_openssl,
+	},
+#endif
+};
+
+int			random_source_type = DEFAULT_RANDOM_SOURCE_TYPE;
+
+/* Assign hook for random_source_type */
+void
+assign_random_source_type(int newval, void *extra)
+{
+	pg_strong_random_init_impl = random_source_type_table[newval].initfn;
+	pg_strong_random_impl = random_source_type_table[newval].genfn;
+}
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 92fe2f531f7..bcf7fb0f20c 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1109,6 +1109,16 @@ choose_dsm_implementation(void)
 #endif
 }
 
+static const char *
+choose_random_source_type(void)
+{
+#ifdef USE_OPENSSL
+	return "openssl";
+#else
+	return "system";
+#endif
+}
+
 /*
  * Determine platform-specific config settings
  *
@@ -1356,6 +1366,9 @@ setup_config(void)
 	conflines = replace_guc_value(conflines, "dynamic_shared_memory_type",
 								  dynamic_shared_memory_type, false);
 
+	conflines = replace_guc_value(conflines, "random_source_type",
+								  choose_random_source_type(), false);
+
 	/* Caution: these depend on wal_segment_size_mb, they're not constants */
 	conflines = replace_guc_value(conflines, "min_wal_size",
 								  pretty_wal_size(DEFAULT_MIN_WAL_SEGS), false);
diff --git a/src/include/port.h b/src/include/port.h
index 3964d3b1293..d7464c231a5 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -509,8 +509,35 @@ 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);
+extern void pg_strong_random_init_system(void);
+extern bool pg_strong_random_system(void *buf, size_t len);
+#ifdef USE_OPENSSL
+extern void pg_strong_random_init_openssl(void);
+extern bool pg_strong_random_openssl(void *buf, size_t len);
+#endif
+
+typedef void (*pg_strong_random_init_fn) (void);
+typedef bool (*pg_strong_random_fn) (void *buf, size_t len);
+
+/* Function pointers to the random data generation implementations */
+extern pg_strong_random_init_fn pg_strong_random_init_impl;
+extern pg_strong_random_fn pg_strong_random_impl;
+
+/*
+ * Public functions to generate strong random data. The functions invoked
+ * from these function can be replaced by setting function pointers.
+ */
+static pg_attribute_always_inline void
+pg_strong_random_init(void)
+{
+	(*pg_strong_random_init_impl) ();
+}
+
+static pg_attribute_always_inline bool
+pg_strong_random(void *buf, size_t len)
+{
+	return (*pg_strong_random_impl) (buf, len);
+}
 
 /*
  * pg_backend_random used to be a wrapper for pg_strong_random before
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f21ec37da89..c64e99318fa 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -343,6 +343,7 @@ extern PGDLLIMPORT bool optimize_bounded_sort;
 extern PGDLLIMPORT const struct config_enum_entry archive_mode_options[];
 extern PGDLLIMPORT const struct config_enum_entry dynamic_shared_memory_options[];
 extern PGDLLIMPORT const struct config_enum_entry io_method_options[];
+extern PGDLLIMPORT const struct config_enum_entry random_source_type_options[];
 extern PGDLLIMPORT const struct config_enum_entry recovery_target_action_options[];
 extern PGDLLIMPORT const struct config_enum_entry wal_level_options[];
 extern PGDLLIMPORT const struct config_enum_entry wal_sync_method_options[];
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 82ac8646a8d..7bc8f6217ce 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -96,6 +96,7 @@ extern bool check_primary_slot_name(char **newval, void **extra,
 									GucSource source);
 extern bool check_random_seed(double *newval, void **extra, GucSource source);
 extern void assign_random_seed(double newval, void *extra);
+extern void assign_random_source_type(int newval, void *extra);
 extern const char *show_random_seed(void);
 extern bool check_recovery_prefetch(int *new_value, void **extra,
 									GucSource source);
diff --git a/src/include/utils/random_source.h b/src/include/utils/random_source.h
new file mode 100644
index 00000000000..b4f8a88db43
--- /dev/null
+++ b/src/include/utils/random_source.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * random_source.h
+ *
+ * Copyright (c) 2007-2025, PostgreSQL Global Development Group
+ *
+ * src/include/utils/random_source.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef RANDOM_SOURCE_H
+#define RANDOM_SOURCE_H
+
+typedef enum RandomSourceType
+{
+	RANDOM_SOURCE_TYPE_SYSTEM = 0,
+#ifdef USE_OPENSSL
+	RANDOM_SOURCE_TYPE_OSSL,
+#endif
+}			RandomSourceType;
+
+#ifdef USE_OPENSSL
+#define DEFAULT_RANDOM_SOURCE_TYPE RANDOM_SOURCE_TYPE_OSSL
+#else
+#define DEFAULT_RANDOM_SOURCE_TYPE RANDOM_SOURCE_TYPE_SYSTEM
+#endif
+
+/* GUC */
+extern PGDLLIMPORT int random_source_type;
+
+#endif							/* RANDOM_SOURCE_H */
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index ea6780dcc9f..231995e42af 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -25,7 +25,7 @@
 #include <sys/time.h>
 
 /*
- * pg_strong_random & pg_strong_random_init
+ * pg_strong_random & pg_strong_random_init implementations.
  *
  * Generate requested number of random bytes. The returned bytes are
  * cryptographically secure, suitable for use e.g. in authentication.
@@ -48,6 +48,21 @@
  * would lead to predictable keys and security issues.
  */
 
+/*
+ * Set default implementations.
+ *
+ * The pg_strong_random and pg_strong_random_init implementations are fixed to
+ * the implementations follows in FRONTEND builds. On non-FRONTEND builds (i.e.,
+ * backends) the implementations could be replaced by random_source_type GUC
+ * parameter.
+ */
+#ifdef USE_OPENSSL
+pg_strong_random_init_fn pg_strong_random_init_impl = pg_strong_random_init_openssl;
+pg_strong_random_fn pg_strong_random_impl = pg_strong_random_openssl;
+#else
+pg_strong_random_init_fn pg_strong_random_init_impl = pg_strong_random_init_system;
+pg_strong_random_fn pg_strong_random_impl = pg_strong_random_system;
+#endif
 
 
 #ifdef USE_OPENSSL
@@ -55,13 +70,13 @@
 #include <openssl/rand.h>
 
 void
-pg_strong_random_init(void)
+pg_strong_random_init_openssl(void)
 {
 	/* No initialization needed */
 }
 
 bool
-pg_strong_random(void *buf, size_t len)
+pg_strong_random_openssl(void *buf, size_t len)
 {
 	int			i;
 
@@ -92,7 +107,9 @@ pg_strong_random(void *buf, size_t len)
 	return false;
 }
 
-#elif WIN32
+#endif
+
+#if WIN32
 
 #include <wincrypt.h>
 /*
@@ -102,13 +119,13 @@ pg_strong_random(void *buf, size_t len)
 static HCRYPTPROV hProvider = 0;
 
 void
-pg_strong_random_init(void)
+pg_strong_random_init_system(void)
 {
 	/* No initialization needed on WIN32 */
 }
 
 bool
-pg_strong_random(void *buf, size_t len)
+pg_strong_random_system(void *buf, size_t len)
 {
 	if (hProvider == 0)
 	{
@@ -134,20 +151,20 @@ pg_strong_random(void *buf, size_t len)
 	return false;
 }
 
-#else							/* not USE_OPENSSL or WIN32 */
+#else							/* not WIN32 */
 
 /*
- * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
+ * On Unix-like platforms, just read /dev/urandom ourselves.
  */
 
 void
-pg_strong_random_init(void)
+pg_strong_random_init_system(void)
 {
 	/* No initialization needed */
 }
 
 bool
-pg_strong_random(void *buf, size_t len)
+pg_strong_random_system(void *buf, size_t len)
 {
 	int			f;
 	char	   *p = buf;
-- 
2.47.3

