Minor improvements to arc4random():

- Decrease reseeding interval from every 64 to every 16384 runs
  to reduce entropy usage.
- Add time based reseeding.  (Every 5 minutes.)
- Throw away the first 256 words of output as suggested in
  "Weaknesses in the Key Scheduling Algorithm of RC4."

Reviewed by: Mark Murray
MFC After: jkh says ok
This commit is contained in:
Mike Silbersack 2001-08-30 01:15:25 +00:00
parent 595aba526e
commit 3a7810bc39
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=82543

View File

@ -13,13 +13,19 @@
#include <sys/types.h>
#include <sys/random.h>
#include <sys/libkern.h>
#include <sys/time.h>
#define ARC4_MAXRUNS 64
#define ARC4_MAXRUNS 16384
#define ARC4_RESEED_SECONDS 300
#define ARC4_KEYBYTES 32 /* 256 bit key */
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 u_int8_t arc4_randbyte(void);
static __inline void
arc4_swap(u_int8_t *a, u_int8_t *b)
@ -43,7 +49,7 @@ arc4_randomstir (void)
/* XXX read_random() returns unsafe numbers if the entropy
* devce is not loaded - MarkM
*/
r = read_random(key, sizeof(key));
r = read_random(key, ARC4_KEYBYTES);
/* if r == 0 || -1, just use what was on the stack */
if (r > 0)
{
@ -56,6 +62,11 @@ arc4_randomstir (void)
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;
arc4_numruns = 0;
}
/*
@ -72,6 +83,15 @@ arc4_init(void)
arc4_randomstir();
arc4_initialized = 1;
/* Now, throw away the first N words out output, as suggested
* in the paper "Weaknesses in the Key Scheduling Algorithm
* of RC4" by Fluher, Mantin, and Shamir.
*
* (N = 256 in our case.)
*/
for (n = 0; n < 256*4; n++)
arc4_randbyte();
}
/*
@ -95,14 +115,19 @@ u_int32_t
arc4random(void)
{
u_int32_t ret;
struct timeval tv_now;
/* Initialize array if needed. */
if (!arc4_initialized)
arc4_init();
if (++arc4_numruns > ARC4_MAXRUNS)
/* Get current time. */
getmicrotime(&tv_now);
if ((++arc4_numruns > ARC4_MAXRUNS) ||
(tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
{
arc4_randomstir();
arc4_numruns = 0;
}
ret = arc4_randbyte();