1 /* $NetBSD: entropy.c,v 1.5 2014/12/10 04:37:59 christos Exp $ */
4 * Copyright (C) 2004-2007, 2009, 2010, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: entropy.c,v 1.22 2010/08/10 23:48:19 tbox Exp */
24 * This is the system independent part of the entropy module. It is
25 * compiled via inclusion from the relevant OS source file, ie,
26 * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c.
28 * \author Much of this code is modeled after the NetBSD /dev/random implementation,
29 * written by Michael Graff <explorer@netbsd.org>.
36 #include <isc/buffer.h>
37 #include <isc/entropy.h>
38 #include <isc/keyboard.h>
40 #include <isc/magic.h>
43 #include <isc/mutex.h>
44 #include <isc/platform.h>
45 #include <isc/region.h>
47 #include <isc/string.h>
52 #include <pk11/pk11.h>
55 #define ENTROPY_MAGIC ISC_MAGIC('E', 'n', 't', 'e')
56 #define SOURCE_MAGIC ISC_MAGIC('E', 'n', 't', 's')
58 #define VALID_ENTROPY(e) ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
59 #define VALID_SOURCE(s) ISC_MAGIC_VALID(s, SOURCE_MAGIC)
62 *** "constants." Do not change these unless you _really_ know what
67 * Size of entropy pool in 32-bit words. This _MUST_ be a power of 2.
69 #define RND_POOLWORDS 128
71 #define RND_POOLBYTES (RND_POOLWORDS * 4)
73 #define RND_POOLBITS (RND_POOLWORDS * 32)
76 * Number of bytes returned per hash. This must be true:
77 * threshold * 2 <= digest_size_in_bytes
79 #define RND_ENTROPY_THRESHOLD 10
80 #define THRESHOLD_BITS (RND_ENTROPY_THRESHOLD * 8)
83 * Size of the input event queue in samples.
85 #define RND_EVENTQSIZE 32
88 * The number of times we'll "reseed" for pseudorandom seeds. This is an
89 * extremely weak pseudorandom seed. If the caller is using lots of
90 * pseudorandom data and they cannot provide a stronger random source,
91 * there is little we can do other than hope they're smart enough to
92 * call _adddata() with something better than we can come up with.
94 #define RND_INITIALIZE 128
98 isc_uint32_t cursor
; /*%< current add point in the pool */
99 isc_uint32_t entropy
; /*%< current entropy estimate in bits */
100 isc_uint32_t pseudo
; /*%< bits extracted in pseudorandom */
101 isc_uint32_t rotate
; /*%< how many bits to rotate by */
102 isc_uint32_t pool
[RND_POOLWORDS
]; /*%< random pool data */
110 isc_uint32_t initialized
;
111 isc_uint32_t initcount
;
112 isc_entropypool_t pool
;
113 unsigned int nsources
;
114 isc_entropysource_t
*nextsource
;
115 ISC_LIST(isc_entropysource_t
) sources
;
120 isc_uint32_t last_time
; /*%< last time recorded */
121 isc_uint32_t last_delta
; /*%< last delta value */
122 isc_uint32_t last_delta2
; /*%< last delta2 value */
123 isc_uint32_t nsamples
; /*%< number of samples filled in */
124 isc_uint32_t
*samples
; /*%< the samples */
125 isc_uint32_t
*extra
; /*%< extra samples added in */
129 sample_queue_t samplequeue
;
130 } isc_entropysamplesource_t
;
133 isc_boolean_t start_called
;
134 isc_entropystart_t startfunc
;
135 isc_entropyget_t getfunc
;
136 isc_entropystop_t stopfunc
;
138 sample_queue_t samplequeue
;
142 FILESOURCE_HANDLE_TYPE handle
;
143 } isc_entropyfilesource_t
;
145 struct isc_entropysource
{
149 isc_uint32_t total
; /*%< entropy from this source */
150 ISC_LINK(isc_entropysource_t
) link
;
153 isc_boolean_t warn_keyboard
;
156 isc_entropysamplesource_t sample
;
157 isc_entropyfilesource_t file
;
158 isc_cbsource_t callback
;
159 isc_entropyusocketsource_t usocket
;
163 #define ENTROPY_SOURCETYPE_SAMPLE 1 /*%< Type is a sample source */
164 #define ENTROPY_SOURCETYPE_FILE 2 /*%< Type is a file source */
165 #define ENTROPY_SOURCETYPE_CALLBACK 3 /*%< Type is a callback source */
166 #define ENTROPY_SOURCETYPE_USOCKET 4 /*%< Type is a Unix socket source */
170 * The random pool "taps"
181 * Declarations for function provided by the system dependent sources that
185 fillpool(isc_entropy_t
*, unsigned int, isc_boolean_t
);
188 wait_for_sources(isc_entropy_t
*);
191 destroyfilesource(isc_entropyfilesource_t
*source
);
194 destroyusocketsource(isc_entropyusocketsource_t
*source
);
199 samplequeue_release(isc_entropy_t
*ent
, sample_queue_t
*sq
) {
200 REQUIRE(sq
->samples
!= NULL
);
201 REQUIRE(sq
->extra
!= NULL
);
203 isc_mem_put(ent
->mctx
, sq
->samples
, RND_EVENTQSIZE
* 4);
204 isc_mem_put(ent
->mctx
, sq
->extra
, RND_EVENTQSIZE
* 4);
210 samplesource_allocate(isc_entropy_t
*ent
, sample_queue_t
*sq
) {
211 sq
->samples
= isc_mem_get(ent
->mctx
, RND_EVENTQSIZE
* 4);
212 if (sq
->samples
== NULL
)
213 return (ISC_R_NOMEMORY
);
215 sq
->extra
= isc_mem_get(ent
->mctx
, RND_EVENTQSIZE
* 4);
216 if (sq
->extra
== NULL
) {
217 isc_mem_put(ent
->mctx
, sq
->samples
, RND_EVENTQSIZE
* 4);
219 return (ISC_R_NOMEMORY
);
224 return (ISC_R_SUCCESS
);
228 * Add in entropy, even when the value we're adding in could be
232 add_entropy(isc_entropy_t
*ent
, isc_uint32_t entropy
) {
233 /* clamp input. Yes, this must be done. */
234 entropy
= ISC_MIN(entropy
, RND_POOLBITS
);
235 /* Add in the entropy we already have. */
236 entropy
+= ent
->pool
.entropy
;
238 ent
->pool
.entropy
= ISC_MIN(entropy
, RND_POOLBITS
);
242 * Decrement the amount of entropy the pool has.
245 subtract_entropy(isc_entropy_t
*ent
, isc_uint32_t entropy
) {
246 entropy
= ISC_MIN(entropy
, ent
->pool
.entropy
);
247 ent
->pool
.entropy
-= entropy
;
251 * Add in entropy, even when the value we're adding in could be
255 add_pseudo(isc_entropy_t
*ent
, isc_uint32_t pseudo
) {
256 /* clamp input. Yes, this must be done. */
257 pseudo
= ISC_MIN(pseudo
, RND_POOLBITS
* 8);
258 /* Add in the pseudo we already have. */
259 pseudo
+= ent
->pool
.pseudo
;
261 ent
->pool
.pseudo
= ISC_MIN(pseudo
, RND_POOLBITS
* 8);
265 * Decrement the amount of pseudo the pool has.
268 subtract_pseudo(isc_entropy_t
*ent
, isc_uint32_t pseudo
) {
269 pseudo
= ISC_MIN(pseudo
, ent
->pool
.pseudo
);
270 ent
->pool
.pseudo
-= pseudo
;
274 * Add one word to the pool, rotating the input as needed.
277 entropypool_add_word(isc_entropypool_t
*rp
, isc_uint32_t val
) {
279 * Steal some values out of the pool, and xor them into the
280 * word we were given.
282 * Mix the new value into the pool using xor. This will
283 * prevent the actual values from being known to the caller
284 * since the previous values are assumed to be unknown as well.
286 val
^= rp
->pool
[(rp
->cursor
+ TAP1
) & (RND_POOLWORDS
- 1)];
287 val
^= rp
->pool
[(rp
->cursor
+ TAP2
) & (RND_POOLWORDS
- 1)];
288 val
^= rp
->pool
[(rp
->cursor
+ TAP3
) & (RND_POOLWORDS
- 1)];
289 val
^= rp
->pool
[(rp
->cursor
+ TAP4
) & (RND_POOLWORDS
- 1)];
290 val
^= rp
->pool
[(rp
->cursor
+ TAP5
) & (RND_POOLWORDS
- 1)];
292 rp
->pool
[rp
->cursor
++] ^= val
;
294 rp
->pool
[rp
->cursor
++] ^=
295 ((val
<< rp
->rotate
) | (val
>> (32 - rp
->rotate
)));
298 * If we have looped around the pool, increment the rotate
299 * variable so the next value will get xored in rotated to
300 * a different position.
301 * Increment by a value that is relatively prime to the word size
302 * to try to spread the bits throughout the pool quickly when the
305 if (rp
->cursor
== RND_POOLWORDS
) {
307 rp
->rotate
= (rp
->rotate
+ 7) & 31;
312 * Add a buffer's worth of data to the pool.
314 * Requires that the lock is held on the entropy pool.
317 entropypool_adddata(isc_entropy_t
*ent
, void *p
, unsigned int len
,
318 isc_uint32_t entropy
)
324 addr
= (unsigned long)p
;
327 if ((addr
& 0x03U
) != 0U) {
334 val
= val
<< 8 | *buf
++;
337 val
= val
<< 8 | *buf
++;
341 entropypool_add_word(&ent
->pool
, val
);
344 for (; len
> 3; len
-= 4) {
345 val
= *((isc_uint32_t
*)buf
);
347 entropypool_add_word(&ent
->pool
, val
);
357 val
= val
<< 8 | *buf
++;
359 val
= val
<< 8 | *buf
++;
362 entropypool_add_word(&ent
->pool
, val
);
365 add_entropy(ent
, entropy
);
366 subtract_pseudo(ent
, entropy
);
370 reseed(isc_entropy_t
*ent
) {
374 if (ent
->initcount
== 0) {
376 entropypool_adddata(ent
, &pid
, sizeof(pid
), 0);
378 entropypool_adddata(ent
, &pid
, sizeof(pid
), 0);
382 * After we've reseeded 100 times, only add new timing info every
383 * 50 requests. This will keep us from using lots and lots of
384 * CPU just to return bad pseudorandom data anyway.
386 if (ent
->initcount
> 100)
387 if ((ent
->initcount
% 50) != 0)
391 entropypool_adddata(ent
, &t
, sizeof(t
), 0);
395 static inline unsigned int
396 estimate_entropy(sample_queue_t
*sq
, isc_uint32_t t
) {
402 * If the time counter has overflowed, calculate the real difference.
403 * If it has not, it is simpler.
405 if (t
< sq
->last_time
)
406 delta
= UINT_MAX
- sq
->last_time
+ t
;
408 delta
= sq
->last_time
- t
;
414 * Calculate the second and third order differentials
416 delta2
= sq
->last_delta
- delta
;
420 delta3
= sq
->last_delta2
- delta2
;
425 sq
->last_delta
= delta
;
426 sq
->last_delta2
= delta2
;
429 * If any delta is 0, we got no entropy. If all are non-zero, we
430 * might have something.
432 if (delta
== 0 || delta2
== 0 || delta3
== 0)
436 * We could find the smallest delta and claim we got log2(delta)
437 * bits, but for now return that we found 1 bit.
443 crunchsamples(isc_entropy_t
*ent
, sample_queue_t
*sq
) {
447 if (sq
->nsamples
< 6)
451 sq
->last_time
= sq
->samples
[0];
456 * Prime the values by adding in the first 4 samples in. This
457 * should completely initialize the delta calculations.
459 for (ns
= 0; ns
< 4; ns
++)
460 (void)estimate_entropy(sq
, sq
->samples
[ns
]);
462 for (ns
= 4; ns
< sq
->nsamples
; ns
++)
463 added
+= estimate_entropy(sq
, sq
->samples
[ns
]);
465 entropypool_adddata(ent
, sq
->samples
, sq
->nsamples
* 4, added
);
466 entropypool_adddata(ent
, sq
->extra
, sq
->nsamples
* 4, 0);
469 * Move the last 4 samples into the first 4 positions, and start
470 * adding new samples from that point.
472 for (ns
= 0; ns
< 4; ns
++) {
473 sq
->samples
[ns
] = sq
->samples
[sq
->nsamples
- 4 + ns
];
474 sq
->extra
[ns
] = sq
->extra
[sq
->nsamples
- 4 + ns
];
483 get_from_callback(isc_entropysource_t
*source
, unsigned int desired
,
484 isc_boolean_t blocking
)
486 isc_entropy_t
*ent
= source
->ent
;
487 isc_cbsource_t
*cbs
= &source
->sources
.callback
;
498 if (!cbs
->start_called
&& cbs
->startfunc
!= NULL
) {
499 result
= cbs
->startfunc(source
, cbs
->arg
, blocking
);
500 if (result
!= ISC_R_SUCCESS
)
502 cbs
->start_called
= ISC_TRUE
;
506 result
= ISC_R_SUCCESS
;
507 while (desired
> 0 && result
== ISC_R_SUCCESS
) {
508 result
= cbs
->getfunc(source
, cbs
->arg
, blocking
);
509 if (result
== ISC_R_QUEUEFULL
) {
510 got
= crunchsamples(ent
, &cbs
->samplequeue
);
512 desired
-= ISC_MIN(got
, desired
);
513 result
= ISC_R_SUCCESS
;
514 } else if (result
!= ISC_R_SUCCESS
&&
515 result
!= ISC_R_NOTBLOCKING
)
516 source
->bad
= ISC_TRUE
;
524 * Extract some number of bytes from the random pool, decreasing the
525 * estimate of randomness as each byte is extracted.
527 * Do this by stiring the pool and returning a part of hash as randomness.
528 * Note that no secrets are given away here since parts of the hash are
529 * xored together before returned.
531 * Honor the request from the caller to only return good data, any data,
535 isc_entropy_getdata(isc_entropy_t
*ent
, void *data
, unsigned int length
,
536 unsigned int *returned
, unsigned int flags
)
540 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
541 isc_uint32_t remain
, deltae
, count
, total
;
543 isc_boolean_t goodonly
, partial
, blocking
;
545 REQUIRE(VALID_ENTROPY(ent
));
546 REQUIRE(data
!= NULL
);
549 goodonly
= ISC_TF((flags
& ISC_ENTROPY_GOODONLY
) != 0);
550 partial
= ISC_TF((flags
& ISC_ENTROPY_PARTIAL
) != 0);
551 blocking
= ISC_TF((flags
& ISC_ENTROPY_BLOCKING
) != 0);
553 REQUIRE(!partial
|| returned
!= NULL
);
560 while (remain
!= 0) {
561 count
= ISC_MIN(remain
, RND_ENTROPY_THRESHOLD
);
564 * If we are extracting good data only, make certain we
565 * have enough data in our pool for this pass. If we don't,
566 * get some, and fail if we can't, and partial returns
570 unsigned int fillcount
;
572 fillcount
= ISC_MAX(remain
* 8, count
* 8);
575 * If, however, we have at least THRESHOLD_BITS
576 * of entropy in the pool, don't block here. It is
577 * better to drain the pool once in a while and
578 * then refill it than it is to constantly keep the
581 if (ent
->pool
.entropy
>= THRESHOLD_BITS
)
582 fillpool(ent
, fillcount
, ISC_FALSE
);
584 fillpool(ent
, fillcount
, blocking
);
587 * Verify that we got enough entropy to do one
588 * extraction. If we didn't, bail.
590 if (ent
->pool
.entropy
< THRESHOLD_BITS
) {
598 * If we've extracted half our pool size in bits
599 * since the last refresh, try to refresh here.
601 if (ent
->initialized
< THRESHOLD_BITS
)
602 fillpool(ent
, THRESHOLD_BITS
, blocking
);
604 fillpool(ent
, 0, ISC_FALSE
);
607 * If we've not initialized with enough good random
608 * data, seed with our crappy code.
610 if (ent
->initialized
< THRESHOLD_BITS
)
614 isc_sha1_init(&hash
);
615 isc_sha1_update(&hash
, (void *)(ent
->pool
.pool
),
617 isc_sha1_final(&hash
, digest
);
620 * Stir the extracted data (all of it) back into the pool.
622 entropypool_adddata(ent
, digest
, ISC_SHA1_DIGESTLENGTH
, 0);
624 for (i
= 0; i
< count
; i
++)
625 buf
[i
] = digest
[i
] ^ digest
[i
+ RND_ENTROPY_THRESHOLD
];
631 deltae
= ISC_MIN(deltae
, ent
->pool
.entropy
);
633 subtract_entropy(ent
, deltae
);
634 add_pseudo(ent
, count
* 8);
638 memset(digest
, 0, sizeof(digest
));
640 if (returned
!= NULL
)
641 *returned
= (length
- remain
);
645 return (ISC_R_SUCCESS
);
648 /* put the entropy we almost extracted back */
649 add_entropy(ent
, total
);
650 memset(data
, 0, length
);
651 memset(digest
, 0, sizeof(digest
));
652 if (returned
!= NULL
)
657 return (ISC_R_NOENTROPY
);
661 isc_entropypool_init(isc_entropypool_t
*pool
) {
662 pool
->cursor
= RND_POOLWORDS
- 1;
666 memset(pool
->pool
, 0, RND_POOLBYTES
);
670 isc_entropypool_invalidate(isc_entropypool_t
*pool
) {
675 memset(pool
->pool
, 0, RND_POOLBYTES
);
679 isc_entropy_create(isc_mem_t
*mctx
, isc_entropy_t
**entp
) {
683 REQUIRE(mctx
!= NULL
);
684 REQUIRE(entp
!= NULL
&& *entp
== NULL
);
686 ent
= isc_mem_get(mctx
, sizeof(isc_entropy_t
));
688 return (ISC_R_NOMEMORY
);
693 result
= isc_mutex_init(&ent
->lock
);
694 if (result
!= ISC_R_SUCCESS
)
698 * From here down, no failures will/can occur.
700 ISC_LIST_INIT(ent
->sources
);
701 ent
->nextsource
= NULL
;
704 isc_mem_attach(mctx
, &ent
->mctx
);
706 ent
->initialized
= 0;
708 ent
->magic
= ENTROPY_MAGIC
;
710 isc_entropypool_init(&ent
->pool
);
713 return (ISC_R_SUCCESS
);
716 isc_mem_put(mctx
, ent
, sizeof(isc_entropy_t
));
722 * Requires "ent" be locked.
725 destroysource(isc_entropysource_t
**sourcep
) {
726 isc_entropysource_t
*source
;
734 ISC_LIST_UNLINK(ent
->sources
, source
, link
);
735 ent
->nextsource
= NULL
;
736 REQUIRE(ent
->nsources
> 0);
739 switch (source
->type
) {
740 case ENTROPY_SOURCETYPE_FILE
:
742 destroyfilesource(&source
->sources
.file
);
744 case ENTROPY_SOURCETYPE_USOCKET
:
746 destroyusocketsource(&source
->sources
.usocket
);
748 case ENTROPY_SOURCETYPE_SAMPLE
:
749 samplequeue_release(ent
, &source
->sources
.sample
.samplequeue
);
751 case ENTROPY_SOURCETYPE_CALLBACK
:
752 cbs
= &source
->sources
.callback
;
753 if (cbs
->start_called
&& cbs
->stopfunc
!= NULL
) {
754 cbs
->stopfunc(source
, cbs
->arg
);
755 cbs
->start_called
= ISC_FALSE
;
757 samplequeue_release(ent
, &cbs
->samplequeue
);
761 memset(source
, 0, sizeof(isc_entropysource_t
));
763 isc_mem_put(ent
->mctx
, source
, sizeof(isc_entropysource_t
));
766 static inline isc_boolean_t
767 destroy_check(isc_entropy_t
*ent
) {
768 isc_entropysource_t
*source
;
773 source
= ISC_LIST_HEAD(ent
->sources
);
774 while (source
!= NULL
) {
775 switch (source
->type
) {
776 case ENTROPY_SOURCETYPE_FILE
:
777 case ENTROPY_SOURCETYPE_USOCKET
:
782 source
= ISC_LIST_NEXT(source
, link
);
789 destroy(isc_entropy_t
**entp
) {
791 isc_entropysource_t
*source
;
794 REQUIRE(entp
!= NULL
&& *entp
!= NULL
);
800 REQUIRE(ent
->refcnt
== 0);
803 * Here, detach non-sample sources.
805 source
= ISC_LIST_HEAD(ent
->sources
);
806 while (source
!= NULL
) {
807 switch(source
->type
) {
808 case ENTROPY_SOURCETYPE_FILE
:
809 case ENTROPY_SOURCETYPE_USOCKET
:
810 destroysource(&source
);
813 source
= ISC_LIST_HEAD(ent
->sources
);
817 * If there are other types of sources, we've found a bug.
819 REQUIRE(ISC_LIST_EMPTY(ent
->sources
));
823 isc_entropypool_invalidate(&ent
->pool
);
827 DESTROYLOCK(&ent
->lock
);
829 memset(ent
, 0, sizeof(isc_entropy_t
));
830 isc_mem_put(mctx
, ent
, sizeof(isc_entropy_t
));
831 isc_mem_detach(&mctx
);
835 isc_entropy_destroysource(isc_entropysource_t
**sourcep
) {
836 isc_entropysource_t
*source
;
838 isc_boolean_t killit
;
840 REQUIRE(sourcep
!= NULL
);
841 REQUIRE(VALID_SOURCE(*sourcep
));
847 REQUIRE(VALID_ENTROPY(ent
));
851 destroysource(&source
);
853 killit
= destroy_check(ent
);
862 isc_entropy_createcallbacksource(isc_entropy_t
*ent
,
863 isc_entropystart_t start
,
864 isc_entropyget_t get
,
865 isc_entropystop_t stop
,
867 isc_entropysource_t
**sourcep
)
870 isc_entropysource_t
*source
;
873 REQUIRE(VALID_ENTROPY(ent
));
874 REQUIRE(get
!= NULL
);
875 REQUIRE(sourcep
!= NULL
&& *sourcep
== NULL
);
879 source
= isc_mem_get(ent
->mctx
, sizeof(isc_entropysource_t
));
880 if (source
== NULL
) {
881 result
= ISC_R_NOMEMORY
;
884 source
->bad
= ISC_FALSE
;
886 cbs
= &source
->sources
.callback
;
888 result
= samplesource_allocate(ent
, &cbs
->samplequeue
);
889 if (result
!= ISC_R_SUCCESS
)
892 cbs
->start_called
= ISC_FALSE
;
893 cbs
->startfunc
= start
;
895 cbs
->stopfunc
= stop
;
899 * From here down, no failures can occur.
901 source
->magic
= SOURCE_MAGIC
;
902 source
->type
= ENTROPY_SOURCETYPE_CALLBACK
;
905 memset(source
->name
, 0, sizeof(source
->name
));
906 ISC_LINK_INIT(source
, link
);
909 * Hook it into the entropy system.
911 ISC_LIST_APPEND(ent
->sources
, source
, link
);
917 return (ISC_R_SUCCESS
);
921 isc_mem_put(ent
->mctx
, source
, sizeof(isc_entropysource_t
));
929 isc_entropy_stopcallbacksources(isc_entropy_t
*ent
) {
930 isc_entropysource_t
*source
;
933 REQUIRE(VALID_ENTROPY(ent
));
937 source
= ISC_LIST_HEAD(ent
->sources
);
938 while (source
!= NULL
) {
939 if (source
->type
== ENTROPY_SOURCETYPE_CALLBACK
) {
940 cbs
= &source
->sources
.callback
;
941 if (cbs
->start_called
&& cbs
->stopfunc
!= NULL
) {
942 cbs
->stopfunc(source
, cbs
->arg
);
943 cbs
->start_called
= ISC_FALSE
;
947 source
= ISC_LIST_NEXT(source
, link
);
954 isc_entropy_createsamplesource(isc_entropy_t
*ent
,
955 isc_entropysource_t
**sourcep
)
958 isc_entropysource_t
*source
;
961 REQUIRE(VALID_ENTROPY(ent
));
962 REQUIRE(sourcep
!= NULL
&& *sourcep
== NULL
);
966 source
= isc_mem_get(ent
->mctx
, sizeof(isc_entropysource_t
));
967 if (source
== NULL
) {
968 result
= ISC_R_NOMEMORY
;
972 sq
= &source
->sources
.sample
.samplequeue
;
973 result
= samplesource_allocate(ent
, sq
);
974 if (result
!= ISC_R_SUCCESS
)
978 * From here down, no failures can occur.
980 source
->magic
= SOURCE_MAGIC
;
981 source
->type
= ENTROPY_SOURCETYPE_SAMPLE
;
984 memset(source
->name
, 0, sizeof(source
->name
));
985 ISC_LINK_INIT(source
, link
);
988 * Hook it into the entropy system.
990 ISC_LIST_APPEND(ent
->sources
, source
, link
);
996 return (ISC_R_SUCCESS
);
1000 isc_mem_put(ent
->mctx
, source
, sizeof(isc_entropysource_t
));
1008 * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
1009 * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
1010 * queue was full when this function was called.
1013 addsample(sample_queue_t
*sq
, isc_uint32_t sample
, isc_uint32_t extra
) {
1014 if (sq
->nsamples
>= RND_EVENTQSIZE
)
1015 return (ISC_R_NOMORE
);
1017 sq
->samples
[sq
->nsamples
] = sample
;
1018 sq
->extra
[sq
->nsamples
] = extra
;
1021 if (sq
->nsamples
>= RND_EVENTQSIZE
)
1022 return (ISC_R_QUEUEFULL
);
1024 return (ISC_R_SUCCESS
);
1028 isc_entropy_addsample(isc_entropysource_t
*source
, isc_uint32_t sample
,
1033 unsigned int entropy
;
1034 isc_result_t result
;
1036 REQUIRE(VALID_SOURCE(source
));
1042 sq
= &source
->sources
.sample
.samplequeue
;
1043 result
= addsample(sq
, sample
, extra
);
1044 if (result
== ISC_R_QUEUEFULL
) {
1045 entropy
= crunchsamples(ent
, sq
);
1046 add_entropy(ent
, entropy
);
1055 isc_entropy_addcallbacksample(isc_entropysource_t
*source
, isc_uint32_t sample
,
1059 isc_result_t result
;
1061 REQUIRE(VALID_SOURCE(source
));
1062 REQUIRE(source
->type
== ENTROPY_SOURCETYPE_CALLBACK
);
1064 sq
= &source
->sources
.callback
.samplequeue
;
1065 result
= addsample(sq
, sample
, extra
);
1071 isc_entropy_putdata(isc_entropy_t
*ent
, void *data
, unsigned int length
,
1072 isc_uint32_t entropy
)
1074 REQUIRE(VALID_ENTROPY(ent
));
1078 entropypool_adddata(ent
, data
, length
, entropy
);
1080 if (ent
->initialized
< THRESHOLD_BITS
)
1081 ent
->initialized
= THRESHOLD_BITS
;
1087 dumpstats(isc_entropy_t
*ent
, FILE *out
) {
1089 isc_msgcat_get(isc_msgcat
, ISC_MSGSET_ENTROPY
,
1090 ISC_MSG_ENTROPYSTATS
,
1091 "Entropy pool %p: refcnt %u cursor %u,"
1092 " rotate %u entropy %u pseudo %u nsources %u"
1093 " nextsource %p initialized %u initcount %u\n"),
1095 ent
->pool
.cursor
, ent
->pool
.rotate
,
1096 ent
->pool
.entropy
, ent
->pool
.pseudo
,
1097 ent
->nsources
, ent
->nextsource
, ent
->initialized
,
1102 * This function ignores locking. Use at your own risk.
1105 isc_entropy_stats(isc_entropy_t
*ent
, FILE *out
) {
1106 REQUIRE(VALID_ENTROPY(ent
));
1109 dumpstats(ent
, out
);
1114 isc_entropy_status(isc_entropy_t
*ent
) {
1115 unsigned int estimate
;
1118 estimate
= ent
->pool
.entropy
;
1125 isc_entropy_attach(isc_entropy_t
*ent
, isc_entropy_t
**entp
) {
1126 REQUIRE(VALID_ENTROPY(ent
));
1127 REQUIRE(entp
!= NULL
&& *entp
== NULL
);
1138 isc_entropy_detach(isc_entropy_t
**entp
) {
1140 isc_boolean_t killit
;
1142 REQUIRE(entp
!= NULL
&& VALID_ENTROPY(*entp
));
1148 REQUIRE(ent
->refcnt
> 0);
1151 killit
= destroy_check(ent
);
1160 kbdstart(isc_entropysource_t
*source
, void *arg
, isc_boolean_t blocking
) {
1162 * The intent of "first" is to provide a warning message only once
1163 * during the run of a program that might try to gather keyboard
1164 * entropy multiple times.
1166 static isc_boolean_t first
= ISC_TRUE
;
1171 return (ISC_R_NOENTROPY
);
1174 if (source
->warn_keyboard
)
1175 fprintf(stderr
, "You must use the keyboard to create "
1176 "entropy, since your system is lacking\n"
1177 "/dev/random (or equivalent)\n\n");
1180 fprintf(stderr
, "start typing:\n");
1182 return (isc_keyboard_open(&source
->kbd
));
1186 kbdstop(isc_entropysource_t
*source
, void *arg
) {
1190 if (! isc_keyboard_canceled(&source
->kbd
))
1191 fprintf(stderr
, "stop typing.\r\n");
1193 (void)isc_keyboard_close(&source
->kbd
, 3);
1197 kbdget(isc_entropysource_t
*source
, void *arg
, isc_boolean_t blocking
) {
1198 isc_result_t result
;
1200 isc_uint32_t sample
;
1207 return (ISC_R_NOTBLOCKING
);
1209 result
= isc_keyboard_getchar(&source
->kbd
, &c
);
1210 if (result
!= ISC_R_SUCCESS
)
1215 sample
= isc_time_nanoseconds(&t
);
1218 result
= isc_entropy_addcallbacksample(source
, sample
, extra
);
1219 if (result
!= ISC_R_SUCCESS
) {
1220 fprintf(stderr
, "\r\n");
1224 fprintf(stderr
, ".");
1231 isc_entropy_usebestsource(isc_entropy_t
*ectx
, isc_entropysource_t
**source
,
1232 const char *randomfile
, int use_keyboard
)
1234 isc_result_t result
;
1235 isc_result_t final_result
= ISC_R_NOENTROPY
;
1236 isc_boolean_t userfile
= ISC_TRUE
;
1238 REQUIRE(VALID_ENTROPY(ectx
));
1239 REQUIRE(source
!= NULL
&& *source
== NULL
);
1240 REQUIRE(use_keyboard
== ISC_ENTROPY_KEYBOARDYES
||
1241 use_keyboard
== ISC_ENTROPY_KEYBOARDNO
||
1242 use_keyboard
== ISC_ENTROPY_KEYBOARDMAYBE
);
1245 if (randomfile
!= NULL
)
1246 pk11_rand_seed_fromfile(randomfile
);
1249 #ifdef PATH_RANDOMDEV
1250 if (randomfile
== NULL
) {
1251 randomfile
= PATH_RANDOMDEV
;
1252 userfile
= ISC_FALSE
;
1256 if (randomfile
!= NULL
&& use_keyboard
!= ISC_ENTROPY_KEYBOARDYES
) {
1257 result
= isc_entropy_createfilesource(ectx
, randomfile
);
1258 if (result
== ISC_R_SUCCESS
&&
1259 use_keyboard
== ISC_ENTROPY_KEYBOARDMAYBE
)
1260 use_keyboard
= ISC_ENTROPY_KEYBOARDNO
;
1261 if (result
!= ISC_R_SUCCESS
&& userfile
)
1264 final_result
= result
;
1267 if (use_keyboard
!= ISC_ENTROPY_KEYBOARDNO
) {
1268 result
= isc_entropy_createcallbacksource(ectx
, kbdstart
,
1271 if (result
== ISC_R_SUCCESS
)
1272 (*source
)->warn_keyboard
=
1273 ISC_TF(use_keyboard
==
1274 ISC_ENTROPY_KEYBOARDMAYBE
);
1276 if (final_result
!= ISC_R_SUCCESS
)
1277 final_result
= result
;
1281 * final_result is ISC_R_SUCCESS if at least one source of entropy
1282 * could be started, otherwise it is the error from the most recently
1283 * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
1284 * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
1286 return (final_result
);