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