"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/isc/entropy.c" (7 Sep 2020, 29262 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "entropy.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 
   13 /*! \file
   14  * \brief
   15  * This is the system independent part of the entropy module.  It is
   16  * compiled via inclusion from the relevant OS source file, ie,
   17  * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c.
   18  *
   19  * \author Much of this code is modeled after the NetBSD /dev/random implementation,
   20  * written by Michael Graff <explorer@netbsd.org>.
   21  */
   22 
   23 #include <errno.h>
   24 #include <fcntl.h>
   25 #include <stdbool.h>
   26 #include <stdio.h>
   27 
   28 #include <isc/buffer.h>
   29 #include <isc/entropy.h>
   30 #include <isc/keyboard.h>
   31 #include <isc/list.h>
   32 #include <isc/magic.h>
   33 #include <isc/mem.h>
   34 #include <isc/msgs.h>
   35 #include <isc/mutex.h>
   36 #include <isc/platform.h>
   37 #include <isc/print.h>
   38 #include <isc/region.h>
   39 #include <isc/safe.h>
   40 #include <isc/sha1.h>
   41 #include <isc/string.h>
   42 #include <isc/time.h>
   43 #include <isc/util.h>
   44 
   45 #ifdef PKCS11CRYPTO
   46 #include <pk11/pk11.h>
   47 #endif
   48 
   49 #define ENTROPY_MAGIC       ISC_MAGIC('E', 'n', 't', 'e')
   50 #define SOURCE_MAGIC        ISC_MAGIC('E', 'n', 't', 's')
   51 
   52 #define VALID_ENTROPY(e)    ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
   53 #define VALID_SOURCE(s)     ISC_MAGIC_VALID(s, SOURCE_MAGIC)
   54 
   55 /***
   56  *** "constants."  Do not change these unless you _really_ know what
   57  *** you are doing.
   58  ***/
   59 
   60 /*%
   61  * Size of entropy pool in 32-bit words.  This _MUST_ be a power of 2.
   62  */
   63 #define RND_POOLWORDS   128
   64 /*% Pool in bytes. */
   65 #define RND_POOLBYTES   (RND_POOLWORDS * 4)
   66 /*% Pool in bits. */
   67 #define RND_POOLBITS    (RND_POOLWORDS * 32)
   68 
   69 /*%
   70  * Number of bytes returned per hash.  This must be true:
   71  *  threshold * 2 <= digest_size_in_bytes
   72  */
   73 #define RND_ENTROPY_THRESHOLD   10
   74 #define THRESHOLD_BITS      (RND_ENTROPY_THRESHOLD * 8)
   75 
   76 /*%
   77  * Size of the input event queue in samples.
   78  */
   79 #define RND_EVENTQSIZE  32
   80 
   81 /*%
   82  * The number of times we'll "reseed" for pseudorandom seeds.  This is an
   83  * extremely weak pseudorandom seed.  If the caller is using lots of
   84  * pseudorandom data and they cannot provide a stronger random source,
   85  * there is little we can do other than hope they're smart enough to
   86  * call _adddata() with something better than we can come up with.
   87  */
   88 #define RND_INITIALIZE  128
   89 
   90 /*% Entropy Pool */
   91 typedef struct {
   92     uint32_t    cursor;     /*%< current add point in the pool */
   93     uint32_t    entropy;    /*%< current entropy estimate in bits */
   94     uint32_t    pseudo;     /*%< bits extracted in pseudorandom */
   95     uint32_t    rotate;     /*%< how many bits to rotate by */
   96     uint32_t    pool[RND_POOLWORDS];    /*%< random pool data */
   97 } isc_entropypool_t;
   98 
   99 struct isc_entropy {
  100     unsigned int            magic;
  101     isc_mem_t              *mctx;
  102     isc_mutex_t         lock;
  103     unsigned int            refcnt;
  104     uint32_t            initialized;
  105     uint32_t            initcount;
  106     isc_entropypool_t       pool;
  107     unsigned int            nsources;
  108     isc_entropysource_t        *nextsource;
  109     ISC_LIST(isc_entropysource_t)   sources;
  110 };
  111 
  112 /*% Sample Queue */
  113 typedef struct {
  114     uint32_t    last_time;  /*%< last time recorded */
  115     uint32_t    last_delta; /*%< last delta value */
  116     uint32_t    last_delta2;    /*%< last delta2 value */
  117     uint32_t    nsamples;   /*%< number of samples filled in */
  118     uint32_t   *samples;    /*%< the samples */
  119     uint32_t   *extra;      /*%< extra samples added in */
  120 } sample_queue_t;
  121 
  122 typedef struct {
  123     sample_queue_t  samplequeue;
  124 } isc_entropysamplesource_t;
  125 
  126 typedef struct {
  127     bool        start_called;
  128     isc_entropystart_t  startfunc;
  129     isc_entropyget_t    getfunc;
  130     isc_entropystop_t   stopfunc;
  131     void               *arg;
  132     sample_queue_t      samplequeue;
  133 } isc_cbsource_t;
  134 
  135 typedef struct {
  136     FILESOURCE_HANDLE_TYPE handle;
  137 } isc_entropyfilesource_t;
  138 
  139 struct isc_entropysource {
  140     unsigned int    magic;
  141     unsigned int    type;
  142     isc_entropy_t  *ent;
  143     uint32_t    total;      /*%< entropy from this source */
  144     ISC_LINK(isc_entropysource_t)   link;
  145     char        name[32];
  146     bool    bad;
  147     bool    warn_keyboard;
  148     isc_keyboard_t  kbd;
  149     union {
  150         isc_entropysamplesource_t   sample;
  151         isc_entropyfilesource_t     file;
  152         isc_cbsource_t          callback;
  153         isc_entropyusocketsource_t  usocket;
  154     } sources;
  155 };
  156 
  157 #define ENTROPY_SOURCETYPE_SAMPLE   1   /*%< Type is a sample source */
  158 #define ENTROPY_SOURCETYPE_FILE     2   /*%< Type is a file source */
  159 #define ENTROPY_SOURCETYPE_CALLBACK 3   /*%< Type is a callback source */
  160 #define ENTROPY_SOURCETYPE_USOCKET  4   /*%< Type is a Unix socket source */
  161 
  162 /*@{*/
  163 /*%
  164  * The random pool "taps"
  165  */
  166 #define TAP1    99
  167 #define TAP2    59
  168 #define TAP3    31
  169 #define TAP4     9
  170 #define TAP5     7
  171 /*@}*/
  172 
  173 /*@{*/
  174 /*%
  175  * Declarations for function provided by the system dependent sources that
  176  * include this file.
  177  */
  178 static void
  179 fillpool(isc_entropy_t *, unsigned int, bool);
  180 
  181 static int
  182 wait_for_sources(isc_entropy_t *);
  183 
  184 static void
  185 destroyfilesource(isc_entropyfilesource_t *source);
  186 
  187 static void
  188 destroyusocketsource(isc_entropyusocketsource_t *source);
  189 
  190 /*@}*/
  191 
  192 static void
  193 samplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) {
  194     REQUIRE(sq->samples != NULL);
  195     REQUIRE(sq->extra != NULL);
  196 
  197     isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
  198     isc_mem_put(ent->mctx, sq->extra, RND_EVENTQSIZE * 4);
  199     sq->samples = NULL;
  200     sq->extra = NULL;
  201 }
  202 
  203 static isc_result_t
  204 samplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) {
  205     sq->samples = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
  206     if (sq->samples == NULL)
  207         return (ISC_R_NOMEMORY);
  208 
  209     sq->extra = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
  210     if (sq->extra == NULL) {
  211         isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
  212         sq->samples = NULL;
  213         return (ISC_R_NOMEMORY);
  214     }
  215 
  216     sq->nsamples = 0;
  217 
  218     return (ISC_R_SUCCESS);
  219 }
  220 
  221 /*%
  222  * Add in entropy, even when the value we're adding in could be
  223  * very large.
  224  */
  225 static inline void
  226 add_entropy(isc_entropy_t *ent, uint32_t entropy) {
  227     /* clamp input.  Yes, this must be done. */
  228     entropy = ISC_MIN(entropy, RND_POOLBITS);
  229     /* Add in the entropy we already have. */
  230     entropy += ent->pool.entropy;
  231     /* Clamp. */
  232     ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS);
  233 }
  234 
  235 /*%
  236  * Decrement the amount of entropy the pool has.
  237  */
  238 static inline void
  239 subtract_entropy(isc_entropy_t *ent, uint32_t entropy) {
  240     entropy = ISC_MIN(entropy, ent->pool.entropy);
  241     ent->pool.entropy -= entropy;
  242 }
  243 
  244 /*!
  245  * Add in entropy, even when the value we're adding in could be
  246  * very large.
  247  */
  248 static inline void
  249 add_pseudo(isc_entropy_t *ent, uint32_t pseudo) {
  250     /* clamp input.  Yes, this must be done. */
  251     pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
  252     /* Add in the pseudo we already have. */
  253     pseudo += ent->pool.pseudo;
  254     /* Clamp. */
  255     ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
  256 }
  257 
  258 /*!
  259  * Decrement the amount of pseudo the pool has.
  260  */
  261 static inline void
  262 subtract_pseudo(isc_entropy_t *ent, uint32_t pseudo) {
  263     pseudo = ISC_MIN(pseudo, ent->pool.pseudo);
  264     ent->pool.pseudo -= pseudo;
  265 }
  266 
  267 /*!
  268  * Add one word to the pool, rotating the input as needed.
  269  */
  270 static inline void
  271 entropypool_add_word(isc_entropypool_t *rp, uint32_t val) {
  272     /*
  273      * Steal some values out of the pool, and xor them into the
  274      * word we were given.
  275      *
  276      * Mix the new value into the pool using xor.  This will
  277      * prevent the actual values from being known to the caller
  278      * since the previous values are assumed to be unknown as well.
  279      */
  280     val ^= rp->pool[(rp->cursor + TAP1) & (RND_POOLWORDS - 1)];
  281     val ^= rp->pool[(rp->cursor + TAP2) & (RND_POOLWORDS - 1)];
  282     val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
  283     val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
  284     val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
  285     if (rp->rotate == 0)
  286         rp->pool[rp->cursor++] ^= val;
  287     else
  288         rp->pool[rp->cursor++] ^=
  289           ((val << rp->rotate) | (val >> (32 - rp->rotate)));
  290 
  291     /*
  292      * If we have looped around the pool, increment the rotate
  293      * variable so the next value will get xored in rotated to
  294      * a different position.
  295      * Increment by a value that is relatively prime to the word size
  296      * to try to spread the bits throughout the pool quickly when the
  297      * pool is empty.
  298      */
  299     if (rp->cursor == RND_POOLWORDS) {
  300         rp->cursor = 0;
  301         rp->rotate = (rp->rotate + 7) & 31;
  302     }
  303 }
  304 
  305 /*!
  306  * Add a buffer's worth of data to the pool.
  307  *
  308  * Requires that the lock is held on the entropy pool.
  309  */
  310 static void
  311 entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
  312             uint32_t entropy)
  313 {
  314     uint32_t val;
  315     unsigned long addr;
  316     uint8_t *buf;
  317 
  318     /* Silly MSVC in 64 bit mode complains here... */
  319 #ifdef _WIN64
  320     addr = (unsigned long)((unsigned long long)p);
  321 #else
  322     addr = (unsigned long)p;
  323 #endif
  324     buf = p;
  325 
  326     if ((addr & 0x03U) != 0U) {
  327         val = 0;
  328         switch (len) {
  329         case 3:
  330             val = *buf++;
  331             len--;
  332             /* FALLTHROUGH */
  333         case 2:
  334             val = val << 8 | *buf++;
  335             len--;
  336             /* FALLTHROUGH */
  337         case 1:
  338             val = val << 8 | *buf++;
  339             len--;
  340         }
  341 
  342         entropypool_add_word(&ent->pool, val);
  343     }
  344 
  345     for (; len > 3; len -= 4) {
  346         val = *((uint32_t *)buf);
  347 
  348         entropypool_add_word(&ent->pool, val);
  349         buf += 4;
  350     }
  351 
  352     if (len != 0) {
  353         val = 0;
  354         switch (len) {
  355         case 3:
  356             val = *buf++;
  357             /* FALLTHROUGH */
  358         case 2:
  359             val = val << 8 | *buf++;
  360             /* FALLTHROUGH */
  361         case 1:
  362             val = val << 8 | *buf++;
  363         }
  364 
  365         entropypool_add_word(&ent->pool, val);
  366     }
  367 
  368     add_entropy(ent, entropy);
  369     subtract_pseudo(ent, entropy);
  370 }
  371 
  372 static inline void
  373 reseed(isc_entropy_t *ent) {
  374     isc_time_t t;
  375     pid_t pid;
  376 
  377     if (ent->initcount == 0) {
  378         pid = getpid();
  379         entropypool_adddata(ent, &pid, sizeof(pid), 0);
  380         pid = getppid();
  381         entropypool_adddata(ent, &pid, sizeof(pid), 0);
  382     }
  383 
  384     /*!
  385      * After we've reseeded 100 times, only add new timing info every
  386      * 50 requests.  This will keep us from using lots and lots of
  387      * CPU just to return bad pseudorandom data anyway.
  388      */
  389     if (ent->initcount > 100)
  390         if ((ent->initcount % 50) != 0)
  391             return;
  392 
  393     TIME_NOW(&t);
  394     entropypool_adddata(ent, &t, sizeof(t), 0);
  395     ent->initcount++;
  396 }
  397 
  398 static inline unsigned int
  399 estimate_entropy(sample_queue_t *sq, uint32_t t) {
  400     int32_t     delta;
  401     int32_t     delta2;
  402     int32_t     delta3;
  403 
  404     /*!
  405      * If the time counter has overflowed, calculate the real difference.
  406      * If it has not, it is simpler.
  407      */
  408     if (t < sq->last_time)
  409         delta = UINT_MAX - sq->last_time + t;
  410     else
  411         delta = sq->last_time - t;
  412 
  413     if (delta < 0)
  414         delta = -delta;
  415 
  416     /*
  417      * Calculate the second and third order differentials
  418      */
  419     delta2 = sq->last_delta - delta;
  420     if (delta2 < 0)
  421         delta2 = -delta2;
  422 
  423     delta3 = sq->last_delta2 - delta2;
  424     if (delta3 < 0)
  425         delta3 = -delta3;
  426 
  427     sq->last_time = t;
  428     sq->last_delta = delta;
  429     sq->last_delta2 = delta2;
  430 
  431     /*
  432      * If any delta is 0, we got no entropy.  If all are non-zero, we
  433      * might have something.
  434      */
  435     if (delta == 0 || delta2 == 0 || delta3 == 0)
  436         return 0;
  437 
  438     /*
  439      * We could find the smallest delta and claim we got log2(delta)
  440      * bits, but for now return that we found 1 bit.
  441      */
  442     return 1;
  443 }
  444 
  445 static unsigned int
  446 crunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
  447     unsigned int ns;
  448     unsigned int added;
  449 
  450     if (sq->nsamples < 6)
  451         return (0);
  452 
  453     added = 0;
  454     sq->last_time = sq->samples[0];
  455     sq->last_delta = 0;
  456     sq->last_delta2 = 0;
  457 
  458     /*
  459      * Prime the values by adding in the first 4 samples in.  This
  460      * should completely initialize the delta calculations.
  461      */
  462     for (ns = 0; ns < 4; ns++)
  463         (void)estimate_entropy(sq, sq->samples[ns]);
  464 
  465     for (ns = 4; ns < sq->nsamples; ns++)
  466         added += estimate_entropy(sq, sq->samples[ns]);
  467 
  468     entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
  469     entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
  470 
  471     /*
  472      * Move the last 4 samples into the first 4 positions, and start
  473      * adding new samples from that point.
  474      */
  475     for (ns = 0; ns < 4; ns++) {
  476         sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
  477         sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
  478     }
  479 
  480     sq->nsamples = 4;
  481 
  482     return (added);
  483 }
  484 
  485 static unsigned int
  486 get_from_callback(isc_entropysource_t *source, unsigned int desired,
  487           bool blocking)
  488 {
  489     isc_entropy_t *ent = source->ent;
  490     isc_cbsource_t *cbs = &source->sources.callback;
  491     unsigned int added;
  492     unsigned int got;
  493     isc_result_t result;
  494 
  495     if (desired == 0)
  496         return (0);
  497 
  498     if (source->bad)
  499         return (0);
  500 
  501     if (!cbs->start_called && cbs->startfunc != NULL) {
  502         result = cbs->startfunc(source, cbs->arg, blocking);
  503         if (result != ISC_R_SUCCESS)
  504             return (0);
  505         cbs->start_called = true;
  506     }
  507 
  508     added = 0;
  509     result = ISC_R_SUCCESS;
  510     while (desired > 0 && result == ISC_R_SUCCESS) {
  511         result = cbs->getfunc(source, cbs->arg, blocking);
  512         if (result == ISC_R_QUEUEFULL) {
  513             got = crunchsamples(ent, &cbs->samplequeue);
  514             added += got;
  515             desired -= ISC_MIN(got, desired);
  516             result = ISC_R_SUCCESS;
  517         } else if (result != ISC_R_SUCCESS &&
  518                result != ISC_R_NOTBLOCKING)
  519             source->bad = true;
  520 
  521     }
  522 
  523     return (added);
  524 }
  525 
  526 /*
  527  * Extract some number of bytes from the random pool, decreasing the
  528  * estimate of randomness as each byte is extracted.
  529  *
  530  * Do this by stirring the pool and returning a part of hash as randomness.
  531  * Note that no secrets are given away here since parts of the hash are
  532  * xored together before returned.
  533  *
  534  * Honor the request from the caller to only return good data, any data,
  535  * etc.
  536  */
  537 isc_result_t
  538 isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
  539             unsigned int *returned, unsigned int flags)
  540 {
  541     unsigned int i;
  542     isc_sha1_t hash;
  543     unsigned char digest[ISC_SHA1_DIGESTLENGTH];
  544     uint32_t remain, deltae, count, total;
  545     uint8_t *buf;
  546     bool goodonly, partial, blocking;
  547 
  548     REQUIRE(VALID_ENTROPY(ent));
  549     REQUIRE(data != NULL);
  550     REQUIRE(length > 0);
  551 
  552     goodonly = (flags & ISC_ENTROPY_GOODONLY);
  553     partial = (flags & ISC_ENTROPY_PARTIAL);
  554     blocking = (flags & ISC_ENTROPY_BLOCKING);
  555 
  556     REQUIRE(!partial || returned != NULL);
  557 
  558     LOCK(&ent->lock);
  559 
  560     remain = length;
  561     buf = data;
  562     total = 0;
  563     while (remain != 0) {
  564         count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
  565 
  566         /*
  567          * If we are extracting good data only, make certain we
  568          * have enough data in our pool for this pass.  If we don't,
  569          * get some, and fail if we can't, and partial returns
  570          * are not ok.
  571          */
  572         if (goodonly) {
  573             unsigned int fillcount;
  574 
  575             fillcount = ISC_MAX(remain * 8, count * 8);
  576 
  577             /*
  578              * If, however, we have at least THRESHOLD_BITS
  579              * of entropy in the pool, don't block here.  It is
  580              * better to drain the pool once in a while and
  581              * then refill it than it is to constantly keep the
  582              * pool full.
  583              */
  584             if (ent->pool.entropy >= THRESHOLD_BITS)
  585                 fillpool(ent, fillcount, false);
  586             else
  587                 fillpool(ent, fillcount, blocking);
  588 
  589             /*
  590              * Verify that we got enough entropy to do one
  591              * extraction.  If we didn't, bail.
  592              */
  593             if (ent->pool.entropy < THRESHOLD_BITS) {
  594                 if (!partial)
  595                     goto zeroize;
  596                 else
  597                     goto partial_output;
  598             }
  599         } else {
  600             /*
  601              * If we've extracted half our pool size in bits
  602              * since the last refresh, try to refresh here.
  603              */
  604             if (ent->initialized < THRESHOLD_BITS)
  605                 fillpool(ent, THRESHOLD_BITS, blocking);
  606             else
  607                 fillpool(ent, 0, false);
  608 
  609             /*
  610              * If we've not initialized with enough good random
  611              * data, seed with our crappy code.
  612              */
  613             if (ent->initialized < THRESHOLD_BITS)
  614                 reseed(ent);
  615         }
  616 
  617         isc_sha1_init(&hash);
  618         isc_sha1_update(&hash, (void *)(ent->pool.pool),
  619                 RND_POOLBYTES);
  620         isc_sha1_final(&hash, digest);
  621 
  622         /*
  623          * Stir the extracted data (all of it) back into the pool.
  624          */
  625         entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
  626 
  627         for (i = 0; i < count; i++)
  628             buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
  629 
  630         buf += count;
  631         remain -= count;
  632 
  633         deltae = count * 8;
  634         deltae = ISC_MIN(deltae, ent->pool.entropy);
  635         total += deltae;
  636         subtract_entropy(ent, deltae);
  637         add_pseudo(ent, count * 8);
  638     }
  639 
  640  partial_output:
  641     isc_safe_memwipe(digest, sizeof(digest));
  642 
  643     if (returned != NULL)
  644         *returned = (length - remain);
  645 
  646     UNLOCK(&ent->lock);
  647 
  648     return (ISC_R_SUCCESS);
  649 
  650  zeroize:
  651     /* put the entropy we almost extracted back */
  652     add_entropy(ent, total);
  653     isc_safe_memwipe(data, length);
  654     isc_safe_memwipe(digest, sizeof(digest));
  655     if (returned != NULL)
  656         *returned = 0;
  657 
  658     UNLOCK(&ent->lock);
  659 
  660     return (ISC_R_NOENTROPY);
  661 }
  662 
  663 static void
  664 isc_entropypool_init(isc_entropypool_t *pool) {
  665     pool->cursor = RND_POOLWORDS - 1;
  666     pool->entropy = 0;
  667     pool->pseudo = 0;
  668     pool->rotate = 0;
  669     memset(pool->pool, 0, RND_POOLBYTES);
  670 }
  671 
  672 static void
  673 isc_entropypool_invalidate(isc_entropypool_t *pool) {
  674     pool->cursor = 0;
  675     pool->entropy = 0;
  676     pool->pseudo = 0;
  677     pool->rotate = 0;
  678     memset(pool->pool, 0, RND_POOLBYTES);
  679 }
  680 
  681 isc_result_t
  682 isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
  683     isc_result_t result;
  684     isc_entropy_t *ent;
  685 
  686     REQUIRE(mctx != NULL);
  687     REQUIRE(entp != NULL && *entp == NULL);
  688 
  689     ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
  690     if (ent == NULL)
  691         return (ISC_R_NOMEMORY);
  692 
  693     /*
  694      * We need a lock.
  695      */
  696     result = isc_mutex_init(&ent->lock);
  697     if (result != ISC_R_SUCCESS)
  698         goto errout;
  699 
  700     /*
  701      * From here down, no failures will/can occur.
  702      */
  703     ISC_LIST_INIT(ent->sources);
  704     ent->nextsource = NULL;
  705     ent->nsources = 0;
  706     ent->mctx = NULL;
  707     isc_mem_attach(mctx, &ent->mctx);
  708     ent->refcnt = 1;
  709     ent->initialized = 0;
  710     ent->initcount = 0;
  711     ent->magic = ENTROPY_MAGIC;
  712 
  713     isc_entropypool_init(&ent->pool);
  714 
  715     *entp = ent;
  716     return (ISC_R_SUCCESS);
  717 
  718  errout:
  719     isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
  720 
  721     return (result);
  722 }
  723 
  724 /*!
  725  * Requires "ent" be locked.
  726  */
  727 static void
  728 destroysource(isc_entropysource_t **sourcep) {
  729     isc_entropysource_t *source;
  730     isc_entropy_t *ent;
  731     isc_cbsource_t *cbs;
  732 
  733     source = *sourcep;
  734     *sourcep = NULL;
  735     ent = source->ent;
  736 
  737     ISC_LIST_UNLINK(ent->sources, source, link);
  738     ent->nextsource = NULL;
  739     REQUIRE(ent->nsources > 0);
  740     ent->nsources--;
  741 
  742     switch (source->type) {
  743     case ENTROPY_SOURCETYPE_FILE:
  744         if (! source->bad)
  745             destroyfilesource(&source->sources.file);
  746         break;
  747     case ENTROPY_SOURCETYPE_USOCKET:
  748         if (! source->bad)
  749             destroyusocketsource(&source->sources.usocket);
  750         break;
  751     case ENTROPY_SOURCETYPE_SAMPLE:
  752         samplequeue_release(ent, &source->sources.sample.samplequeue);
  753         break;
  754     case ENTROPY_SOURCETYPE_CALLBACK:
  755         cbs = &source->sources.callback;
  756         if (cbs->start_called && cbs->stopfunc != NULL) {
  757             cbs->stopfunc(source, cbs->arg);
  758             cbs->start_called = false;
  759         }
  760         samplequeue_release(ent, &cbs->samplequeue);
  761         break;
  762     }
  763 
  764     isc_safe_memwipe(source, sizeof(*source));
  765     isc_mem_put(ent->mctx, source, sizeof(*source));
  766 }
  767 
  768 static inline bool
  769 destroy_check(isc_entropy_t *ent) {
  770     isc_entropysource_t *source;
  771 
  772     if (ent->refcnt > 0)
  773         return (false);
  774 
  775     source = ISC_LIST_HEAD(ent->sources);
  776     while (source != NULL) {
  777         switch (source->type) {
  778         case ENTROPY_SOURCETYPE_FILE:
  779         case ENTROPY_SOURCETYPE_USOCKET:
  780             break;
  781         default:
  782             return (false);
  783         }
  784         source = ISC_LIST_NEXT(source, link);
  785     }
  786 
  787     return (true);
  788 }
  789 
  790 static void
  791 destroy(isc_entropy_t **entp) {
  792     isc_entropy_t *ent;
  793     isc_entropysource_t *source;
  794     isc_mem_t *mctx;
  795 
  796     REQUIRE(entp != NULL && *entp != NULL);
  797     ent = *entp;
  798     *entp = NULL;
  799 
  800     LOCK(&ent->lock);
  801 
  802     REQUIRE(ent->refcnt == 0);
  803 
  804     /*
  805      * Here, detach non-sample sources.
  806      */
  807     source = ISC_LIST_HEAD(ent->sources);
  808     while (source != NULL) {
  809         switch(source->type) {
  810         case ENTROPY_SOURCETYPE_FILE:
  811         case ENTROPY_SOURCETYPE_USOCKET:
  812             destroysource(&source);
  813             break;
  814         }
  815         source = ISC_LIST_HEAD(ent->sources);
  816     }
  817 
  818     /*
  819      * If there are other types of sources, we've found a bug.
  820      */
  821     REQUIRE(ISC_LIST_EMPTY(ent->sources));
  822 
  823     mctx = ent->mctx;
  824 
  825     isc_entropypool_invalidate(&ent->pool);
  826 
  827     UNLOCK(&ent->lock);
  828 
  829     DESTROYLOCK(&ent->lock);
  830 
  831     isc_safe_memwipe(ent, sizeof(*ent));
  832     isc_mem_put(mctx, ent, sizeof(*ent));
  833     isc_mem_detach(&mctx);
  834 }
  835 
  836 void
  837 isc_entropy_destroysource(isc_entropysource_t **sourcep) {
  838     isc_entropysource_t *source;
  839     isc_entropy_t *ent;
  840     bool killit;
  841 
  842     REQUIRE(sourcep != NULL);
  843     REQUIRE(VALID_SOURCE(*sourcep));
  844 
  845     source = *sourcep;
  846     *sourcep = NULL;
  847 
  848     ent = source->ent;
  849     REQUIRE(VALID_ENTROPY(ent));
  850 
  851     LOCK(&ent->lock);
  852 
  853     destroysource(&source);
  854 
  855     killit = destroy_check(ent);
  856 
  857     UNLOCK(&ent->lock);
  858 
  859     if (killit)
  860         destroy(&ent);
  861 }
  862 
  863 isc_result_t
  864 isc_entropy_createcallbacksource(isc_entropy_t *ent,
  865                  isc_entropystart_t start,
  866                  isc_entropyget_t get,
  867                  isc_entropystop_t stop,
  868                  void *arg,
  869                  isc_entropysource_t **sourcep)
  870 {
  871     isc_result_t result;
  872     isc_entropysource_t *source;
  873     isc_cbsource_t *cbs;
  874 
  875     REQUIRE(VALID_ENTROPY(ent));
  876     REQUIRE(get != NULL);
  877     REQUIRE(sourcep != NULL && *sourcep == NULL);
  878 
  879     LOCK(&ent->lock);
  880 
  881     source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
  882     if (source == NULL) {
  883         result = ISC_R_NOMEMORY;
  884         goto errout;
  885     }
  886     source->bad = false;
  887 
  888     cbs = &source->sources.callback;
  889 
  890     result = samplesource_allocate(ent, &cbs->samplequeue);
  891     if (result != ISC_R_SUCCESS)
  892         goto errout;
  893 
  894     cbs->start_called = false;
  895     cbs->startfunc = start;
  896     cbs->getfunc = get;
  897     cbs->stopfunc = stop;
  898     cbs->arg = arg;
  899 
  900     /*
  901      * From here down, no failures can occur.
  902      */
  903     source->magic = SOURCE_MAGIC;
  904     source->type = ENTROPY_SOURCETYPE_CALLBACK;
  905     source->ent = ent;
  906     source->total = 0;
  907     memset(source->name, 0, sizeof(source->name));
  908     ISC_LINK_INIT(source, link);
  909 
  910     /*
  911      * Hook it into the entropy system.
  912      */
  913     ISC_LIST_APPEND(ent->sources, source, link);
  914     ent->nsources++;
  915 
  916     *sourcep = source;
  917 
  918     UNLOCK(&ent->lock);
  919     return (ISC_R_SUCCESS);
  920 
  921  errout:
  922     if (source != NULL)
  923         isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
  924 
  925     UNLOCK(&ent->lock);
  926 
  927     return (result);
  928 }
  929 
  930 void
  931 isc_entropy_stopcallbacksources(isc_entropy_t *ent) {
  932     isc_entropysource_t *source;
  933     isc_cbsource_t *cbs;
  934 
  935     REQUIRE(VALID_ENTROPY(ent));
  936 
  937     LOCK(&ent->lock);
  938 
  939     source = ISC_LIST_HEAD(ent->sources);
  940     while (source != NULL) {
  941         if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
  942             cbs = &source->sources.callback;
  943             if (cbs->start_called && cbs->stopfunc != NULL) {
  944                 cbs->stopfunc(source, cbs->arg);
  945                 cbs->start_called = false;
  946             }
  947         }
  948 
  949         source = ISC_LIST_NEXT(source, link);
  950     }
  951 
  952     UNLOCK(&ent->lock);
  953 }
  954 
  955 isc_result_t
  956 isc_entropy_createsamplesource(isc_entropy_t *ent,
  957                    isc_entropysource_t **sourcep)
  958 {
  959     isc_result_t result;
  960     isc_entropysource_t *source;
  961     sample_queue_t *sq;
  962 
  963     REQUIRE(VALID_ENTROPY(ent));
  964     REQUIRE(sourcep != NULL && *sourcep == NULL);
  965 
  966     LOCK(&ent->lock);
  967 
  968     source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
  969     if (source == NULL) {
  970         result = ISC_R_NOMEMORY;
  971         goto errout;
  972     }
  973 
  974     sq = &source->sources.sample.samplequeue;
  975     result = samplesource_allocate(ent, sq);
  976     if (result != ISC_R_SUCCESS)
  977         goto errout;
  978 
  979     /*
  980      * From here down, no failures can occur.
  981      */
  982     source->magic = SOURCE_MAGIC;
  983     source->type = ENTROPY_SOURCETYPE_SAMPLE;
  984     source->ent = ent;
  985     source->total = 0;
  986     memset(source->name, 0, sizeof(source->name));
  987     ISC_LINK_INIT(source, link);
  988 
  989     /*
  990      * Hook it into the entropy system.
  991      */
  992     ISC_LIST_APPEND(ent->sources, source, link);
  993     ent->nsources++;
  994 
  995     *sourcep = source;
  996 
  997     UNLOCK(&ent->lock);
  998     return (ISC_R_SUCCESS);
  999 
 1000  errout:
 1001     if (source != NULL)
 1002         isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
 1003 
 1004     UNLOCK(&ent->lock);
 1005 
 1006     return (result);
 1007 }
 1008 
 1009 /*!
 1010  * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
 1011  * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
 1012  * queue was full when this function was called.
 1013  */
 1014 static isc_result_t
 1015 addsample(sample_queue_t *sq, uint32_t sample, uint32_t extra) {
 1016     if (sq->nsamples >= RND_EVENTQSIZE)
 1017         return (ISC_R_NOMORE);
 1018 
 1019     sq->samples[sq->nsamples] = sample;
 1020     sq->extra[sq->nsamples] = extra;
 1021     sq->nsamples++;
 1022 
 1023     if (sq->nsamples >= RND_EVENTQSIZE)
 1024         return (ISC_R_QUEUEFULL);
 1025 
 1026     return (ISC_R_SUCCESS);
 1027 }
 1028 
 1029 isc_result_t
 1030 isc_entropy_addsample(isc_entropysource_t *source, uint32_t sample,
 1031               uint32_t extra)
 1032 {
 1033     isc_entropy_t *ent;
 1034     sample_queue_t *sq;
 1035     unsigned int entropy;
 1036     isc_result_t result;
 1037 
 1038     REQUIRE(VALID_SOURCE(source));
 1039 
 1040     ent = source->ent;
 1041 
 1042     LOCK(&ent->lock);
 1043 
 1044     sq = &source->sources.sample.samplequeue;
 1045     result = addsample(sq, sample, extra);
 1046     if (result == ISC_R_QUEUEFULL) {
 1047         entropy = crunchsamples(ent, sq);
 1048         add_entropy(ent, entropy);
 1049     }
 1050 
 1051     UNLOCK(&ent->lock);
 1052 
 1053     return (result);
 1054 }
 1055 
 1056 isc_result_t
 1057 isc_entropy_addcallbacksample(isc_entropysource_t *source, uint32_t sample,
 1058                   uint32_t extra)
 1059 {
 1060     sample_queue_t *sq;
 1061     isc_result_t result;
 1062 
 1063     REQUIRE(VALID_SOURCE(source));
 1064     REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
 1065 
 1066     sq = &source->sources.callback.samplequeue;
 1067     result = addsample(sq, sample, extra);
 1068 
 1069     return (result);
 1070 }
 1071 
 1072 void
 1073 isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
 1074             uint32_t entropy)
 1075 {
 1076     REQUIRE(VALID_ENTROPY(ent));
 1077 
 1078     LOCK(&ent->lock);
 1079 
 1080     entropypool_adddata(ent, data, length, entropy);
 1081 
 1082     if (ent->initialized < THRESHOLD_BITS)
 1083         ent->initialized = THRESHOLD_BITS;
 1084 
 1085     UNLOCK(&ent->lock);
 1086 }
 1087 
 1088 static void
 1089 dumpstats(isc_entropy_t *ent, FILE *out) {
 1090     fprintf(out,
 1091         isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
 1092                    ISC_MSG_ENTROPYSTATS,
 1093                    "Entropy pool %p:  refcnt %u cursor %u,"
 1094                    " rotate %u entropy %u pseudo %u nsources %u"
 1095                    " nextsource %p initialized %u initcount %u\n"),
 1096         ent, ent->refcnt,
 1097         ent->pool.cursor, ent->pool.rotate,
 1098         ent->pool.entropy, ent->pool.pseudo,
 1099         ent->nsources, ent->nextsource, ent->initialized,
 1100         ent->initcount);
 1101 }
 1102 
 1103 /*
 1104  * This function ignores locking.  Use at your own risk.
 1105  */
 1106 void
 1107 isc_entropy_stats(isc_entropy_t *ent, FILE *out) {
 1108     REQUIRE(VALID_ENTROPY(ent));
 1109 
 1110     LOCK(&ent->lock);
 1111     dumpstats(ent, out);
 1112     UNLOCK(&ent->lock);
 1113 }
 1114 
 1115 unsigned int
 1116 isc_entropy_status(isc_entropy_t *ent) {
 1117     unsigned int estimate;
 1118 
 1119     LOCK(&ent->lock);
 1120     estimate = ent->pool.entropy;
 1121     UNLOCK(&ent->lock);
 1122 
 1123     return estimate;
 1124 }
 1125 
 1126 void
 1127 isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
 1128     REQUIRE(VALID_ENTROPY(ent));
 1129     REQUIRE(entp != NULL && *entp == NULL);
 1130 
 1131     LOCK(&ent->lock);
 1132 
 1133     ent->refcnt++;
 1134     *entp = ent;
 1135 
 1136     UNLOCK(&ent->lock);
 1137 }
 1138 
 1139 void
 1140 isc_entropy_detach(isc_entropy_t **entp) {
 1141     isc_entropy_t *ent;
 1142     bool killit;
 1143 
 1144     REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
 1145     ent = *entp;
 1146     *entp = NULL;
 1147 
 1148     LOCK(&ent->lock);
 1149 
 1150     REQUIRE(ent->refcnt > 0);
 1151     ent->refcnt--;
 1152 
 1153     killit = destroy_check(ent);
 1154 
 1155     UNLOCK(&ent->lock);
 1156 
 1157     if (killit)
 1158         destroy(&ent);
 1159 }
 1160 
 1161 static isc_result_t
 1162 kbdstart(isc_entropysource_t *source, void *arg, bool blocking) {
 1163     /*
 1164      * The intent of "first" is to provide a warning message only once
 1165      * during the run of a program that might try to gather keyboard
 1166      * entropy multiple times.
 1167      */
 1168     static bool first = true;
 1169 
 1170     UNUSED(arg);
 1171 
 1172     if (! blocking)
 1173         return (ISC_R_NOENTROPY);
 1174 
 1175     if (first) {
 1176         if (source->warn_keyboard)
 1177             fprintf(stderr, "You must use the keyboard to create "
 1178                 "entropy, since your system is lacking\n"
 1179                 "/dev/random (or equivalent)\n\n");
 1180         first = false;
 1181     }
 1182     fprintf(stderr, "start typing:\n");
 1183 
 1184     return (isc_keyboard_open(&source->kbd));
 1185 }
 1186 
 1187 static void
 1188 kbdstop(isc_entropysource_t *source, void *arg) {
 1189 
 1190     UNUSED(arg);
 1191 
 1192     if (! isc_keyboard_canceled(&source->kbd))
 1193         fprintf(stderr, "stop typing.\r\n");
 1194 
 1195     (void)isc_keyboard_close(&source->kbd, 3);
 1196 }
 1197 
 1198 static isc_result_t
 1199 kbdget(isc_entropysource_t *source, void *arg, bool blocking) {
 1200     isc_result_t result;
 1201     isc_time_t t;
 1202     uint32_t sample;
 1203     uint32_t extra;
 1204     unsigned char c;
 1205 
 1206     UNUSED(arg);
 1207 
 1208     if (!blocking)
 1209         return (ISC_R_NOTBLOCKING);
 1210 
 1211     result = isc_keyboard_getchar(&source->kbd, &c);
 1212     if (result != ISC_R_SUCCESS)
 1213         return (result);
 1214 
 1215     TIME_NOW(&t);
 1216 
 1217     sample = isc_time_nanoseconds(&t);
 1218     extra = c;
 1219 
 1220     result = isc_entropy_addcallbacksample(source, sample, extra);
 1221     if (result != ISC_R_SUCCESS) {
 1222         fprintf(stderr, "\r\n");
 1223         return (result);
 1224     }
 1225 
 1226     fprintf(stderr, ".");
 1227     fflush(stderr);
 1228 
 1229     return (result);
 1230 }
 1231 
 1232 isc_result_t
 1233 isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
 1234               const char *randomfile, int use_keyboard)
 1235 {
 1236     isc_result_t result;
 1237     isc_result_t final_result = ISC_R_NOENTROPY;
 1238     bool userfile = true;
 1239 
 1240     REQUIRE(VALID_ENTROPY(ectx));
 1241     REQUIRE(source != NULL && *source == NULL);
 1242     REQUIRE(use_keyboard == ISC_ENTROPY_KEYBOARDYES ||
 1243         use_keyboard == ISC_ENTROPY_KEYBOARDNO  ||
 1244         use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
 1245 
 1246 #ifdef PKCS11CRYPTO
 1247     if (randomfile != NULL)
 1248         pk11_rand_seed_fromfile(randomfile);
 1249 #endif
 1250 
 1251 #ifdef PATH_RANDOMDEV
 1252     if (randomfile == NULL) {
 1253         randomfile = PATH_RANDOMDEV;
 1254         userfile = false;
 1255     }
 1256 #endif
 1257 
 1258     if (randomfile != NULL && use_keyboard != ISC_ENTROPY_KEYBOARDYES) {
 1259         result = isc_entropy_createfilesource(ectx, randomfile);
 1260         if (result == ISC_R_SUCCESS &&
 1261             use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE)
 1262             use_keyboard = ISC_ENTROPY_KEYBOARDNO;
 1263         if (result != ISC_R_SUCCESS && userfile)
 1264             return (result);
 1265 
 1266         final_result = result;
 1267     }
 1268 
 1269     if (use_keyboard != ISC_ENTROPY_KEYBOARDNO) {
 1270         result = isc_entropy_createcallbacksource(ectx, kbdstart,
 1271                               kbdget, kbdstop,
 1272                               NULL, source);
 1273         if (result == ISC_R_SUCCESS)
 1274             (*source)->warn_keyboard =
 1275                 (use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
 1276 
 1277         if (final_result != ISC_R_SUCCESS)
 1278             final_result = result;
 1279     }
 1280 
 1281     /*
 1282      * final_result is ISC_R_SUCCESS if at least one source of entropy
 1283      * could be started, otherwise it is the error from the most recently
 1284      * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
 1285      * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
 1286      */
 1287     return (final_result);
 1288 }