diff options
author | Matt Mackall <mpm@selenic.com> | 2008-04-29 04:03:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 11:06:24 -0400 |
commit | 1c0ad3d492adf670e47bf0a3d65c6ba5cdee0114 (patch) | |
tree | b043456b0ddb74dfbff51efa57170a9c38eac729 /drivers/char/random.c | |
parent | ffd8d3fa5813430fe3926fe950fde23630f6b1a0 (diff) |
random: make backtracking attacks harder
At each extraction, we change (poolbits / 16) + 32 bits in the pool,
or 96 bits in the case of the secondary pools. Thus, a brute-force
backtracking attack on the pool state is less difficult than breaking
the hash. In certain cases, this difficulty may be is reduced to 2^64
iterations.
Instead, hash the entire pool in one go, then feedback the whole hash
(160 bits) in one go. This will make backtracking at least as hard as
inverting the hash.
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>
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r-- | drivers/char/random.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index d125a4b792d0..e52f64cbef04 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -767,37 +767,35 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
767 | int i; | 767 | int i; |
768 | __u32 extract[16], hash[5], workspace[SHA_WORKSPACE_WORDS]; | 768 | __u32 extract[16], hash[5], workspace[SHA_WORKSPACE_WORDS]; |
769 | 769 | ||
770 | /* Generate a hash across the pool, 16 words (512 bits) at a time */ | ||
770 | sha_init(hash); | 771 | sha_init(hash); |
772 | for (i = 0; i < r->poolinfo->poolwords; i += 16) | ||
773 | sha_transform(hash, (__u8 *)(r->pool + i), workspace); | ||
774 | |||
771 | /* | 775 | /* |
772 | * As we hash the pool, we mix intermediate values of | 776 | * We mix the hash back into the pool to prevent backtracking |
773 | * the hash back into the pool. This eliminates | 777 | * attacks (where the attacker knows the state of the pool |
774 | * backtracking attacks (where the attacker knows | 778 | * plus the current outputs, and attempts to find previous |
775 | * the state of the pool plus the current outputs, and | 779 | * ouputs), unless the hash function can be inverted. By |
776 | * attempts to find previous ouputs), unless the hash | 780 | * mixing at least a SHA1 worth of hash data back, we make |
777 | * function can be inverted. | 781 | * brute-forcing the feedback as hard as brute-forcing the |
782 | * hash. | ||
778 | */ | 783 | */ |
779 | for (i = 0; i < r->poolinfo->poolwords; i += 16) { | 784 | __add_entropy_words(r, hash, 5, extract); |
780 | /* hash blocks of 16 words = 512 bits */ | ||
781 | sha_transform(hash, (__u8 *)(r->pool + i), workspace); | ||
782 | /* feed back portion of the resulting hash */ | ||
783 | add_entropy_words(r, &hash[i % 5], 1); | ||
784 | } | ||
785 | 785 | ||
786 | /* | 786 | /* |
787 | * To avoid duplicates, we atomically extract a | 787 | * To avoid duplicates, we atomically extract a portion of the |
788 | * portion of the pool while mixing, and hash one | 788 | * pool while mixing, and hash one final time. |
789 | * final time. | ||
790 | */ | 789 | */ |
791 | __add_entropy_words(r, &hash[i % 5], 1, extract); | ||
792 | sha_transform(hash, (__u8 *)extract, workspace); | 790 | sha_transform(hash, (__u8 *)extract, workspace); |
793 | memset(extract, 0, sizeof(extract)); | 791 | memset(extract, 0, sizeof(extract)); |
794 | memset(workspace, 0, sizeof(workspace)); | 792 | memset(workspace, 0, sizeof(workspace)); |
795 | 793 | ||
796 | /* | 794 | /* |
797 | * In case the hash function has some recognizable | 795 | * In case the hash function has some recognizable output |
798 | * output pattern, we fold it in half. | 796 | * pattern, we fold it in half. Thus, we always feed back |
797 | * twice as much data as we output. | ||
799 | */ | 798 | */ |
800 | |||
801 | hash[0] ^= hash[3]; | 799 | hash[0] ^= hash[3]; |
802 | hash[1] ^= hash[4]; | 800 | hash[1] ^= hash[4]; |
803 | hash[2] ^= rol32(hash[2], 16); | 801 | hash[2] ^= rol32(hash[2], 16); |