| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: kern_rndq.c,v 1.60 2015/04/14 13:57:35 riastradh Exp $ */ | | 1 | /* $NetBSD: kern_rndq.c,v 1.61 2015/04/14 14:11:51 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1997-2013 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1997-2013 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | | 8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. |
9 | * This code uses ideas and algorithms from the Linux driver written by | | 9 | * This code uses ideas and algorithms from the Linux driver written by |
10 | * Ted Ts'o. | | 10 | * Ted Ts'o. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -22,27 +22,27 @@ | | | @@ -22,27 +22,27 @@ |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. | | 31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.60 2015/04/14 13:57:35 riastradh Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.61 2015/04/14 14:11:51 riastradh Exp $"); |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/atomic.h> | | 38 | #include <sys/atomic.h> |
39 | #include <sys/ioctl.h> | | 39 | #include <sys/ioctl.h> |
40 | #include <sys/fcntl.h> | | 40 | #include <sys/fcntl.h> |
41 | #include <sys/select.h> | | 41 | #include <sys/select.h> |
42 | #include <sys/poll.h> | | 42 | #include <sys/poll.h> |
43 | #include <sys/kmem.h> | | 43 | #include <sys/kmem.h> |
44 | #include <sys/mutex.h> | | 44 | #include <sys/mutex.h> |
45 | #include <sys/proc.h> | | 45 | #include <sys/proc.h> |
46 | #include <sys/kernel.h> | | 46 | #include <sys/kernel.h> |
47 | #include <sys/conf.h> | | 47 | #include <sys/conf.h> |
48 | #include <sys/systm.h> | | 48 | #include <sys/systm.h> |
| @@ -280,45 +280,26 @@ rnd_getmore(size_t byteswanted) | | | @@ -280,45 +280,26 @@ rnd_getmore(size_t byteswanted) |
280 | rnd_printf_verbose("rnd: asking source %s for %zu bytes\n", | | 280 | rnd_printf_verbose("rnd: asking source %s for %zu bytes\n", |
281 | rs->name, byteswanted); | | 281 | rs->name, byteswanted); |
282 | } | | 282 | } |
283 | mutex_spin_exit(&rnd_global.lock); | | 283 | mutex_spin_exit(&rnd_global.lock); |
284 | } | | 284 | } |
285 | | | 285 | |
286 | /* | | 286 | /* |
287 | * Check to see if there are readers waiting on us. If so, kick them. | | 287 | * Check to see if there are readers waiting on us. If so, kick them. |
288 | */ | | 288 | */ |
289 | static void | | 289 | static void |
290 | rnd_wakeup_readers(void) | | 290 | rnd_wakeup_readers(void) |
291 | { | | 291 | { |
292 | | | 292 | |
293 | /* | | | |
294 | * XXX This bookkeeping shouldn't be here -- this is not where | | | |
295 | * the rnd_initial_entropy state change actually happens. | | | |
296 | */ | | | |
297 | mutex_spin_enter(&rnd_global.lock); | | | |
298 | const size_t entropy_count = rndpool_get_entropy_count(&rnd_global.pool); | | | |
299 | if (entropy_count < RND_ENTROPY_THRESHOLD * 8) { | | | |
300 | mutex_spin_exit(&rnd_global.lock); | | | |
301 | return; | | | |
302 | } else { | | | |
303 | #ifdef RND_VERBOSE | | | |
304 | if (__predict_false(!rnd_initial_entropy)) | | | |
305 | rnd_printf_verbose("rnd: have initial entropy (%zu)\n", | | | |
306 | entropy_count); | | | |
307 | #endif | | | |
308 | rnd_initial_entropy = 1; | | | |
309 | } | | | |
310 | mutex_spin_exit(&rnd_global.lock); | | | |
311 | | | | |
312 | rndsinks_distribute(); | | 293 | rndsinks_distribute(); |
313 | } | | 294 | } |
314 | | | 295 | |
315 | /* | | 296 | /* |
316 | * Use the timing/value of the event to estimate the entropy gathered. | | 297 | * Use the timing/value of the event to estimate the entropy gathered. |
317 | * If all the differentials (first, second, and third) are non-zero, return | | 298 | * If all the differentials (first, second, and third) are non-zero, return |
318 | * non-zero. If any of these are zero, return zero. | | 299 | * non-zero. If any of these are zero, return zero. |
319 | */ | | 300 | */ |
320 | static inline uint32_t | | 301 | static inline uint32_t |
321 | rnd_delta_estimate(rnd_delta_t *d, uint32_t v, int32_t delta) | | 302 | rnd_delta_estimate(rnd_delta_t *d, uint32_t v, int32_t delta) |
322 | { | | 303 | { |
323 | int32_t delta2, delta3; | | 304 | int32_t delta2, delta3; |
324 | | | 305 | |
| @@ -473,26 +454,47 @@ rnd_skew_intr(void *arg) | | | @@ -473,26 +454,47 @@ rnd_skew_intr(void *arg) |
473 | if (RND_ENABLED(&rnd_skew.source)) { | | 454 | if (RND_ENABLED(&rnd_skew.source)) { |
474 | if (flipflop) { | | 455 | if (flipflop) { |
475 | rnd_add_uint32(&rnd_skew.source, rnd_counter()); | | 456 | rnd_add_uint32(&rnd_skew.source, rnd_counter()); |
476 | callout_schedule(&rnd_skew.callout, hz / 10); | | 457 | callout_schedule(&rnd_skew.callout, hz / 10); |
477 | } else { | | 458 | } else { |
478 | callout_schedule(&rnd_skew.callout, 1); | | 459 | callout_schedule(&rnd_skew.callout, 1); |
479 | } | | 460 | } |
480 | } | | 461 | } |
481 | mutex_spin_exit(&rnd_skew.lock); | | 462 | mutex_spin_exit(&rnd_skew.lock); |
482 | } | | 463 | } |
483 | #endif | | 464 | #endif |
484 | | | 465 | |
485 | /* | | 466 | /* |
| | | 467 | * Entropy was just added to the pool. If we crossed the threshold for |
| | | 468 | * the first time, set rnd_initial_entropy = 1. |
| | | 469 | */ |
| | | 470 | static void |
| | | 471 | rnd_entropy_added(void) |
| | | 472 | { |
| | | 473 | uint32_t pool_entropy; |
| | | 474 | |
| | | 475 | KASSERT(mutex_owned(&rnd_global.lock)); |
| | | 476 | |
| | | 477 | if (__predict_true(rnd_initial_entropy)) |
| | | 478 | return; |
| | | 479 | pool_entropy = rndpool_get_entropy_count(&rnd_global.pool); |
| | | 480 | if (pool_entropy > RND_ENTROPY_THRESHOLD * NBBY) { |
| | | 481 | rnd_printf_verbose("rnd: have initial entropy (%zu)\n", |
| | | 482 | pool_entropy); |
| | | 483 | rnd_initial_entropy = 1; |
| | | 484 | } |
| | | 485 | } |
| | | 486 | |
| | | 487 | /* |
486 | * initialize the global random pool for our use. | | 488 | * initialize the global random pool for our use. |
487 | * rnd_init() must be called very early on in the boot process, so | | 489 | * rnd_init() must be called very early on in the boot process, so |
488 | * the pool is ready for other devices to attach as sources. | | 490 | * the pool is ready for other devices to attach as sources. |
489 | */ | | 491 | */ |
490 | void | | 492 | void |
491 | rnd_init(void) | | 493 | rnd_init(void) |
492 | { | | 494 | { |
493 | uint32_t c; | | 495 | uint32_t c; |
494 | | | 496 | |
495 | if (rnd_ready) | | 497 | if (rnd_ready) |
496 | return; | | 498 | return; |
497 | | | 499 | |
498 | /* | | 500 | /* |
| @@ -556,31 +558,28 @@ rnd_init(void) | | | @@ -556,31 +558,28 @@ rnd_init(void) |
556 | rnd_attach_source(&rnd_skew.source, "callout", RND_TYPE_SKEW, | | 558 | rnd_attach_source(&rnd_skew.source, "callout", RND_TYPE_SKEW, |
557 | RND_FLAG_COLLECT_VALUE|RND_FLAG_ESTIMATE_VALUE| | | 559 | RND_FLAG_COLLECT_VALUE|RND_FLAG_ESTIMATE_VALUE| |
558 | RND_FLAG_HASCB|RND_FLAG_HASENABLE); | | 560 | RND_FLAG_HASCB|RND_FLAG_HASENABLE); |
559 | rnd_skew_intr(NULL); | | 561 | rnd_skew_intr(NULL); |
560 | #endif | | 562 | #endif |
561 | | | 563 | |
562 | rnd_printf_verbose("rnd: initialised (%u)%s", RND_POOLBITS, | | 564 | rnd_printf_verbose("rnd: initialised (%u)%s", RND_POOLBITS, |
563 | c ? " with counter\n" : "\n"); | | 565 | c ? " with counter\n" : "\n"); |
564 | if (boot_rsp != NULL) { | | 566 | if (boot_rsp != NULL) { |
565 | mutex_spin_enter(&rnd_global.lock); | | 567 | mutex_spin_enter(&rnd_global.lock); |
566 | rndpool_add_data(&rnd_global.pool, boot_rsp->data, | | 568 | rndpool_add_data(&rnd_global.pool, boot_rsp->data, |
567 | sizeof(boot_rsp->data), | | 569 | sizeof(boot_rsp->data), |
568 | MIN(boot_rsp->entropy, RND_POOLBITS / 2)); | | 570 | MIN(boot_rsp->entropy, RND_POOLBITS / 2)); |
569 | if (rndpool_get_entropy_count(&rnd_global.pool) > | | 571 | rnd_entropy_added(); |
570 | RND_ENTROPY_THRESHOLD * 8) { | | 572 | mutex_spin_exit(&rnd_global.lock); |
571 | rnd_initial_entropy = 1; | | | |
572 | } | | | |
573 | mutex_spin_exit(&rnd_global.lock); | | | |
574 | rnd_printf("rnd: seeded with %d bits\n", | | 573 | rnd_printf("rnd: seeded with %d bits\n", |
575 | MIN(boot_rsp->entropy, RND_POOLBITS / 2)); | | 574 | MIN(boot_rsp->entropy, RND_POOLBITS / 2)); |
576 | memset(boot_rsp, 0, sizeof(*boot_rsp)); | | 575 | memset(boot_rsp, 0, sizeof(*boot_rsp)); |
577 | } | | 576 | } |
578 | rnd_attach_source(&rnd_printf_source, "printf", RND_TYPE_UNKNOWN, | | 577 | rnd_attach_source(&rnd_printf_source, "printf", RND_TYPE_UNKNOWN, |
579 | RND_FLAG_NO_ESTIMATE); | | 578 | RND_FLAG_NO_ESTIMATE); |
580 | rnd_attach_source(&rnd_autoconf_source, "autoconf", | | 579 | rnd_attach_source(&rnd_autoconf_source, "autoconf", |
581 | RND_TYPE_UNKNOWN, | | 580 | RND_TYPE_UNKNOWN, |
582 | RND_FLAG_COLLECT_TIME|RND_FLAG_ESTIMATE_TIME); | | 581 | RND_FLAG_COLLECT_TIME|RND_FLAG_ESTIMATE_TIME); |
583 | rnd_ready = 1; | | 582 | rnd_ready = 1; |
584 | } | | 583 | } |
585 | | | 584 | |
586 | static rnd_sample_t * | | 585 | static rnd_sample_t * |
| @@ -1085,26 +1084,27 @@ rnd_process_events(void) | | | @@ -1085,26 +1084,27 @@ rnd_process_events(void) |
1085 | } | | 1084 | } |
1086 | if (source->flags & RND_FLAG_COLLECT_TIME) { | | 1085 | if (source->flags & RND_FLAG_COLLECT_TIME) { |
1087 | rndpool_add_data(&rnd_global.pool, sample->ts, | | 1086 | rndpool_add_data(&rnd_global.pool, sample->ts, |
1088 | sample_count * | | 1087 | sample_count * |
1089 | sizeof(sample->ts[1]), | | 1088 | sizeof(sample->ts[1]), |
1090 | 0); | | 1089 | 0); |
1091 | } | | 1090 | } |
1092 | | | 1091 | |
1093 | pool_entropy += entropy; | | 1092 | pool_entropy += entropy; |
1094 | source->total += sample->entropy; | | 1093 | source->total += sample->entropy; |
1095 | skip: SIMPLEQ_INSERT_TAIL(&df_samples, sample, next); | | 1094 | skip: SIMPLEQ_INSERT_TAIL(&df_samples, sample, next); |
1096 | } | | 1095 | } |
1097 | rndpool_set_entropy_count(&rnd_global.pool, pool_entropy); | | 1096 | rndpool_set_entropy_count(&rnd_global.pool, pool_entropy); |
| | | 1097 | rnd_entropy_added(); |
1098 | mutex_spin_exit(&rnd_global.lock); | | 1098 | mutex_spin_exit(&rnd_global.lock); |
1099 | | | 1099 | |
1100 | /* | | 1100 | /* |
1101 | * If we filled the pool past the threshold, wake anyone | | 1101 | * If we filled the pool past the threshold, wake anyone |
1102 | * waiting for entropy. Otherwise, ask all the entropy sources | | 1102 | * waiting for entropy. Otherwise, ask all the entropy sources |
1103 | * for more. | | 1103 | * for more. |
1104 | */ | | 1104 | */ |
1105 | if (pool_entropy > RND_ENTROPY_THRESHOLD * 8) { | | 1105 | if (pool_entropy > RND_ENTROPY_THRESHOLD * 8) { |
1106 | wake++; | | 1106 | wake++; |
1107 | } else { | | 1107 | } else { |
1108 | rnd_getmore(howmany((RND_POOLBITS - pool_entropy), NBBY)); | | 1108 | rnd_getmore(howmany((RND_POOLBITS - pool_entropy), NBBY)); |
1109 | rnd_printf_verbose("rnd: empty, asking for %d bytes\n", | | 1109 | rnd_printf_verbose("rnd: empty, asking for %d bytes\n", |
1110 | (int)(howmany((RND_POOLBITS - pool_entropy), NBBY))); | | 1110 | (int)(howmany((RND_POOLBITS - pool_entropy), NBBY))); |
| @@ -1597,26 +1597,27 @@ rnd_system_ioctl(struct file *fp, u_long | | | @@ -1597,26 +1597,27 @@ rnd_system_ioctl(struct file *fp, u_long |
1597 | * do not flood the pool with entropy such that | | 1597 | * do not flood the pool with entropy such that |
1598 | * new samples are discarded henceforth. | | 1598 | * new samples are discarded henceforth. |
1599 | */ | | 1599 | */ |
1600 | estimate = MIN((rnddata->len * NBBY) / 2, | | 1600 | estimate = MIN((rnddata->len * NBBY) / 2, |
1601 | MIN(rnddata->entropy, | | 1601 | MIN(rnddata->entropy, |
1602 | RND_POOLBITS / 2)); | | 1602 | RND_POOLBITS / 2)); |
1603 | } else { | | 1603 | } else { |
1604 | estimate = 0; | | 1604 | estimate = 0; |
1605 | } | | 1605 | } |
1606 | | | 1606 | |
1607 | mutex_spin_enter(&rnd_global.lock); | | 1607 | mutex_spin_enter(&rnd_global.lock); |
1608 | rndpool_add_data(&rnd_global.pool, rnddata->data, | | 1608 | rndpool_add_data(&rnd_global.pool, rnddata->data, |
1609 | rnddata->len, estimate); | | 1609 | rnddata->len, estimate); |
| | | 1610 | rnd_entropy_added(); |
1610 | mutex_spin_exit(&rnd_global.lock); | | 1611 | mutex_spin_exit(&rnd_global.lock); |
1611 | | | 1612 | |
1612 | rnd_wakeup_readers(); | | 1613 | rnd_wakeup_readers(); |
1613 | } else { | | 1614 | } else { |
1614 | rnd_printf_verbose("rnd" | | 1615 | rnd_printf_verbose("rnd" |
1615 | ": already seeded by boot loader\n"); | | 1616 | ": already seeded by boot loader\n"); |
1616 | } | | 1617 | } |
1617 | break; | | 1618 | break; |
1618 | | | 1619 | |
1619 | default: | | 1620 | default: |
1620 | return ENOTTY; | | 1621 | return ENOTTY; |
1621 | } | | 1622 | } |
1622 | | | 1623 | |