Hi Kevin,

On 2026-04-21T21:20:17+0800, Kevin J. McCarthy wrote:
> 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.

AFAIK, these days getrandom(2) doesn't block except in weird cases at
boot.

The manual page random(7) needs to be updated, but I need someone expert
in the matter to send and discuss patches.  (CC += Mingye)

BTW, Greg, would you be able to help with that?

> 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.

It makes sense to start with getrandom(2), since as you say, it's easy
to swap to it.


Cheers,
Alex

> 
> 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



-- 
<https://www.alejandro-colomar.es>

Attachment: signature.asc
Description: PGP signature

Reply via email to