summaryrefslogtreecommitdiffstats
path: root/sys/libkern/arc4random.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-10-11 13:13:08 +0000
committerphk <phk@FreeBSD.org>2002-10-11 13:13:08 +0000
commit775372e52e220ea57ea15373e6c1778c9b1e2885 (patch)
tree5c4b8bec4ec8c16f1f1c6a313fa7d665fc8e8ad1 /sys/libkern/arc4random.c
parent50fb07a0692e71731aa2dc5776ea519ad91490ef (diff)
downloadFreeBSD-src-775372e52e220ea57ea15373e6c1778c9b1e2885.zip
FreeBSD-src-775372e52e220ea57ea15373e6c1778c9b1e2885.tar.gz
Slight overhaul of arc4random() and friends.
One bug fixed: Use getmicrouptime() to trigger reseeds so that we cannot be tricked by a clock being stepped backwards. Express parameters in natural units and with natural names. Don't use struct timeval more than we need to. Various stylistic and readability polishing. Introduce arc4rand(void *ptr, u_int len, int reseed) function which returns a stream of pseudo-random bytes, observing the automatic reseed criteria as well as allowing forced reseeds. Rewrite arc4random() in terms of arc4rand(). Sponsored by: DARPA & NAI Labs.
Diffstat (limited to 'sys/libkern/arc4random.c')
-rw-r--r--sys/libkern/arc4random.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/sys/libkern/arc4random.c b/sys/libkern/arc4random.c
index 993f764..6d6ed22 100644
--- a/sys/libkern/arc4random.c
+++ b/sys/libkern/arc4random.c
@@ -15,15 +15,15 @@
#include <sys/libkern.h>
#include <sys/time.h>
-#define ARC4_MAXRUNS 16384
+#define ARC4_RESEED_BYTES 65536
#define ARC4_RESEED_SECONDS 300
-#define ARC4_KEYBYTES 32 /* 256 bit key */
+#define ARC4_KEYBYTES (256 / 8)
static u_int8_t arc4_i, arc4_j;
static int arc4_initialized = 0;
static int arc4_numruns = 0;
static u_int8_t arc4_sbox[256];
-static struct timeval arc4_tv_nextreseed;
+static time_t arc4_t_reseed;
static u_int8_t arc4_randbyte(void);
@@ -45,6 +45,7 @@ arc4_randomstir (void)
{
u_int8_t key[256];
int r, n;
+ struct timeval tv_now;
/*
* XXX read_random() returns unsafe numbers if the entropy
@@ -52,21 +53,19 @@ arc4_randomstir (void)
*/
r = read_random(key, ARC4_KEYBYTES);
/* If r == 0 || -1, just use what was on the stack. */
- if (r > 0)
- {
+ if (r > 0) {
for (n = r; n < sizeof(key); n++)
key[n] = key[n % r];
}
- for (n = 0; n < 256; n++)
- {
+ for (n = 0; n < 256; n++) {
arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
}
/* Reset for next reseed cycle. */
- getmicrotime(&arc4_tv_nextreseed);
- arc4_tv_nextreseed.tv_sec += ARC4_RESEED_SECONDS;
+ getmicrouptime(&tv_now);
+ arc4_t_reseed = tv_now.tv_sec + ARC4_RESEED_SECONDS;
arc4_numruns = 0;
}
@@ -111,27 +110,33 @@ arc4_randbyte(void)
return arc4_sbox[arc4_t];
}
-u_int32_t
-arc4random(void)
+void
+arc4rand(void *ptr, u_int len, int reseed)
{
- u_int32_t ret;
- struct timeval tv_now;
+ u_char *p;
+ struct timeval tv;
/* Initialize array if needed. */
if (!arc4_initialized)
arc4_init();
- getmicrotime(&tv_now);
- if ((++arc4_numruns > ARC4_MAXRUNS) ||
- (tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
- {
+ getmicrouptime(&tv);
+ arc4_numruns += len;
+ if (reseed ||
+ (arc4_numruns > ARC4_RESEED_BYTES) ||
+ (tv.tv_sec > arc4_t_reseed))
arc4_randomstir();
- }
- ret = arc4_randbyte();
- ret |= arc4_randbyte() << 8;
- ret |= arc4_randbyte() << 16;
- ret |= arc4_randbyte() << 24;
+ p = ptr;
+ while (len--)
+ *p++ = arc4_randbyte();
+}
+
+uint32_t
+arc4random(void)
+{
+ uint32_t ret;
+ arc4rand(&ret, sizeof ret, 0);
return ret;
}
OpenPOWER on IntegriCloud