aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2013-09-10 23:16:17 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-10-10 14:32:15 -0400
commit30e37ec516ae5a6957596de7661673c615c82ea4 (patch)
treef05b433d712c0d74e2e86dea92de700b940c6a42 /drivers/char/random.c
parenta283b5c459784f9762a74c312b134e9a524f5a5f (diff)
random: account for entropy loss due to overwrites
When we write entropy into a non-empty pool, we currently don't account at all for the fact that we will probabilistically overwrite some of the entropy in that pool. This means that unless the pool is fully empty, we are currently *guaranteed* to overestimate the amount of entropy in the pool! Assuming Shannon entropy with zero correlations we end up with an exponentally decaying value of new entropy added: entropy <- entropy + (pool_size - entropy) * (1 - exp(-add_entropy/pool_size)) However, calculations involving fractional exponentials are not practical in the kernel, so apply a piecewise linearization: For add_entropy <= pool_size/2 then (1 - exp(-add_entropy/pool_size)) >= (add_entropy/pool_size)*0.7869... ... so we can approximate the exponential with 3/4*add_entropy/pool_size and still be on the safe side by adding at most pool_size/2 at a time. In order for the loop not to take arbitrary amounts of time if a bad ioctl is received, terminate if we are within one bit of full. This way the loop is guaranteed to terminate after no more than log2(poolsize) iterations, no matter what the input value is. The vast majority of the time the loop will be executed exactly once. The piecewise linearization is very conservative, approaching 3/4 of the usable input value for small inputs, however, our entropy estimation is pretty weak at best, especially for small values; we have no handle on correlation; and the Shannon entropy measure (Rényi entropy of order 1) is not the correct one to use in the first place, but rather the correct entropy measure is the min-entropy, the Rényi entropy of infinite order. As such, this conservatism seems more than justified. This does introduce fractional bit values. I have left it to have 3 bits of fraction, so that with a pool of 2^12 bits the multiply in credit_entropy_bits() can still fit into an int, as 2*(3+12) < 31. It is definitely possible to allow for more fractional accounting, but that multiply then would have to be turned into a 32*32 -> 64 multiply. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: DJ Johnston <dj.johnston@intel.com>
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c2957656c5bc..867b823e7fea 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -272,10 +272,12 @@
272/* 272/*
273 * Configuration information 273 * Configuration information
274 */ 274 */
275#define INPUT_POOL_WORDS 128 275#define INPUT_POOL_SHIFT 12
276#define OUTPUT_POOL_WORDS 32 276#define INPUT_POOL_WORDS (1 << (INPUT_POOL_SHIFT-5))
277#define SEC_XFER_SIZE 512 277#define OUTPUT_POOL_SHIFT 10
278#define EXTRACT_SIZE 10 278#define OUTPUT_POOL_WORDS (1 << (OUTPUT_POOL_SHIFT-5))
279#define SEC_XFER_SIZE 512
280#define EXTRACT_SIZE 10
279 281
280#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) 282#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
281 283
@@ -284,6 +286,9 @@
284 * this many fractional bits: 286 * this many fractional bits:
285 * 287 *
286 * entropy_count, trickle_thresh 288 * entropy_count, trickle_thresh
289 *
290 * 2*(ENTROPY_SHIFT + log2(poolbits)) must <= 31, or the multiply in
291 * credit_entropy_bits() needs to be 64 bits wide.
287 */ 292 */
288#define ENTROPY_SHIFT 3 293#define ENTROPY_SHIFT 3
289#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT) 294#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
@@ -427,7 +432,7 @@ module_param(debug, bool, 0644);
427struct entropy_store; 432struct entropy_store;
428struct entropy_store { 433struct entropy_store {
429 /* read-only data: */ 434 /* read-only data: */
430 struct poolinfo *poolinfo; 435 const struct poolinfo *poolinfo;
431 __u32 *pool; 436 __u32 *pool;
432 const char *name; 437 const char *name;
433 struct entropy_store *pull; 438 struct entropy_store *pull;
@@ -596,6 +601,8 @@ static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
596static void credit_entropy_bits(struct entropy_store *r, int nbits) 601static void credit_entropy_bits(struct entropy_store *r, int nbits)
597{ 602{
598 int entropy_count, orig; 603 int entropy_count, orig;
604 const int pool_size = r->poolinfo->poolfracbits;
605 int nfrac = nbits << ENTROPY_SHIFT;
599 606
600 if (!nbits) 607 if (!nbits)
601 return; 608 return;
@@ -603,13 +610,50 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
603 DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); 610 DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
604retry: 611retry:
605 entropy_count = orig = ACCESS_ONCE(r->entropy_count); 612 entropy_count = orig = ACCESS_ONCE(r->entropy_count);
606 entropy_count += nbits << ENTROPY_SHIFT; 613 if (nfrac < 0) {
614 /* Debit */
615 entropy_count += nfrac;
616 } else {
617 /*
618 * Credit: we have to account for the possibility of
619 * overwriting already present entropy. Even in the
620 * ideal case of pure Shannon entropy, new contributions
621 * approach the full value asymptotically:
622 *
623 * entropy <- entropy + (pool_size - entropy) *
624 * (1 - exp(-add_entropy/pool_size))
625 *
626 * For add_entropy <= pool_size/2 then
627 * (1 - exp(-add_entropy/pool_size)) >=
628 * (add_entropy/pool_size)*0.7869...
629 * so we can approximate the exponential with
630 * 3/4*add_entropy/pool_size and still be on the
631 * safe side by adding at most pool_size/2 at a time.
632 *
633 * The use of pool_size-2 in the while statement is to
634 * prevent rounding artifacts from making the loop
635 * arbitrarily long; this limits the loop to log2(pool_size)*2
636 * turns no matter how large nbits is.
637 */
638 int pnfrac = nfrac;
639 const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
640 /* The +2 corresponds to the /4 in the denominator */
641
642 do {
643 unsigned int anfrac = min(pnfrac, pool_size/2);
644 unsigned int add =
645 ((pool_size - entropy_count)*anfrac*3) >> s;
646
647 entropy_count += add;
648 pnfrac -= anfrac;
649 } while (unlikely(entropy_count < pool_size-2 && pnfrac));
650 }
607 651
608 if (entropy_count < 0) { 652 if (entropy_count < 0) {
609 DEBUG_ENT("negative entropy/overflow\n"); 653 DEBUG_ENT("negative entropy/overflow\n");
610 entropy_count = 0; 654 entropy_count = 0;
611 } else if (entropy_count > r->poolinfo->poolfracbits) 655 } else if (entropy_count > pool_size)
612 entropy_count = r->poolinfo->poolfracbits; 656 entropy_count = pool_size;
613 if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) 657 if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
614 goto retry; 658 goto retry;
615 659