aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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