PageRenderTime 144ms CodeModel.GetById 84ms app.highlight 51ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/bind9/lib/isc/entropy.c

https://bitbucket.org/freebsd/freebsd-head/
C | 1277 lines | 823 code | 234 blank | 220 comment | 170 complexity | b85226294bc3e4c735e5bac93a513575 MD5 | raw file
   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 */
  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	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 */
 311static void
 312entropypool_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
 364static inline void
 365reseed(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
 390static inline unsigned int
 391estimate_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
 437static unsigned int
 438crunchsamples(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
 477static unsigned int
 478get_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 */
 529isc_result_t
 530isc_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
 655static void
 656isc_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
 664static void
 665isc_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
 673isc_result_t
 674isc_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 */
 719static void
 720destroysource(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
 761static inline isc_boolean_t
 762destroy_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
 783static void
 784destroy(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
 829void
 830isc_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
 856isc_result_t
 857isc_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
 923void
 924isc_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
 948isc_result_t
 949isc_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 */
1007static isc_result_t
1008addsample(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
1022isc_result_t
1023isc_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
1049isc_result_t
1050isc_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
1065void
1066isc_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
1081static void
1082dumpstats(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 */
1099void
1100isc_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
1108unsigned int
1109isc_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
1119void
1120isc_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
1132void
1133isc_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
1154static isc_result_t
1155kbdstart(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
1180static void
1181kbdstop(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
1191static isc_result_t
1192kbdget(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
1225isc_result_t
1226isc_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}