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

https://bitbucket.org/freebsd/freebsd-head/ · C · 1277 lines · 823 code · 234 blank · 220 comment · 171 complexity · b85226294bc3e4c735e5bac93a513575 MD5 · raw file

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