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

Attachment: signature.asc
Description: PGP signature

Reply via email to