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