diff options
author | Matt Mackall <mpm@selenic.com> | 2008-04-29 04:03:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 11:06:25 -0400 |
commit | e68e5b664ecb9bccf68102557107a6b6d739a97c (patch) | |
tree | f74a1d9585295463f166fdcffcc8e28527728b1a | |
parent | 993ba2114c554c1561a018e5c63a771ec8e1c469 (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.c | 37 |
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 | */ |
451 | static void __add_entropy_words(struct entropy_store *r, const __u32 *in, | 451 | static 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 | ||
508 | static inline void add_entropy_words(struct entropy_store *r, const __u32 *in, | 510 | static 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, | |||
758 | static void extract_buf(struct entropy_store *r, __u8 *out) | 759 | static 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 | ||
895 | static int rand_initialize(void) | 896 | static 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 | ||