entropy.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2007, 2009, 2010, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: entropy.c,v 1.22 2010/08/10 23:48:19 tbox Exp $ */
00019 
00020 /*! \file
00021  * \brief
00022  * This is the system independent part of the entropy module.  It is
00023  * compiled via inclusion from the relevant OS source file, ie,
00024  * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c.
00025  *
00026  * \author Much of this code is modeled after the NetBSD /dev/random implementation,
00027  * written by Michael Graff <explorer@netbsd.org>.
00028  */
00029 
00030 #include <errno.h>
00031 #include <fcntl.h>
00032 #include <stdio.h>
00033 
00034 #include <isc/buffer.h>
00035 #include <isc/entropy.h>
00036 #include <isc/keyboard.h>
00037 #include <isc/list.h>
00038 #include <isc/magic.h>
00039 #include <isc/mem.h>
00040 #include <isc/msgs.h>
00041 #include <isc/mutex.h>
00042 #include <isc/platform.h>
00043 #include <isc/region.h>
00044 #include <isc/sha1.h>
00045 #include <isc/string.h>
00046 #include <isc/time.h>
00047 #include <isc/util.h>
00048 
00049 #ifdef PKCS11CRYPTO
00050 #include <pk11/pk11.h>
00051 #endif
00052 
00053 #define ENTROPY_MAGIC           ISC_MAGIC('E', 'n', 't', 'e')
00054 #define SOURCE_MAGIC            ISC_MAGIC('E', 'n', 't', 's')
00055 
00056 #define VALID_ENTROPY(e)        ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
00057 #define VALID_SOURCE(s)         ISC_MAGIC_VALID(s, SOURCE_MAGIC)
00058 
00059 /***
00060  *** "constants."  Do not change these unless you _really_ know what
00061  *** you are doing.
00062  ***/
00063 
00064 /*%
00065  * Size of entropy pool in 32-bit words.  This _MUST_ be a power of 2.
00066  */
00067 #define RND_POOLWORDS   128
00068 /*% Pool in bytes. */
00069 #define RND_POOLBYTES   (RND_POOLWORDS * 4)
00070 /*% Pool in bits. */
00071 #define RND_POOLBITS    (RND_POOLWORDS * 32)
00072 
00073 /*%
00074  * Number of bytes returned per hash.  This must be true:
00075  *      threshold * 2 <= digest_size_in_bytes
00076  */
00077 #define RND_ENTROPY_THRESHOLD   10
00078 #define THRESHOLD_BITS          (RND_ENTROPY_THRESHOLD * 8)
00079 
00080 /*%
00081  * Size of the input event queue in samples.
00082  */
00083 #define RND_EVENTQSIZE  32
00084 
00085 /*%
00086  * The number of times we'll "reseed" for pseudorandom seeds.  This is an
00087  * extremely weak pseudorandom seed.  If the caller is using lots of
00088  * pseudorandom data and they cannot provide a stronger random source,
00089  * there is little we can do other than hope they're smart enough to
00090  * call _adddata() with something better than we can come up with.
00091  */
00092 #define RND_INITIALIZE  128
00093 
00094 /*% Entropy Pool */
00095 typedef struct {
00096         isc_uint32_t    cursor;         /*%< current add point in the pool */
00097         isc_uint32_t    entropy;        /*%< current entropy estimate in bits */
00098         isc_uint32_t    pseudo;         /*%< bits extracted in pseudorandom */
00099         isc_uint32_t    rotate;         /*%< how many bits to rotate by */
00100         isc_uint32_t    pool[RND_POOLWORDS];    /*%< random pool data */
00101 } isc_entropypool_t;
00102 
00103 struct isc_entropy {
00104         unsigned int                    magic;
00105         isc_mem_t                      *mctx;
00106         isc_mutex_t                     lock;
00107         unsigned int                    refcnt;
00108         isc_uint32_t                    initialized;
00109         isc_uint32_t                    initcount;
00110         isc_entropypool_t               pool;
00111         unsigned int                    nsources;
00112         isc_entropysource_t            *nextsource;
00113         ISC_LIST(isc_entropysource_t)   sources;
00114 };
00115 
00116 /*% Sample Queue */
00117 typedef struct {
00118         isc_uint32_t    last_time;      /*%< last time recorded */
00119         isc_uint32_t    last_delta;     /*%< last delta value */
00120         isc_uint32_t    last_delta2;    /*%< last delta2 value */
00121         isc_uint32_t    nsamples;       /*%< number of samples filled in */
00122         isc_uint32_t   *samples;        /*%< the samples */
00123         isc_uint32_t   *extra;          /*%< extra samples added in */
00124 } sample_queue_t;
00125 
00126 typedef struct {
00127         sample_queue_t  samplequeue;
00128 } isc_entropysamplesource_t;
00129 
00130 typedef struct {
00131         isc_boolean_t           start_called;
00132         isc_entropystart_t      startfunc;
00133         isc_entropyget_t        getfunc;
00134         isc_entropystop_t       stopfunc;
00135         void                   *arg;
00136         sample_queue_t          samplequeue;
00137 } isc_cbsource_t;
00138 
00139 typedef struct {
00140         FILESOURCE_HANDLE_TYPE handle;
00141 } isc_entropyfilesource_t;
00142 
00143 struct isc_entropysource {
00144         unsigned int    magic;
00145         unsigned int    type;
00146         isc_entropy_t  *ent;
00147         isc_uint32_t    total;          /*%< entropy from this source */
00148         ISC_LINK(isc_entropysource_t)   link;
00149         char            name[32];
00150         isc_boolean_t   bad;
00151         isc_boolean_t   warn_keyboard;
00152         isc_keyboard_t  kbd;
00153         union {
00154                 isc_entropysamplesource_t       sample;
00155                 isc_entropyfilesource_t         file;
00156                 isc_cbsource_t                  callback;
00157                 isc_entropyusocketsource_t      usocket;
00158         } sources;
00159 };
00160 
00161 #define ENTROPY_SOURCETYPE_SAMPLE       1       /*%< Type is a sample source */
00162 #define ENTROPY_SOURCETYPE_FILE         2       /*%< Type is a file source */
00163 #define ENTROPY_SOURCETYPE_CALLBACK     3       /*%< Type is a callback source */
00164 #define ENTROPY_SOURCETYPE_USOCKET      4       /*%< Type is a Unix socket source */
00165 
00166 /*@{*/
00167 /*%
00168  * The random pool "taps"
00169  */
00170 #define TAP1    99
00171 #define TAP2    59
00172 #define TAP3    31
00173 #define TAP4     9
00174 #define TAP5     7
00175 /*@}*/
00176 
00177 /*@{*/
00178 /*%
00179  * Declarations for function provided by the system dependent sources that
00180  * include this file.
00181  */
00182 static void
00183 fillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
00184 
00185 static int
00186 wait_for_sources(isc_entropy_t *);
00187 
00188 static void
00189 destroyfilesource(isc_entropyfilesource_t *source);
00190 
00191 static void
00192 destroyusocketsource(isc_entropyusocketsource_t *source);
00193 
00194 /*@}*/
00195 
00196 static void
00197 samplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) {
00198         REQUIRE(sq->samples != NULL);
00199         REQUIRE(sq->extra != NULL);
00200 
00201         isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
00202         isc_mem_put(ent->mctx, sq->extra, RND_EVENTQSIZE * 4);
00203         sq->samples = NULL;
00204         sq->extra = NULL;
00205 }
00206 
00207 static isc_result_t
00208 samplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) {
00209         sq->samples = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
00210         if (sq->samples == NULL)
00211                 return (ISC_R_NOMEMORY);
00212 
00213         sq->extra = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
00214         if (sq->extra == NULL) {
00215                 isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
00216                 sq->samples = NULL;
00217                 return (ISC_R_NOMEMORY);
00218         }
00219 
00220         sq->nsamples = 0;
00221 
00222         return (ISC_R_SUCCESS);
00223 }
00224 
00225 /*%
00226  * Add in entropy, even when the value we're adding in could be
00227  * very large.
00228  */
00229 static inline void
00230 add_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
00231         /* clamp input.  Yes, this must be done. */
00232         entropy = ISC_MIN(entropy, RND_POOLBITS);
00233         /* Add in the entropy we already have. */
00234         entropy += ent->pool.entropy;
00235         /* Clamp. */
00236         ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS);
00237 }
00238 
00239 /*%
00240  * Decrement the amount of entropy the pool has.
00241  */
00242 static inline void
00243 subtract_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
00244         entropy = ISC_MIN(entropy, ent->pool.entropy);
00245         ent->pool.entropy -= entropy;
00246 }
00247 
00248 /*!
00249  * Add in entropy, even when the value we're adding in could be
00250  * very large.
00251  */
00252 static inline void
00253 add_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
00254         /* clamp input.  Yes, this must be done. */
00255         pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
00256         /* Add in the pseudo we already have. */
00257         pseudo += ent->pool.pseudo;
00258         /* Clamp. */
00259         ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
00260 }
00261 
00262 /*!
00263  * Decrement the amount of pseudo the pool has.
00264  */
00265 static inline void
00266 subtract_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
00267         pseudo = ISC_MIN(pseudo, ent->pool.pseudo);
00268         ent->pool.pseudo -= pseudo;
00269 }
00270 
00271 /*!
00272  * Add one word to the pool, rotating the input as needed.
00273  */
00274 static inline void
00275 entropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) {
00276         /*
00277          * Steal some values out of the pool, and xor them into the
00278          * word we were given.
00279          *
00280          * Mix the new value into the pool using xor.  This will
00281          * prevent the actual values from being known to the caller
00282          * since the previous values are assumed to be unknown as well.
00283          */
00284         val ^= rp->pool[(rp->cursor + TAP1) & (RND_POOLWORDS - 1)];
00285         val ^= rp->pool[(rp->cursor + TAP2) & (RND_POOLWORDS - 1)];
00286         val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
00287         val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
00288         val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
00289         if (rp->rotate == 0)
00290                 rp->pool[rp->cursor++] ^= val;
00291         else
00292                 rp->pool[rp->cursor++] ^=
00293                   ((val << rp->rotate) | (val >> (32 - rp->rotate)));
00294 
00295         /*
00296          * If we have looped around the pool, increment the rotate
00297          * variable so the next value will get xored in rotated to
00298          * a different position.
00299          * Increment by a value that is relatively prime to the word size
00300          * to try to spread the bits throughout the pool quickly when the
00301          * pool is empty.
00302          */
00303         if (rp->cursor == RND_POOLWORDS) {
00304                 rp->cursor = 0;
00305                 rp->rotate = (rp->rotate + 7) & 31;
00306         }
00307 }
00308 
00309 /*!
00310  * Add a buffer's worth of data to the pool.
00311  *
00312  * Requires that the lock is held on the entropy pool.
00313  */
00314 static void
00315 entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
00316                     isc_uint32_t entropy)
00317 {
00318         isc_uint32_t val;
00319         unsigned long addr;
00320         isc_uint8_t *buf;
00321 
00322         /* Silly MSVC in 64 bit mode complains here... */
00323 #ifdef _WIN64
00324         addr = (unsigned long)((unsigned long long)p);
00325 #else
00326         addr = (unsigned long)p;
00327 #endif
00328         buf = p;
00329 
00330         if ((addr & 0x03U) != 0U) {
00331                 val = 0;
00332                 switch (len) {
00333                 case 3:
00334                         val = *buf++;
00335                         len--;
00336                 case 2:
00337                         val = val << 8 | *buf++;
00338                         len--;
00339                 case 1:
00340                         val = val << 8 | *buf++;
00341                         len--;
00342                 }
00343 
00344                 entropypool_add_word(&ent->pool, val);
00345         }
00346 
00347         for (; len > 3; len -= 4) {
00348                 val = *((isc_uint32_t *)buf);
00349 
00350                 entropypool_add_word(&ent->pool, val);
00351                 buf += 4;
00352         }
00353 
00354         if (len != 0) {
00355                 val = 0;
00356                 switch (len) {
00357                 case 3:
00358                         val = *buf++;
00359                 case 2:
00360                         val = val << 8 | *buf++;
00361                 case 1:
00362                         val = val << 8 | *buf++;
00363                 }
00364 
00365                 entropypool_add_word(&ent->pool, val);
00366         }
00367 
00368         add_entropy(ent, entropy);
00369         subtract_pseudo(ent, entropy);
00370 }
00371 
00372 static inline void
00373 reseed(isc_entropy_t *ent) {
00374         isc_time_t t;
00375         pid_t pid;
00376 
00377         if (ent->initcount == 0) {
00378                 pid = getpid();
00379                 entropypool_adddata(ent, &pid, sizeof(pid), 0);
00380                 pid = getppid();
00381                 entropypool_adddata(ent, &pid, sizeof(pid), 0);
00382         }
00383 
00384         /*!
00385          * After we've reseeded 100 times, only add new timing info every
00386          * 50 requests.  This will keep us from using lots and lots of
00387          * CPU just to return bad pseudorandom data anyway.
00388          */
00389         if (ent->initcount > 100)
00390                 if ((ent->initcount % 50) != 0)
00391                         return;
00392 
00393         TIME_NOW(&t);
00394         entropypool_adddata(ent, &t, sizeof(t), 0);
00395         ent->initcount++;
00396 }
00397 
00398 static inline unsigned int
00399 estimate_entropy(sample_queue_t *sq, isc_uint32_t t) {
00400         isc_int32_t             delta;
00401         isc_int32_t             delta2;
00402         isc_int32_t             delta3;
00403 
00404         /*!
00405          * If the time counter has overflowed, calculate the real difference.
00406          * If it has not, it is simpler.
00407          */
00408         if (t < sq->last_time)
00409                 delta = UINT_MAX - sq->last_time + t;
00410         else
00411                 delta = sq->last_time - t;
00412 
00413         if (delta < 0)
00414                 delta = -delta;
00415 
00416         /*
00417          * Calculate the second and third order differentials
00418          */
00419         delta2 = sq->last_delta - delta;
00420         if (delta2 < 0)
00421                 delta2 = -delta2;
00422 
00423         delta3 = sq->last_delta2 - delta2;
00424         if (delta3 < 0)
00425                 delta3 = -delta3;
00426 
00427         sq->last_time = t;
00428         sq->last_delta = delta;
00429         sq->last_delta2 = delta2;
00430 
00431         /*
00432          * If any delta is 0, we got no entropy.  If all are non-zero, we
00433          * might have something.
00434          */
00435         if (delta == 0 || delta2 == 0 || delta3 == 0)
00436                 return 0;
00437 
00438         /*
00439          * We could find the smallest delta and claim we got log2(delta)
00440          * bits, but for now return that we found 1 bit.
00441          */
00442         return 1;
00443 }
00444 
00445 static unsigned int
00446 crunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
00447         unsigned int ns;
00448         unsigned int added;
00449 
00450         if (sq->nsamples < 6)
00451                 return (0);
00452 
00453         added = 0;
00454         sq->last_time = sq->samples[0];
00455         sq->last_delta = 0;
00456         sq->last_delta2 = 0;
00457 
00458         /*
00459          * Prime the values by adding in the first 4 samples in.  This
00460          * should completely initialize the delta calculations.
00461          */
00462         for (ns = 0; ns < 4; ns++)
00463                 (void)estimate_entropy(sq, sq->samples[ns]);
00464 
00465         for (ns = 4; ns < sq->nsamples; ns++)
00466                 added += estimate_entropy(sq, sq->samples[ns]);
00467 
00468         entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
00469         entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
00470 
00471         /*
00472          * Move the last 4 samples into the first 4 positions, and start
00473          * adding new samples from that point.
00474          */
00475         for (ns = 0; ns < 4; ns++) {
00476                 sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
00477                 sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
00478         }
00479 
00480         sq->nsamples = 4;
00481 
00482         return (added);
00483 }
00484 
00485 static unsigned int
00486 get_from_callback(isc_entropysource_t *source, unsigned int desired,
00487                   isc_boolean_t blocking)
00488 {
00489         isc_entropy_t *ent = source->ent;
00490         isc_cbsource_t *cbs = &source->sources.callback;
00491         unsigned int added;
00492         unsigned int got;
00493         isc_result_t result;
00494 
00495         if (desired == 0)
00496                 return (0);
00497 
00498         if (source->bad)
00499                 return (0);
00500 
00501         if (!cbs->start_called && cbs->startfunc != NULL) {
00502                 result = cbs->startfunc(source, cbs->arg, blocking);
00503                 if (result != ISC_R_SUCCESS)
00504                         return (0);
00505                 cbs->start_called = ISC_TRUE;
00506         }
00507 
00508         added = 0;
00509         result = ISC_R_SUCCESS;
00510         while (desired > 0 && result == ISC_R_SUCCESS) {
00511                 result = cbs->getfunc(source, cbs->arg, blocking);
00512                 if (result == ISC_R_QUEUEFULL) {
00513                         got = crunchsamples(ent, &cbs->samplequeue);
00514                         added += got;
00515                         desired -= ISC_MIN(got, desired);
00516                         result = ISC_R_SUCCESS;
00517                 } else if (result != ISC_R_SUCCESS &&
00518                            result != ISC_R_NOTBLOCKING)
00519                         source->bad = ISC_TRUE;
00520 
00521         }
00522 
00523         return (added);
00524 }
00525 
00526 /*
00527  * Extract some number of bytes from the random pool, decreasing the
00528  * estimate of randomness as each byte is extracted.
00529  *
00530  * Do this by stiring the pool and returning a part of hash as randomness.
00531  * Note that no secrets are given away here since parts of the hash are
00532  * xored together before returned.
00533  *
00534  * Honor the request from the caller to only return good data, any data,
00535  * etc.
00536  */
00537 isc_result_t
00538 isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
00539                     unsigned int *returned, unsigned int flags)
00540 {
00541         unsigned int i;
00542         isc_sha1_t hash;
00543         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
00544         isc_uint32_t remain, deltae, count, total;
00545         isc_uint8_t *buf;
00546         isc_boolean_t goodonly, partial, blocking;
00547 
00548         REQUIRE(VALID_ENTROPY(ent));
00549         REQUIRE(data != NULL);
00550         REQUIRE(length > 0);
00551 
00552         goodonly = ISC_TF((flags & ISC_ENTROPY_GOODONLY) != 0);
00553         partial = ISC_TF((flags & ISC_ENTROPY_PARTIAL) != 0);
00554         blocking = ISC_TF((flags & ISC_ENTROPY_BLOCKING) != 0);
00555 
00556         REQUIRE(!partial || returned != NULL);
00557 
00558         LOCK(&ent->lock);
00559 
00560         remain = length;
00561         buf = data;
00562         total = 0;
00563         while (remain != 0) {
00564                 count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
00565 
00566                 /*
00567                  * If we are extracting good data only, make certain we
00568                  * have enough data in our pool for this pass.  If we don't,
00569                  * get some, and fail if we can't, and partial returns
00570                  * are not ok.
00571                  */
00572                 if (goodonly) {
00573                         unsigned int fillcount;
00574 
00575                         fillcount = ISC_MAX(remain * 8, count * 8);
00576 
00577                         /*
00578                          * If, however, we have at least THRESHOLD_BITS
00579                          * of entropy in the pool, don't block here.  It is
00580                          * better to drain the pool once in a while and
00581                          * then refill it than it is to constantly keep the
00582                          * pool full.
00583                          */
00584                         if (ent->pool.entropy >= THRESHOLD_BITS)
00585                                 fillpool(ent, fillcount, ISC_FALSE);
00586                         else
00587                                 fillpool(ent, fillcount, blocking);
00588 
00589                         /*
00590                          * Verify that we got enough entropy to do one
00591                          * extraction.  If we didn't, bail.
00592                          */
00593                         if (ent->pool.entropy < THRESHOLD_BITS) {
00594                                 if (!partial)
00595                                         goto zeroize;
00596                                 else
00597                                         goto partial_output;
00598                         }
00599                 } else {
00600                         /*
00601                          * If we've extracted half our pool size in bits
00602                          * since the last refresh, try to refresh here.
00603                          */
00604                         if (ent->initialized < THRESHOLD_BITS)
00605                                 fillpool(ent, THRESHOLD_BITS, blocking);
00606                         else
00607                                 fillpool(ent, 0, ISC_FALSE);
00608 
00609                         /*
00610                          * If we've not initialized with enough good random
00611                          * data, seed with our crappy code.
00612                          */
00613                         if (ent->initialized < THRESHOLD_BITS)
00614                                 reseed(ent);
00615                 }
00616 
00617                 isc_sha1_init(&hash);
00618                 isc_sha1_update(&hash, (void *)(ent->pool.pool),
00619                                 RND_POOLBYTES);
00620                 isc_sha1_final(&hash, digest);
00621 
00622                 /*
00623                  * Stir the extracted data (all of it) back into the pool.
00624                  */
00625                 entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
00626 
00627                 for (i = 0; i < count; i++)
00628                         buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
00629 
00630                 buf += count;
00631                 remain -= count;
00632 
00633                 deltae = count * 8;
00634                 deltae = ISC_MIN(deltae, ent->pool.entropy);
00635                 total += deltae;
00636                 subtract_entropy(ent, deltae);
00637                 add_pseudo(ent, count * 8);
00638         }
00639 
00640  partial_output:
00641         memset(digest, 0, sizeof(digest));
00642 
00643         if (returned != NULL)
00644                 *returned = (length - remain);
00645 
00646         UNLOCK(&ent->lock);
00647 
00648         return (ISC_R_SUCCESS);
00649 
00650  zeroize:
00651         /* put the entropy we almost extracted back */
00652         add_entropy(ent, total);
00653         memset(data, 0, length);
00654         memset(digest, 0, sizeof(digest));
00655         if (returned != NULL)
00656                 *returned = 0;
00657 
00658         UNLOCK(&ent->lock);
00659 
00660         return (ISC_R_NOENTROPY);
00661 }
00662 
00663 static void
00664 isc_entropypool_init(isc_entropypool_t *pool) {
00665         pool->cursor = RND_POOLWORDS - 1;
00666         pool->entropy = 0;
00667         pool->pseudo = 0;
00668         pool->rotate = 0;
00669         memset(pool->pool, 0, RND_POOLBYTES);
00670 }
00671 
00672 static void
00673 isc_entropypool_invalidate(isc_entropypool_t *pool) {
00674         pool->cursor = 0;
00675         pool->entropy = 0;
00676         pool->pseudo = 0;
00677         pool->rotate = 0;
00678         memset(pool->pool, 0, RND_POOLBYTES);
00679 }
00680 
00681 isc_result_t
00682 isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
00683         isc_result_t result;
00684         isc_entropy_t *ent;
00685 
00686         REQUIRE(mctx != NULL);
00687         REQUIRE(entp != NULL && *entp == NULL);
00688 
00689         ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
00690         if (ent == NULL)
00691                 return (ISC_R_NOMEMORY);
00692 
00693         /*
00694          * We need a lock.
00695          */
00696         result = isc_mutex_init(&ent->lock);
00697         if (result != ISC_R_SUCCESS)
00698                 goto errout;
00699 
00700         /*
00701          * From here down, no failures will/can occur.
00702          */
00703         ISC_LIST_INIT(ent->sources);
00704         ent->nextsource = NULL;
00705         ent->nsources = 0;
00706         ent->mctx = NULL;
00707         isc_mem_attach(mctx, &ent->mctx);
00708         ent->refcnt = 1;
00709         ent->initialized = 0;
00710         ent->initcount = 0;
00711         ent->magic = ENTROPY_MAGIC;
00712 
00713         isc_entropypool_init(&ent->pool);
00714 
00715         *entp = ent;
00716         return (ISC_R_SUCCESS);
00717 
00718  errout:
00719         isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
00720 
00721         return (result);
00722 }
00723 
00724 /*!
00725  * Requires "ent" be locked.
00726  */
00727 static void
00728 destroysource(isc_entropysource_t **sourcep) {
00729         isc_entropysource_t *source;
00730         isc_entropy_t *ent;
00731         isc_cbsource_t *cbs;
00732 
00733         source = *sourcep;
00734         *sourcep = NULL;
00735         ent = source->ent;
00736 
00737         ISC_LIST_UNLINK(ent->sources, source, link);
00738         ent->nextsource = NULL;
00739         REQUIRE(ent->nsources > 0);
00740         ent->nsources--;
00741 
00742         switch (source->type) {
00743         case ENTROPY_SOURCETYPE_FILE:
00744                 if (! source->bad)
00745                         destroyfilesource(&source->sources.file);
00746                 break;
00747         case ENTROPY_SOURCETYPE_USOCKET:
00748                 if (! source->bad)
00749                         destroyusocketsource(&source->sources.usocket);
00750                 break;
00751         case ENTROPY_SOURCETYPE_SAMPLE:
00752                 samplequeue_release(ent, &source->sources.sample.samplequeue);
00753                 break;
00754         case ENTROPY_SOURCETYPE_CALLBACK:
00755                 cbs = &source->sources.callback;
00756                 if (cbs->start_called && cbs->stopfunc != NULL) {
00757                         cbs->stopfunc(source, cbs->arg);
00758                         cbs->start_called = ISC_FALSE;
00759                 }
00760                 samplequeue_release(ent, &cbs->samplequeue);
00761                 break;
00762         }
00763 
00764         memset(source, 0, sizeof(isc_entropysource_t));
00765 
00766         isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
00767 }
00768 
00769 static inline isc_boolean_t
00770 destroy_check(isc_entropy_t *ent) {
00771         isc_entropysource_t *source;
00772 
00773         if (ent->refcnt > 0)
00774                 return (ISC_FALSE);
00775 
00776         source = ISC_LIST_HEAD(ent->sources);
00777         while (source != NULL) {
00778                 switch (source->type) {
00779                 case ENTROPY_SOURCETYPE_FILE:
00780                 case ENTROPY_SOURCETYPE_USOCKET:
00781                         break;
00782                 default:
00783                         return (ISC_FALSE);
00784                 }
00785                 source = ISC_LIST_NEXT(source, link);
00786         }
00787 
00788         return (ISC_TRUE);
00789 }
00790 
00791 static void
00792 destroy(isc_entropy_t **entp) {
00793         isc_entropy_t *ent;
00794         isc_entropysource_t *source;
00795         isc_mem_t *mctx;
00796 
00797         REQUIRE(entp != NULL && *entp != NULL);
00798         ent = *entp;
00799         *entp = NULL;
00800 
00801         LOCK(&ent->lock);
00802 
00803         REQUIRE(ent->refcnt == 0);
00804 
00805         /*
00806          * Here, detach non-sample sources.
00807          */
00808         source = ISC_LIST_HEAD(ent->sources);
00809         while (source != NULL) {
00810                 switch(source->type) {
00811                 case ENTROPY_SOURCETYPE_FILE:
00812                 case ENTROPY_SOURCETYPE_USOCKET:
00813                         destroysource(&source);
00814                         break;
00815                 }
00816                 source = ISC_LIST_HEAD(ent->sources);
00817         }
00818 
00819         /*
00820          * If there are other types of sources, we've found a bug.
00821          */
00822         REQUIRE(ISC_LIST_EMPTY(ent->sources));
00823 
00824         mctx = ent->mctx;
00825 
00826         isc_entropypool_invalidate(&ent->pool);
00827 
00828         UNLOCK(&ent->lock);
00829 
00830         DESTROYLOCK(&ent->lock);
00831 
00832         memset(ent, 0, sizeof(isc_entropy_t));
00833         isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
00834         isc_mem_detach(&mctx);
00835 }
00836 
00837 void
00838 isc_entropy_destroysource(isc_entropysource_t **sourcep) {
00839         isc_entropysource_t *source;
00840         isc_entropy_t *ent;
00841         isc_boolean_t killit;
00842 
00843         REQUIRE(sourcep != NULL);
00844         REQUIRE(VALID_SOURCE(*sourcep));
00845 
00846         source = *sourcep;
00847         *sourcep = NULL;
00848 
00849         ent = source->ent;
00850         REQUIRE(VALID_ENTROPY(ent));
00851 
00852         LOCK(&ent->lock);
00853 
00854         destroysource(&source);
00855 
00856         killit = destroy_check(ent);
00857 
00858         UNLOCK(&ent->lock);
00859 
00860         if (killit)
00861                 destroy(&ent);
00862 }
00863 
00864 isc_result_t
00865 isc_entropy_createcallbacksource(isc_entropy_t *ent,
00866                                  isc_entropystart_t start,
00867                                  isc_entropyget_t get,
00868                                  isc_entropystop_t stop,
00869                                  void *arg,
00870                                  isc_entropysource_t **sourcep)
00871 {
00872         isc_result_t result;
00873         isc_entropysource_t *source;
00874         isc_cbsource_t *cbs;
00875 
00876         REQUIRE(VALID_ENTROPY(ent));
00877         REQUIRE(get != NULL);
00878         REQUIRE(sourcep != NULL && *sourcep == NULL);
00879 
00880         LOCK(&ent->lock);
00881 
00882         source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
00883         if (source == NULL) {
00884                 result = ISC_R_NOMEMORY;
00885                 goto errout;
00886         }
00887         source->bad = ISC_FALSE;
00888 
00889         cbs = &source->sources.callback;
00890 
00891         result = samplesource_allocate(ent, &cbs->samplequeue);
00892         if (result != ISC_R_SUCCESS)
00893                 goto errout;
00894 
00895         cbs->start_called = ISC_FALSE;
00896         cbs->startfunc = start;
00897         cbs->getfunc = get;
00898         cbs->stopfunc = stop;
00899         cbs->arg = arg;
00900 
00901         /*
00902          * From here down, no failures can occur.
00903          */
00904         source->magic = SOURCE_MAGIC;
00905         source->type = ENTROPY_SOURCETYPE_CALLBACK;
00906         source->ent = ent;
00907         source->total = 0;
00908         memset(source->name, 0, sizeof(source->name));
00909         ISC_LINK_INIT(source, link);
00910 
00911         /*
00912          * Hook it into the entropy system.
00913          */
00914         ISC_LIST_APPEND(ent->sources, source, link);
00915         ent->nsources++;
00916 
00917         *sourcep = source;
00918 
00919         UNLOCK(&ent->lock);
00920         return (ISC_R_SUCCESS);
00921 
00922  errout:
00923         if (source != NULL)
00924                 isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
00925 
00926         UNLOCK(&ent->lock);
00927 
00928         return (result);
00929 }
00930 
00931 void
00932 isc_entropy_stopcallbacksources(isc_entropy_t *ent) {
00933         isc_entropysource_t *source;
00934         isc_cbsource_t *cbs;
00935 
00936         REQUIRE(VALID_ENTROPY(ent));
00937 
00938         LOCK(&ent->lock);
00939 
00940         source = ISC_LIST_HEAD(ent->sources);
00941         while (source != NULL) {
00942                 if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
00943                         cbs = &source->sources.callback;
00944                         if (cbs->start_called && cbs->stopfunc != NULL) {
00945                                 cbs->stopfunc(source, cbs->arg);
00946                                 cbs->start_called = ISC_FALSE;
00947                         }
00948                 }
00949 
00950                 source = ISC_LIST_NEXT(source, link);
00951         }
00952 
00953         UNLOCK(&ent->lock);
00954 }
00955 
00956 isc_result_t
00957 isc_entropy_createsamplesource(isc_entropy_t *ent,
00958                                isc_entropysource_t **sourcep)
00959 {
00960         isc_result_t result;
00961         isc_entropysource_t *source;
00962         sample_queue_t *sq;
00963 
00964         REQUIRE(VALID_ENTROPY(ent));
00965         REQUIRE(sourcep != NULL && *sourcep == NULL);
00966 
00967         LOCK(&ent->lock);
00968 
00969         source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
00970         if (source == NULL) {
00971                 result = ISC_R_NOMEMORY;
00972                 goto errout;
00973         }
00974 
00975         sq = &source->sources.sample.samplequeue;
00976         result = samplesource_allocate(ent, sq);
00977         if (result != ISC_R_SUCCESS)
00978                 goto errout;
00979 
00980         /*
00981          * From here down, no failures can occur.
00982          */
00983         source->magic = SOURCE_MAGIC;
00984         source->type = ENTROPY_SOURCETYPE_SAMPLE;
00985         source->ent = ent;
00986         source->total = 0;
00987         memset(source->name, 0, sizeof(source->name));
00988         ISC_LINK_INIT(source, link);
00989 
00990         /*
00991          * Hook it into the entropy system.
00992          */
00993         ISC_LIST_APPEND(ent->sources, source, link);
00994         ent->nsources++;
00995 
00996         *sourcep = source;
00997 
00998         UNLOCK(&ent->lock);
00999         return (ISC_R_SUCCESS);
01000 
01001  errout:
01002         if (source != NULL)
01003                 isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
01004 
01005         UNLOCK(&ent->lock);
01006 
01007         return (result);
01008 }
01009 
01010 /*!
01011  * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
01012  * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
01013  * queue was full when this function was called.
01014  */
01015 static isc_result_t
01016 addsample(sample_queue_t *sq, isc_uint32_t sample, isc_uint32_t extra) {
01017         if (sq->nsamples >= RND_EVENTQSIZE)
01018                 return (ISC_R_NOMORE);
01019 
01020         sq->samples[sq->nsamples] = sample;
01021         sq->extra[sq->nsamples] = extra;
01022         sq->nsamples++;
01023 
01024         if (sq->nsamples >= RND_EVENTQSIZE)
01025                 return (ISC_R_QUEUEFULL);
01026 
01027         return (ISC_R_SUCCESS);
01028 }
01029 
01030 isc_result_t
01031 isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
01032                       isc_uint32_t extra)
01033 {
01034         isc_entropy_t *ent;
01035         sample_queue_t *sq;
01036         unsigned int entropy;
01037         isc_result_t result;
01038 
01039         REQUIRE(VALID_SOURCE(source));
01040 
01041         ent = source->ent;
01042 
01043         LOCK(&ent->lock);
01044 
01045         sq = &source->sources.sample.samplequeue;
01046         result = addsample(sq, sample, extra);
01047         if (result == ISC_R_QUEUEFULL) {
01048                 entropy = crunchsamples(ent, sq);
01049                 add_entropy(ent, entropy);
01050         }
01051 
01052         UNLOCK(&ent->lock);
01053 
01054         return (result);
01055 }
01056 
01057 isc_result_t
01058 isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
01059                               isc_uint32_t extra)
01060 {
01061         sample_queue_t *sq;
01062         isc_result_t result;
01063 
01064         REQUIRE(VALID_SOURCE(source));
01065         REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
01066 
01067         sq = &source->sources.callback.samplequeue;
01068         result = addsample(sq, sample, extra);
01069 
01070         return (result);
01071 }
01072 
01073 void
01074 isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
01075                     isc_uint32_t entropy)
01076 {
01077         REQUIRE(VALID_ENTROPY(ent));
01078 
01079         LOCK(&ent->lock);
01080 
01081         entropypool_adddata(ent, data, length, entropy);
01082 
01083         if (ent->initialized < THRESHOLD_BITS)
01084                 ent->initialized = THRESHOLD_BITS;
01085 
01086         UNLOCK(&ent->lock);
01087 }
01088 
01089 static void
01090 dumpstats(isc_entropy_t *ent, FILE *out) {
01091         fprintf(out,
01092                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
01093                                ISC_MSG_ENTROPYSTATS,
01094                                "Entropy pool %p:  refcnt %u cursor %u,"
01095                                " rotate %u entropy %u pseudo %u nsources %u"
01096                                " nextsource %p initialized %u initcount %u\n"),
01097                 ent, ent->refcnt,
01098                 ent->pool.cursor, ent->pool.rotate,
01099                 ent->pool.entropy, ent->pool.pseudo,
01100                 ent->nsources, ent->nextsource, ent->initialized,
01101                 ent->initcount);
01102 }
01103 
01104 /*
01105  * This function ignores locking.  Use at your own risk.
01106  */
01107 void
01108 isc_entropy_stats(isc_entropy_t *ent, FILE *out) {
01109         REQUIRE(VALID_ENTROPY(ent));
01110 
01111         LOCK(&ent->lock);
01112         dumpstats(ent, out);
01113         UNLOCK(&ent->lock);
01114 }
01115 
01116 unsigned int
01117 isc_entropy_status(isc_entropy_t *ent) {
01118         unsigned int estimate;
01119 
01120         LOCK(&ent->lock);
01121         estimate = ent->pool.entropy;
01122         UNLOCK(&ent->lock);
01123 
01124         return estimate;
01125 }
01126 
01127 void
01128 isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
01129         REQUIRE(VALID_ENTROPY(ent));
01130         REQUIRE(entp != NULL && *entp == NULL);
01131 
01132         LOCK(&ent->lock);
01133 
01134         ent->refcnt++;
01135         *entp = ent;
01136 
01137         UNLOCK(&ent->lock);
01138 }
01139 
01140 void
01141 isc_entropy_detach(isc_entropy_t **entp) {
01142         isc_entropy_t *ent;
01143         isc_boolean_t killit;
01144 
01145         REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
01146         ent = *entp;
01147         *entp = NULL;
01148 
01149         LOCK(&ent->lock);
01150 
01151         REQUIRE(ent->refcnt > 0);
01152         ent->refcnt--;
01153 
01154         killit = destroy_check(ent);
01155 
01156         UNLOCK(&ent->lock);
01157 
01158         if (killit)
01159                 destroy(&ent);
01160 }
01161 
01162 static isc_result_t
01163 kbdstart(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
01164         /*
01165          * The intent of "first" is to provide a warning message only once
01166          * during the run of a program that might try to gather keyboard
01167          * entropy multiple times.
01168          */
01169         static isc_boolean_t first = ISC_TRUE;
01170 
01171         UNUSED(arg);
01172 
01173         if (! blocking)
01174                 return (ISC_R_NOENTROPY);
01175 
01176         if (first) {
01177                 if (source->warn_keyboard)
01178                         fprintf(stderr, "You must use the keyboard to create "
01179                                 "entropy, since your system is lacking\n"
01180                                 "/dev/random (or equivalent)\n\n");
01181                 first = ISC_FALSE;
01182         }
01183         fprintf(stderr, "start typing:\n");
01184 
01185         return (isc_keyboard_open(&source->kbd));
01186 }
01187 
01188 static void
01189 kbdstop(isc_entropysource_t *source, void *arg) {
01190 
01191         UNUSED(arg);
01192 
01193         if (! isc_keyboard_canceled(&source->kbd))
01194                 fprintf(stderr, "stop typing.\r\n");
01195 
01196         (void)isc_keyboard_close(&source->kbd, 3);
01197 }
01198 
01199 static isc_result_t
01200 kbdget(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
01201         isc_result_t result;
01202         isc_time_t t;
01203         isc_uint32_t sample;
01204         isc_uint32_t extra;
01205         unsigned char c;
01206 
01207         UNUSED(arg);
01208 
01209         if (!blocking)
01210                 return (ISC_R_NOTBLOCKING);
01211 
01212         result = isc_keyboard_getchar(&source->kbd, &c);
01213         if (result != ISC_R_SUCCESS)
01214                 return (result);
01215 
01216         TIME_NOW(&t);
01217 
01218         sample = isc_time_nanoseconds(&t);
01219         extra = c;
01220 
01221         result = isc_entropy_addcallbacksample(source, sample, extra);
01222         if (result != ISC_R_SUCCESS) {
01223                 fprintf(stderr, "\r\n");
01224                 return (result);
01225         }
01226 
01227         fprintf(stderr, ".");
01228         fflush(stderr);
01229 
01230         return (result);
01231 }
01232 
01233 isc_result_t
01234 isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
01235                           const char *randomfile, int use_keyboard)
01236 {
01237         isc_result_t result;
01238         isc_result_t final_result = ISC_R_NOENTROPY;
01239         isc_boolean_t userfile = ISC_TRUE;
01240 
01241         REQUIRE(VALID_ENTROPY(ectx));
01242         REQUIRE(source != NULL && *source == NULL);
01243         REQUIRE(use_keyboard == ISC_ENTROPY_KEYBOARDYES ||
01244                 use_keyboard == ISC_ENTROPY_KEYBOARDNO  ||
01245                 use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
01246 
01247 #ifdef PKCS11CRYPTO
01248         if (randomfile != NULL)
01249                 pk11_rand_seed_fromfile(randomfile);
01250 #endif
01251 
01252 #ifdef PATH_RANDOMDEV
01253         if (randomfile == NULL) {
01254                 randomfile = PATH_RANDOMDEV;
01255                 userfile = ISC_FALSE;
01256         }
01257 #endif
01258 
01259         if (randomfile != NULL && use_keyboard != ISC_ENTROPY_KEYBOARDYES) {
01260                 result = isc_entropy_createfilesource(ectx, randomfile);
01261                 if (result == ISC_R_SUCCESS &&
01262                     use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE)
01263                         use_keyboard = ISC_ENTROPY_KEYBOARDNO;
01264                 if (result != ISC_R_SUCCESS && userfile)
01265                         return (result);
01266 
01267                 final_result = result;
01268         }
01269 
01270         if (use_keyboard != ISC_ENTROPY_KEYBOARDNO) {
01271                 result = isc_entropy_createcallbacksource(ectx, kbdstart,
01272                                                           kbdget, kbdstop,
01273                                                           NULL, source);
01274                 if (result == ISC_R_SUCCESS)
01275                         (*source)->warn_keyboard =
01276                                 ISC_TF(use_keyboard ==
01277                                        ISC_ENTROPY_KEYBOARDMAYBE);
01278 
01279                 if (final_result != ISC_R_SUCCESS)
01280                         final_result = result;
01281         }
01282 
01283         /*
01284          * final_result is ISC_R_SUCCESS if at least one source of entropy
01285          * could be started, otherwise it is the error from the most recently
01286          * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
01287          * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
01288          */
01289         return (final_result);
01290 }

Generated on Tue Apr 28 17:41:04 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha