entropy.c revision ee303f481dfefcd4e4994f8b8b17f2de32aa4d69
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/*
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 2000 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Permission to use, copy, modify, and distribute this software for any
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * purpose with or without fee is hereby granted, provided that the above
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15a44745412679c30a6d022733925af70a38b715David Lawrence * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15a44745412679c30a6d022733925af70a38b715David Lawrence * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson/* $Id: entropy.c,v 1.54 2000/12/27 00:11:26 bwelling Exp $ */
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff#include <config.h>
de153390f5a1f6d4fa86af91d4cae772d9846ca0Mark Andrews
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff#include <sys/types.h>
822f6cdabb1edd44472c7a758b5cae71376fa9beBrian Wellington#include <sys/time.h>
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <errno.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <fcntl.h>
25a66b4e41e2b0a2af4840749bac80ae78c678bfMark Andrews#include <stdio.h>
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#include <unistd.h>
973a19342597823f111fce6a8cd5adfd0e2e7c0dMark Andrews
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff#include <isc/buffer.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/entropy.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/list.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/magic.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/mem.h>
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington#include <isc/msgs.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/mutex.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <isc/region.h>
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews#include <isc/sha1.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/string.h>
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews#include <isc/time.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/util.h>
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson/*
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * Much of this code is modeled after the NetBSD /dev/random implementation,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * written by Michael Graff <explorer@netbsd.org>.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define ENTROPY_MAGIC ISC_MAGIC('E', 'n', 't', 'e')
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define SOURCE_MAGIC ISC_MAGIC('E', 'n', 't', 's')
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define VALID_ENTROPY(e) ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define VALID_SOURCE(s) ISC_MAGIC_VALID(s, SOURCE_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews/***
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews *** "constants." Do not change these unless you _really_ know what
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews *** you are doing.
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews ***/
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews/*
eb6bd543c7d072efdca509eb17f8f301c1467b53Mark Andrews * size of entropy pool in 32-bit words. This _MUST_ be a power of 2.
deaaf94332abbfdb3aff53675546acfed16e5eb6Mark Andrews */
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence#define RND_POOLWORDS 128
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define RND_POOLBITS (RND_POOLWORDS * 32)
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews/*
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Number of bytes returned per hash. This must be true:
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * threshold * 2 <= digest_size_in_bytes
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define RND_ENTROPY_THRESHOLD 10
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence#define THRESHOLD_BITS (RND_ENTROPY_THRESHOLD * 8)
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence/*
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Size of the input event queue in samples.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define RND_EVENTQSIZE 32
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence/*
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * The number of times we'll "reseed" for pseudorandom seeds. This is an
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence * extremely weak pseudorandom seed. If the caller is using lots of
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * pseudorandom data and they cannot provide a stronger random source,
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * there is little we can do other than hope they're smart enough to
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * call _adddata() with something better than we can come up with.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define RND_INITIALIZE 128
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencetypedef struct {
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_uint32_t magic;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_uint32_t cursor; /* current add point in the pool */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_uint32_t entropy; /* current entropy estimate in bits */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_uint32_t pseudo; /* bits extracted in pseudorandom */
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_uint32_t rotate; /* how many bits to rotate by */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_uint32_t pool[RND_POOLWORDS]; /* random pool data */
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson} isc_entropypool_t;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssonstruct isc_entropy {
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_uint32_t magic;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_mem_t *mctx;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_mutex_t lock;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson unsigned int refcnt;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_uint32_t initialized;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_uint32_t initcount;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_entropypool_t pool;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int nsources;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropysource_t *nextsource;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ISC_LIST(isc_entropysource_t) sources;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence};
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencetypedef struct {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t last_time; /* last time recorded */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t last_delta; /* last delta value */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t last_delta2; /* last delta2 value */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t nsamples; /* number of samples filled in */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t *samples; /* the samples */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t *extra; /* extra samples added in */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence} sample_queue_t;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencetypedef struct {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence sample_queue_t samplequeue;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence} isc_entropysamplesource_t;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellingtontypedef struct {
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington isc_boolean_t start_called;
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington isc_entropystart_t startfunc;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropyget_t getfunc;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropystop_t stopfunc;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence void *arg;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence sample_queue_t samplequeue;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence} isc_cbsource_t;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencetypedef struct {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence int fd; /* fd for the file, or -1 if closed */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence} isc_entropyfilesource_t;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestruct isc_entropysource {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t magic;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int type;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropy_t *ent;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_uint32_t total; /* entropy from this source */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ISC_LINK(isc_entropysource_t) link;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence char name[32];
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_boolean_t bad;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence union {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropysamplesource_t sample;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropyfilesource_t file;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_cbsource_t callback;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence } sources;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence};
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define ENTROPY_SOURCETYPE_SAMPLE 1 /* Type is a sample source */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define ENTROPY_SOURCETYPE_FILE 2 /* Type is a file source */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define ENTROPY_SOURCETYPE_CALLBACK 3 /* Type is a callback source */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence/*
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * The random pool "taps"
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define TAP1 99
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define TAP2 59
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define TAP3 31
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define TAP4 9
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#define TAP5 7
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic inline void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrenceentropypool_add_word(isc_entropypool_t *, isc_uint32_t);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencefillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic int
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencewait_for_sources(isc_entropy_t *);
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafssonstatic unsigned int
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencecrunchsamples(isc_entropy_t *, sample_queue_t *sq);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic inline void
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencereseed(isc_entropy_t *ent);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic void
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrewssamplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) {
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews REQUIRE(sq->samples != NULL);
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews REQUIRE(sq->extra != NULL);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_put(ent->mctx, sq->extra, RND_EVENTQSIZE * 4);
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson sq->samples = NULL;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews sq->extra = NULL;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews}
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrewsstatic isc_result_t
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrewssamplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) {
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews sq->samples = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews if (sq->samples == NULL)
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews return (ISC_R_NOMEMORY);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews sq->extra = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews if (sq->extra == NULL) {
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews sq->samples = NULL;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews return (ISC_R_NOMEMORY);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews }
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews sq->nsamples = 0;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews return (ISC_R_SUCCESS);
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews}
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews/*
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews * Add in entropy, even when the value we're adding in could be
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington * very large.
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrewsstatic inline void
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrewsadd_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews /* clamp input. Yes, this must be done. */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews entropy = ISC_MIN(entropy, RND_POOLBITS);
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews /* Add in the entropy we already have. */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews entropy += ent->pool.entropy;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews /* Clamp. */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS);
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews}
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews/*
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews * Decrement the amount of entropy the pool has.
f6407f9a0b890bebbfd5f738d9c4aef3d3315fe9Michael Graff */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrewsstatic inline void
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrewssubtract_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews entropy = ISC_MIN(entropy, ent->pool.entropy);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews ent->pool.entropy -= entropy;
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Add in entropy, even when the value we're adding in could be
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrews * very large.
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrews */
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrewsstatic inline void
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrewsadd_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews /* clamp input. Yes, this must be done. */
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews /* Add in the pseudo we already have. */
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews pseudo += ent->pool.pseudo;
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews /* Clamp. */
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews}
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews/*
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews * Decrement the amount of pseudo the pool has.
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews */
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellingtonstatic inline void
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellingtonsubtract_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington pseudo = ISC_MIN(pseudo, ent->pool.pseudo);
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews ent->pool.pseudo -= pseudo;
613991eef6bb79b9703382aff26cddd0281da915Bob Halley}
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews/*
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington * Add one word to the pool, rotating the input as needed.
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington */
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellingtonstatic inline void
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellingtonentropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) {
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington /*
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington * Steal some values out of the pool, and xor them into the
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington * word we were given.
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington *
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington * Mix the new value into the pool using xor. This will
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington * prevent the actual values from being known to the caller
87ecd67dae468cf5c9bae213c6fa321449b2ebc2Andreas Gustafsson * since the previous values are assumed to be unknown as well.
87ecd67dae468cf5c9bae213c6fa321449b2ebc2Andreas Gustafsson */
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews val ^= rp->pool[(rp->cursor + TAP1) & (RND_POOLWORDS - 1)];
87ecd67dae468cf5c9bae213c6fa321449b2ebc2Andreas Gustafsson val ^= rp->pool[(rp->cursor + TAP2) & (RND_POOLWORDS - 1)];
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews rp->pool[rp->cursor++] ^=
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews ((val << rp->rotate) | (val >> (32 - rp->rotate)));
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews
36e37042c6c9252cdf6eb99bd71ccb6e6c43ba6dBrian Wellington /*
bcd7fdf06ca76eb2f6eb157f56b612c503e062a7Mark Andrews * If we have looped around the pool, increment the rotate
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews * variable so the next value will get xored in rotated to
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington * a different position.
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington * Increment by a value that is relativly prime to the word size
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington * to try to spread the bits throughout the pool quickly when the
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington * pool is empty.
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington */
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington if (rp->cursor == RND_POOLWORDS) {
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington rp->cursor = 0;
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington rp->rotate = (rp->rotate + 7) & 31;
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews }
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews}
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson/*
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Add a buffer's worth of data to the pool.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson *
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Requires that the lock is held on the entropy pool.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonstatic void
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonentropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_uint32_t entropy)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson{
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews isc_uint32_t val;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff unsigned long addr;
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews isc_uint8_t *buf;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence addr = (unsigned long)p;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff buf = p;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington if ((addr & 0x03) != 0) {
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington val = 0;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff switch (len) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff case 3:
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff val = *buf++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson len--;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson case 2:
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence val = val << 8 | *buf++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson len--;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson case 1:
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson val = val << 8 | *buf++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson len--;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson entropypool_add_word(&ent->pool, val);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson for (; len > 3 ; len -= 4) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson val = *((isc_uint32_t *)buf);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson entropypool_add_word(&ent->pool, val);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson buf += 4;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if (len != 0) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson val = 0;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson switch (len) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson case 3:
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson val = *buf++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson case 2:
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson val = val << 8 | *buf++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson case 1:
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson val = val << 8 | *buf++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson entropypool_add_word(&ent->pool, val);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson add_entropy(ent, entropy);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson subtract_pseudo(ent, entropy);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson}
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic inline void
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonreseed(isc_entropy_t *ent) {
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews isc_result_t result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_time_t t;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews pid_t pid;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ent->initcount == 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews pid = getpid();
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews entropypool_adddata(ent, &pid, sizeof pid, 0);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews pid = getppid();
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews entropypool_adddata(ent, &pid, sizeof pid, 0);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * After we've reseeded 100 times, only add new timing info every
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * 50 requests. This will keep us from using lots and lots of
e6bd97dded968f82e26b270842b789bff7bca422Mark Andrews * CPU just to return bad pseudorandom data anyway.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ent->initcount > 100)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if ((ent->initcount % 50) != 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return;
5d2026ea7b5ae43bbd69d98b747f75ba3290bef1Mark Andrews
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington result = isc_time_now(&t);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (result == ISC_R_SUCCESS) {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews entropypool_adddata(ent, &t, sizeof t, 0);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews ent->initcount++;
5d2026ea7b5ae43bbd69d98b747f75ba3290bef1Mark Andrews }
6c29053a20f7614167bafa4388c666644a095349Andreas Gustafsson}
5d2026ea7b5ae43bbd69d98b747f75ba3290bef1Mark Andrews
5d2026ea7b5ae43bbd69d98b747f75ba3290bef1Mark Andrewsstatic unsigned int
6c29053a20f7614167bafa4388c666644a095349Andreas Gustafssonget_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
6c29053a20f7614167bafa4388c666644a095349Andreas Gustafsson isc_entropy_t *ent = source->ent;
5d2026ea7b5ae43bbd69d98b747f75ba3290bef1Mark Andrews unsigned char buf[128];
5f7a9845e900bc491db9feab137895721073631fMark Andrews int fd = source->sources.file.fd;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews ssize_t n, ndesired;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews unsigned int added;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews if (source->bad)
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews return (0);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews added = 0;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews while (desired > 0) {
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews ndesired = ISC_MIN(desired, sizeof(buf));
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews n = read(fd, buf, ndesired);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews if (n < 0) {
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews if (errno == EAGAIN)
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews goto out;
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews close(fd);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews source->bad = ISC_TRUE;
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews goto out;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (n == 0) {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews close(fd);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews source->bad = ISC_TRUE;
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews goto out;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington entropypool_adddata(ent, buf, n, n * 8);
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington added += n * 8;
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington desired -= n;
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews out:
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews return (added);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews}
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic unsigned int
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsget_from_callback(isc_entropysource_t *source, unsigned int desired,
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews isc_boolean_t blocking)
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews{
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews isc_entropy_t *ent = source->ent;
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews isc_cbsource_t *cbs = &source->sources.callback;
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews unsigned int added;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned int got;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_result_t result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (desired == 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (0);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews if (source->bad)
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews return (0);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (!cbs->start_called && cbs->startfunc != NULL) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = cbs->startfunc(source, cbs->arg, blocking);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (0);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews cbs->start_called = ISC_TRUE;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley added = 0;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley result = ISC_R_SUCCESS;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews while (desired > 0 && result == ISC_R_SUCCESS) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = cbs->getfunc(source, cbs->arg, blocking);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result == ISC_R_QUEUEFULL) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews got = crunchsamples(ent, &cbs->samplequeue);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews added += got;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews desired -= ISC_MIN(got, desired);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews result = ISC_R_SUCCESS;
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews } else if (result != ISC_R_SUCCESS &&
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews result != ISC_R_NOTBLOCKING)
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews source->bad = ISC_TRUE;
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews }
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (added);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Poll each source, trying to get data from it to stuff into the entropy
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * pool.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic void
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsfillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley unsigned int added;
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews unsigned int remaining;
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews unsigned int needed;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence unsigned int nsource;
19d365e4448f1782611280b020987988b7ac3210Mark Andrews isc_entropysource_t *source;
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington
19d365e4448f1782611280b020987988b7ac3210Mark Andrews REQUIRE(VALID_ENTROPY(ent));
19d365e4448f1782611280b020987988b7ac3210Mark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews needed = desired;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * This logic is a little strange, so an explanation is in order.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley *
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * If needed is 0, it means we are being asked to "fill to whatever
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * we think is best." This means that if we have at least a
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * partially full pool (say, > 1/4th of the pool) we probably don't
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * need to add anything.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Also, we will check to see if the "pseudo" count is too high.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * If it is, try to mix in better data. Too high is currently
19d365e4448f1782611280b020987988b7ac3210Mark Andrews * defined as 1/4th of the pool.
19d365e4448f1782611280b020987988b7ac3210Mark Andrews *
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * Next, if we are asked to add a specific bit of entropy, make
19d365e4448f1782611280b020987988b7ac3210Mark Andrews * certain that we will do so. Clamp how much we try to add to
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Note that if we are in a blocking mode, we will only try to
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * get as much data as we need, not as much as we might want
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * to build up.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley */
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews if (needed == 0) {
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews REQUIRE(!blocking);
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews if ((ent->pool.entropy >= RND_POOLBITS / 4)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff && (ent->pool.pseudo <= RND_POOLBITS / 4))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews needed = THRESHOLD_BITS * 4;
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews } else {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews needed = ISC_MAX(needed, THRESHOLD_BITS);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews needed = ISC_MIN(needed, RND_POOLBITS);
19d365e4448f1782611280b020987988b7ac3210Mark Andrews }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington /*
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * In any case, clamp how much we need to how much we can add.
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews */
19d365e4448f1782611280b020987988b7ac3210Mark Andrews needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson /*
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson * But wait! If we're not yet initialized, we need at least
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * THRESHOLD_BITS
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * of randomness.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (ent->initialized < THRESHOLD_BITS)
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Poll each file source to see if we can read anything useful from
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews * it. XXXMLG When where are multiple sources, we should keep a
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews * record of which one we last used so we can start from it (or the
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews * next one) to avoid letting some sources build up entropy while
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews * others are always drained.
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews */
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews added = 0;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews remaining = needed;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (ent->nextsource == NULL) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews ent->nextsource = ISC_LIST_HEAD(ent->sources);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ent->nextsource == NULL)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence return;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence }
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence source = ent->nextsource;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff again_file:
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews for (nsource = 0 ; nsource < ent->nsources ; nsource++) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned int got;
ad7209ea70d346527ffdcda335153831341d9dcfAndreas Gustafsson
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews if (remaining == 0)
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews break;
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley got = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (source->type == ENTROPY_SOURCETYPE_FILE)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff got = get_from_filesource(source, remaining);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews added += got;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews remaining -= ISC_MIN(remaining, got);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews source = ISC_LIST_NEXT(source, link);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (source == NULL)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews source = ISC_LIST_HEAD(ent->sources);
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews#if 0
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (added >= needed)
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews break;
f0a5bb8f86631ce638cb2b6c65bbb9bcf9b0cdc0Bob Halley#endif
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ent->nextsource = source;
19d365e4448f1782611280b020987988b7ac3210Mark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (blocking && remaining != 0) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence int fds;
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson fds = wait_for_sources(ent);
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson if (fds > 0)
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson goto again_file;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson /*
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * Here, if there are bits remaining to be had and we can block,
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson * check to see if we have a callback source. If so, call them.
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews */
19d365e4448f1782611280b020987988b7ac3210Mark Andrews source = ISC_LIST_HEAD(ent->sources);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews while ((remaining != 0) && (source != NULL)) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence unsigned int got;
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence got = 0;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
f0a5bb8f86631ce638cb2b6c65bbb9bcf9b0cdc0Bob Halley got = get_from_callback(source, remaining, blocking);
f0a5bb8f86631ce638cb2b6c65bbb9bcf9b0cdc0Bob Halley
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff added += got;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews remaining -= ISC_MIN(remaining, got);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews if (added >= needed)
7c0378745269fe49a05904935afc42b85528f53aDavid Lawrence break;
7c0378745269fe49a05904935afc42b85528f53aDavid Lawrence
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews source = ISC_LIST_NEXT(source, link);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson * Mark as initialized if we've added enough data.
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson */
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson if (ent->initialized < THRESHOLD_BITS)
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson ent->initialized += added;
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson}
3a16668468060842e847ea6556e80e1405d35cd6Brian Wellington
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafssonstatic int
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellingtonwait_for_sources(isc_entropy_t *ent) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews isc_entropysource_t *source;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington int maxfd, fd;
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews int cc;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington fd_set reads;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
942d1a339b1fe617f7d17d66cb5fccce798d15aeBrian Wellington maxfd = -1;
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington FD_ZERO(&reads);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington source = ISC_LIST_HEAD(ent->sources);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington while (source != NULL) {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (source->type == ENTROPY_SOURCETYPE_FILE) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews fd = source->sources.file.fd;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (fd >= 0) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews maxfd = ISC_MAX(maxfd, fd);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington FD_SET(fd, &reads);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington }
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington }
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington source = ISC_LIST_NEXT(source, link);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington }
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (maxfd < 0)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington return (-1);
de5247ae1683ce145662180ee50272d2214a0232Andreas Gustafsson
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington cc = select(maxfd + 1, &reads, NULL, NULL, NULL);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (cc < 0)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington return (-1);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington return (cc);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington}
f16495732753175e4a9fc144323a12fdcc29b561Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington/*
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * Extract some number of bytes from the random pool, decreasing the
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * estimate of randomness as each byte is extracted.
e086935752b6e2f51ef2985fee21ccfff617b115David Lawrence *
e086935752b6e2f51ef2985fee21ccfff617b115David Lawrence * Do this by stiring the pool and returning a part of hash as randomness.
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * Note that no secrets are given away here since parts of the hash are
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * xored together before returned.
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington *
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * Honor the request from the caller to only return good data, any data,
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * etc.
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington */
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellingtonisc_result_t
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellingtonisc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson unsigned int *returned, unsigned int flags)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington{
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington unsigned int i;
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_sha1_t hash;
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington unsigned char digest[ISC_SHA1_DIGESTLENGTH];
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_uint32_t remain, deltae, count, total;
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_uint8_t *buf;
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_boolean_t goodonly, partial, blocking;
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington REQUIRE(VALID_ENTROPY(ent));
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington REQUIRE(data != NULL);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington REQUIRE(length > 0);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington goodonly = ISC_TF((flags & ISC_ENTROPY_GOODONLY) != 0);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington partial = ISC_TF((flags & ISC_ENTROPY_PARTIAL) != 0);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington blocking = ISC_TF((flags & ISC_ENTROPY_BLOCKING) != 0);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff REQUIRE(!partial || returned != NULL);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews LOCK(&ent->lock);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews remain = length;
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews buf = data;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff total = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews while (remain != 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
f305d86668bfd4d4727c3e0f70e7e97a2fa1b772Bob Halley /*
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson * If we are extracting good data only, make certain we
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * have enough data in our pool for this pass. If we don't,
20b20b23948b90cb2f7d7f402da99d09f837efd0David Lawrence * get some, and fail if we can't, and partial returns
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * are not ok.
8dd5237a27e2e824d18f835dc711573aeb23a173Mark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (goodonly) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence unsigned int fillcount;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington fillcount = ISC_MAX(remain * 8, count * 8);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews /*
19d365e4448f1782611280b020987988b7ac3210Mark Andrews * If, however, we have at least THRESHOLD_BITS
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * of entropy in the pool, don't block here. It is
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * better to drain the pool once in a while and
228c679d7a269423019f7c528db92e855f08240bMark Andrews * then refill it than it is to constantly keep the
228c679d7a269423019f7c528db92e855f08240bMark Andrews * pool full.
228c679d7a269423019f7c528db92e855f08240bMark Andrews */
228c679d7a269423019f7c528db92e855f08240bMark Andrews if (ent->pool.entropy >= THRESHOLD_BITS)
228c679d7a269423019f7c528db92e855f08240bMark Andrews fillpool(ent, fillcount, ISC_FALSE);
228c679d7a269423019f7c528db92e855f08240bMark Andrews else
228c679d7a269423019f7c528db92e855f08240bMark Andrews fillpool(ent, fillcount, blocking);
228c679d7a269423019f7c528db92e855f08240bMark Andrews
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington /*
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * Verify that we got enough entropy to do one
228c679d7a269423019f7c528db92e855f08240bMark Andrews * extraction. If we didn't, bail.
228c679d7a269423019f7c528db92e855f08240bMark Andrews */
228c679d7a269423019f7c528db92e855f08240bMark Andrews if (ent->pool.entropy < THRESHOLD_BITS) {
228c679d7a269423019f7c528db92e855f08240bMark Andrews if (!partial)
228c679d7a269423019f7c528db92e855f08240bMark Andrews goto zeroize;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington else
228c679d7a269423019f7c528db92e855f08240bMark Andrews goto partial_output;
228c679d7a269423019f7c528db92e855f08240bMark Andrews }
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington } else {
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington /*
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * If we've extracted half our pool size in bits
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * since the last refresh, try to refresh here.
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington */
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington if (ent->initialized < THRESHOLD_BITS)
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews fillpool(ent, THRESHOLD_BITS, blocking);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews else
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews fillpool(ent, 0, ISC_FALSE);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews /*
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * If we've not initialized with enough good random
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews * data, seed with our crappy code.
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews */
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews if (ent->initialized < THRESHOLD_BITS)
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews reseed(ent);
8dd5237a27e2e824d18f835dc711573aeb23a173Mark Andrews }
8dd5237a27e2e824d18f835dc711573aeb23a173Mark Andrews
8dd5237a27e2e824d18f835dc711573aeb23a173Mark Andrews isc_sha1_init(&hash);
8dd5237a27e2e824d18f835dc711573aeb23a173Mark Andrews isc_sha1_update(&hash, (void *)(ent->pool.pool),
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews RND_POOLWORDS * 4);
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews isc_sha1_final(&hash, digest);
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews /*
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews * Stir the extracted data (all of it) back into the pool.
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews for (i = 0; i < count; i++)
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews buf += count;
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews remain -= count;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews deltae = count * 8;
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews deltae = ISC_MIN(deltae, ent->pool.entropy);
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews total += deltae;
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews subtract_entropy(ent, deltae);
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews add_pseudo(ent, count * 8);
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews }
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews partial_output:
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews memset(digest, 0, sizeof(digest));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (returned != NULL)
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews *returned = (length - remain);
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews UNLOCK(&ent->lock);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (ISC_R_SUCCESS);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews zeroize:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* put the entropy we almost extracted back */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews add_entropy(ent, total);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(data, 0, length);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(digest, 0, sizeof(digest));
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (returned != NULL)
ae70d32b67cf30e06553c01479e71c87b21d984cBob Halley *returned = 0;
ae70d32b67cf30e06553c01479e71c87b21d984cBob Halley
19d365e4448f1782611280b020987988b7ac3210Mark Andrews UNLOCK(&ent->lock);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews return (ISC_R_NOENTROPY);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews}
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic void
19d365e4448f1782611280b020987988b7ac3210Mark Andrewsisc_entropypool_init(isc_entropypool_t *pool) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence pool->cursor = RND_POOLWORDS - 1;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence pool->entropy = 0;
19d365e4448f1782611280b020987988b7ac3210Mark Andrews pool->pseudo = 0;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence pool->rotate = 0;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence memset(pool->pool, 0, RND_POOLWORDS);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence}
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrewsstatic void
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffisc_entropypool_invalidate(isc_entropypool_t *pool) {
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews pool->cursor = 0;
f8aae502686e2448c48f56697c212a50e2a1cbaeAndreas Gustafsson pool->entropy = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews pool->pseudo = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews pool->rotate = 0;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews memset(pool->pool, 0, RND_POOLWORDS);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington}
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrewsisc_result_t
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrewsisc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews isc_result_t ret;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews isc_entropy_t *ent;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews REQUIRE(mctx != NULL);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews REQUIRE(entp != NULL && *entp == NULL);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (ent == NULL)
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington return (ISC_R_NOMEMORY);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington /*
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews * We need a lock.
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews */
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (isc_mutex_init(&ent->lock) != ISC_R_SUCCESS) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews ret = ISC_R_UNEXPECTED;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews goto errout;
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * From here down, no failures will/can occur.
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ISC_LIST_INIT(ent->sources);
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson ent->nextsource = NULL;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews ent->nsources = 0;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews ent->mctx = NULL;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews isc_mem_attach(mctx, &ent->mctx);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews ent->refcnt = 1;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ent->initialized = 0;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ent->initcount = 0;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ent->magic = ENTROPY_MAGIC;
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson isc_entropypool_init(&ent->pool);
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson *entp = ent;
ae70d32b67cf30e06553c01479e71c87b21d984cBob Halley return (ISC_R_SUCCESS);
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson errout:
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson return (ret);
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson}
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews/*
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * Requires "ent" be locked.
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews */
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencedestroysource(isc_entropysource_t **sourcep) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropysource_t *source;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_entropy_t *ent;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_cbsource_t *cbs;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson int fd;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson source = *sourcep;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson *sourcep = NULL;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson ent = source->ent;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson ISC_LIST_UNLINK(ent->sources, source, link);
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson ent->nextsource = NULL;
ae70d32b67cf30e06553c01479e71c87b21d984cBob Halley REQUIRE(ent->nsources > 0);
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson ent->nsources--;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff switch (source->type) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley case ENTROPY_SOURCETYPE_FILE:
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews fd = source->sources.file.fd;
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews if (!source->bad)
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews close(fd);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case ENTROPY_SOURCETYPE_SAMPLE:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews samplequeue_release(ent, &source->sources.sample.samplequeue);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case ENTROPY_SOURCETYPE_CALLBACK:
19d365e4448f1782611280b020987988b7ac3210Mark Andrews cbs = &source->sources.callback;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (cbs->start_called && cbs->stopfunc != NULL) {
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington cbs->stopfunc(source, cbs->arg);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews cbs->start_called = ISC_FALSE;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
19d365e4448f1782611280b020987988b7ac3210Mark Andrews samplequeue_release(ent, &cbs->samplequeue);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(source, 0, sizeof(isc_entropysource_t));
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrewsstatic inline isc_boolean_t
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrewsdestroy_check(isc_entropy_t *ent) {
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews isc_entropysource_t *source;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ent->refcnt > 0)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return (ISC_FALSE);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews source = ISC_LIST_HEAD(ent->sources);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews while (source != NULL) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews switch (source->type) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff case ENTROPY_SOURCETYPE_FILE:
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews break;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff default:
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews return (ISC_FALSE);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
19d365e4448f1782611280b020987988b7ac3210Mark Andrews source = ISC_LIST_NEXT(source, link);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
19d365e4448f1782611280b020987988b7ac3210Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (ISC_TRUE);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrewsstatic void
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrewsdestroy(isc_entropy_t **entp) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_entropy_t *ent;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_entropysource_t *source;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_mem_t *mctx;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews REQUIRE(entp != NULL && *entp != NULL);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews ent = *entp;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews *entp = NULL;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews LOCK(&ent->lock);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews REQUIRE(ent->refcnt == 0);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
d981ca645597116d227a48bf37cc5edc061c854dBob Halley /*
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * Here, detach non-sample sources.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff source = ISC_LIST_HEAD(ent->sources);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley while (source != NULL) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley switch(source->type) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley case ENTROPY_SOURCETYPE_FILE:
d981ca645597116d227a48bf37cc5edc061c854dBob Halley destroysource(&source);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley break;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley }
d981ca645597116d227a48bf37cc5edc061c854dBob Halley source = ISC_LIST_HEAD(ent->sources);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley }
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews /*
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * If there are other types of sources, we've found a bug.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley */
d981ca645597116d227a48bf37cc5edc061c854dBob Halley REQUIRE(ISC_LIST_EMPTY(ent->sources));
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley mctx = ent->mctx;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley isc_entropypool_invalidate(&ent->pool);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
d981ca645597116d227a48bf37cc5edc061c854dBob Halley UNLOCK(&ent->lock);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff DESTROYLOCK(&ent->lock);
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff memset(ent, 0, sizeof(isc_entropy_t));
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews isc_mem_detach(&mctx);
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley}
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley/*
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley * Make a fd non-blocking
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley */
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halleystatic isc_result_t
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halleymake_nonblock(int fd) {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews int ret;
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley int flags;
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley flags = fcntl(fd, F_GETFL, 0);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews flags |= O_NONBLOCK;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews ret = fcntl(fd, F_SETFL, flags);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (ret == -1) {
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley UNEXPECTED_ERROR(__FILE__, __LINE__,
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley "fcntl(%d, F_SETFL, %d): %s",
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley fd, flags, strerror(errno));
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff return (ISC_R_UNEXPECTED);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff }
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff return (ISC_R_SUCCESS);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff}
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffisc_result_t
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffisc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff int fd;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_result_t ret;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_entropysource_t *source;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson REQUIRE(VALID_ENTROPY(ent));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson REQUIRE(fname != NULL);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson LOCK(&ent->lock);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
88ba491496daf4463a2c898be8a6c47775a6d048Mark Andrews source = NULL;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson fd = open(fname, O_RDONLY | O_NONBLOCK, 0);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if (fd < 0) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson ret = ISC_R_IOERROR;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson goto errout;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson ret = make_nonblock(fd);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if (ret != ISC_R_SUCCESS)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson goto closefd;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (source == NULL) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson ret = ISC_R_NOMEMORY;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson goto closefd;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
34b394b43e2207e8f8f3703f0402422121455638David Lawrence
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /*
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * From here down, no failures can occur.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence source->magic = SOURCE_MAGIC;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence source->type = ENTROPY_SOURCETYPE_FILE;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence source->ent = ent;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson source->total = 0;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence source->bad = ISC_FALSE;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson memset(source->name, 0, sizeof(source->name));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ISC_LINK_INIT(source, link);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson source->sources.file.fd = fd;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /*
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Hook it into the entropy system.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson ISC_LIST_APPEND(ent->sources, source, link);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson ent->nsources++;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson UNLOCK(&ent->lock);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (ISC_R_SUCCESS);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson closefd:
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson close(fd);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson errout:
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if (source != NULL)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson UNLOCK(&ent->lock);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (ret);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson}
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonvoid
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonisc_entropy_destroysource(isc_entropysource_t **sourcep) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_entropysource_t *source;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff isc_entropy_t *ent;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff isc_boolean_t killit;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff REQUIRE(sourcep != NULL);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff REQUIRE(VALID_SOURCE(*sourcep));
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence source = *sourcep;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington *sourcep = NULL;
600cfa2ba4c50017581b6c14e3a688a82ecebbe0David Lawrence
600cfa2ba4c50017581b6c14e3a688a82ecebbe0David Lawrence ent = source->ent;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington REQUIRE(VALID_ENTROPY(ent));
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff LOCK(&ent->lock);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fc024be774c7cdee938da018aa3994be746e36deDavid Lawrence destroysource(&source);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington killit = destroy_check(ent);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff UNLOCK(&ent->lock);
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafsson
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafsson if (killit)
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafsson destroy(&ent);
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafsson}
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafsson
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellingtonisc_result_t
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellingtonisc_entropy_createcallbacksource(isc_entropy_t *ent,
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_entropystart_t start,
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_entropyget_t get,
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_entropystop_t stop,
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington void *arg,
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_entropysource_t **sourcep)
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington{
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_result_t ret;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_entropysource_t *source;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_cbsource_t *cbs;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff REQUIRE(VALID_ENTROPY(ent));
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff REQUIRE(get != NULL);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington REQUIRE(sourcep != NULL && *sourcep == NULL);
e6f17474cb43a138bf7fc9ad30c6b3a2847cb7a7Mark Andrews
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff LOCK(&ent->lock);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff if (source == NULL) {
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff ret = ISC_R_NOMEMORY;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington goto errout;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff }
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff source->bad = ISC_FALSE;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff cbs = &source->sources.callback;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff ret = samplesource_allocate(ent, &cbs->samplequeue);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff if (ret != ISC_R_SUCCESS)
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff goto errout;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews cbs->start_called = ISC_FALSE;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews cbs->startfunc = start;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff cbs->getfunc = get;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cbs->stopfunc = stop;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington cbs->arg = arg;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff /*
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff * From here down, no failures can occur.
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff */
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff source->magic = SOURCE_MAGIC;
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafsson source->type = ENTROPY_SOURCETYPE_CALLBACK;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff source->ent = ent;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff source->total = 0;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff memset(source->name, 0, sizeof(source->name));
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff ISC_LINK_INIT(source, link);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff /*
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff * Hook it into the entropy system.
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff */
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff ISC_LIST_APPEND(ent->sources, source, link);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington ent->nsources++;
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff *sourcep = source;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews UNLOCK(&ent->lock);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson return (ISC_R_SUCCESS);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson errout:
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson if (source != NULL)
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson UNLOCK(&ent->lock);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson return (ret);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson}
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssonvoid
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssonisc_entropy_stopcallbacksources(isc_entropy_t *ent) {
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_entropysource_t *source;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_cbsource_t *cbs;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson REQUIRE(VALID_ENTROPY(ent));
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson LOCK(&ent->lock);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson source = ISC_LIST_HEAD(ent->sources);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson while (source != NULL) {
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
79eec6934923f97a61edb8dbe2641ce56dc30085Bob Halley cbs = &source->sources.callback;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (cbs->start_called && cbs->stopfunc != NULL) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cbs->stopfunc(source, cbs->arg);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff cbs->start_called = ISC_FALSE;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff source = ISC_LIST_NEXT(source, link);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff UNLOCK(&ent->lock);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff}
47b26abe77184f9bedc68e36bdad03332cf67570David Lawrence
47b26abe77184f9bedc68e36bdad03332cf67570David Lawrenceisc_result_t
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graffisc_entropy_createsamplesource(isc_entropy_t *ent,
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff isc_entropysource_t **sourcep)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff{
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff isc_result_t ret;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff isc_entropysource_t *source;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff sample_queue_t *sq;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff REQUIRE(VALID_ENTROPY(ent));
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff REQUIRE(sourcep != NULL && *sourcep == NULL);
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington LOCK(&ent->lock);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington if (source == NULL) {
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington ret = ISC_R_NOMEMORY;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington goto errout;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington }
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington sq = &source->sources.sample.samplequeue;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews ret = samplesource_allocate(ent, sq);
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews if (ret != ISC_R_SUCCESS)
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews goto errout;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence /*
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * From here down, no failures can occur.
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff */
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff source->magic = SOURCE_MAGIC;
5cca7753fde4cbfe15d0c0c2cf1fd519f61f2e7fBrian Wellington source->type = ENTROPY_SOURCETYPE_SAMPLE;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff source->ent = ent;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff source->total = 0;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff memset(source->name, 0, sizeof(source->name));
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff ISC_LINK_INIT(source, link);
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews /*
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson * Hook it into the entropy system.
8c962eba3d6faebc008806ebb6bb9d08089118e9Andreas Gustafsson */
8c962eba3d6faebc008806ebb6bb9d08089118e9Andreas Gustafsson ISC_LIST_APPEND(ent->sources, source, link);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson ent->nsources++;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson *sourcep = source;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson UNLOCK(&ent->lock);
8c962eba3d6faebc008806ebb6bb9d08089118e9Andreas Gustafsson return (ISC_R_SUCCESS);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson errout:
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson if (source != NULL)
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson UNLOCK(&ent->lock);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson return (ret);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson}
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssonstatic inline unsigned int
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssonestimate_entropy(sample_queue_t *sq, isc_uint32_t t)
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson{
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_int32_t delta;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_int32_t delta2;
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson isc_int32_t delta3;
79eec6934923f97a61edb8dbe2641ce56dc30085Bob Halley
79eec6934923f97a61edb8dbe2641ce56dc30085Bob Halley /*
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * If the time counter has overflowed, calculate the real difference.
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews * If it has not, it is simplier.
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington */
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington if (t < sq->last_time)
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington delta = UINT_MAX - sq->last_time + t;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington else
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews delta = sq->last_time - t;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (delta < 0)
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews delta = -delta;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews /*
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews * Calculate the second and third order differentials
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington */
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington delta2 = sq->last_delta - delta;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington if (delta2 < 0)
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington delta2 = -delta2;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington delta3 = sq->last_delta2 - delta2;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington if (delta3 < 0)
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington delta3 = -delta3;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington sq->last_time = t;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence sq->last_delta = delta;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington sq->last_delta2 = delta2;
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff /*
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews * If any delta is 0, we got no entropy. If all are non-zero, we
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * might have something.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if (delta == 0 || delta2 == 0 || delta3 == 0)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return 0;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews /*
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * We could find the smallest delta and claim we got log2(delta)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * bits, but for now return that we found 1 bit.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence */
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews return 1;
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews}
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonstatic unsigned int
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssoncrunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson unsigned int ns;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson unsigned int added;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if (sq->nsamples < 6)
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews return (0);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson added = 0;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sq->last_time = sq->samples[0];
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews sq->last_delta = 0;
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews sq->last_delta2 = 0;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /*
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Prime the values by adding in the first 4 samples in. This
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * should completely initialize the delta calculations.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff for (ns = 0 ; ns < 4 ; ns++)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson (void)estimate_entropy(sq, sq->samples[ns]);
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff for (ns = 4 ; ns < sq->nsamples ; ns++)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson added += estimate_entropy(sq, sq->samples[ns]);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /*
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Move the last 4 samples into the first 4 positions, and start
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * adding new samples from that point.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson for (ns = 0 ; ns < 4 ; ns++) {
88ba491496daf4463a2c898be8a6c47775a6d048Mark Andrews sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
88ba491496daf4463a2c898be8a6c47775a6d048Mark Andrews sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sq->nsamples = 4;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (added);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson}
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson/*
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * queue was full when this function was called.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonstatic isc_result_t
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonaddsample(sample_queue_t *sq, isc_uint32_t sample, isc_uint32_t extra) {
34b394b43e2207e8f8f3703f0402422121455638David Lawrence if (sq->nsamples >= RND_EVENTQSIZE)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (ISC_R_NOMORE);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sq->samples[sq->nsamples] = sample;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sq->extra[sq->nsamples] = extra;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sq->nsamples++;
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (sq->nsamples >= RND_EVENTQSIZE)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (ISC_R_QUEUEFULL);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (ISC_R_SUCCESS);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson}
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonisc_result_t
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonisc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_uint32_t extra)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson{
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_entropy_t *ent;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sample_queue_t *sq;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson unsigned int entropy;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_result_t result;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews REQUIRE(VALID_SOURCE(source));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson ent = source->ent;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson LOCK(&ent->lock);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson sq = &source->sources.sample.samplequeue;
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson result = addsample(sq, sample, extra);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (result == ISC_R_QUEUEFULL) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson entropy = crunchsamples(ent, sq);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson add_entropy(ent, entropy);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson }
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson UNLOCK(&ent->lock);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews return (result);
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews}
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrenceisc_result_t
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrenceisc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews isc_uint32_t extra)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews{
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews sample_queue_t *sq;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_result_t result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(VALID_SOURCE(source));
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews sq = &source->sources.callback.samplequeue;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = addsample(sq, sample, extra);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
fe47f41b13620bfafc4f8cf65d5df24f1e568764Bob Halley return (result);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrencevoid
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsisc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
fe47f41b13620bfafc4f8cf65d5df24f1e568764Bob Halley isc_uint32_t entropy)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews{
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(VALID_ENTROPY(ent));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews LOCK(&ent->lock);
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews entropypool_adddata(ent, data, length, entropy);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (ent->initialized < THRESHOLD_BITS)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ent->initialized = THRESHOLD_BITS;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews UNLOCK(&ent->lock);
ca2912424b1d7c348186a325dd2078a37bb8d818Andreas Gustafsson}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffstatic void
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsdumpstats(isc_entropy_t *ent, FILE *out) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews fprintf(out,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ISC_MSG_ENTROPYSTATS,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "Entropy pool %p: refcnt %u cursor %u,"
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews " rotate %u entropy %u pseudo %u nsources %u"
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews " nextsource %p initialized %u initcount %u\n"),
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff ent, ent->refcnt,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ent->pool.cursor, ent->pool.rotate,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ent->pool.entropy, ent->pool.pseudo,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ent->nsources, ent->nextsource, ent->initialized,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ent->initcount);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * This function ignores locking. Use at your own risk.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffvoid
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsisc_entropy_stats(isc_entropy_t *ent, FILE *out) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(VALID_ENTROPY(ent));
fe47f41b13620bfafc4f8cf65d5df24f1e568764Bob Halley
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews LOCK(&ent->lock);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff dumpstats(ent, out);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews UNLOCK(&ent->lock);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsvoid
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsisc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews REQUIRE(VALID_ENTROPY(ent));
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews REQUIRE(entp != NULL && *entp == NULL);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews LOCK(&ent->lock);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews ent->refcnt++;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *entp = ent;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews UNLOCK(&ent->lock);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews}
f0ff273b530afa730025e1c5ad311950f7ff4328Mark Andrews
f0ff273b530afa730025e1c5ad311950f7ff4328Mark Andrewsvoid
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrewsisc_entropy_detach(isc_entropy_t **entp) {
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews isc_entropy_t *ent;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff isc_boolean_t killit;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ent = *entp;
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews *entp = NULL;
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence LOCK(&ent->lock);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence REQUIRE(ent->refcnt > 0);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews ent->refcnt--;
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews killit = destroy_check(ent);
ad493ef9ddb5a3e78e9d99f57abe75552f36a8f4Andreas Gustafsson
7c0378745269fe49a05904935afc42b85528f53aDavid Lawrence UNLOCK(&ent->lock);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews if (killit)
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews destroy(&ent);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews}
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews