From 6fdd9d715ee04ec337ca4f4602d99fe9c87d2394 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Mon, 8 Feb 2021 23:52:39 +0100
Subject: [PATCH v35 4/9] nss: pg_strong_random support

This adds support for using the RNG in libnss as a backend for
pg_strong_random.
---
 src/port/pg_strong_random.c | 52 +++++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 07f24c0089..1f8441acff 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -137,10 +137,58 @@ pg_strong_random(void *buf, size_t len)
 	return false;
 }
 
-#else							/* not USE_OPENSSL or WIN32 */
+#elif defined(USE_NSS)
+
+#define pg_BITS_PER_BYTE BITS_PER_BYTE
+#undef BITS_PER_BYTE
+#define NO_NSPR_10_SUPPORT
+#include <nss/nss.h>
+#include <nss/pk11pub.h>
+#if defined(BITS_PER_BYTE)
+#if BITS_PER_BYTE != pg_BITS_PER_BYTE
+#error "incompatible byte widths between NSPR and postgres"
+#endif
+#else
+#define BITS_PER_BYTE pg_BITS_PER_BYTE
+#endif
+#undef pg_BITS_PER_BYTE
+
+void
+pg_strong_random_init(void)
+{
+	/* No initialization needed on NSS */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+	NSSInitParameters params;
+	NSSInitContext *nss_context;
+	SECStatus	status;
+
+	memset(&params, 0, sizeof(params));
+	params.length = sizeof(params);
+	nss_context = NSS_InitContext("", "", "", "", &params,
+								  NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
+								  NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
+								  NSS_INIT_NOROOTINIT | NSS_INIT_PK11RELOAD);
+
+	if (!nss_context)
+		return false;
+
+	status = PK11_GenerateRandom(buf, len);
+	NSS_ShutdownContext(nss_context);
+
+	if (status == SECSuccess)
+		return true;
+
+	return false;
+}
+
+#else							/* not USE_OPENSSL, USE_NSS or WIN32 */
 
 /*
- * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
+ * Without OpenSSL, NSS or Win32 support, just read /dev/urandom ourselves.
  */
 
 void
-- 
2.31.0

