Re: Random MIME boundary needed? (was: Security findings)
"Kevin J. McCarthy" <[email protected]>
| Newsgroups | gmane.mail.mutt.devel |
|---|---|
| Message-ID | <aed5kfh65zdpnkIM@qinghai> |
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
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEiXWpszqjeRA4XFMIre92hIAxa9oFAmnneZEACgkQre92hIAx a9rcYw//QBujchbt8ua2NWVt68yRkqLLZye2W7/oIFbqpqyB07M+otuwyQGeh/SF U0STT71U6dvhglZWwlDp0CTg/2/DpnwNDYy5d/JGZSQ/n4n5iPd3YIAtJHU1OUDO tfCy6CUnpdeSEaCWq0Sa1m/tsVbEWAqHEhZs2fPjinQ16n51UGv2FZxQIn66c1ct /mDRXQKBwBrwEKNaj1hdEKGq/NF7AiwlzKhygygR1mxkQi64E5J+LMy3gpeFm/sS 7rr24/1s8y5x8aeYfJkw6IC191liIfojutfPuVQJX4unhLb72n7UQCjy6x+jt//L m/5X5UBLuwFkIxdh6iG5h6AkqjQQsjDjOTQzv+BPoEXLBi9uwjGMKjI979BCECMg 9JkA+zuc9//rQamifwlwAFIluC/8ZNa0FlofA5Xj+u7vI6koWmiPOcpx4OxROOIs /6VjUHK+TnUeOQtyseLCdsTfwOTDgjMZjJcOZz4qPO7UXHqqJqVgF8+S45FtWjVG FWqEF7bFi3QLcQ7NrvGb/o8ZtI45y/yfI6GzpiNo1V1exOtbOu1g6ECNj99ljQJa 4KRr73WoKWTpHItVylcoEdm+qUmPfQdWMncA2VNW5gWz/4IG+coRbQczu0bIBdui ji/sBY1ueZmbiD0jJAh5+dnvfsZ8bw4PUihM3q1wWilJCRQ4S74= =Jdn1 -----END PGP SIGNATURE-----