From ace0b7c6acbb64800bb63bfd86d5798c179cae57 Mon Sep 17 00:00:00 2001 From: mengensun Date: Mon, 9 May 2022 11:24:07 +0800 Subject: [PATCH] random: add a switch of using rdrand ins in _extract_crng on some old AMD CPU(eg: older then AMD EPYC 7K62) , rdrand is slowly, random using rdrand to make the random num more hard to be guessed. while the randomness is not really affect by rdrand. when user not using random for security case, (eg: just geting some random num, not using it to generate password) using rdrand on old amd processor is so expensive. so, add a swith to rdrand, by default using the rdrand, when closed using tsc, jiffies, and entropy from the fast_pool to emulate the rdrand testing on AMD EPYC 7K62 like follow: --- echo 1 > /proc/sys/kernel/random/tos_use_rdrand stress-ng --urandom 2 --timeout 10s --times --metrics bogo ops real time usr time sys time bogo ops/s bogo ops/s (secs) (secs) (secs) (real time) (usr+sys time) 16542 10.00 0.00 19.98 1654.09 827.93 --- echo 0 > /proc/sys/kernel/random/tos_use_rdrand stress-ng --urandom 2 --timeout 10s --times --metrics bogo ops real time usr time sys time bogo ops/s bogo ops/s (secs) (secs) (secs) (real time) (usr+sys time) 222005 10.00 0.05 19.93 22200.41 11111.36 /dev/urandom reading and geturandom syscall 13 times faster then using really rdrand. Signed-off-by: mengensun Reviewed-by: frankjpliu Reviewed-by: anakinzhang Reviewed-by: Ruippan --- drivers/char/random.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index ffd61aadb..c2ab64b8f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -514,6 +514,9 @@ static struct ratelimit_state urandom_warning = static int ratelimit_disable __read_mostly; +static int use_rdrand = 1; +static unsigned long simulation_rdrand(void); + module_param_named(ratelimit_disable, ratelimit_disable, int, 0644); MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression"); @@ -1048,6 +1051,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) } } + static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]) { @@ -1057,9 +1061,16 @@ static void _extract_crng(struct crng_state *crng, (time_after(crng_global_init_time, crng->init_time) || time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))) crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL); + spin_lock_irqsave(&crng->lock, flags); - if (arch_get_random_long(&v)) + /* primary_crng is seldomly extracted */ + if (!use_rdrand && crng != &primary_crng) { + v = simulation_rdrand(); crng->state[14] ^= v; + } else if (arch_get_random_long(&v)) { + crng->state[14] ^= v; + } + chacha20_block(&crng->state[0], out); if (crng->state[12] == 0) crng->state[13]++; @@ -1268,6 +1279,21 @@ void add_input_randomness(unsigned int type, unsigned int code, EXPORT_SYMBOL_GPL(add_input_randomness); static DEFINE_PER_CPU(struct fast_pool, irq_randomness); +static unsigned long simulation_rdrand() +{ + unsigned long entropy; + struct fast_pool *fast_pool; + + entropy = random_get_entropy(); + fast_pool = this_cpu_ptr(&irq_randomness); + + entropy ^= fast_pool->pool[0]; + entropy ^= fast_pool->pool[1]; + entropy ^= fast_pool->pool[2]; + entropy ^= fast_pool->pool[3]; + entropy ^= jiffies; + return entropy; +} #ifdef ADD_INTERRUPT_BENCH static unsigned long avg_cycles, avg_deviation; @@ -2327,6 +2353,15 @@ struct ctl_table random_table[] = { .mode = 0444, .proc_handler = proc_do_uuid, }, + { + .procname = "tos_use_rdrand", + .data = &use_rdrand, + .maxlen = sizeof(use_rdrand), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE + }, #ifdef ADD_INTERRUPT_BENCH { .procname = "add_interrupt_avg_cycles",