All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Theodore Tso <tytso@mit.edu>,
	"Jason A. Donenfeld" <Jason@zx2c4.com>
Subject: [PATCH 5.18 20/47] random: insist on random_get_entropy() existing in order to simplify
Date: Fri, 27 May 2022 10:50:00 +0200	[thread overview]
Message-ID: <20220527084804.729317069@linuxfoundation.org> (raw)
In-Reply-To: <20220527084801.223648383@linuxfoundation.org>

From: "Jason A. Donenfeld" <Jason@zx2c4.com>

commit 4b758eda851eb9336ca86a0041a4d3da55f66511 upstream.

All platforms are now guaranteed to provide some value for
random_get_entropy(). In case some bug leads to this not being so, we
print a warning, because that indicates that something is really very
wrong (and likely other things are impacted too). This should never be
hit, but it's a good and cheap way of finding out if something ever is
problematic.

Since we now have viable fallback code for random_get_entropy() on all
platforms, which is, in the worst case, not worse than jiffies, we can
count on getting the best possible value out of it. That means there's
no longer a use for using jiffies as entropy input. It also means we no
longer have a reason for doing the round-robin register flow in the IRQ
handler, which was always of fairly dubious value.

Instead we can greatly simplify the IRQ handler inputs and also unify
the construction between 64-bits and 32-bits. We now collect the cycle
counter and the return address, since those are the two things that
matter. Because the return address and the irq number are likely
related, to the extent we mix in the irq number, we can just xor it into
the top unchanging bytes of the return address, rather than the bottom
changing bytes of the cycle counter as before. Then, we can do a fixed 2
rounds of SipHash/HSipHash. Finally, we use the same construction of
hashing only half of the [H]SipHash state on 32-bit and 64-bit. We're
not actually discarding any entropy, since that entropy is carried
through until the next time. And more importantly, it lets us do the
same sponge-like construction everywhere.

Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/char/random.c |   86 +++++++++++++++-----------------------------------
 1 file changed, 26 insertions(+), 60 deletions(-)

--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1025,15 +1025,14 @@ int __init rand_initialize(void)
  */
 void add_device_randomness(const void *buf, size_t size)
 {
-	unsigned long cycles = random_get_entropy();
-	unsigned long flags, now = jiffies;
+	unsigned long entropy = random_get_entropy();
+	unsigned long flags;
 
 	if (crng_init == 0 && size)
 		crng_pre_init_inject(buf, size, false);
 
 	spin_lock_irqsave(&input_pool.lock, flags);
-	_mix_pool_bytes(&cycles, sizeof(cycles));
-	_mix_pool_bytes(&now, sizeof(now));
+	_mix_pool_bytes(&entropy, sizeof(entropy));
 	_mix_pool_bytes(buf, size);
 	spin_unlock_irqrestore(&input_pool.lock, flags);
 }
