Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83664a69 authored by H. Peter Anvin's avatar H. Peter Anvin Committed by Theodore Ts'o
Browse files

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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent d20f78d2
Loading
Loading
Loading
Loading
+20 −4
Original line number Original line Diff line number Diff line
@@ -844,6 +844,8 @@ void add_interrupt_randomness(int irq, int irq_flags)
	cycles_t		cycles = random_get_entropy();
	cycles_t		cycles = random_get_entropy();
	__u32			input[4], c_high, j_high;
	__u32			input[4], c_high, j_high;
	__u64			ip;
	__u64			ip;
	unsigned long		seed;
	int			credit;


	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
@@ -862,20 +864,33 @@ void add_interrupt_randomness(int irq, int irq_flags)


	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);

	/*
	/*
	 * If we don't have a valid cycle counter, and we see
	 * If we don't have a valid cycle counter, and we see
	 * back-to-back timer interrupts, then skip giving credit for
	 * back-to-back timer interrupts, then skip giving credit for
	 * any entropy.
	 * any entropy, otherwise credit 1 bit.
	 */
	 */
	credit = 1;
	if (cycles == 0) {
	if (cycles == 0) {
		if (irq_flags & __IRQF_TIMER) {
		if (irq_flags & __IRQF_TIMER) {
			if (fast_pool->last_timer_intr)
			if (fast_pool->last_timer_intr)
				return;
				credit = 0;
			fast_pool->last_timer_intr = 1;
			fast_pool->last_timer_intr = 1;
		} else
		} else
			fast_pool->last_timer_intr = 0;
			fast_pool->last_timer_intr = 0;
	}
	}
	credit_entropy_bits(r, 1);

	/*
	 * If we have architectural seed generator, produce a seed and
	 * add it to the pool.  For the sake of paranoia count it as
	 * 50% entropic.
	 */
	if (arch_get_random_seed_long(&seed)) {
		__mix_pool_bytes(r, &seed, sizeof(seed), NULL);
		credit += sizeof(seed) * 4;
	}

	credit_entropy_bits(r, credit);
}
}


#ifdef CONFIG_BLOCK
#ifdef CONFIG_BLOCK
@@ -1235,7 +1250,8 @@ static void init_std_data(struct entropy_store *r)
	r->last_pulled = jiffies;
	r->last_pulled = jiffies;
	mix_pool_bytes(r, &now, sizeof(now), NULL);
	mix_pool_bytes(r, &now, sizeof(now), NULL);
	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
		if (!arch_get_random_long(&rv))
		if (!arch_get_random_seed_long(&rv) &&
		    !arch_get_random_long(&rv))
			rv = random_get_entropy();
			rv = random_get_entropy();
		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
	}
	}