diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2014-03-17 19:36:28 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-03-19 22:22:06 -0400 |
commit | 83664a6928a420b5ccfc0cf23ddbfe3634fea271 (patch) | |
tree | b8849a88a88a0894c1131a0234100a98b0d73d02 /drivers/char | |
parent | d20f78d252778e0fae8f8256e602bd682eb2185c (diff) |
random: Use arch_get_random_seed*() at init time and once a second
Use arch_get_random_seed*() in two places in the Linux random
driver (drivers/char/random.c):
1. During entropy pool initialization, use RDSEED in favor of RDRAND,
with a fallback to the latter. Entropy exhaustion is unlikely to
happen there on physical hardware as the machine is single-threaded
at that point, but could happen in a virtual machine. In that
case, the fallback to RDRAND will still provide more than adequate
entropy pool initialization.
2. Once a second, issue RDSEED and, if successful, feed it to the
entropy pool. To ensure an extra layer of security, only credit
half the entropy just in case.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/random.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index d07575c99a5f..a4bea7775e0f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -844,6 +844,8 @@ void add_interrupt_randomness(int irq, int irq_flags) | |||
844 | cycles_t cycles = random_get_entropy(); | 844 | cycles_t cycles = random_get_entropy(); |
845 | __u32 input[4], c_high, j_high; | 845 | __u32 input[4], c_high, j_high; |
846 | __u64 ip; | 846 | __u64 ip; |
847 | unsigned long seed; | ||
848 | int credit; | ||
847 | 849 | ||
848 | c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0; | 850 | c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0; |
849 | j_high = (sizeof(now) > 4) ? now >> 32 : 0; | 851 | j_high = (sizeof(now) > 4) ? now >> 32 : 0; |
@@ -862,20 +864,33 @@ void add_interrupt_randomness(int irq, int irq_flags) | |||
862 | 864 | ||
863 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; | 865 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; |
864 | __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); | 866 | __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); |
867 | |||
865 | /* | 868 | /* |
866 | * If we don't have a valid cycle counter, and we see | 869 | * If we don't have a valid cycle counter, and we see |
867 | * back-to-back timer interrupts, then skip giving credit for | 870 | * back-to-back timer interrupts, then skip giving credit for |
868 | * any entropy. | 871 | * any entropy, otherwise credit 1 bit. |
869 | */ | 872 | */ |
873 | credit = 1; | ||
870 | if (cycles == 0) { | 874 | if (cycles == 0) { |
871 | if (irq_flags & __IRQF_TIMER) { | 875 | if (irq_flags & __IRQF_TIMER) { |
872 | if (fast_pool->last_timer_intr) | 876 | if (fast_pool->last_timer_intr) |
873 | return; | 877 | credit = 0; |
874 | fast_pool->last_timer_intr = 1; | 878 | fast_pool->last_timer_intr = 1; |
875 | } else | 879 | } else |
876 | fast_pool->last_timer_intr = 0; | 880 | fast_pool->last_timer_intr = 0; |
877 | } | 881 | } |
878 | credit_entropy_bits(r, 1); | 882 | |
883 | /* | ||
884 | * If we have architectural seed generator, produce a seed and | ||
885 | * add it to the pool. For the sake of paranoia count it as | ||
886 | * 50% entropic. | ||
887 | */ | ||
888 | if (arch_get_random_seed_long(&seed)) { | ||
889 | __mix_pool_bytes(r, &seed, sizeof(seed), NULL); | ||
890 | credit += sizeof(seed) * 4; | ||
891 | } | ||
892 | |||
893 | credit_entropy_bits(r, credit); | ||
879 | } | 894 | } |
880 | 895 | ||
881 | #ifdef CONFIG_BLOCK | 896 | #ifdef CONFIG_BLOCK |
@@ -1235,7 +1250,8 @@ static void init_std_data(struct entropy_store *r) | |||
1235 | r->last_pulled = jiffies; | 1250 | r->last_pulled = jiffies; |
1236 | mix_pool_bytes(r, &now, sizeof(now), NULL); | 1251 | mix_pool_bytes(r, &now, sizeof(now), NULL); |
1237 | for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) { | 1252 | for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) { |
1238 | if (!arch_get_random_long(&rv)) | 1253 | if (!arch_get_random_seed_long(&rv) && |
1254 | !arch_get_random_long(&rv)) | ||
1239 | rv = random_get_entropy(); | 1255 | rv = random_get_entropy(); |
1240 | mix_pool_bytes(r, &rv, sizeof(rv), NULL); | 1256 | mix_pool_bytes(r, &rv, sizeof(rv), NULL); |
1241 | } | 1257 | } |