summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/random.930
-rw-r--r--sys/libkern/arc4random.c49
-rw-r--r--sys/sys/libkern.h3
3 files changed, 53 insertions, 29 deletions
diff --git a/share/man/man9/random.9 b/share/man/man9/random.9
index 734e583..98d0ffa 100644
--- a/share/man/man9/random.9
+++ b/share/man/man9/random.9
@@ -41,6 +41,8 @@
.Fn srandom "u_long seed"
.Ft u_long
.Fn random "void"
+.Ft void
+.Fn arc4rand "void *ptr" "u_int length" "int reseed"
.Ft u_int32_t
.Fn arc4random "void"
.Pp
@@ -68,12 +70,17 @@ function is entirely predictable, and is therefore not of use where
knowledge of the sequence of numbers may be of benefit to an attacker.
.Pp
The
-.Fn arc4random
+.Fn arc4rand
function will return very good quality random numbers, slightly better
suited for security-related purposes.
The random numbers from
-.Fn arc4random
+.Fn arc4rand
are seeded from the entropy device if it is available.
+Automatic reseeds happen after a certain timeinterval and after a
+certain number of bytes have been delivered.
+A forced reseed can be forced by passing a non-zero value in the
+.Ar reseed
+argument.
.Pp
The
.Fn read_random
@@ -90,16 +97,22 @@ is filled with no more than
bytes. It is advised that
.Fn read_random
is not used; instead use
-.Fn arc4random .
+.Fn arc4rand
.Pp
All the bits generated by
.Fn random ,
-.Fn arc4random
+.Fn arc4rand
and
.Fn read_random
are usable. For example,
.Sq Li random()&01
will produce a random binary value.
+.Pp
+The
+.Fn arc4random
+is a convenience function which calls
+.Fn arc4rand
+to return a 32 bit pseudo-random integer.
.Sh RETURN VALUES
The
.Fn random
@@ -114,10 +127,15 @@ The period of this random number generator is very large, approximately
.if n 16*((2**31)\(mi1).
.Pp
The
+.Fn arc4rand
+function uses the RC4 algorithm to generate successive pseudo-random
+bytes.
+The
.Fn arc4random
function
-uses the RC4 algorithm to generate successive pseudo-random
-numbers in the range from 0 to
+uses
+.Fn arc4rand
+to generate pseudo-random numbers in the range from 0 to
.if t 2\u\s732\s10\d\(mi1.
.if n (2**32)\(mi1.
.Pp
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;
}
diff --git a/sys/sys/libkern.h b/sys/sys/libkern.h
index 0471840..65ab341 100644
--- a/sys/sys/libkern.h
+++ b/sys/sys/libkern.h
@@ -64,7 +64,8 @@ static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); }
static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); }
/* Prototypes for non-quad routines. */
-u_int32_t arc4random(void);
+uint32_t arc4random(void);
+void arc4rand(void *ptr, u_int len, int reseed);
int bcmp(const void *, const void *, size_t);
void *bsearch(const void *, const void *, size_t,
size_t, int (*)(const void *, const void *));
OpenPOWER on IntegriCloud