1 /*
2  * Copyright (C) 2004-2007, 2009, 2010  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.22 2010/08/10 23:48:19 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 */
92 typedef 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 
100 struct 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 */
114 typedef 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 
123 typedef struct {
124 	sample_queue_t	samplequeue;
125 } isc_entropysamplesource_t;
126 
127 typedef 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 
136 typedef struct {
137 	FILESOURCE_HANDLE_TYPE handle;
138 } isc_entropyfilesource_t;
139 
140 struct 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  */
179 static void
180 fillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
181 
182 static int
183 wait_for_sources(isc_entropy_t *);
184 
185 static void
186 destroyfilesource(isc_entropyfilesource_t *source);
187 
188 static void
189 destroyusocketsource(isc_entropyusocketsource_t *source);
190 
191 /*@}*/
192 
193 static void
samplequeue_release(isc_entropy_t * ent,sample_queue_t * sq)194 samplequeue_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 
204 static isc_result_t
samplesource_allocate(isc_entropy_t * ent,sample_queue_t * sq)205 samplesource_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  */
226 static inline void
add_entropy(isc_entropy_t * ent,isc_uint32_t entropy)227 add_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  */
239 static inline void
subtract_entropy(isc_entropy_t * ent,isc_uint32_t entropy)240 subtract_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  */
249 static inline void
add_pseudo(isc_entropy_t * ent,isc_uint32_t pseudo)250 add_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  */
262 static inline void
subtract_pseudo(isc_entropy_t * ent,isc_uint32_t pseudo)263 subtract_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  */
271 static inline void
entropypool_add_word(isc_entropypool_t * rp,isc_uint32_t val)272 entropypool_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 	if (rp->rotate == 0)
287 		rp->pool[rp->cursor++] ^= val;
288 	else
289 		rp->pool[rp->cursor++] ^=
290 		  ((val << rp->rotate) | (val >> (32 - rp->rotate)));
291 
292 	/*
293 	 * If we have looped around the pool, increment the rotate
294 	 * variable so the next value will get xored in rotated to
295 	 * a different position.
296 	 * Increment by a value that is relatively prime to the word size
297 	 * to try to spread the bits throughout the pool quickly when the
298 	 * pool is empty.
299 	 */
300 	if (rp->cursor == RND_POOLWORDS) {
301 		rp->cursor = 0;
302 		rp->rotate = (rp->rotate + 7) & 31;
303 	}
304 }
305 
306 /*!
307  * Add a buffer's worth of data to the pool.
308  *
309  * Requires that the lock is held on the entropy pool.
310  */
311 static void
entropypool_adddata(isc_entropy_t * ent,void * p,unsigned int len,isc_uint32_t entropy)312 entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
313 		    isc_uint32_t entropy)
314 {
315 	isc_uint32_t val;
316 	unsigned long addr;
317 	isc_uint8_t *buf;
318 
319 	addr = (unsigned long)p;
320 	buf = p;
321 
322 	if ((addr & 0x03U) != 0U) {
323 		val = 0;
324 		switch (len) {
325 		case 3:
326 			val = *buf++;
327 			len--;
328 		case 2:
329 			val = val << 8 | *buf++;
330 			len--;
331 		case 1:
332 			val = val << 8 | *buf++;
333 			len--;
334 		}
335 
336 		entropypool_add_word(&ent->pool, val);
337 	}
338 
339 	for (; len > 3; len -= 4) {
340 		val = *((isc_uint32_t *)buf);
341 
342 		entropypool_add_word(&ent->pool, val);
343 		buf += 4;
344 	}
345 
346 	if (len != 0) {
347 		val = 0;
348 		switch (len) {
349 		case 3:
350 			val = *buf++;
351 		case 2:
352 			val = val << 8 | *buf++;
353 		case 1:
354 			val = val << 8 | *buf++;
355 		}
356 
357 		entropypool_add_word(&ent->pool, val);
358 	}
359 
360 	add_entropy(ent, entropy);
361 	subtract_pseudo(ent, entropy);
362 }
363 
364 static inline void
reseed(isc_entropy_t * ent)365 reseed(isc_entropy_t *ent) {
366 	isc_time_t t;
367 	pid_t pid;
368 
369 	if (ent->initcount == 0) {
370 		pid = getpid();
371 		entropypool_adddata(ent, &pid, sizeof(pid), 0);
372 		pid = getppid();
373 		entropypool_adddata(ent, &pid, sizeof(pid), 0);
374 	}
375 
376 	/*!
377 	 * After we've reseeded 100 times, only add new timing info every
378 	 * 50 requests.  This will keep us from using lots and lots of
379 	 * CPU just to return bad pseudorandom data anyway.
380 	 */
381 	if (ent->initcount > 100)
382 		if ((ent->initcount % 50) != 0)
383 			return;
384 
385 	TIME_NOW(&t);
386 	entropypool_adddata(ent, &t, sizeof(t), 0);
387 	ent->initcount++;
388 }
389 
390 static inline unsigned int
estimate_entropy(sample_queue_t * sq,isc_uint32_t t)391 estimate_entropy(sample_queue_t *sq, isc_uint32_t t) {
392 	isc_int32_t		delta;
393 	isc_int32_t		delta2;
394 	isc_int32_t		delta3;
395 
396 	/*!
397 	 * If the time counter has overflowed, calculate the real difference.
398 	 * If it has not, it is simpler.
399 	 */
400 	if (t < sq->last_time)
401 		delta = UINT_MAX - sq->last_time + t;
402 	else
403 		delta = sq->last_time - t;
404 
405 	if (delta < 0)
406 		delta = -delta;
407 
408 	/*
409 	 * Calculate the second and third order differentials
410 	 */
411 	delta2 = sq->last_delta - delta;
412 	if (delta2 < 0)
413 		delta2 = -delta2;
414 
415 	delta3 = sq->last_delta2 - delta2;
416 	if (delta3 < 0)
417 		delta3 = -delta3;
418 
419 	sq->last_time = t;
420 	sq->last_delta = delta;
421 	sq->last_delta2 = delta2;
422 
423 	/*
424 	 * If any delta is 0, we got no entropy.  If all are non-zero, we
425 	 * might have something.
426 	 */
427 	if (delta == 0 || delta2 == 0 || delta3 == 0)
428 		return 0;
429 
430 	/*
431 	 * We could find the smallest delta and claim we got log2(delta)
432 	 * bits, but for now return that we found 1 bit.
433 	 */
434 	return 1;
435 }
436 
437 static unsigned int
crunchsamples(isc_entropy_t * ent,sample_queue_t * sq)438 crunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
439 	unsigned int ns;
440 	unsigned int added;
441 
442 	if (sq->nsamples < 6)
443 		return (0);
444 
445 	added = 0;
446 	sq->last_time = sq->samples[0];
447 	sq->last_delta = 0;
448 	sq->last_delta2 = 0;
449 
450 	/*
451 	 * Prime the values by adding in the first 4 samples in.  This
452 	 * should completely initialize the delta calculations.
453 	 */
454 	for (ns = 0; ns < 4; ns++)
455 		(void)estimate_entropy(sq, sq->samples[ns]);
456 
457 	for (ns = 4; ns < sq->nsamples; ns++)
458 		added += estimate_entropy(sq, sq->samples[ns]);
459 
460 	entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
461 	entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
462 
463 	/*
464 	 * Move the last 4 samples into the first 4 positions, and start
465 	 * adding new samples from that point.
466 	 */
467 	for (ns = 0; ns < 4; ns++) {
468 		sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
469 		sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
470 	}
471 
472 	sq->nsamples = 4;
473 
474 	return (added);
475 }
476 
477 static unsigned int
get_from_callback(isc_entropysource_t * source,unsigned int desired,isc_boolean_t blocking)478 get_from_callback(isc_entropysource_t *source, unsigned int desired,
479 		  isc_boolean_t blocking)
480 {
481 	isc_entropy_t *ent = source->ent;
482 	isc_cbsource_t *cbs = &source->sources.callback;
483 	unsigned int added;
484 	unsigned int got;
485 	isc_result_t result;
486 
487 	if (desired == 0)
488 		return (0);
489 
490 	if (source->bad)
491 		return (0);
492 
493 	if (!cbs->start_called && cbs->startfunc != NULL) {
494 		result = cbs->startfunc(source, cbs->arg, blocking);
495 		if (result != ISC_R_SUCCESS)
496 			return (0);
497 		cbs->start_called = ISC_TRUE;
498 	}
499 
500 	added = 0;
501 	result = ISC_R_SUCCESS;
502 	while (desired > 0 && result == ISC_R_SUCCESS) {
503 		result = cbs->getfunc(source, cbs->arg, blocking);
504 		if (result == ISC_R_QUEUEFULL) {
505 			got = crunchsamples(ent, &cbs->samplequeue);
506 			added += got;
507 			desired -= ISC_MIN(got, desired);
508 			result = ISC_R_SUCCESS;
509 		} else if (result != ISC_R_SUCCESS &&
510 			   result != ISC_R_NOTBLOCKING)
511 			source->bad = ISC_TRUE;
512 
513 	}
514 
515 	return (added);
516 }
517 
518 /*
519  * Extract some number of bytes from the random pool, decreasing the
520  * estimate of randomness as each byte is extracted.
521  *
522  * Do this by stiring the pool and returning a part of hash as randomness.
523  * Note that no secrets are given away here since parts of the hash are
524  * xored together before returned.
525  *
526  * Honor the request from the caller to only return good data, any data,
527  * etc.
528  */
529 isc_result_t
isc_entropy_getdata(isc_entropy_t * ent,void * data,unsigned int length,unsigned int * returned,unsigned int flags)530 isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
531 		    unsigned int *returned, unsigned int flags)
532 {
533 	unsigned int i;
534 	isc_sha1_t hash;
535 	unsigned char digest[ISC_SHA1_DIGESTLENGTH];
536 	isc_uint32_t remain, deltae, count, total;
537 	isc_uint8_t *buf;
538 	isc_boolean_t goodonly, partial, blocking;
539 
540 	REQUIRE(VALID_ENTROPY(ent));
541 	REQUIRE(data != NULL);
542 	REQUIRE(length > 0);
543 
544 	goodonly = ISC_TF((flags & ISC_ENTROPY_GOODONLY) != 0);
545 	partial = ISC_TF((flags & ISC_ENTROPY_PARTIAL) != 0);
546 	blocking = ISC_TF((flags & ISC_ENTROPY_BLOCKING) != 0);
547 
548 	REQUIRE(!partial || returned != NULL);
549 
550 	LOCK(&ent->lock);
551 
552 	remain = length;
553 	buf = data;
554 	total = 0;
555 	while (remain != 0) {
556 		count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
557 
558 		/*
559 		 * If we are extracting good data only, make certain we
560 		 * have enough data in our pool for this pass.  If we don't,
561 		 * get some, and fail if we can't, and partial returns
562 		 * are not ok.
563 		 */
564 		if (goodonly) {
565 			unsigned int fillcount;
566 
567 			fillcount = ISC_MAX(remain * 8, count * 8);
568 
569 			/*
570 			 * If, however, we have at least THRESHOLD_BITS
571 			 * of entropy in the pool, don't block here.  It is
572 			 * better to drain the pool once in a while and
573 			 * then refill it than it is to constantly keep the
574 			 * pool full.
575 			 */
576 			if (ent->pool.entropy >= THRESHOLD_BITS)
577 				fillpool(ent, fillcount, ISC_FALSE);
578 			else
579 				fillpool(ent, fillcount, blocking);
580 
581 			/*
582 			 * Verify that we got enough entropy to do one
583 			 * extraction.  If we didn't, bail.
584 			 */
585 			if (ent->pool.entropy < THRESHOLD_BITS) {
586 				if (!partial)
587 					goto zeroize;
588 				else
589 					goto partial_output;
590 			}
591 		} else {
592 			/*
593 			 * If we've extracted half our pool size in bits
594 			 * since the last refresh, try to refresh here.
595 			 */
596 			if (ent->initialized < THRESHOLD_BITS)
597 				fillpool(ent, THRESHOLD_BITS, blocking);
598 			else
599 				fillpool(ent, 0, ISC_FALSE);
600 
601 			/*
602 			 * If we've not initialized with enough good random
603 			 * data, seed with our crappy code.
604 			 */
605 			if (ent->initialized < THRESHOLD_BITS)
606 				reseed(ent);
607 		}
608 
609 		isc_sha1_init(&hash);
610 		isc_sha1_update(&hash, (void *)(ent->pool.pool),
611 				RND_POOLBYTES);
612 		isc_sha1_final(&hash, digest);
613 
614 		/*
615 		 * Stir the extracted data (all of it) back into the pool.
616 		 */
617 		entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
618 
619 		for (i = 0; i < count; i++)
620 			buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
621 
622 		buf += count;
623 		remain -= count;
624 
625 		deltae = count * 8;
626 		deltae = ISC_MIN(deltae, ent->pool.entropy);
627 		total += deltae;
628 		subtract_entropy(ent, deltae);
629 		add_pseudo(ent, count * 8);
630 	}
631 
632  partial_output:
633 	memset(digest, 0, sizeof(digest));
634 
635 	if (returned != NULL)
636 		*returned = (length - remain);
637 
638 	UNLOCK(&ent->lock);
639 
640 	return (ISC_R_SUCCESS);
641 
642  zeroize:
643 	/* put the entropy we almost extracted back */
644 	add_entropy(ent, total);
645 	memset(data, 0, length);
646 	memset(digest, 0, sizeof(digest));
647 	if (returned != NULL)
648 		*returned = 0;
649 
650 	UNLOCK(&ent->lock);
651 
652 	return (ISC_R_NOENTROPY);
653 }
654 
655 static void
isc_entropypool_init(isc_entropypool_t * pool)656 isc_entropypool_init(isc_entropypool_t *pool) {
657 	pool->cursor = RND_POOLWORDS - 1;
658 	pool->entropy = 0;
659 	pool->pseudo = 0;
660 	pool->rotate = 0;
661 	memset(pool->pool, 0, RND_POOLBYTES);
662 }
663 
664 static void
isc_entropypool_invalidate(isc_entropypool_t * pool)665 isc_entropypool_invalidate(isc_entropypool_t *pool) {
666 	pool->cursor = 0;
667 	pool->entropy = 0;
668 	pool->pseudo = 0;
669 	pool->rotate = 0;
670 	memset(pool->pool, 0, RND_POOLBYTES);
671 }
672 
673 isc_result_t
isc_entropy_create(isc_mem_t * mctx,isc_entropy_t ** entp)674 isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
675 	isc_result_t result;
676 	isc_entropy_t *ent;
677 
678 	REQUIRE(mctx != NULL);
679 	REQUIRE(entp != NULL && *entp == NULL);
680 
681 	ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
682 	if (ent == NULL)
683 		return (ISC_R_NOMEMORY);
684 
685 	/*
686 	 * We need a lock.
687 	 */
688 	result = isc_mutex_init(&ent->lock);
689 	if (result != ISC_R_SUCCESS)
690 		goto errout;
691 
692 	/*
693 	 * From here down, no failures will/can occur.
694 	 */
695 	ISC_LIST_INIT(ent->sources);
696 	ent->nextsource = NULL;
697 	ent->nsources = 0;
698 	ent->mctx = NULL;
699 	isc_mem_attach(mctx, &ent->mctx);
700 	ent->refcnt = 1;
701 	ent->initialized = 0;
702 	ent->initcount = 0;
703 	ent->magic = ENTROPY_MAGIC;
704 
705 	isc_entropypool_init(&ent->pool);
706 
707 	*entp = ent;
708 	return (ISC_R_SUCCESS);
709 
710  errout:
711 	isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
712 
713 	return (result);
714 }
715 
716 /*!
717  * Requires "ent" be locked.
718  */
719 static void
destroysource(isc_entropysource_t ** sourcep)720 destroysource(isc_entropysource_t **sourcep) {
721 	isc_entropysource_t *source;
722 	isc_entropy_t *ent;
723 	isc_cbsource_t *cbs;
724 
725 	source = *sourcep;
726 	*sourcep = NULL;
727 	ent = source->ent;
728 
729 	ISC_LIST_UNLINK(ent->sources, source, link);
730 	ent->nextsource = NULL;
731 	REQUIRE(ent->nsources > 0);
732 	ent->nsources--;
733 
734 	switch (source->type) {
735 	case ENTROPY_SOURCETYPE_FILE:
736 		if (! source->bad)
737 			destroyfilesource(&source->sources.file);
738 		break;
739 	case ENTROPY_SOURCETYPE_USOCKET:
740 		if (! source->bad)
741 			destroyusocketsource(&source->sources.usocket);
742 		break;
743 	case ENTROPY_SOURCETYPE_SAMPLE:
744 		samplequeue_release(ent, &source->sources.sample.samplequeue);
745 		break;
746 	case ENTROPY_SOURCETYPE_CALLBACK:
747 		cbs = &source->sources.callback;
748 		if (cbs->start_called && cbs->stopfunc != NULL) {
749 			cbs->stopfunc(source, cbs->arg);
750 			cbs->start_called = ISC_FALSE;
751 		}
752 		samplequeue_release(ent, &cbs->samplequeue);
753 		break;
754 	}
755 
756 	memset(source, 0, sizeof(isc_entropysource_t));
757 
758 	isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
759 }
760 
761 static inline isc_boolean_t
destroy_check(isc_entropy_t * ent)762 destroy_check(isc_entropy_t *ent) {
763 	isc_entropysource_t *source;
764 
765 	if (ent->refcnt > 0)
766 		return (ISC_FALSE);
767 
768 	source = ISC_LIST_HEAD(ent->sources);
769 	while (source != NULL) {
770 		switch (source->type) {
771 		case ENTROPY_SOURCETYPE_FILE:
772 		case ENTROPY_SOURCETYPE_USOCKET:
773 			break;
774 		default:
775 			return (ISC_FALSE);
776 		}
777 		source = ISC_LIST_NEXT(source, link);
778 	}
779 
780 	return (ISC_TRUE);
781 }
782 
783 static void
destroy(isc_entropy_t ** entp)784 destroy(isc_entropy_t **entp) {
785 	isc_entropy_t *ent;
786 	isc_entropysource_t *source;
787 	isc_mem_t *mctx;
788 
789 	REQUIRE(entp != NULL && *entp != NULL);
790 	ent = *entp;
791 	*entp = NULL;
792 
793 	LOCK(&ent->lock);
794 
795 	REQUIRE(ent->refcnt == 0);
796 
797 	/*
798 	 * Here, detach non-sample sources.
799 	 */
800 	source = ISC_LIST_HEAD(ent->sources);
801 	while (source != NULL) {
802 		switch(source->type) {
803 		case ENTROPY_SOURCETYPE_FILE:
804 		case ENTROPY_SOURCETYPE_USOCKET:
805 			destroysource(&source);
806 			break;
807 		}
808 		source = ISC_LIST_HEAD(ent->sources);
809 	}
810 
811 	/*
812 	 * If there are other types of sources, we've found a bug.
813 	 */
814 	REQUIRE(ISC_LIST_EMPTY(ent->sources));
815 
816 	mctx = ent->mctx;
817 
818 	isc_entropypool_invalidate(&ent->pool);
819 
820 	UNLOCK(&ent->lock);
821 
822 	DESTROYLOCK(&ent->lock);
823 
824 	memset(ent, 0, sizeof(isc_entropy_t));
825 	isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
826 	isc_mem_detach(&mctx);
827 }
828 
829 void
isc_entropy_destroysource(isc_entropysource_t ** sourcep)830 isc_entropy_destroysource(isc_entropysource_t **sourcep) {
831 	isc_entropysource_t *source;
832 	isc_entropy_t *ent;
833 	isc_boolean_t killit;
834 
835 	REQUIRE(sourcep != NULL);
836 	REQUIRE(VALID_SOURCE(*sourcep));
837 
838 	source = *sourcep;
839 	*sourcep = NULL;
840 
841 	ent = source->ent;
842 	REQUIRE(VALID_ENTROPY(ent));
843 
844 	LOCK(&ent->lock);
845 
846 	destroysource(&source);
847 
848 	killit = destroy_check(ent);
849 
850 	UNLOCK(&ent->lock);
851 
852 	if (killit)
853 		destroy(&ent);
854 }
855 
856 isc_result_t
isc_entropy_createcallbacksource(isc_entropy_t * ent,isc_entropystart_t start,isc_entropyget_t get,isc_entropystop_t stop,void * arg,isc_entropysource_t ** sourcep)857 isc_entropy_createcallbacksource(isc_entropy_t *ent,
858 				 isc_entropystart_t start,
859 				 isc_entropyget_t get,
860 				 isc_entropystop_t stop,
861 				 void *arg,
862 				 isc_entropysource_t **sourcep)
863 {
864 	isc_result_t result;
865 	isc_entropysource_t *source;
866 	isc_cbsource_t *cbs;
867 
868 	REQUIRE(VALID_ENTROPY(ent));
869 	REQUIRE(get != NULL);
870 	REQUIRE(sourcep != NULL && *sourcep == NULL);
871 
872 	LOCK(&ent->lock);
873 
874 	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
875 	if (source == NULL) {
876 		result = ISC_R_NOMEMORY;
877 		goto errout;
878 	}
879 	source->bad = ISC_FALSE;
880 
881 	cbs = &source->sources.callback;
882 
883 	result = samplesource_allocate(ent, &cbs->samplequeue);
884 	if (result != ISC_R_SUCCESS)
885 		goto errout;
886 
887 	cbs->start_called = ISC_FALSE;
888 	cbs->startfunc = start;
889 	cbs->getfunc = get;
890 	cbs->stopfunc = stop;
891 	cbs->arg = arg;
892 
893 	/*
894 	 * From here down, no failures can occur.
895 	 */
896 	source->magic = SOURCE_MAGIC;
897 	source->type = ENTROPY_SOURCETYPE_CALLBACK;
898 	source->ent = ent;
899 	source->total = 0;
900 	memset(source->name, 0, sizeof(source->name));
901 	ISC_LINK_INIT(source, link);
902 
903 	/*
904 	 * Hook it into the entropy system.
905 	 */
906 	ISC_LIST_APPEND(ent->sources, source, link);
907 	ent->nsources++;
908 
909 	*sourcep = source;
910 
911 	UNLOCK(&ent->lock);
912 	return (ISC_R_SUCCESS);
913 
914  errout:
915 	if (source != NULL)
916 		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
917 
918 	UNLOCK(&ent->lock);
919 
920 	return (result);
921 }
922 
923 void
isc_entropy_stopcallbacksources(isc_entropy_t * ent)924 isc_entropy_stopcallbacksources(isc_entropy_t *ent) {
925 	isc_entropysource_t *source;
926 	isc_cbsource_t *cbs;
927 
928 	REQUIRE(VALID_ENTROPY(ent));
929 
930 	LOCK(&ent->lock);
931 
932 	source = ISC_LIST_HEAD(ent->sources);
933 	while (source != NULL) {
934 		if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
935 			cbs = &source->sources.callback;
936 			if (cbs->start_called && cbs->stopfunc != NULL) {
937 				cbs->stopfunc(source, cbs->arg);
938 				cbs->start_called = ISC_FALSE;
939 			}
940 		}
941 
942 		source = ISC_LIST_NEXT(source, link);
943 	}
944 
945 	UNLOCK(&ent->lock);
946 }
947 
948 isc_result_t
isc_entropy_createsamplesource(isc_entropy_t * ent,isc_entropysource_t ** sourcep)949 isc_entropy_createsamplesource(isc_entropy_t *ent,
950 			       isc_entropysource_t **sourcep)
951 {
952 	isc_result_t result;
953 	isc_entropysource_t *source;
954 	sample_queue_t *sq;
955 
956 	REQUIRE(VALID_ENTROPY(ent));
957 	REQUIRE(sourcep != NULL && *sourcep == NULL);
958 
959 	LOCK(&ent->lock);
960 
961 	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
962 	if (source == NULL) {
963 		result = ISC_R_NOMEMORY;
964 		goto errout;
965 	}
966 
967 	sq = &source->sources.sample.samplequeue;
968 	result = samplesource_allocate(ent, sq);
969 	if (result != ISC_R_SUCCESS)
970 		goto errout;
971 
972 	/*
973 	 * From here down, no failures can occur.
974 	 */
975 	source->magic = SOURCE_MAGIC;
976 	source->type = ENTROPY_SOURCETYPE_SAMPLE;
977 	source->ent = ent;
978 	source->total = 0;
979 	memset(source->name, 0, sizeof(source->name));
980 	ISC_LINK_INIT(source, link);
981 
982 	/*
983 	 * Hook it into the entropy system.
984 	 */
985 	ISC_LIST_APPEND(ent->sources, source, link);
986 	ent->nsources++;
987 
988 	*sourcep = source;
989 
990 	UNLOCK(&ent->lock);
991 	return (ISC_R_SUCCESS);
992 
993  errout:
994 	if (source != NULL)
995 		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
996 
997 	UNLOCK(&ent->lock);
998 
999 	return (result);
1000 }
1001 
1002 /*!
1003  * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
1004  * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
1005  * queue was full when this function was called.
1006  */
1007 static isc_result_t
addsample(sample_queue_t * sq,isc_uint32_t sample,isc_uint32_t extra)1008 addsample(sample_queue_t *sq, isc_uint32_t sample, isc_uint32_t extra) {
1009 	if (sq->nsamples >= RND_EVENTQSIZE)
1010 		return (ISC_R_NOMORE);
1011 
1012 	sq->samples[sq->nsamples] = sample;
1013 	sq->extra[sq->nsamples] = extra;
1014 	sq->nsamples++;
1015 
1016 	if (sq->nsamples >= RND_EVENTQSIZE)
1017 		return (ISC_R_QUEUEFULL);
1018 
1019 	return (ISC_R_SUCCESS);
1020 }
1021 
1022 isc_result_t
isc_entropy_addsample(isc_entropysource_t * source,isc_uint32_t sample,isc_uint32_t extra)1023 isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
1024 		      isc_uint32_t extra)
1025 {
1026 	isc_entropy_t *ent;
1027 	sample_queue_t *sq;
1028 	unsigned int entropy;
1029 	isc_result_t result;
1030 
1031 	REQUIRE(VALID_SOURCE(source));
1032 
1033 	ent = source->ent;
1034 
1035 	LOCK(&ent->lock);
1036 
1037 	sq = &source->sources.sample.samplequeue;
1038 	result = addsample(sq, sample, extra);
1039 	if (result == ISC_R_QUEUEFULL) {
1040 		entropy = crunchsamples(ent, sq);
1041 		add_entropy(ent, entropy);
1042 	}
1043 
1044 	UNLOCK(&ent->lock);
1045 
1046 	return (result);
1047 }
1048 
1049 isc_result_t
isc_entropy_addcallbacksample(isc_entropysource_t * source,isc_uint32_t sample,isc_uint32_t extra)1050 isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
1051 			      isc_uint32_t extra)
1052 {
1053 	sample_queue_t *sq;
1054 	isc_result_t result;
1055 
1056 	REQUIRE(VALID_SOURCE(source));
1057 	REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
1058 
1059 	sq = &source->sources.callback.samplequeue;
1060 	result = addsample(sq, sample, extra);
1061 
1062 	return (result);
1063 }
1064 
1065 void
isc_entropy_putdata(isc_entropy_t * ent,void * data,unsigned int length,isc_uint32_t entropy)1066 isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
1067 		    isc_uint32_t entropy)
1068 {
1069 	REQUIRE(VALID_ENTROPY(ent));
1070 
1071 	LOCK(&ent->lock);
1072 
1073 	entropypool_adddata(ent, data, length, entropy);
1074 
1075 	if (ent->initialized < THRESHOLD_BITS)
1076 		ent->initialized = THRESHOLD_BITS;
1077 
1078 	UNLOCK(&ent->lock);
1079 }
1080 
1081 static void
dumpstats(isc_entropy_t * ent,FILE * out)1082 dumpstats(isc_entropy_t *ent, FILE *out) {
1083 	fprintf(out,
1084 		isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
1085 			       ISC_MSG_ENTROPYSTATS,
1086 			       "Entropy pool %p:  refcnt %u cursor %u,"
1087 			       " rotate %u entropy %u pseudo %u nsources %u"
1088 			       " nextsource %p initialized %u initcount %u\n"),
1089 		ent, ent->refcnt,
1090 		ent->pool.cursor, ent->pool.rotate,
1091 		ent->pool.entropy, ent->pool.pseudo,
1092 		ent->nsources, ent->nextsource, ent->initialized,
1093 		ent->initcount);
1094 }
1095 
1096 /*
1097  * This function ignores locking.  Use at your own risk.
1098  */
1099 void
isc_entropy_stats(isc_entropy_t * ent,FILE * out)1100 isc_entropy_stats(isc_entropy_t *ent, FILE *out) {
1101 	REQUIRE(VALID_ENTROPY(ent));
1102 
1103 	LOCK(&ent->lock);
1104 	dumpstats(ent, out);
1105 	UNLOCK(&ent->lock);
1106 }
1107 
1108 unsigned int
isc_entropy_status(isc_entropy_t * ent)1109 isc_entropy_status(isc_entropy_t *ent) {
1110 	unsigned int estimate;
1111 
1112 	LOCK(&ent->lock);
1113 	estimate = ent->pool.entropy;
1114 	UNLOCK(&ent->lock);
1115 
1116 	return estimate;
1117 }
1118 
1119 void
isc_entropy_attach(isc_entropy_t * ent,isc_entropy_t ** entp)1120 isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
1121 	REQUIRE(VALID_ENTROPY(ent));
1122 	REQUIRE(entp != NULL && *entp == NULL);
1123 
1124 	LOCK(&ent->lock);
1125 
1126 	ent->refcnt++;
1127 	*entp = ent;
1128 
1129 	UNLOCK(&ent->lock);
1130 }
1131 
1132 void
isc_entropy_detach(isc_entropy_t ** entp)1133 isc_entropy_detach(isc_entropy_t **entp) {
1134 	isc_entropy_t *ent;
1135 	isc_boolean_t killit;
1136 
1137 	REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
1138 	ent = *entp;
1139 	*entp = NULL;
1140 
1141 	LOCK(&ent->lock);
1142 
1143 	REQUIRE(ent->refcnt > 0);
1144 	ent->refcnt--;
1145 
1146 	killit = destroy_check(ent);
1147 
1148 	UNLOCK(&ent->lock);
1149 
1150 	if (killit)
1151 		destroy(&ent);
1152 }
1153 
1154 static isc_result_t
kbdstart(isc_entropysource_t * source,void * arg,isc_boolean_t blocking)1155 kbdstart(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
1156 	/*
1157 	 * The intent of "first" is to provide a warning message only once
1158 	 * during the run of a program that might try to gather keyboard
1159 	 * entropy multiple times.
1160 	 */
1161 	static isc_boolean_t first = ISC_TRUE;
1162 
1163 	UNUSED(arg);
1164 
1165 	if (! blocking)
1166 		return (ISC_R_NOENTROPY);
1167 
1168 	if (first) {
1169 		if (source->warn_keyboard)
1170 			fprintf(stderr, "You must use the keyboard to create "
1171 				"entropy, since your system is lacking\n"
1172 				"/dev/random (or equivalent)\n\n");
1173 		first = ISC_FALSE;
1174 	}
1175 	fprintf(stderr, "start typing:\n");
1176 
1177 	return (isc_keyboard_open(&source->kbd));
1178 }
1179 
1180 static void
kbdstop(isc_entropysource_t * source,void * arg)1181 kbdstop(isc_entropysource_t *source, void *arg) {
1182 
1183 	UNUSED(arg);
1184 
1185 	if (! isc_keyboard_canceled(&source->kbd))
1186 		fprintf(stderr, "stop typing.\r\n");
1187 
1188 	(void)isc_keyboard_close(&source->kbd, 3);
1189 }
1190 
1191 static isc_result_t
kbdget(isc_entropysource_t * source,void * arg,isc_boolean_t blocking)1192 kbdget(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
1193 	isc_result_t result;
1194 	isc_time_t t;
1195 	isc_uint32_t sample;
1196 	isc_uint32_t extra;
1197 	unsigned char c;
1198 
1199 	UNUSED(arg);
1200 
1201 	if (!blocking)
1202 		return (ISC_R_NOTBLOCKING);
1203 
1204 	result = isc_keyboard_getchar(&source->kbd, &c);
1205 	if (result != ISC_R_SUCCESS)
1206 		return (result);
1207 
1208 	TIME_NOW(&t);
1209 
1210 	sample = isc_time_nanoseconds(&t);
1211 	extra = c;
1212 
1213 	result = isc_entropy_addcallbacksample(source, sample, extra);
1214 	if (result != ISC_R_SUCCESS) {
1215 		fprintf(stderr, "\r\n");
1216 		return (result);
1217 	}
1218 
1219 	fprintf(stderr, ".");
1220 	fflush(stderr);
1221 
1222 	return (result);
1223 }
1224 
1225 isc_result_t
isc_entropy_usebestsource(isc_entropy_t * ectx,isc_entropysource_t ** source,const char * randomfile,int use_keyboard)1226 isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
1227 			  const char *randomfile, int use_keyboard)
1228 {
1229 	isc_result_t result;
1230 	isc_result_t final_result = ISC_R_NOENTROPY;
1231 	isc_boolean_t userfile = ISC_TRUE;
1232 
1233 	REQUIRE(VALID_ENTROPY(ectx));
1234 	REQUIRE(source != NULL && *source == NULL);
1235 	REQUIRE(use_keyboard == ISC_ENTROPY_KEYBOARDYES ||
1236 		use_keyboard == ISC_ENTROPY_KEYBOARDNO  ||
1237 		use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
1238 
1239 #ifdef PATH_RANDOMDEV
1240 	if (randomfile == NULL) {
1241 		randomfile = PATH_RANDOMDEV;
1242 		userfile = ISC_FALSE;
1243 	}
1244 #endif
1245 
1246 	if (randomfile != NULL && use_keyboard != ISC_ENTROPY_KEYBOARDYES) {
1247 		result = isc_entropy_createfilesource(ectx, randomfile);
1248 		if (result == ISC_R_SUCCESS &&
1249 		    use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE)
1250 			use_keyboard = ISC_ENTROPY_KEYBOARDNO;
1251 		if (result != ISC_R_SUCCESS && userfile)
1252 			return (result);
1253 
1254 		final_result = result;
1255 	}
1256 
1257 	if (use_keyboard != ISC_ENTROPY_KEYBOARDNO) {
1258 		result = isc_entropy_createcallbacksource(ectx, kbdstart,
1259 							  kbdget, kbdstop,
1260 							  NULL, source);
1261 		if (result == ISC_R_SUCCESS)
1262 			(*source)->warn_keyboard =
1263 				ISC_TF(use_keyboard ==
1264 				       ISC_ENTROPY_KEYBOARDMAYBE);
1265 
1266 		if (final_result != ISC_R_SUCCESS)
1267 			final_result = result;
1268 	}
1269 
1270 	/*
1271 	 * final_result is ISC_R_SUCCESS if at least one source of entropy
1272 	 * could be started, otherwise it is the error from the most recently
1273 	 * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
1274 	 * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
1275 	 */
1276 	return (final_result);
1277 }
1278