yarrow.c revision 72364
162053Smarkm/*-
262765Smarkm * Copyright (c) 2000 Mark R V Murray
362053Smarkm * All rights reserved.
462053Smarkm *
562053Smarkm * Redistribution and use in source and binary forms, with or without
662053Smarkm * modification, are permitted provided that the following conditions
762053Smarkm * are met:
862053Smarkm * 1. Redistributions of source code must retain the above copyright
962053Smarkm *    notice, this list of conditions and the following disclaimer
1062053Smarkm *    in this position and unchanged.
1162053Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1262053Smarkm *    notice, this list of conditions and the following disclaimer in the
1362053Smarkm *    documentation and/or other materials provided with the distribution.
1462053Smarkm *
1562053Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1662053Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1762053Smarkm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1862053Smarkm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1962053Smarkm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2062053Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2162053Smarkm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2262053Smarkm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2362053Smarkm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2462053Smarkm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2562053Smarkm *
2662053Smarkm * $FreeBSD: head/sys/dev/random/yarrow.c 72364 2001-02-11 16:21:35Z markm $
2762053Smarkm */
2862053Smarkm
2962053Smarkm/* NOTE NOTE NOTE - This is not finished! It will supply numbers, but
3063771Smarkm *                  it is not yet cryptographically secure!!
3163771Smarkm */
3262053Smarkm
3362053Smarkm#include <sys/param.h>
3462053Smarkm#include <sys/systm.h>
3565686Smarkm#include <sys/kernel.h>
3665686Smarkm#include <sys/kthread.h>
3762053Smarkm#include <sys/libkern.h>
3867365Sjhb#include <sys/mutex.h>
3970834Swollman#include <sys/selinfo.h>
4062053Smarkm#include <sys/random.h>
4162053Smarkm#include <sys/types.h>
4265712Sjhb#include <sys/unistd.h>
4369168Smarkm
4469526Smarkm#include <machine/atomic.h>
4569168Smarkm#include <machine/cpu.h>
4669168Smarkm
4762053Smarkm#include <crypto/blowfish/blowfish.h>
4862053Smarkm
4967112Smarkm#include <dev/random/hash.h>
5067112Smarkm#include <dev/random/yarrow.h>
5162053Smarkm
5262765Smarkm/* #define DEBUG */
5362053Smarkm
5462765Smarkmstatic void generator_gate(void);
5562765Smarkmstatic void reseed(int);
5669168Smarkmstatic void random_harvest_internal(u_int64_t, void *, u_int, u_int, u_int, enum esource);
5762053Smarkm
5865686Smarkmstatic void random_kthread(void *);
5965686Smarkm
6062765Smarkm/* Structure holding the entropy state */
6162765Smarkmstruct random_state random_state;
6262765Smarkm
6365686Smarkm/* These are used to queue harvested packets of entropy. The entropy
6467112Smarkm * buffer size is pretty arbitrary.
6563771Smarkm */
6665686Smarkmstruct harvest {
6769168Smarkm	u_int64_t somecounter;		/* fast counter for clock jitter */
6867112Smarkm	u_char entropy[HARVESTSIZE];	/* the harvested entropy */
6965686Smarkm	u_int size, bits, frac;		/* stats about the entropy */
7065686Smarkm	enum esource source;		/* stats about the entropy */
7165686Smarkm};
7262765Smarkm
7369526Smarkm/* Ring buffer holding harvested entropy */
7469526Smarkmstatic struct harvestring {
7572364Smarkm	volatile int	head;
7672364Smarkm	volatile int	tail;
7769526Smarkm	struct harvest	data[HARVEST_RING_SIZE];
7869526Smarkm} harvestring;
7969526Smarkm
8065686Smarkm/* The reseed thread mutex */
8165856Sjhbstatic struct mtx random_reseed_mtx;
8262765Smarkm
8365686Smarkm/* <0 to end the kthread, 0 to let it run */
8465686Smarkmstatic int random_kthread_control = 0;
8565686Smarkm
8665686Smarkmstatic struct proc *random_kthread_proc;
8765686Smarkm
8862765Smarkmstatic void
8967112Smarkmrandom_kthread(void *arg /* NOTUSED */)
9062765Smarkm{
9172364Smarkm	int pl, src, overthreshhold[2], newtail;
9265686Smarkm	struct harvest *event;
9365686Smarkm	struct source *source;
9465686Smarkm
9562765Smarkm#ifdef DEBUG
9672200Sbmilekic	mtx_lock(&Giant);
9769526Smarkm	printf("OWNERSHIP Giant == %d sched_lock == %d\n",
9869526Smarkm		mtx_owned(&Giant), mtx_owned(&sched_lock));
9972200Sbmilekic	mtx_unlock(&Giant);
10062765Smarkm#endif
10165686Smarkm
10265686Smarkm	for (pl = 0; pl < 2; pl++)
10365686Smarkm		yarrow_hash_init(&random_state.pool[pl].hash, NULL, 0);
10465686Smarkm
10565686Smarkm	for (;;) {
10665686Smarkm
10772364Smarkm		if (harvestring.tail == harvestring.head)
10872364Smarkm			tsleep(&harvestring, PUSER, "rndslp", hz/10);
10965686Smarkm
11069526Smarkm		else {
11165686Smarkm
11265686Smarkm			/* Suck the harvested entropy out of the queue and hash
11369526Smarkm			 * it into the appropriate pool.
11465686Smarkm			 */
11565686Smarkm
11672364Smarkm			newtail = (harvestring.tail + 1) & HARVEST_RING_MASK;
11769526Smarkm			event = &harvestring.data[harvestring.tail];
11872364Smarkm
11972364Smarkm			/* Bump the ring counter. This action is assumed
12072364Smarkm			 * to be atomic.
12172364Smarkm			 */
12269526Smarkm			harvestring.tail = newtail;
12365686Smarkm
12472364Smarkm			pl = random_state.which = !random_state.which;
12572364Smarkm
12672364Smarkm			source = &random_state.pool[pl].source[event->source];
12772364Smarkm			yarrow_hash_iterate(&random_state.pool[pl].hash,
12869526Smarkm				event->entropy, sizeof(event->entropy));
12972364Smarkm			yarrow_hash_iterate(&random_state.pool[pl].hash,
13069526Smarkm				&event->somecounter, sizeof(event->somecounter));
13169526Smarkm			source->frac += event->frac;
13269526Smarkm			source->bits += event->bits + source->frac/1024;
13369526Smarkm			source->frac %= 1024;
13465686Smarkm
13565686Smarkm			/* Count the over-threshold sources in each pool */
13665686Smarkm			for (pl = 0; pl < 2; pl++) {
13765686Smarkm				overthreshhold[pl] = 0;
13865686Smarkm				for (src = 0; src < ENTROPYSOURCE; src++) {
13965686Smarkm					if (random_state.pool[pl].source[src].bits
14065686Smarkm						> random_state.pool[pl].thresh)
14165686Smarkm						overthreshhold[pl]++;
14265686Smarkm				}
14365686Smarkm			}
14465686Smarkm
14565686Smarkm			/* if any fast source over threshhold, reseed */
14665686Smarkm			if (overthreshhold[FAST])
14765686Smarkm				reseed(FAST);
14869526Smarkm
14965686Smarkm			/* if enough slow sources are over threshhold, reseed */
15065686Smarkm			if (overthreshhold[SLOW] >= random_state.slowoverthresh)
15165686Smarkm				reseed(SLOW);
15265686Smarkm
15365686Smarkm		}
15465686Smarkm
15565686Smarkm		/* Is the thread scheduled for a shutdown? */
15667112Smarkm		if (random_kthread_control != 0) {
15765686Smarkm#ifdef DEBUG
15872200Sbmilekic			mtx_lock(&Giant);
15965686Smarkm			printf("Random kthread setting terminate\n");
16072200Sbmilekic			mtx_unlock(&Giant);
16165686Smarkm#endif
16267112Smarkm			random_set_wakeup_exit(&random_kthread_control);
16367112Smarkm			/* NOTREACHED */
16465686Smarkm			break;
16565686Smarkm		}
16665686Smarkm
16765686Smarkm	}
16865686Smarkm
16962765Smarkm}
17062765Smarkm
17165686Smarkmint
17262765Smarkmrandom_init(void)
17362053Smarkm{
17465686Smarkm	int error;
17565686Smarkm
17662765Smarkm#ifdef DEBUG
17772200Sbmilekic	mtx_lock(&Giant);
17865686Smarkm	printf("Random initialise\n");
17972200Sbmilekic	mtx_unlock(&Giant);
18062765Smarkm#endif
18165686Smarkm
18271037Smarkm	/* This can be turned off by the very paranoid
18371037Smarkm	 * a reseed will turn it back on.
18471037Smarkm	 */
18571037Smarkm	random_state.seeded = 1;
18671037Smarkm
18772364Smarkm	/* Yarrow parameters. Do not adjust these unless you have
18872364Smarkm	 * have a very good clue about what they do!
18972364Smarkm	 */
19062765Smarkm	random_state.gengateinterval = 10;
19162765Smarkm	random_state.bins = 10;
19262765Smarkm	random_state.pool[0].thresh = 100;
19362765Smarkm	random_state.pool[1].thresh = 160;
19462765Smarkm	random_state.slowoverthresh = 2;
19562765Smarkm	random_state.which = FAST;
19665686Smarkm
19765686Smarkm	mtx_init(&random_reseed_mtx, "random reseed", MTX_DEF);
19865686Smarkm
19969526Smarkm	harvestring.head = 0;
20069526Smarkm	harvestring.tail = 0;
20169526Smarkm
20265686Smarkm	/* Start the hash/reseed thread */
20367112Smarkm	error = kthread_create(random_kthread, NULL,
20465712Sjhb		&random_kthread_proc, RFHIGHPID, "random");
20565686Smarkm	if (error != 0)
20665686Smarkm		return error;
20765686Smarkm
20865686Smarkm	/* Register the randomness harvesting routine */
20967112Smarkm	random_init_harvester(random_harvest_internal, read_random_real);
21065686Smarkm
21165686Smarkm#ifdef DEBUG
21272200Sbmilekic	mtx_lock(&Giant);
21372180Sasmodai	printf("Random initialise finish\n");
21472200Sbmilekic	mtx_unlock(&Giant);
21565686Smarkm#endif
21665686Smarkm
21765686Smarkm	return 0;
21862053Smarkm}
21962053Smarkm
22062053Smarkmvoid
22162765Smarkmrandom_deinit(void)
22262053Smarkm{
22362765Smarkm#ifdef DEBUG
22472200Sbmilekic	mtx_lock(&Giant);
22572180Sasmodai	printf("Random deinitialise\n");
22672200Sbmilekic	mtx_unlock(&Giant);
22762765Smarkm#endif
22865686Smarkm
22965686Smarkm	/* Deregister the randomness harvesting routine */
23062765Smarkm	random_deinit_harvester();
23165686Smarkm
23265686Smarkm#ifdef DEBUG
23372200Sbmilekic	mtx_lock(&Giant);
23472180Sasmodai	printf("Random deinitialise waiting for thread to terminate\n");
23572200Sbmilekic	mtx_unlock(&Giant);
23665686Smarkm#endif
23765686Smarkm
23865686Smarkm	/* Command the hash/reseed thread to end and wait for it to finish */
23965686Smarkm	random_kthread_control = -1;
24072364Smarkm	tsleep((void *)&random_kthread_control, PUSER, "rndend", 0);
24165686Smarkm
24265686Smarkm#ifdef DEBUG
24372200Sbmilekic	mtx_lock(&Giant);
24472180Sasmodai	printf("Random deinitialise removing mutexes\n");
24572200Sbmilekic	mtx_unlock(&Giant);
24665686Smarkm#endif
24765686Smarkm
24865686Smarkm	mtx_destroy(&random_reseed_mtx);
24965686Smarkm
25065686Smarkm#ifdef DEBUG
25172200Sbmilekic	mtx_lock(&Giant);
25272180Sasmodai	printf("Random deinitialise finish\n");
25372200Sbmilekic	mtx_unlock(&Giant);
25465686Smarkm#endif
25562765Smarkm}
25662765Smarkm
25762765Smarkmstatic void
25862765Smarkmreseed(int fastslow)
25962765Smarkm{
26065686Smarkm	/* Interrupt-context stack is a limited resource; make large
26165686Smarkm	 * structures static.
26263771Smarkm	 */
26365686Smarkm	static u_char v[TIMEBIN][KEYSIZE];	/* v[i] */
26465686Smarkm	static struct yarrowhash context;
26565686Smarkm	u_char hash[KEYSIZE];			/* h' */
26665686Smarkm	u_char temp[KEYSIZE];
26762053Smarkm	int i, j;
26862053Smarkm
26962765Smarkm#ifdef DEBUG
27072200Sbmilekic	mtx_lock(&Giant);
27162765Smarkm	printf("Reseed type %d\n", fastslow);
27272200Sbmilekic	mtx_unlock(&Giant);
27362765Smarkm#endif
27462765Smarkm
27565686Smarkm	/* The reseed task must not be jumped on */
27672200Sbmilekic	mtx_lock(&random_reseed_mtx);
27765686Smarkm
27862053Smarkm	/* 1. Hash the accumulated entropy into v[0] */
27962053Smarkm
28065686Smarkm	yarrow_hash_init(&context, NULL, 0);
28165686Smarkm	/* Feed the slow pool hash in if slow */
28265686Smarkm	if (fastslow == SLOW)
28365686Smarkm		yarrow_hash_iterate(&context,
28465686Smarkm			&random_state.pool[SLOW].hash, sizeof(struct yarrowhash));
28562053Smarkm
28665686Smarkm	yarrow_hash_iterate(&context,
28765686Smarkm		&random_state.pool[FAST].hash, sizeof(struct yarrowhash));
28862765Smarkm
28963771Smarkm	/* 2. Compute hash values for all v. _Supposed_ to be computationally
29063771Smarkm	 *    intensive.
29163771Smarkm	 */
29262053Smarkm
29362765Smarkm	if (random_state.bins > TIMEBIN)
29462765Smarkm		random_state.bins = TIMEBIN;
29562765Smarkm	for (i = 1; i < random_state.bins; i++) {
29665686Smarkm		yarrow_hash_init(&context, NULL, 0);
29762765Smarkm		/* v[i] #= h(v[i-1]) */
29865686Smarkm		yarrow_hash_iterate(&context, v[i - 1], KEYSIZE);
29962765Smarkm		/* v[i] #= h(v[0]) */
30065686Smarkm		yarrow_hash_iterate(&context, v[0], KEYSIZE);
30162765Smarkm		/* v[i] #= h(i) */
30265686Smarkm		yarrow_hash_iterate(&context, &i, sizeof(int));
30365686Smarkm		/* Return the hashval */
30465686Smarkm		yarrow_hash_finish(&context, v[i]);
30562053Smarkm	}
30662053Smarkm
30765686Smarkm	/* 3. Compute a new key; h' is the identity function here;
30865686Smarkm	 *    it is not being ignored!
30965686Smarkm	 */
31062053Smarkm
31165686Smarkm	yarrow_hash_init(&context, NULL, 0);
31265686Smarkm	yarrow_hash_iterate(&context, &random_state.key, KEYSIZE);
31365686Smarkm	for (i = 1; i < random_state.bins; i++)
31465686Smarkm		yarrow_hash_iterate(&context, &v[i], KEYSIZE);
31565686Smarkm	yarrow_hash_finish(&context, temp);
31665686Smarkm	yarrow_encrypt_init(&random_state.key, temp, KEYSIZE);
31762053Smarkm
31862053Smarkm	/* 4. Recompute the counter */
31962053Smarkm
32062765Smarkm	random_state.counter = 0;
32165686Smarkm	yarrow_encrypt(&random_state.key, &random_state.counter, temp,
32265686Smarkm		sizeof(random_state.counter));
32362765Smarkm	memcpy(&random_state.counter, temp, random_state.counter);
32462053Smarkm
32562765Smarkm	/* 5. Reset entropy estimate accumulators to zero */
32662053Smarkm
32762765Smarkm	for (i = 0; i <= fastslow; i++) {
32862765Smarkm		for (j = 0; j < ENTROPYSOURCE; j++) {
32965686Smarkm			if (random_state.pool[i].source[j].bits >
33065686Smarkm				random_state.pool[i].thresh) {
33165686Smarkm				random_state.pool[i].source[j].bits = 0;
33265686Smarkm				random_state.pool[i].source[j].frac = 0;
33365686Smarkm			}
33462765Smarkm		}
33562765Smarkm	}
33662053Smarkm
33762053Smarkm	/* 6. Wipe memory of intermediate values */
33862053Smarkm
33965686Smarkm	memset((void *)v, 0, sizeof(v));
34065686Smarkm	memset((void *)temp, 0, sizeof(temp));
34165686Smarkm	memset((void *)hash, 0, sizeof(hash));
34262053Smarkm
34365686Smarkm	/* 7. Dump to seed file */
34465686Smarkm	/* XXX Not done here yet */
34562053Smarkm
34665686Smarkm	/* Release the reseed mutex */
34772200Sbmilekic	mtx_unlock(&random_reseed_mtx);
34865686Smarkm
34965686Smarkm#ifdef DEBUG
35072200Sbmilekic	mtx_lock(&Giant);
35165686Smarkm	printf("Reseed finish\n");
35272200Sbmilekic	mtx_unlock(&Giant);
35365686Smarkm#endif
35465686Smarkm
35567112Smarkm	if (!random_state.seeded) {
35667112Smarkm		random_state.seeded = 1;
35767112Smarkm		selwakeup(&random_state.rsel);
35867112Smarkm		wakeup(&random_state);
35967112Smarkm	}
36067112Smarkm
36162053Smarkm}
36262053Smarkm
36362053Smarkmu_int
36467112Smarkmread_random_real(void *buf, u_int count)
36562053Smarkm{
36663855Smarkm	static u_int64_t genval;
36762053Smarkm	static int cur = 0;
36862053Smarkm	static int gate = 1;
36962053Smarkm	u_int i;
37062053Smarkm	u_int retval;
37162053Smarkm
37262875Smarkm	/* The reseed task must not be jumped on */
37372200Sbmilekic	mtx_lock(&random_reseed_mtx);
37462875Smarkm
37562053Smarkm	if (gate) {
37662053Smarkm		generator_gate();
37762765Smarkm		random_state.outputblocks = 0;
37862053Smarkm		gate = 0;
37962053Smarkm	}
38062765Smarkm	if (count >= sizeof(random_state.counter)) {
38162053Smarkm		retval = 0;
38262765Smarkm		for (i = 0; i < count; i += sizeof(random_state.counter)) {
38362765Smarkm			random_state.counter++;
38465686Smarkm			yarrow_encrypt(&random_state.key, &random_state.counter,
38565686Smarkm				&genval, sizeof(random_state.counter));
38663855Smarkm			memcpy((char *)buf + i, &genval,
38763855Smarkm				sizeof(random_state.counter));
38862765Smarkm			if (++random_state.outputblocks >= random_state.gengateinterval) {
38962053Smarkm				generator_gate();
39062765Smarkm				random_state.outputblocks = 0;
39162053Smarkm			}
39262765Smarkm			retval += sizeof(random_state.counter);
39362053Smarkm		}
39462053Smarkm	}
39562053Smarkm	else {
39662053Smarkm		if (!cur) {
39762765Smarkm			random_state.counter++;
39865686Smarkm			yarrow_encrypt(&random_state.key, &random_state.counter,
39965686Smarkm				&genval, sizeof(random_state.counter));
40062053Smarkm			memcpy(buf, &genval, count);
40162765Smarkm			cur = sizeof(random_state.counter) - count;
40262765Smarkm			if (++random_state.outputblocks >= random_state.gengateinterval) {
40362053Smarkm				generator_gate();
40462765Smarkm				random_state.outputblocks = 0;
40562053Smarkm			}
40662053Smarkm			retval = count;
40762053Smarkm		}
40862053Smarkm		else {
40962053Smarkm			retval = cur < count ? cur : count;
41062053Smarkm			memcpy(buf,
41163855Smarkm				(char *)&genval +
41263855Smarkm					(sizeof(random_state.counter) - cur),
41362053Smarkm				retval);
41462053Smarkm			cur -= retval;
41562053Smarkm		}
41662053Smarkm	}
41772200Sbmilekic	mtx_unlock(&random_reseed_mtx);
41862053Smarkm	return retval;
41962053Smarkm}
42062053Smarkm
42163306Smarkmvoid
42263855Smarkmwrite_random(void *buf, u_int count)
42363306Smarkm{
42463306Smarkm	u_int i;
42563306Smarkm
42669168Smarkm	/* Break the input up into HARVESTSIZE chunks.
42769168Smarkm	 * The writer has too much control here, so "estimate" the
42869168Smarkm	 * the entropy as zero.
42969168Smarkm	 */
43067112Smarkm	for (i = 0; i < count; i += HARVESTSIZE) {
43169168Smarkm		random_harvest_internal(get_cyclecount(), (char *)buf + i,
43269168Smarkm			HARVESTSIZE, 0, 0, RANDOM_WRITE);
43363306Smarkm	}
43465686Smarkm
43563855Smarkm	/* Maybe the loop iterated at least once */
43663855Smarkm	if (i > count)
43767112Smarkm		i -= HARVESTSIZE;
43865686Smarkm
43969168Smarkm	/* Get the last bytes even if the input length is not
44069168Smarkm	 * a multiple of HARVESTSIZE.
44169168Smarkm	 */
44267112Smarkm	count %= HARVESTSIZE;
44363855Smarkm	if (count) {
44469526Smarkm		random_harvest_internal(get_cyclecount(), (char *)buf + i,
44569526Smarkm			count, 0, 0, RANDOM_WRITE);
44663855Smarkm	}
44763306Smarkm}
44863306Smarkm
44962765Smarkmstatic void
45062053Smarkmgenerator_gate(void)
45162053Smarkm{
45262053Smarkm	int i;
45365686Smarkm	u_char temp[KEYSIZE];
45462053Smarkm
45562765Smarkm#ifdef DEBUG
45672200Sbmilekic	mtx_lock(&Giant);
45762875Smarkm	printf("Generator gate\n");
45872200Sbmilekic	mtx_unlock(&Giant);
45962765Smarkm#endif
46062875Smarkm
46162765Smarkm	for (i = 0; i < KEYSIZE; i += sizeof(random_state.counter)) {
46262765Smarkm		random_state.counter++;
46365686Smarkm		yarrow_encrypt(&random_state.key, &random_state.counter,
46465686Smarkm			&(temp[i]), sizeof(random_state.counter));
46562053Smarkm	}
46662053Smarkm
46765686Smarkm	yarrow_encrypt_init(&random_state.key, temp, KEYSIZE);
46865686Smarkm	memset((void *)temp, 0, KEYSIZE);
46962875Smarkm
47065686Smarkm#ifdef DEBUG
47172200Sbmilekic	mtx_lock(&Giant);
47265686Smarkm	printf("Generator gate finish\n");
47372200Sbmilekic	mtx_unlock(&Giant);
47465686Smarkm#endif
47562053Smarkm}
47662765Smarkm
47763771Smarkm/* Entropy harvesting routine. This is supposed to be fast; do
47863771Smarkm * not do anything slow in here!
47963771Smarkm */
48062765Smarkm
48162765Smarkmstatic void
48269168Smarkmrandom_harvest_internal(u_int64_t somecounter, void *entropy, u_int count,
48362841Smarkm	u_int bits, u_int frac, enum esource origin)
48462765Smarkm{
48569526Smarkm	struct harvest *harvest;
48672364Smarkm	int newhead;
48762765Smarkm
48872364Smarkm	newhead = (harvestring.head + 1) & HARVEST_RING_MASK;
48962765Smarkm
49072364Smarkm	if (newhead != harvestring.tail) {
49162850Smarkm
49272364Smarkm		/* Add the harvested data to the ring buffer */
49362765Smarkm
49472364Smarkm		harvest = &harvestring.data[harvestring.head];
49562765Smarkm
49672364Smarkm		/* Stuff the harvested data into the ring */
49772364Smarkm		harvest->somecounter = somecounter;
49872364Smarkm		count = count > HARVESTSIZE ? HARVESTSIZE : count;
49972364Smarkm		memcpy(harvest->entropy, entropy, count);
50072364Smarkm		harvest->size = count;
50172364Smarkm		harvest->bits = bits;
50272364Smarkm		harvest->frac = frac;
50372364Smarkm		harvest->source = origin < ENTROPYSOURCE ? origin : 0;
50462765Smarkm
50572364Smarkm		/* Bump the ring counter. This action is assumed
50672364Smarkm		 * to be atomic.
50772364Smarkm		 */
50872364Smarkm		harvestring.head = newhead;
50962765Smarkm
51072364Smarkm	}
51162765Smarkm
51262765Smarkm}
51369172Smarkm
51469172Smarkm/* Helper routine to perform explicit reseeds */
51569172Smarkmvoid
51669172Smarkmrandom_reseed(void)
51769172Smarkm{
51869172Smarkm	reseed(FAST);
51969172Smarkm}
520