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