@@ -1056,12 +1055,11 @@ struct timer_rand_state {
  */
 static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
 {
-	unsigned long cycles = random_get_entropy(), now = jiffies, flags;
+	unsigned long entropy = random_get_entropy(), now = jiffies, flags;
 	long delta, delta2, delta3;
 
 	spin_lock_irqsave(&input_pool.lock, flags);
-	_mix_pool_bytes(&cycles, sizeof(cycles));
-	_mix_pool_bytes(&now, sizeof(now));
+	_mix_pool_bytes(&entropy, sizeof(entropy));
 	_mix_pool_bytes(&num, sizeof(num));
 	spin_unlock_irqrestore(&input_pool.lock, flags);
 
@@ -1223,7 +1221,6 @@ struct fast_pool {
 	unsigned long pool[4];
 	unsigned long last;
 	unsigned int count;
-	u16 reg_idx;
 };
 
 static DEFINE_PER_CPU(struct fast_pool, irq_randomness) = {
@@ -1241,13 +1238,13 @@ static DEFINE_PER_CPU(struct fast_pool,
  * This is [Half]SipHash-1-x, starting from an empty key. Because
  * the key is fixed, it assumes that its inputs are non-malicious,
  * and therefore this has no security on its own. s represents the
- * 128 or 256-bit SipHash state, while v represents a 128-bit input.
+ * four-word SipHash state, while v represents a two-word input.
  */
-static void fast_mix(unsigned long s[4], const unsigned long *v)
+static void fast_mix(unsigned long s[4], const unsigned long v[2])
 {
 	size_t i;
 
-	for (i = 0; i < 16 / sizeof(long); ++i) {
+	for (i = 0; i < 2; ++i) {
 		s[3] ^= v[i];
 #ifdef CONFIG_64BIT
 		s[0] += s[1]; s[1] = rol64(s[1], 13); s[1] ^= s[0]; s[0] = rol64(s[0], 32);
@@ -1287,33 +1284,17 @@ int random_online_cpu(unsigned int cpu)
 }
 #endif
 
-static unsigned long get_reg(struct fast_pool *f, struct pt_regs *regs)
-{
-	unsigned long *ptr = (unsigned long *)regs;
-	unsigned int idx;
-
-	if (regs == NULL)
-		return 0;
-	idx = READ_ONCE(f->reg_idx);
-	if (idx >= sizeof(struct pt_regs) / sizeof(unsigned long))
-		idx = 0;
-	ptr += idx++;
-	WRITE_ONCE(f->reg_idx, idx);
-	return *ptr;
-}
-
 static void mix_interrupt_randomness(struct work_struct *work)
 {
 	struct fast_pool *fast_pool = container_of(work, struct fast_pool, mix);
 	/*
-	 * The size of the copied stack pool is explicitly 16 bytes so that we
-	 * tax mix_pool_byte()'s compression function the same amount on all
-	 * platforms. This means on 64-bit we copy half the pool into this,
-	 * while on 32-bit we copy all of it. The entropy is supposed to be
-	 * sufficiently dispersed between bits that in the sponge-like
-	 * half case, on average we don't wind up "losing" some.
+	 * The size of the copied stack pool is explicitly 2 longs so that we
+	 * only ever ingest half of the siphash output each time, retaining
+	 * the other half as the next "key" that carries over. The entropy is
+	 * supposed to be sufficiently dispersed between bits so on average
+	 * we don't wind up "losing" some.
 	 */
-	u8 pool[16];
+	unsigned long pool[2];
 
 	/* Check to see if we're running on the wrong CPU due to hotplug. */
 	local_irq_disable();
@@ -1345,36 +1326,21 @@ static void mix_interrupt_randomness(str
 void add_interrupt_randomness(int irq)
 {
 	enum { MIX_INFLIGHT = 1U << 31 };
-	unsigned long cycles = random_get_entropy(), now = jiffies;
+	unsigned long entropy = random_get_entropy();
 	struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
 	struct pt_regs *regs = get_irq_regs();
 	unsigned int new_count;
-	union {
-		u32 u32[4];
-		u64 u64[2];
-		unsigned long longs[16 / sizeof(long)];
-	} irq_data;
-
-	if (cycles == 0)
-		cycles = get_reg(fast_pool, regs);
-
-	if (sizeof(unsigned long) == 8) {
-		irq_data.u64[0] = cycles ^ rol64(now, 32) ^ irq;
-		irq_data.u64[1] = regs ? instruction_pointer(regs) : _RET_IP_;
-	} else {
-		irq_data.u32[0] = cycles ^ irq;
-		irq_data.u32[1] = now;
-		irq_data.u32[2] = regs ? instruction_pointer(regs) : _RET_IP_;
-		irq_data.u32[3] = get_reg(fast_pool, regs);
-	}
 
-	fast_mix(fast_pool->pool, irq_data.longs);
+	fast_mix(fast_pool->pool, (unsigned long[2]){
+		entropy,
+		(regs ? instruction_pointer(regs) : _RET_IP_) ^ swab(irq)
+	});
 	new_count = ++fast_pool->count;
 
 	if (new_count & MIX_INFLIGHT)
 		return;
 
-	if (new_count < 64 && (!time_after(now, fast_pool->last + HZ) ||
+	if (new_count < 64 && (!time_is_before_jiffies(fast_pool->last + HZ) ||
 			       unlikely(crng_init == 0)))
 		return;
 
@@ -1410,28 +1376,28 @@ static void entropy_timer(struct timer_l
 static void try_to_generate_entropy(void)
 {
 	struct {
-		unsigned long cycles;
+		unsigned long entropy;
 		struct timer_list timer;
 	} stack;
 
-	stack.cycles = random_get_entropy();
+	stack.entropy = random_get_entropy();
 
 	/* Slow counter - or none. Don't even bother */
-	if (stack.cycles == random_get_entropy())
+	if (stack.entropy == random_get_entropy())
 		return;
 
 	timer_setup_on_stack(&stack.timer, entropy_timer, 0);
 	while (!crng_ready() && !signal_pending(current)) {
 		if (!timer_pending(&stack.timer))
 			mod_timer(&stack.timer, jiffies + 1);
-		mix_pool_bytes(&stack.cycles, sizeof(stack.cycles));
+		mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
 		schedule();
-		stack.cycles = random_get_entropy();
+		stack.entropy = random_get_entropy();
 	}
 
 	del_timer_sync(&stack.timer);
 	destroy_timer_on_stack(&stack.timer);
-	mix_pool_bytes(&stack.cycles, sizeof(stack.cycles));
+	mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
 }
 
 



  parent reply	other threads:[~2022-05-27  8:58 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-27  8:49 [PATCH 5.18 00/47] 5.18.1-rc1 review Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 01/47] lockdown: also lock down previous kgdb use Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 02/47] HID: amd_sfh: Add support for sensor discovery Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 03/47] random: fix sysctl documentation nits Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 04/47] init: call time_init() before rand_initialize() Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 05/47] ia64: define get_cycles macro for arch-override Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 06/47] s390: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 07/47] parisc: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 08/47] alpha: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 09/47] powerpc: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 10/47] timekeeping: Add raw clock fallback for random_get_entropy() Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 11/47] m68k: use fallback for random_get_entropy() instead of zero Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 12/47] riscv: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 13/47] mips: use fallback for random_get_entropy() instead of just c0 random Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 14/47] arm: use fallback for random_get_entropy() instead of zero Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 15/47] nios2: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 16/47] x86/tsc: Use " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 17/47] um: use " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 18/47] sparc: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 19/47] xtensa: " Greg Kroah-Hartman
