On Tue, Dec 21, 2010 at 08:27:49PM +0100, Kurt Knochner wrote:
> 2010/12/21 Joachim Schipper <[email protected]>:
> > + get_random_bytes(buf, sizeof(buf));
> > + nanotime(&ts);
> > + for (i = 0; i < sizeof(ts); i++)
> > + buf[i] ^= ((uint8_t *) &ts)[i];
>
> I like the idea of using XOR. However, there are two issues:
>
> 1.) if nanotime() was called because of not enough random data from
> get_random_bytes() then you could end up with only the value &ts in
> buf. Why not use a md5 hash of the time value (better than the plain
> time value) or better just don't use the time value at all.
New diff.
Improvements:
- document the "why" of this loop (from Otto's message)
- Instead of XOR'ing the results of nanotime into the buffer, XOR
MD5(time), MD5(time + 1ns), MD5(time + 2ns) etc into the buffer. This
does not increase entropy, but having more-or-less uncorrelated data
in the entire buffer should make attacks more difficult.
Joachim
Index: ../../dev/rnd.c
===================================================================
RCS file: /usr/cvs/src/src/sys/dev/rnd.c,v
retrieving revision 1.104
diff -u -p -r1.104 rnd.c
--- ../../dev/rnd.c 21 Nov 2010 22:58:40 -0000 1.104
+++ ../../dev/rnd.c 21 Dec 2010 20:01:02 -0000
@@ -779,13 +779,29 @@ get_random_bytes(void *buf, size_t nbyte
static void
arc4_stir(void)
{
- u_int8_t buf[256];
- int len;
+ u_int8_t buf[256], md5_buf[MD5_DIGEST_LENGTH];
+ MD5_CTX md5_ctx;
+ struct timespec ts;
+ int i, j;
- nanotime((struct timespec *) buf);
- len = sizeof(buf) - sizeof(struct timespec);
- get_random_bytes(buf + sizeof (struct timespec), len);
- len += sizeof(struct timespec);
+ get_random_bytes(buf, sizeof(buf));
+
+ /*
+ * extract_entropy(), and thus get_random_bytes(), may not actually be
+ * very random early in the startup sequence of some machines. This is
+ * a desperate attempt to increase the randomness in the pool by mixing
+ * in nanotime().
+ */
+ nanotime(&ts);
+ KDASSERT(sizeof(buf) % MD5_DIGEST_LENGTH == 0);
+ for (i = 0; i < sizeof(buf); i += MD5_DIGEST_LENGTH) {
+ ts.tv_nsec = (ts.tv_nsec + 1) % (1000 * 1000 * 1000);
+ MD5Init(&md5_ctx);
+ MD5Update(&md5_ctx, (u_int8_t *) &ts, sizeof(ts));
+ MD5Final(md5_buf, &md5_ctx);
+ for (j = 0; j < MD5_DIGEST_LENGTH; j++)
+ buf[i + j] ^= md5_buf[j];
+ }
mtx_enter(&rndlock);
if (rndstats.arc4_nstirs > 0)
@@ -793,7 +809,7 @@ arc4_stir(void)
rc4_keysetup(&arc4random_state, buf, sizeof(buf));
arc4random_count = 0;
- rndstats.arc4_stirs += len;
+ rndstats.arc4_stirs += sizeof(buf);
rndstats.arc4_nstirs++;
/*