Re: [PATCH v2] random: avoid superfluous call to RDRAND in CRNG extraction

From: Sandy Harris
Date: Tue Jan 04 2022 - 00:04:01 EST


If we are removing RDRAND, what about adding some
cheaper mixing? Something along these lines?

The current code's mixing is triggered only once in 2^32
iterations, depends only on crng->state[], always changes
the same state word, and introduces no new entropy.

Make it happen more often, depend on a randomly initialised
counter as well as state[], make a data-dependent choice of
word to change, and use random_get_entropy().
---
drivers/char/random.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 605969ed0f96..d2be079f004d 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -985,6 +985,10 @@ static void crng_reseed(struct crng_state *crng,
struct entropy_store *r)
}
}

+#define CC_SHIFT 8
+#define CC_MASK ((1<<CC_SHIFT)-1)
+static u32 cc_count = 0 ;
+
static void _extract_crng(struct crng_state *crng,
__u8 out[CHACHA_BLOCK_SIZE])
{
@@ -998,8 +1002,22 @@ static void _extract_crng(struct crng_state *crng,
if (arch_get_random_long(&v))
crng->state[14] ^= v;
chacha20_block(&crng->state[0], out);
- if (crng->state[12] == 0)
- crng->state[13]++;
+ if (cc_count == 0)
+ cc_count = crng->state[9] ^ random_get_entropy() ;
+ switch ((crng->state[12] ^ cc_count) & CC_MASK) {
+ case 0:
+ cc_count = crng->state[10] ^ (cc_count>>CC_SHIFT);
+ break ;
+ case 31: case 97: case 253:
+ crng->state[crng->state[13]&7]++;
+ break ;
+ case 61: case 127:
+ crng->state[crng->state[11]&7] += random_get_entropy();
+ break ;
+ default:
+ break ;
+ }
+ cc_count++ ;
spin_unlock_irqrestore(&crng->lock, flags);
}

--
Signed-off-by: Sandy Harris <sandyinchina@xxxxxxxxx>