This change allows the arc4random() subsystem to self-initialize from
boot-supplied data, upon first call. It uses rs_buf[] to build the
chacha context, then permits drawing of up to 1GB of data without
entering the difficult reseeding or rekeying codepaths.
When other required subsystems are ready, kernel main() properly
starts the entropy flow as before.
This is intended to allow super-early random use.
Index: dev/rnd.c
===================================================================
RCS file: /cvs/src/sys/dev/rnd.c,v
retrieving revision 1.152
diff -u -p -u -r1.152 rnd.c
--- dev/rnd.c 19 Jan 2014 00:39:40 -0000 1.152
+++ dev/rnd.c 19 Jan 2014 12:57:22 -0000
@@ -540,7 +540,8 @@ void arc4_init(void *, void *); /* actu
#define RSBUFSZ (16*BLOCKSZ)
static int rs_initialized;
static chacha_ctx rs; /* chacha context for random keystream */
-static u_char rs_buf[RSBUFSZ]; /* keystream blocks */
+/* keystream blocks (also chacha seed from boot) */
+static u_char rs_buf[RSBUFSZ] __attribute__((section(".openbsd.randomdata")));
static size_t rs_have; /* valid bytes at end of rs_buf */
static size_t rs_count; /* bytes till reseed */
@@ -557,14 +558,7 @@ _rs_init(u_char *buf, size_t n)
static void
_rs_seed(u_char *buf, size_t n)
{
- if (!rs_initialized) {
- rs_initialized = 1;
- rnd_states[RND_SRC_TIMER].dont_count_entropy = 1;
- rnd_states[RND_SRC_TRUE].dont_count_entropy = 1;
- rnd_states[RND_SRC_TRUE].max_entropy = 1;
- _rs_init(buf, n);
- } else
- _rs_rekey(buf, n);
+ _rs_rekey(buf, n);
/* invalidate rs_buf */
rs_have = 0;
@@ -605,7 +599,11 @@ _rs_stir(int do_lock)
static inline void
_rs_stir_if_needed(size_t len)
{
- if (rs_count <= len || !rs_initialized)
+ if (!rs_initialized) {
+ _rs_init(rs_buf, KEYSZ + IVSZ);
+ rs_count = 1024 * 1024 * 1024; /* until main() runs */
+ rs_initialized = 1;
+ } else if (rs_count <= len)
_rs_stir(0);
else
rs_count -= len;
@@ -745,21 +743,6 @@ arc4_reinit(void *v)
timeout_add_sec(&arc4_timeout, 10 * 60);
}
-void
-random_init(void)
-{
- int off;
-
- /*
- * MI code did not initialize us with a seed, so we are
- * hitting the fall-back from kernel main(). Do the best
- * we can... We assume there are at 8192 bytes mapped after
- * version, because we want to pull some "code" in as well.
- */
- for (off = 0; off < 8192 - KEYSZ - IVSZ; off += KEYSZ + IVSZ)
- _rs_seed((u_int8_t *)version + off, KEYSZ + IVSZ);
-}
-
/*
* Start periodic services inside the random subsystem, which pull
* entropy forward, hash it, and re-seed the random stream as needed.
@@ -767,14 +750,24 @@ random_init(void)
void
random_start(void)
{
- /*
- * At this point, the message buffer is mapped, and may contain
- * some historical information still.
- */
+ rnd_states[RND_SRC_TIMER].dont_count_entropy = 1;
+ rnd_states[RND_SRC_TRUE].dont_count_entropy = 1;
+ rnd_states[RND_SRC_TRUE].max_entropy = 1;
+
+ /* Provide some data from this kernel */
+ add_entropy_words((u_int32_t *)version,
+ strlen(version) / sizeof(u_int32_t));
+
+ /* Provide some data from this kernel */
+ add_entropy_words((u_int32_t *)cfdata,
+ 8192 / sizeof(u_int32_t));
+
+ /* Message buffer may contain data from previous boot */
if (msgbufp->msg_magic == MSG_MAGIC)
add_entropy_words((u_int32_t *)msgbufp->msg_bufc,
msgbufp->msg_bufs / sizeof(u_int32_t));
+ rs_initialized = 1;
dequeue_randomness(NULL);
arc4_init(NULL, NULL);
task_set(&arc4_task, arc4_init, NULL, NULL);
Index: dev/rndvar.h
===================================================================
RCS file: /cvs/src/sys/dev/rndvar.h,v
retrieving revision 1.32
diff -u -p -u -r1.32 rndvar.h
--- dev/rndvar.h 19 Jan 2014 00:39:40 -0000 1.32
+++ dev/rndvar.h 19 Jan 2014 06:53:33 -0000
@@ -69,7 +69,6 @@ extern struct rndstats rndstats;
#define add_audio_randomness(d) enqueue_randomness(RND_SRC_AUDIO,
(int)(d))
#define add_video_randomness(d) enqueue_randomness(RND_SRC_VIDEO,
(int)(d))
-void random_init(void);
void random_start(void);
void enqueue_randomness(int, int);
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.199
diff -u -p -u -r1.199 init_main.c
--- kern/init_main.c 19 Jan 2014 00:39:40 -0000 1.199
+++ kern/init_main.c 19 Jan 2014 08:19:11 -0000
@@ -218,8 +218,6 @@ main(void *framep)
KERNEL_LOCK_INIT();
SCHED_LOCK_INIT();
- random_init();
-
uvm_init();
disk_init(); /* must come before autoconfiguration */
tty_init(); /* initialise tty's */