2022-05-27  8:50 ` Greg Kroah-Hartman [this message]
2022-05-27  8:50 ` [PATCH 5.18 21/47] random: do not use batches when !crng_ready() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 22/47] random: use first 128 bits of input as fast init Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 23/47] random: do not pretend to handle premature next security model Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 24/47] random: order timer entropy functions below interrupt functions Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 25/47] random: do not use input pool from hard IRQs Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 26/47] random: help compiler out with fast_mix() by using simpler arguments Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 27/47] siphash: use one source of truth for siphash permutations Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 28/47] random: use symbolic constants for crng_init states Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 29/47] random: avoid initializing twice in credit race Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 30/47] random: move initialization out of reseeding hot path Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 31/47] random: remove ratelimiting for in-kernel unseeded randomness Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 32/47] random: use proper jiffies comparison macro Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 33/47] random: handle latent entropy and command line from random_init() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 34/47] random: credit architectural init the exact amount Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 35/47] random: use static branch for crng_ready() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 36/47] random: remove extern from functions in header Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 37/47] random: use proper return types on get_random_{int,long}_wait() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 38/47] random: make consistent use of buf and len Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 39/47] random: move initialization functions out of hot pages Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 40/47] random: move randomize_page() into mm where it belongs Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 41/47] random: unify batched entropy implementations Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 42/47] random: convert to using fops->read_iter() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 43/47] random: convert to using fops->write_iter() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 44/47] random: wire up fops->splice_{read,write}_iter() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 45/47] random: check for signals after page of pool writes Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 46/47] ACPI: sysfs: Fix BERT error region memory mapping Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 47/47] ALSA: ctxfi: Add SB046x PCI ID Greg Kroah-Hartman
2022-05-27 22:40 ` [PATCH 5.18 00/47] 5.18.1-rc1 review Guenter Roeck
2022-05-28  1:53 ` Justin Forbes
2022-05-28  2:24 ` Ron Economos
2022-05-28  2:50 ` Bagas Sanjaya
2022-05-28 11:16 ` Naresh Kamboju
2022-05-28 13:39 ` Rudi Heitbaum
2022-05-29  2:48 ` Fox Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220527084804.729317069@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=Jason@zx2c4.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.