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>
signature.asc
Description: PGP signature
