We've used random_read_wakeup_bits for two quite different purposes
that may be best with different values.  The minimum number of bits
to wake up a blocked /dev/random reader has long been 64 by
default, and users may want to keep it there.  The minimum number
of bits in a seed for /dev/urandom and the kernel's general use, on
the other hand, should be at least 128 for good commercial security
and users may want it higher.

Make a new parameter for the minimum size of a reseed, and make it
128 by default.

Signed-off-by: Greg Price <pr...@mit.edu>
---
 drivers/char/random.c | 46 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1f9c69662..b354fd15f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -292,8 +292,14 @@
 #define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
 
 /*
+ * The minimum number of bits of estimated entropy to use in a reseed
+ * of the main output pool.
+ */
+static int min_reseed_bits = 128;
+
+/*
  * The minimum number of bits of entropy before we wake up a read on
- * /dev/random.  Should be enough to do a significant reseed.
+ * /dev/random.
  */
 static int random_read_wakeup_bits = 64;
 
@@ -594,7 +600,7 @@ random_readable(int input_entropy_bits)
        int thresh = random_read_wakeup_bits;
        if (!nonblocking_pool.initialized)
                /* ... that aren't reserved for the nonblocking pool. */
-               thresh += random_read_wakeup_bits;
+               thresh += min_reseed_bits;
        return input_entropy_bits >= thresh;
 }
 
@@ -665,7 +671,7 @@ retry:
 
        if (r == &nonblocking_pool) {
                r->entropy_total += nbits;
-               if (!r->initialized && r->entropy_total > 128) {
+               if (!r->initialized && r->entropy_total >= min_reseed_bits) {
                        r->initialized = 1;
                        prandom_reseed_late();
                        pr_notice("random: %s pool is initialized\n", r->name);
@@ -692,7 +698,7 @@ retry:
                 */
                r->entropy_since_push += nbits;
                if (entropy_bits > random_write_wakeup_bits &&
-                   r->entropy_since_push >= 2*random_read_wakeup_bits) {
+                   r->entropy_since_push >= min_reseed_bits) {
                        static struct entropy_store *last = &blocking_pool;
                        struct entropy_store *other = &blocking_pool;
 
@@ -929,15 +935,15 @@ static void xfer_secondary_pool(struct entropy_store *r, 
size_t nbytes)
 static void account_xfer(struct entropy_store *dest, int nbytes,
                         int *min_bytes, int *reserved_bytes)
 {
-       /* Try to pull a full wakeup's worth if we might have just woken up
-        * for it, and a full reseed's worth (which is controlled by the same
-        * parameter) for the nonblocking pool... */
-       if (dest == &blocking_pool || dest->initialized) {
+       /* Try to pull a full wakeup's worth if we might have just
+        * woken up for it... */
+       if (dest == &blocking_pool) {
                *min_bytes = random_read_wakeup_bits / 8;
        } else {
-               /* ... except if we're hardly seeded at all, we'll settle for
-                * enough to double what we have. */
-               *min_bytes = min(random_read_wakeup_bits / 8,
+               /* ... or a full reseed's worth for the nonblocking
+                * pool, except if we're hardly seeded at all, we'll
+                * settle for enough to double what we have. */
+               *min_bytes = min(min_reseed_bits / 8,
                                 (dest->entropy_total+7) / 8);
        }
 
@@ -945,7 +951,7 @@ static void account_xfer(struct entropy_store *dest, int 
nbytes,
         * when we really need it; later, reserve some for /dev/random */
        *reserved_bytes = 0;
        if (dest == &blocking_pool && !nonblocking_pool.initialized)
-               *reserved_bytes = random_read_wakeup_bits / 8;
+               *reserved_bytes = min_reseed_bits / 8;
        else if (dest == &nonblocking_pool && dest->initialized)
                *reserved_bytes = 2 * (random_read_wakeup_bits / 8);
 }
@@ -974,7 +980,7 @@ static void push_to_pool(struct work_struct *work)
        struct entropy_store *r = container_of(work, struct entropy_store,
                                              push_work);
        BUG_ON(!r);
-       _xfer_secondary_pool(r, random_read_wakeup_bits/8);
+       _xfer_secondary_pool(r, min_reseed_bits/8);
        trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
                           r->pull->entropy_count >> ENTROPY_SHIFT);
 }
@@ -1516,8 +1522,11 @@ EXPORT_SYMBOL(generate_random_uuid);
 
 #include <linux/sysctl.h>
 
-static int min_read_thresh = 8, min_write_thresh;
+static int min_min_reseed_bits = 32;
+static int max_min_reseed_bits = OUTPUT_POOL_WORDS * 32;
+static int min_read_thresh = 8;
 static int max_read_thresh = OUTPUT_POOL_WORDS * 32;
+static int min_write_thresh;
 static int max_write_thresh = INPUT_POOL_WORDS * 32;
 static char sysctl_bootid[16];
 
@@ -1592,6 +1601,15 @@ struct ctl_table random_table[] = {
                .data           = &input_pool.entropy_count,
        },
        {
+               .procname       = "min_reseed_bits",
+               .data           = &min_reseed_bits,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &min_min_reseed_bits,
+               .extra2         = &max_min_reseed_bits,
+       },
+       {
                .procname       = "read_wakeup_threshold",
                .data           = &random_read_wakeup_bits,
                .maxlen         = sizeof(int),
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to