1/*	$NetBSD$	*/
2
3/*
4 * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/* Id: entropy.c,v 1.18.332.2 2009/01/18 23:47:41 tbox Exp */
21
22/*! \file
23 * \brief
24 * This is the system independent part of the entropy module.  It is
25 * compiled via inclusion from the relevant OS source file, ie,
26 * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c.
27 *
28 * \author Much of this code is modeled after the NetBSD /dev/random implementation,
29 * written by Michael Graff <explorer@netbsd.org>.
30 */
31
32#include <errno.h>
33#include <fcntl.h>
34#include <stdio.h>
35
36#include <isc/buffer.h>
37#include <isc/entropy.h>
38#include <isc/keyboard.h>
39#include <isc/list.h>
40#include <isc/magic.h>
41#include <isc/mem.h>
42#include <isc/msgs.h>
43#include <isc/mutex.h>
44#include <isc/platform.h>
45#include <isc/region.h>
46#include <isc/sha1.h>
47#include <isc/string.h>
48#include <isc/time.h>
49#include <isc/util.h>
50
51
52#define ENTROPY_MAGIC		ISC_MAGIC('E', 'n', 't', 'e')
53#define SOURCE_MAGIC		ISC_MAGIC('E', 'n', 't', 's')
54
55#define VALID_ENTROPY(e)	ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
56#define VALID_SOURCE(s)		ISC_MAGIC_VALID(s, SOURCE_MAGIC)
57
58/***
59 *** "constants."  Do not change these unless you _really_ know what
60 *** you are doing.
61 ***/
62
63/*%
64 * Size of entropy pool in 32-bit words.  This _MUST_ be a power of 2.
65 */
66#define RND_POOLWORDS	128
67/*% Pool in bytes. */
68#define RND_POOLBYTES	(RND_POOLWORDS * 4)
69/*% Pool in bits. */
70#define RND_POOLBITS	(RND_POOLWORDS * 32)
71
72/*%
73 * Number of bytes returned per hash.  This must be true:
74 *	threshold * 2 <= digest_size_in_bytes
75 */
76#define RND_ENTROPY_THRESHOLD	10
77#define THRESHOLD_BITS		(RND_ENTROPY_THRESHOLD * 8)
78
79/*%
80 * Size of the input event queue in samples.
81 */
82#define RND_EVENTQSIZE	32
83
84/*%
85 * The number of times we'll "reseed" for pseudorandom seeds.  This is an
86 * extremely weak pseudorandom seed.  If the caller is using lots of
87 * pseudorandom data and they cannot provide a stronger random source,
88 * there is little we can do other than hope they're smart enough to
89 * call _adddata() with something better than we can come up with.
90 */
91#define RND_INITIALIZE	128
92
93/*% Entropy Pool */
94typedef struct {
95	isc_uint32_t	cursor;		/*%< current add point in the pool */
96	isc_uint32_t	entropy;	/*%< current entropy estimate in bits */
97	isc_uint32_t	pseudo;		/*%< bits extracted in pseudorandom */
98	isc_uint32_t	rotate;		/*%< how many bits to rotate by */
99	isc_uint32_t	pool[RND_POOLWORDS];	/*%< random pool data */
100} isc_entropypool_t;
101
102struct isc_entropy {
103	unsigned int			magic;
104	isc_mem_t		       *mctx;
105	isc_mutex_t			lock;
106	unsigned int			refcnt;
107	isc_uint32_t			initialized;
108	isc_uint32_t			initcount;
109	isc_entropypool_t		pool;
110	unsigned int			nsources;
111	isc_entropysource_t	       *nextsource;
112	ISC_LIST(isc_entropysource_t)	sources;
113};
114
115/*% Sample Queue */
116typedef struct {
117	isc_uint32_t	last_time;	/*%< last time recorded */
118	isc_uint32_t	last_delta;	/*%< last delta value */
119	isc_uint32_t	last_delta2;	/*%< last delta2 value */
120	isc_uint32_t	nsamples;	/*%< number of samples filled in */
121	isc_uint32_t   *samples;	/*%< the samples */
122	isc_uint32_t   *extra;		/*%< extra samples added in */
123} sample_queue_t;
124
125typedef struct {
126	sample_queue_t	samplequeue;
127} isc_entropysamplesource_t;
128
129typedef struct {
130	isc_boolean_t		start_called;
131	isc_entropystart_t	startfunc;
132	isc_entropyget_t	getfunc;
133	isc_entropystop_t	stopfunc;
134	void		       *arg;
135	sample_queue_t		samplequeue;
136} isc_cbsource_t;
137
138typedef struct {
139	FILESOURCE_HANDLE_TYPE handle;
140} isc_entropyfilesource_t;
141
142struct isc_entropysource {
143	unsigned int	magic;
144	unsigned int	type;
145	isc_entropy_t  *ent;
146	isc_uint32_t	total;		/*%< entropy from this source */
147	ISC_LINK(isc_entropysource_t)	link;
148	char		name[32];
149	isc_boolean_t	bad;
150	isc_boolean_t	warn_keyboard;
151	isc_keyboard_t	kbd;
152	union {
153		isc_entropysamplesource_t	sample;
154		isc_entropyfilesource_t		file;
155		isc_cbsource_t			callback;
156		isc_entropyusocketsource_t	usocket;
157	} sources;
158};
159
160#define ENTROPY_SOURCETYPE_SAMPLE	1	/*%< Type is a sample source */
161#define ENTROPY_SOURCETYPE_FILE		2	/*%< Type is a file source */
162#define ENTROPY_SOURCETYPE_CALLBACK	3	/*%< Type is a callback source */
163#define ENTROPY_SOURCETYPE_USOCKET	4	/*%< Type is a Unix socket source */
164
165/*@{*/
166/*%
167 * The random pool "taps"
168 */
169#define TAP1	99
170#define TAP2	59
171#define TAP3	31
172#define TAP4	 9
173#define TAP5	 7
174/*@}*/
175
176/*@{*/
177/*%
178 * Declarations for function provided by the system dependent sources that
179 * include this file.
180 */
181static void
182fillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
183
184static int
185wait_for_sources(isc_entropy_t *);
186
187static void
188destroyfilesource(isc_entropyfilesource_t *source);
189
190static void
191destroyusocketsource(isc_entropyusocketsource_t *source);
192
193/*@}*/
194
195static void
196samplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) {
197	REQUIRE(sq->samples != NULL);
198	REQUIRE(sq->extra != NULL);
199
200	isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
201	isc_mem_put(ent->mctx, sq->extra, RND_EVENTQSIZE * 4);
202	sq->samples = NULL;
203	sq->extra = NULL;
204}
205
206static isc_result_t
207samplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) {
208	sq->samples = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
209	if (sq->samples == NULL)
210		return (ISC_R_NOMEMORY);
211
212	sq->extra = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
213	if (sq->extra == NULL) {
214		isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
215		sq->samples = NULL;
216		return (ISC_R_NOMEMORY);
217	}
218
219	sq->nsamples = 0;
220
221	return (ISC_R_SUCCESS);
222}
223
224/*%
225 * Add in entropy, even when the value we're adding in could be
226 * very large.
227 */
228static inline void
229add_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
230	/* clamp input.  Yes, this must be done. */
231	entropy = ISC_MIN(entropy, RND_POOLBITS);
232	/* Add in the entropy we already have. */
233	entropy += ent->pool.entropy;
234	/* Clamp. */
235	ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS);
236}
237
238/*%
239 * Decrement the amount of entropy the pool has.
240 */
241static inline void
242subtract_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
243	entropy = ISC_MIN(entropy, ent->pool.entropy);
244	ent->pool.entropy -= entropy;
245}
246
247/*!
248 * Add in entropy, even when the value we're adding in could be
249 * very large.
250 */
251static inline void
252add_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
253	/* clamp input.  Yes, this must be done. */
254	pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
255	/* Add in the pseudo we already have. */
256	pseudo += ent->pool.pseudo;
257	/* Clamp. */
258	ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
259}
260
261/*!
262 * Decrement the amount of pseudo the pool has.
263 */
264static inline void
265subtract_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
266	pseudo = ISC_MIN(pseudo, ent->pool.pseudo);
267	ent->pool.pseudo -= pseudo;
268}
269
270/*!
271 * Add one word to the pool, rotating the input as needed.
272 */
273static inline void
274entropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) {
275	/*
276	 * Steal some values out of the pool, and xor them into the
277	 * word we were given.
278	 *
279	 * Mix the new value into the pool using xor.  This will
280	 * prevent the actual values from being known to the caller
281	 * since the previous values are assumed to be unknown as well.
282	 */
283	val ^= rp->pool[(rp->cursor + TAP1) & (RND_POOLWORDS - 1)];
284	val ^= rp->pool[(rp->cursor + TAP2) & (RND_POOLWORDS - 1)];
285	val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
286	val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
287	val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
288	rp->pool[rp->cursor++] ^=
289	  ((val << rp->rotate) | (val >> (32 - rp->rotate)));
290
291	/*
292	 * If we have looped around the pool, increment the rotate
293	 * variable so the next value will get xored in rotated to
294	 * a different position.
295	 * Increment by a value that is relatively prime to the word size
296	 * to try to spread the bits throughout the pool quickly when the
297	 * pool is empty.
298	 */
299	if (rp->cursor == RND_POOLWORDS) {
300		rp->cursor = 0;
301		rp->rotate = (rp->rotate + 7) & 31;
302	}
303}
304
305/*!
306 * Add a buffer's worth of data to the pool.
307 *
308 * Requires that the lock is held on the entropy pool.
309 */
310static void
311entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
312		    isc_uint32_t entropy)
313{
314	isc_uint32_t val;
315	unsigned long addr;
316	isc_uint8_t *buf;
317
318	addr = (unsigned long)p;
319	buf = p;
320
321	if ((addr & 0x03U) != 0U) {
322		val = 0;
323		switch (len) {
324		case 3:
325			val = *buf++;
326			len--;
327		case 2:
328			val = val << 8 | *buf++;
329			len--;
330		case 1:
331			val = val << 8 | *buf++;
332			len--;
333		}
334
335		entropypool_add_word(&ent->pool, val);
336	}
337
338	for (; len > 3; len -= 4) {
339		val = *((isc_uint32_t *)buf);
340
341		entropypool_add_word(&ent->pool, val);
342		buf += 4;
343	}
344
345	if (len != 0) {
346		val = 0;
347		switch (len) {
348		case 3:
349			val = *buf++;
350		case 2:
351			val = val << 8 | *buf++;
352		case 1:
353			val = val << 8 | *buf++;
354		}
355
356		entropypool_add_word(&ent->pool, val);
357	}
358
359	add_entropy(ent, entropy);
360	subtract_pseudo(ent, entropy);
361}
362
363static inline void
364reseed(isc_entropy_t *ent) {
365	isc_time_t t;
366	pid_t pid;
367
368	if (ent->initcount == 0) {
369		pid = getpid();
370		entropypool_adddata(ent, &pid, sizeof(pid), 0);
371		pid = getppid();
372		entropypool_adddata(ent, &pid, sizeof(pid), 0);
373	}
374
375	/*!
376	 * After we've reseeded 100 times, only add new timing info every
377	 * 50 requests.  This will keep us from using lots and lots of
378	 * CPU just to return bad pseudorandom data anyway.
379	 */
380	if (ent->initcount > 100)
381		if ((ent->initcount % 50) != 0)
382			return;
383
384	TIME_NOW(&t);
385	entropypool_adddata(ent, &t, sizeof(t), 0);
386	ent->initcount++;
387}
388
389static inline unsigned int
390estimate_entropy(sample_queue_t *sq, isc_uint32_t t) {
391	isc_int32_t		delta;
392	isc_int32_t		delta2;
393	isc_int32_t		delta3;
394
395	/*!
396	 * If the time counter has overflowed, calculate the real difference.
397	 * If it has not, it is simpler.
398	 */
399	if (t < sq->last_time)
400		delta = UINT_MAX - sq->last_time + t;
401	else
402		delta = sq->last_time - t;
403
404	if (delta < 0)
405		delta = -delta;
406
407	/*
408	 * Calculate the second and third order differentials
409	 */
410	delta2 = sq->last_delta - delta;
411	if (delta2 < 0)
412		delta2 = -delta2;
413
414	delta3 = sq->last_delta2 - delta2;
415	if (delta3 < 0)
416		delta3 = -delta3;
417
418	sq->last_time = t;
419	sq->last_delta = delta;
420	sq->last_delta2 = delta2;
421
422	/*
423	 * If any delta is 0, we got no entropy.  If all are non-zero, we
424	 * might have something.
425	 */
426	if (delta == 0 || delta2 == 0 || delta3 == 0)
427		return 0;
428
429	/*
430	 * We could find the smallest delta and claim we got log2(delta)
431	 * bits, but for now return that we found 1 bit.
432	 */
433	return 1;
434}
435
436static unsigned int
437crunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
438	unsigned int ns;
439	unsigned int added;
440
441	if (sq->nsamples < 6)
442		return (0);
443
444	added = 0;
445	sq->last_time = sq->samples[0];
446	sq->last_delta = 0;
447	sq->last_delta2 = 0;
448
449	/*
450	 * Prime the values by adding in the first 4 samples in.  This
451	 * should completely initialize the delta calculations.
452	 */
453	for (ns = 0; ns < 4; ns++)
454		(void)estimate_entropy(sq, sq->samples[ns]);
455
456	for (ns = 4; ns < sq->nsamples; ns++)
457		added += estimate_entropy(sq, sq->samples[ns]);
458
459	entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
460	entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
461
462	/*
463	 * Move the last 4 samples into the first 4 positions, and start
464	 * adding new samples from that point.
465	 */
466	for (ns = 0; ns < 4; ns++) {
467		sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
468		sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
469	}
470
471	sq->nsamples = 4;
472
473	return (added);
474}
475
476static unsigned int
477get_from_callback(isc_entropysource_t *source, unsigned int desired,
478		  isc_boolean_t blocking)
479{
480	isc_entropy_t *ent = source->ent;
481	isc_cbsource_t *cbs = &source->sources.callback;
482	unsigned int added;
483	unsigned int got;
484	isc_result_t result;
485
486	if (desired == 0)
487		return (0);
488
489	if (source->bad)
490		return (0);
491
492	if (!cbs->start_called && cbs->startfunc != NULL) {
493		result = cbs->startfunc(source, cbs->arg, blocking);
494		if (result != ISC_R_SUCCESS)
495			return (0);
496		cbs->start_called = ISC_TRUE;
497	}
498
499	added = 0;
500	result = ISC_R_SUCCESS;
501	while (desired > 0 && result == ISC_R_SUCCESS) {
502		result = cbs->getfunc(source, cbs->arg, blocking);
503		if (result == ISC_R_QUEUEFULL) {
504			got = crunchsamples(ent, &cbs->samplequeue);
505			added += got;
506			desired -= ISC_MIN(got, desired);
507			result = ISC_R_SUCCESS;
508		} else if (result != ISC_R_SUCCESS &&
509			   result != ISC_R_NOTBLOCKING)
510			source->bad = ISC_TRUE;
511
512	}
513
514	return (added);
515}
516
517/*
518 * Extract some number of bytes from the random pool, decreasing the
519 * estimate of randomness as each byte is extracted.
520 *
521 * Do this by stiring the pool and returning a part of hash as randomness.
522 * Note that no secrets are given away here since parts of the hash are
523 * xored together before returned.
524 *
525 * Honor the request from the caller to only return good data, any data,
526 * etc.
527 */
528isc_result_t
529isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
530		    unsigned int *returned, unsigned int flags)
531{
532	unsigned int i;
533	isc_sha1_t hash;
534	unsigned char digest[ISC_SHA1_DIGESTLENGTH];
535	isc_uint32_t remain, deltae, count, total;
536	isc_uint8_t *buf;
537	isc_boolean_t goodonly, partial, blocking;
538
539	REQUIRE(VALID_ENTROPY(ent));
540	REQUIRE(data != NULL);
541	REQUIRE(length > 0);
542
543	goodonly = ISC_TF((flags & ISC_ENTROPY_GOODONLY) != 0);
544	partial = ISC_TF((flags & ISC_ENTROPY_PARTIAL) != 0);
545	blocking = ISC_TF((flags & ISC_ENTROPY_BLOCKING) != 0);
546
547	REQUIRE(!partial || returned != NULL);
548
549	LOCK(&ent->lock);
550
551	remain = length;
552	buf = data;
553	total = 0;
554	while (remain != 0) {
555		count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
556
557		/*
558		 * If we are extracting good data only, make certain we
559		 * have enough data in our pool for this pass.  If we don't,
560		 * get some, and fail if we can't, and partial returns
561		 * are not ok.
562		 */
563		if (goodonly) {
564			unsigned int fillcount;
565
566			fillcount = ISC_MAX(remain * 8, count * 8);
567
568			/*
569			 * If, however, we have at least THRESHOLD_BITS
570			 * of entropy in the pool, don't block here.  It is
571			 * better to drain the pool once in a while and
572			 * then refill it than it is to constantly keep the
573			 * pool full.
574			 */
575			if (ent->pool.entropy >= THRESHOLD_BITS)
576				fillpool(ent, fillcount, ISC_FALSE);
577			else
578				fillpool(ent, fillcount, blocking);
579
580			/*
581			 * Verify that we got enough entropy to do one
582			 * extraction.  If we didn't, bail.
583			 */
584			if (ent->pool.entropy < THRESHOLD_BITS) {
585				if (!partial)
586					goto zeroize;
587				else
588					goto partial_output;
589			}
590		} else {
591			/*
592			 * If we've extracted half our pool size in bits
593			 * since the last refresh, try to refresh here.
594			 */
595			if (ent->initialized < THRESHOLD_BITS)
596				fillpool(ent, THRESHOLD_BITS, blocking);
597			else
598				fillpool(ent, 0, ISC_FALSE);
599
600			/*
601			 * If we've not initialized with enough good random
602			 * data, seed with our crappy code.
603			 */
604			if (ent->initialized < THRESHOLD_BITS)
605				reseed(ent);
606		}
607
608		isc_sha1_init(&hash);
609		isc_sha1_update(&hash, (void *)(ent->pool.pool),
610				RND_POOLBYTES);
611		isc_sha1_final(&hash, digest);
612
613		/*
614		 * Stir the extracted data (all of it) back into the pool.
615		 */
616		entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
617
618		for (i = 0; i < count; i++)
619			buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
620
621		buf += count;
622		remain -= count;
623
624		deltae = count * 8;
625		deltae = ISC_MIN(deltae, ent->pool.entropy);
626		total += deltae;
627		subtract_entropy(ent, deltae);
628		add_pseudo(ent, count * 8);
629	}
630
631 partial_output:
632	memset(digest, 0, sizeof(digest));
633
634	if (returned != NULL)
635		*returned = (length - remain);
636
637	UNLOCK(&ent->lock);
638
639	return (ISC_R_SUCCESS);
640
641 zeroize:
642	/* put the entropy we almost extracted back */
643	add_entropy(ent, total);
644	memset(data, 0, length);
645	memset(digest, 0, sizeof(digest));
646	if (returned != NULL)
647		*returned = 0;
648
649	UNLOCK(&ent->lock);
650
651	return (ISC_R_NOENTROPY);
652}
653
654static void
655isc_entropypool_init(isc_entropypool_t *pool) {
656	pool->cursor = RND_POOLWORDS - 1;
657	pool->entropy = 0;
658	pool->pseudo = 0;
659	pool->rotate = 0;
660	memset(pool->pool, 0, RND_POOLBYTES);
661}
662
663static void
664isc_entropypool_invalidate(isc_entropypool_t *pool) {
665	pool->cursor = 0;
666	pool->entropy = 0;
667	pool->pseudo = 0;
668	pool->rotate = 0;
669	memset(pool->pool, 0, RND_POOLBYTES);
670}
671
672isc_result_t
673isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
674	isc_result_t result;
675	isc_entropy_t *ent;
676
677	REQUIRE(mctx != NULL);
678	REQUIRE(entp != NULL && *entp == NULL);
679
680	ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
681	if (ent == NULL)
682		return (ISC_R_NOMEMORY);
683
684	/*
685	 * We need a lock.
686	 */
687	result = isc_mutex_init(&ent->lock);
688	if (result != ISC_R_SUCCESS)
689		goto errout;
690
691	/*
692	 * From here down, no failures will/can occur.
693	 */
694	ISC_LIST_INIT(ent->sources);
695	ent->nextsource = NULL;
696	ent->nsources = 0;
697	ent->mctx = NULL;
698	isc_mem_attach(mctx, &ent->mctx);
699	ent->refcnt = 1;
700	ent->initialized = 0;
701	ent->initcount = 0;
702	ent->magic = ENTROPY_MAGIC;
703
704	isc_entropypool_init(&ent->pool);
705
706	*entp = ent;
707	return (ISC_R_SUCCESS);
708
709 errout:
710	isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
711
712	return (result);
713}
714
715/*!
716 * Requires "ent" be locked.
717 */
718static void
719destroysource(isc_entropysource_t **sourcep) {
720	isc_entropysource_t *source;
721	isc_entropy_t *ent;
722	isc_cbsource_t *cbs;
723
724	source = *sourcep;
725	*sourcep = NULL;
726	ent = source->ent;
727
728	ISC_LIST_UNLINK(ent->sources, source, link);
729	ent->nextsource = NULL;
730	REQUIRE(ent->nsources > 0);
731	ent->nsources--;
732
733	switch (source->type) {
734	case ENTROPY_SOURCETYPE_FILE:
735		if (! source->bad)
736			destroyfilesource(&source->sources.file);
737		break;
738	case ENTROPY_SOURCETYPE_USOCKET:
739		if (! source->bad)
740			destroyusocketsource(&source->sources.usocket);
741		break;
742	case ENTROPY_SOURCETYPE_SAMPLE:
743		samplequeue_release(ent, &source->sources.sample.samplequeue);
744		break;
745	case ENTROPY_SOURCETYPE_CALLBACK:
746		cbs = &source->sources.callback;
747		if (cbs->start_called && cbs->stopfunc != NULL) {
748			cbs->stopfunc(source, cbs->arg);
749			cbs->start_called = ISC_FALSE;
750		}
751		samplequeue_release(ent, &cbs->samplequeue);
752		break;
753	}
754
755	memset(source, 0, sizeof(isc_entropysource_t));
756
757	isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
758}
759
760static inline isc_boolean_t
761destroy_check(isc_entropy_t *ent) {
762	isc_entropysource_t *source;
763
764	if (ent->refcnt > 0)
765		return (ISC_FALSE);
766
767	source = ISC_LIST_HEAD(ent->sources);
768	while (source != NULL) {
769		switch (source->type) {
770		case ENTROPY_SOURCETYPE_FILE:
771		case ENTROPY_SOURCETYPE_USOCKET:
772			break;
773		default:
774			return (ISC_FALSE);
775		}
776		source = ISC_LIST_NEXT(source, link);
777	}
778
779	return (ISC_TRUE);
780}
781
782static void
783destroy(isc_entropy_t **entp) {
784	isc_entropy_t *ent;
785	isc_entropysource_t *source;
786	isc_mem_t *mctx;
787
788	REQUIRE(entp != NULL && *entp != NULL);
789	ent = *entp;
790	*entp = NULL;
791
792	LOCK(&ent->lock);
793
794	REQUIRE(ent->refcnt == 0);
795
796	/*
797	 * Here, detach non-sample sources.
798	 */
799	source = ISC_LIST_HEAD(ent->sources);
800	while (source != NULL) {
801		switch(source->type) {
802		case ENTROPY_SOURCETYPE_FILE:
803		case ENTROPY_SOURCETYPE_USOCKET:
804			destroysource(&source);
805			break;
806		}
807		source = ISC_LIST_HEAD(ent->sources);
808	}
809
810	/*
811	 * If there are other types of sources, we've found a bug.
812	 */
813	REQUIRE(ISC_LIST_EMPTY(ent->sources));
814
815	mctx = ent->mctx;
816
817	isc_entropypool_invalidate(&ent->pool);
818
819	UNLOCK(&ent->lock);
820
821	DESTROYLOCK(&ent->lock);
822
823	memset(ent, 0, sizeof(isc_entropy_t));
824	isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
825	isc_mem_detach(&mctx);
826}
827
828void
829isc_entropy_destroysource(isc_entropysource_t **sourcep) {
830	isc_entropysource_t *source;
831	isc_entropy_t *ent;
832	isc_boolean_t killit;
833
834	REQUIRE(sourcep != NULL);
835	REQUIRE(VALID_SOURCE(*sourcep));
836
837	source = *sourcep;
838	*sourcep = NULL;
839
840	ent = source->ent;
841	REQUIRE(VALID_ENTROPY(ent));
842
843	LOCK(&ent->lock);
844
845	destroysource(&source);
846
847	killit = destroy_check(ent);
848
849	UNLOCK(&ent->lock);
850
851	if (killit)
852		destroy(&ent);
853}
854
855isc_result_t
856isc_entropy_createcallbacksource(isc_entropy_t *ent,
857				 isc_entropystart_t start,
858				 isc_entropyget_t get,
859				 isc_entropystop_t stop,
860				 void *arg,
861				 isc_entropysource_t **sourcep)
862{
863	isc_result_t result;
864	isc_entropysource_t *source;
865	isc_cbsource_t *cbs;
866
867	REQUIRE(VALID_ENTROPY(ent));
868	REQUIRE(get != NULL);
869	REQUIRE(sourcep != NULL && *sourcep == NULL);
870
871	LOCK(&ent->lock);
872
873	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
874	if (source == NULL) {
875		result = ISC_R_NOMEMORY;
876		goto errout;
877	}
878	source->bad = ISC_FALSE;
879
880	cbs = &source->sources.callback;
881
882	result = samplesource_allocate(ent, &cbs->samplequeue);
883	if (result != ISC_R_SUCCESS)
884		goto errout;
885
886	cbs->start_called = ISC_FALSE;
887	cbs->startfunc = start;
888	cbs->getfunc = get;
889	cbs->stopfunc = stop;
890	cbs->arg = arg;
891
892	/*
893	 * From here down, no failures can occur.
894	 */
895	source->magic = SOURCE_MAGIC;
896	source->type = ENTROPY_SOURCETYPE_CALLBACK;
897	source->ent = ent;
898	source->total = 0;
899	memset(source->name, 0, sizeof(source->name));
900	ISC_LINK_INIT(source, link);
901
902	/*
903	 * Hook it into the entropy system.
904	 */
905	ISC_LIST_APPEND(ent->sources, source, link);
906	ent->nsources++;
907
908	*sourcep = source;
909
910	UNLOCK(&ent->lock);
911	return (ISC_R_SUCCESS);
912
913 errout:
914	if (source != NULL)
915		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
916
917	UNLOCK(&ent->lock);
918
919	return (result);
920}
921
922void
923isc_entropy_stopcallbacksources(isc_entropy_t *ent) {
924	isc_entropysource_t *source;
925	isc_cbsource_t *cbs;
926
927	REQUIRE(VALID_ENTROPY(ent));
928
929	LOCK(&ent->lock);
930
931	source = ISC_LIST_HEAD(ent->sources);
932	while (source != NULL) {
933		if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
934			cbs = &source->sources.callback;
935			if (cbs->start_called && cbs->stopfunc != NULL) {
936				cbs->stopfunc(source, cbs->arg);
937				cbs->start_called = ISC_FALSE;
938			}
939		}
940
941		source = ISC_LIST_NEXT(source, link);
942	}
943
944	UNLOCK(&ent->lock);
945}
946
947isc_result_t
948isc_entropy_createsamplesource(isc_entropy_t *ent,
949			       isc_entropysource_t **sourcep)
950{
951	isc_result_t result;
952	isc_entropysource_t *source;
953	sample_queue_t *sq;
954
955	REQUIRE(VALID_ENTROPY(ent));
956	REQUIRE(sourcep != NULL && *sourcep == NULL);
957
958	LOCK(&ent->lock);
959
960	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
961	if (source == NULL) {
962		result = ISC_R_NOMEMORY;
963		goto errout;
964	}
965
966	sq = &source->sources.sample.samplequeue;
967	result = samplesource_allocate(ent, sq);
968	if (result != ISC_R_SUCCESS)
969		goto errout;
970
971	/*
972	 * From here down, no failures can occur.
973	 */
974	source->magic = SOURCE_MAGIC;
975	source->type = ENTROPY_SOURCETYPE_SAMPLE;
976	source->ent = ent;
977	source->total = 0;
978	memset(source->name, 0, sizeof(source->name));
979	ISC_LINK_INIT(source, link);
980
981	/*
982	 * Hook it into the entropy system.
983	 */
984	ISC_LIST_APPEND(ent->sources, source, link);
985	ent->nsources++;
986
987	*sourcep = source;
988
989	UNLOCK(&ent->lock);
990	return (ISC_R_SUCCESS);
991
992 errout:
993	if (source != NULL)
994		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
995
996	UNLOCK(&ent->lock);
997
998	return (result);
999}
1000
1001/*!
1002 * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
1003 * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
1004 * queue was full when this function was called.
1005 */
1006static isc_result_t
1007addsample(sample_queue_t *sq, isc_uint32_t sample, isc_uint32_t extra) {
1008	if (sq->nsamples >= RND_EVENTQSIZE)
1009		return (ISC_R_NOMORE);
1010
1011	sq->samples[sq->nsamples] = sample;
1012	sq->extra[sq->nsamples] = extra;
1013	sq->nsamples++;
1014
1015	if (sq->nsamples >= RND_EVENTQSIZE)
1016		return (ISC_R_QUEUEFULL);
1017
1018	return (ISC_R_SUCCESS);
1019}
1020
1021isc_result_t
1022isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
1023		      isc_uint32_t extra)
1024{
1025	isc_entropy_t *ent;
1026	sample_queue_t *sq;
1027	unsigned int entropy;
1028	isc_result_t result;
1029
1030	REQUIRE(VALID_SOURCE(source));
1031
1032	ent = source->ent;
1033
1034	LOCK(&ent->lock);
1035
1036	sq = &source->sources.sample.samplequeue;
1037	result = addsample(sq, sample, extra);
1038	if (result == ISC_R_QUEUEFULL) {
1039		entropy = crunchsamples(ent, sq);
1040		add_entropy(ent, entropy);
1041	}
1042
1043	UNLOCK(&ent->lock);
1044
1045	return (result);
1046}
1047
1048isc_result_t
1049isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
1050			      isc_uint32_t extra)
1051{
1052	sample_queue_t *sq;
1053	isc_result_t result;
1054
1055	REQUIRE(VALID_SOURCE(source));
1056	REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
1057
1058	sq = &source->sources.callback.samplequeue;
1059	result = addsample(sq, sample, extra);
1060
1061	return (result);
1062}
1063
1064void
1065isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
1066		    isc_uint32_t entropy)
1067{
1068	REQUIRE(VALID_ENTROPY(ent));
1069
1070	LOCK(&ent->lock);
1071
1072	entropypool_adddata(ent, data, length, entropy);
1073
1074	if (ent->initialized < THRESHOLD_BITS)
1075		ent->initialized = THRESHOLD_BITS;
1076
1077	UNLOCK(&ent->lock);
1078}
1079
1080static void
1081dumpstats(isc_entropy_t *ent, FILE *out) {
1082	fprintf(out,
1083		isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
1084			       ISC_MSG_ENTROPYSTATS,
1085			       "Entropy pool %p:  refcnt %u cursor %u,"
1086			       " rotate %u entropy %u pseudo %u nsources %u"
1087			       " nextsource %p initialized %u initcount %u\n"),
1088		ent, ent->refcnt,
1089		ent->pool.cursor, ent->pool.rotate,
1090		ent->pool.entropy, ent->pool.pseudo,
1091		ent->nsources, ent->nextsource, ent->initialized,
1092		ent->initcount);
1093}
1094
1095/*
1096 * This function ignores locking.  Use at your own risk.
1097 */
1098void
1099isc_entropy_stats(isc_entropy_t *ent, FILE *out) {
1100	REQUIRE(VALID_ENTROPY(ent));
1101
1102	LOCK(&ent->lock);
1103	dumpstats(ent, out);
1104	UNLOCK(&ent->lock);
1105}
1106
1107unsigned int
1108isc_entropy_status(isc_entropy_t *ent) {
1109	unsigned int estimate;
1110
1111	LOCK(&ent->lock);
1112	estimate = ent->pool.entropy;
1113	UNLOCK(&ent->lock);
1114
1115	return estimate;
1116}
1117
1118void
1119isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
1120	REQUIRE(VALID_ENTROPY(ent));
1121	REQUIRE(entp != NULL && *entp == NULL);
1122
1123	LOCK(&ent->lock);
1124
1125	ent->refcnt++;
1126	*entp = ent;
1127
1128	UNLOCK(&ent->lock);
1129}
1130
1131void
1132isc_entropy_detach(isc_entropy_t **entp) {
1133	isc_entropy_t *ent;
1134	isc_boolean_t killit;
1135
1136	REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
1137	ent = *entp;
1138	*entp = NULL;
1139
1140	LOCK(&ent->lock);
1141
1142	REQUIRE(ent->refcnt > 0);
1143	ent->refcnt--;
1144
1145	killit = destroy_check(ent);
1146
1147	UNLOCK(&ent->lock);
1148
1149	if (killit)
1150		destroy(&ent);
1151}
1152
1153static isc_result_t
1154kbdstart(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
1155	/*
1156	 * The intent of "first" is to provide a warning message only once
1157	 * during the run of a program that might try to gather keyboard
1158	 * entropy multiple times.
1159	 */
1160	static isc_boolean_t first = ISC_TRUE;
1161
1162	UNUSED(arg);
1163
1164	if (! blocking)
1165		return (ISC_R_NOENTROPY);
1166
1167	if (first) {
1168		if (source->warn_keyboard)
1169			fprintf(stderr, "You must use the keyboard to create "
1170				"entropy, since your system is lacking\n"
1171				"/dev/random (or equivalent)\n\n");
1172		first = ISC_FALSE;
1173	}
1174	fprintf(stderr, "start typing:\n");
1175
1176	return (isc_keyboard_open(&source->kbd));
1177}
1178
1179static void
1180kbdstop(isc_entropysource_t *source, void *arg) {
1181
1182	UNUSED(arg);
1183
1184	if (! isc_keyboard_canceled(&source->kbd))
1185		fprintf(stderr, "stop typing.\r\n");
1186
1187	(void)isc_keyboard_close(&source->kbd, 3);
1188}
1189
1190static isc_result_t
1191kbdget(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
1192	isc_result_t result;
1193	isc_time_t t;
1194	isc_uint32_t sample;
1195	isc_uint32_t extra;
1196	unsigned char c;
1197
1198	UNUSED(arg);
1199
1200	if (!blocking)
1201		return (ISC_R_NOTBLOCKING);
1202
1203	result = isc_keyboard_getchar(&source->kbd, &c);
1204	if (result != ISC_R_SUCCESS)
1205		return (result);
1206
1207	TIME_NOW(&t);
1208
1209	sample = isc_time_nanoseconds(&t);
1210	extra = c;
1211
1212	result = isc_entropy_addcallbacksample(source, sample, extra);
1213	if (result != ISC_R_SUCCESS) {
1214		fprintf(stderr, "\r\n");
1215		return (result);
1216	}
1217
1218	fprintf(stderr, ".");
1219	fflush(stderr);
1220
1221	return (result);
1222}
1223
1224isc_result_t
1225isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
1226			  const char *randomfile, int use_keyboard)
1227{
1228	isc_result_t result;
1229	isc_result_t final_result = ISC_R_NOENTROPY;
1230	isc_boolean_t userfile = ISC_TRUE;
1231
1232	REQUIRE(VALID_ENTROPY(ectx));
1233	REQUIRE(source != NULL && *source == NULL);
1234	REQUIRE(use_keyboard == ISC_ENTROPY_KEYBOARDYES ||
1235		use_keyboard == ISC_ENTROPY_KEYBOARDNO  ||
1236		use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
1237
1238#ifdef PATH_RANDOMDEV
1239	if (randomfile == NULL) {
1240		randomfile = PATH_RANDOMDEV;
1241		userfile = ISC_FALSE;
1242	}
1243#endif
1244
1245	if (randomfile != NULL && use_keyboard != ISC_ENTROPY_KEYBOARDYES) {
1246		result = isc_entropy_createfilesource(ectx, randomfile);
1247		if (result == ISC_R_SUCCESS &&
1248		    use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE)
1249			use_keyboard = ISC_ENTROPY_KEYBOARDNO;
1250		if (result != ISC_R_SUCCESS && userfile)
1251			return (result);
1252
1253		final_result = result;
1254	}
1255
1256	if (use_keyboard != ISC_ENTROPY_KEYBOARDNO) {
1257		result = isc_entropy_createcallbacksource(ectx, kbdstart,
1258							  kbdget, kbdstop,
1259							  NULL, source);
1260		if (result == ISC_R_SUCCESS)
1261			(*source)->warn_keyboard =
1262				ISC_TF(use_keyboard ==
1263				       ISC_ENTROPY_KEYBOARDMAYBE);
1264
1265		if (final_result != ISC_R_SUCCESS)
1266			final_result = result;
1267	}
1268
1269	/*
1270	 * final_result is ISC_R_SUCCESS if at least one source of entropy
1271	 * could be started, otherwise it is the error from the most recently
1272	 * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
1273	 * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
1274	 */
1275	return (final_result);
1276}
1277