aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Mackall <mpm@selenic.com>2008-04-29 04:03:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:25 -0400
commite68e5b664ecb9bccf68102557107a6b6d739a97c (patch)
treef74a1d9585295463f166fdcffcc8e28527728b1a
parent993ba2114c554c1561a018e5c63a771ec8e1c469 (diff)
random: make mixing interface byte-oriented
Switch add_entropy_words to a byte-oriented interface, eliminating numerous casts and byte/word size rounding issues. This also reduces the overall bit/byte/word confusion in this code. We now mix a byte at a time into the word-based pool. This takes four times as many iterations, but should be negligible compared to hashing overhead. This also increases our pool churn, which adds some depth against some theoretical failure modes. The function name is changed to emphasize pool mixing and deemphasize entropy (the samples mixed in may not contain any). extract is added to the core function to make it clear that it extracts from the pool. Signed-off-by: Matt Mackall <mpm@selenic.com> Cc: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/char/random.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index ba0d70305384..d33f52cd437b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -439,7 +439,7 @@ static struct entropy_store nonblocking_pool = {
439}; 439};
440 440
441/* 441/*
442 * This function adds a byte into the entropy "pool". It does not 442 * This function adds bytes into the entropy "pool". It does not
443 * update the entropy estimate. The caller should call 443 * update the entropy estimate. The caller should call
444 * credit_entropy_store if this is appropriate. 444 * credit_entropy_store if this is appropriate.
445 * 445 *
@@ -448,8 +448,8 @@ static struct entropy_store nonblocking_pool = {
448 * it's cheap to do so and helps slightly in the expected case where 448 * it's cheap to do so and helps slightly in the expected case where
449 * the entropy is concentrated in the low-order bits. 449 * the entropy is concentrated in the low-order bits.
450 */ 450 */
451static void __add_entropy_words(struct entropy_store *r, const __u32 *in, 451static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
452 int nwords, __u32 out[16]) 452 int nbytes, __u8 out[64])
453{ 453{
454 static __u32 const twist_table[8] = { 454 static __u32 const twist_table[8] = {
455 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, 455 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
@@ -457,6 +457,7 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
457 unsigned long i, j, tap1, tap2, tap3, tap4, tap5; 457 unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
458 int input_rotate; 458 int input_rotate;
459 int wordmask = r->poolinfo->poolwords - 1; 459 int wordmask = r->poolinfo->poolwords - 1;
460 const char *bytes = in;
460 __u32 w; 461 __u32 w;
461 unsigned long flags; 462 unsigned long flags;
462 463
@@ -471,8 +472,9 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
471 input_rotate = r->input_rotate; 472 input_rotate = r->input_rotate;
472 i = r->add_ptr; 473 i = r->add_ptr;
473 474
474 while (nwords--) { 475 /* mix one byte at a time to simplify size handling and churn faster */
475 w = rol32(*in++, input_rotate & 31); 476 while (nbytes--) {
477 w = rol32(*bytes++, input_rotate & 31);
476 i = (i - 1) & wordmask; 478 i = (i - 1) & wordmask;
477 479
478 /* XOR in the various taps */ 480 /* XOR in the various taps */
@@ -500,15 +502,14 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
500 502
501 if (out) 503 if (out)
502 for (j = 0; j < 16; j++) 504 for (j = 0; j < 16; j++)
503 out[j] = r->pool[(i - j) & wordmask]; 505 ((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
504 506
505 spin_unlock_irqrestore(&r->lock, flags); 507 spin_unlock_irqrestore(&r->lock, flags);
506} 508}
507 509
508static inline void add_entropy_words(struct entropy_store *r, const __u32 *in, 510static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
509 int nwords)
510{ 511{
511 __add_entropy_words(r, in, nwords, NULL); 512 mix_pool_bytes_extract(r, in, bytes, NULL);
512} 513}
513 514
514/* 515/*
@@ -584,7 +585,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
584 sample.jiffies = jiffies; 585 sample.jiffies = jiffies;
585 sample.cycles = get_cycles(); 586 sample.cycles = get_cycles();
586 sample.num = num; 587 sample.num = num;
587 add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4); 588 mix_pool_bytes(&input_pool, &sample, sizeof(sample));
588 589
589 /* 590 /*
590 * Calculate number of bits of randomness we probably added. 591 * Calculate number of bits of randomness we probably added.
@@ -700,7 +701,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
700 701
701 bytes = extract_entropy(r->pull, tmp, bytes, 702 bytes = extract_entropy(r->pull, tmp, bytes,
702 random_read_wakeup_thresh / 8, rsvd); 703 random_read_wakeup_thresh / 8, rsvd);
703 add_entropy_words(r, tmp, (bytes + 3) / 4); 704 mix_pool_bytes(r, tmp, bytes);
704 credit_entropy_store(r, bytes*8); 705 credit_entropy_store(r, bytes*8);
705 } 706 }
706} 707}
@@ -758,7 +759,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
758static void extract_buf(struct entropy_store *r, __u8 *out) 759static void extract_buf(struct entropy_store *r, __u8 *out)
759{ 760{
760 int i; 761 int i;
761 __u32 extract[16], hash[5], workspace[SHA_WORKSPACE_WORDS]; 762 __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
763 __u8 extract[64];
762 764
763 /* Generate a hash across the pool, 16 words (512 bits) at a time */ 765 /* Generate a hash across the pool, 16 words (512 bits) at a time */
764 sha_init(hash); 766 sha_init(hash);
@@ -774,13 +776,13 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
774 * brute-forcing the feedback as hard as brute-forcing the 776 * brute-forcing the feedback as hard as brute-forcing the
775 * hash. 777 * hash.
776 */ 778 */
777 __add_entropy_words(r, hash, 5, extract); 779 mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
778 780
779 /* 781 /*
780 * To avoid duplicates, we atomically extract a portion of the 782 * To avoid duplicates, we atomically extract a portion of the
781 * pool while mixing, and hash one final time. 783 * pool while mixing, and hash one final time.
782 */ 784 */
783 sha_transform(hash, (__u8 *)extract, workspace); 785 sha_transform(hash, extract, workspace);
784 memset(extract, 0, sizeof(extract)); 786 memset(extract, 0, sizeof(extract));
785 memset(workspace, 0, sizeof(workspace)); 787 memset(workspace, 0, sizeof(workspace));
786 788
@@ -887,9 +889,8 @@ static void init_std_data(struct entropy_store *r)
887 spin_unlock_irqrestore(&r->lock, flags); 889 spin_unlock_irqrestore(&r->lock, flags);
888 890
889 now = ktime_get_real(); 891 now = ktime_get_real();
890 add_entropy_words(r, (__u32 *)&now, sizeof(now)/4); 892 mix_pool_bytes(r, &now, sizeof(now));
891 add_entropy_words(r, (__u32 *)utsname(), 893 mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
892 sizeof(*(utsname()))/4);
893} 894}
894 895
895static int rand_initialize(void) 896static int rand_initialize(void)
@@ -1030,7 +1031,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
1030 count -= bytes; 1031 count -= bytes;
1031 p += bytes; 1032 p += bytes;
1032 1033
1033 add_entropy_words(r, buf, (bytes + 3) / 4); 1034 mix_pool_bytes(r, buf, bytes);
1034 cond_resched(); 1035 cond_resched();
1035 } 1036 }
1036 1037