On Tue, Apr 21, 2026 at 02:32:54PM +0200, Alejandro Colomar via Mutt-dev wrote: > On 2026-04-21T12:49:43+0200, Greg KH wrote: > > On Tue, Apr 21, 2026 at 06:13:44PM +0800, Kevin J. McCarthy wrote: > > > Perhaps, as Greg KH suggested we could try checking for getrandom(), and > > > then arc4random_buf(), and if both are missing I guess fall back to what > > > we have now? > > > > I would recommend that. I would hope that most modern systems have > > getrandom() by now. > > BTW, getentropy(3) --which itself calls getrandom(2)-- was added to both > glibc and musl in the same versions as getrandom(2). Should we prefer > getentropy(3) or getrandom(2)? getentropy(3) seems to have been > standardized by POSIX.1-2024 --which I'll document in the manual page > right now--.
One tiny advantage for getrandom(2) is the GRND_NONBLOCK flag. But
perhaps there isn't a "real" issue there for the request sizes mutt will
be passing.
I've already been playing with the code some tonight. This is just a
WIP below, compiled but not tested. Of course, it would be easy to swap
to using getentropy() if you and Greg think that's a better idea.
Subject: [PATCH] WIP: new random calls
---
configure.ac | 4 ++++
mutt_random.c | 44 +++++++++++++++++++++++++++++++++-----------
mutt_random.h | 3 +--
3 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/configure.ac b/configure.ac
index 5b455aff..456b916a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -423,6 +423,10 @@ AC_CHECK_TYPE(ssize_t, [],
AC_CHECK_FUNCS(fgetpos memmove memccpy setegid srand48 strerror)
+dnl random data functions
+AC_CHECK_HEADERS(sys/random.h)
+AC_CHECK_FUNCS(getrandom arc4random_buf)
+
AC_REPLACE_FUNCS([setenv strcasecmp strdup strsep strtok_r wcscasecmp])
AC_REPLACE_FUNCS([strcasestr mkdtemp])
diff --git a/mutt_random.c b/mutt_random.c
index 52ba44e5..441a2de8 100644
--- a/mutt_random.c
+++ b/mutt_random.c
@@ -25,25 +25,31 @@
#include <fcntl.h>
#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
+#ifdef HAVE_SYS_TIME_H
+ #include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RANDOM_H
+ #include <sys/random.h>
+#endif
static uint32_t z[4]; /* Keep state for LFRS113 PRNG */
static int rand_bytes_produced = 0;
static time_t time_last_reseed = 0;
-void mutt_random_bytes(char *random_bytes, int length_requested)
+static void prng_reseed(void);
+
+
+static void prng_random_bytes(char *random_bytes, size_t length_requested)
{
/* Reseed every day or after more than a 100000 random bytes produced */
if (time(NULL) - time_last_reseed > 86400 || rand_bytes_produced > 100000)
- mutt_reseed();
+ prng_reseed();
uint32_t b;
/* The loop below is our implementation of the LFRS113 PRNG algorithm by
* Pierre L'Ecuyer */
- for (int i = length_requested; i > 0;)
+ for (size_t i = length_requested; i > 0;)
{
b = ((z[0] << 6) ^ z[0]) >> 13;
z[0] = ((z[0] & 4294967294U) << 18) ^ b;
@@ -56,17 +62,17 @@ void mutt_random_bytes(char *random_bytes, int
length_requested)
b = z[0] ^ z[1] ^ z[2] ^ z[3];
- if (--i >= 0) random_bytes[i] = (b >> 24) & 0xFF;
- if (--i >= 0) random_bytes[i] = (b >> 16) & 0xFF;
- if (--i >= 0) random_bytes[i] = (b >> 8) & 0xFF;
- if (--i >= 0) random_bytes[i] = (b) & 0xFF;
+ if (i > 0) random_bytes[--i] = (b >> 24) & 0xFF;
+ if (i > 0) random_bytes[--i] = (b >> 16) & 0xFF;
+ if (i > 0) random_bytes[--i] = (b >> 8) & 0xFF;
+ if (i > 0) random_bytes[--i] = (b) & 0xFF;
}
rand_bytes_produced += length_requested;
return;
}
-void mutt_reseed(void)
+static void prng_reseed(void)
{
uint32_t t[4]; /* Temp seed values from /dev/urandom */
char computer_says_no = TRUE; /* Whether /dev/urandom was usable */
@@ -106,6 +112,22 @@ void mutt_reseed(void)
z[i] ^= t[i];
}
+/* Generate length_requested random bytes of data */
+void mutt_random_bytes(char *random_bytes, size_t length_requested)
+{
+#if defined(HAVE_GETRANDOM)
+ size_t res;
+
+ res = getrandom(random_bytes, length_requested, GRND_NONBLOCK);
+ if ((res == (size_t) -1) || (res < length_requested))
+ prng_random_bytes(random_bytes, length_requested);
+#elif defined(HAVE_ARC4RANDOM_BUF)
+ arc4random_buf(random_bytes, length_requested);
+#else
+ prng_random_bytes(random_bytes, length_requested);
+#endif
+}
+
/* Generate and Base64 encode 96 random bits and fill the buffer
output_B64 with the result. */
void mutt_base64_random96(char output_B64[static 17])
diff --git a/mutt_random.h b/mutt_random.h
index ed9fdf29..0417e0d6 100644
--- a/mutt_random.h
+++ b/mutt_random.h
@@ -25,6 +25,5 @@ typedef union random64
} RANDOM64;
void mutt_base64_random96(char output_B64[static 17]);
-void mutt_random_bytes(char *random_bytes, int length_requested);
-void mutt_reseed(void);
+void mutt_random_bytes(char *random_bytes, size_t length_requested);
#endif
--
2.53.0
--
Kevin J. McCarthy
GPG Fingerprint: 8975 A9B3 3AA3 7910 385C 5308 ADEF 7684 8031 6BDA
signature.asc
Description: PGP signature
