aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/char
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2020-02-10 13:00:13 +0000
committerTheodore Ts'o <tytso@mit.edu>2020-02-27 23:21:52 -0500
commit253d3194c2b58152fe830fd27c2fd83ebc6fe5ee (patch)
treee9e6c341e7642b3e5cade3e18b57e2e049b75060 /drivers/char
parentrandom: split primary/secondary crng init paths (diff)
downloadwireguard-linux-253d3194c2b58152fe830fd27c2fd83ebc6fe5ee.tar.xz
wireguard-linux-253d3194c2b58152fe830fd27c2fd83ebc6fe5ee.zip
random: add arch_get_random_*long_early()
Some architectures (e.g. arm64) can have heterogeneous CPUs, and the boot CPU may be able to provide entropy while secondary CPUs cannot. On such systems, arch_get_random_long() and arch_get_random_seed_long() will fail unless support for RNG instructions has been detected on all CPUs. This prevents the boot CPU from being able to provide (potentially) trusted entropy when seeding the primary CRNG. To make it possible to seed the primary CRNG from the boot CPU without adversely affecting the runtime versions of arch_get_random_long() and arch_get_random_seed_long(), this patch adds new early versions of the functions used when initializing the primary CRNG. Default implementations are provided atop of the existing arch_get_random_long() and arch_get_random_seed_long() so that only architectures with such constraints need to provide the new helpers. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Mark Brown <broonie@kernel.org> Cc: Theodore Ts'o <tytso@mit.edu> Link: https://lore.kernel.org/r/20200210130015.17664-3-mark.rutland@arm.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/random.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 62d32e62f2da..02a85b87b993 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -799,6 +799,24 @@ static bool crng_init_try_arch(struct crng_state *crng)
return arch_init;
}
+static bool __init crng_init_try_arch_early(struct crng_state *crng)
+{
+ int i;
+ bool arch_init = true;
+ unsigned long rv;
+
+ for (i = 4; i < 16; i++) {
+ if (!arch_get_random_seed_long_early(&rv) &&
+ !arch_get_random_long_early(&rv)) {
+ rv = random_get_entropy();
+ arch_init = false;
+ }
+ crng->state[i] ^= rv;
+ }
+
+ return arch_init;
+}
+
static void crng_initialize_secondary(struct crng_state *crng)
{
memcpy(&crng->state[0], "expand 32-byte k", 16);
@@ -811,7 +829,7 @@ static void __init crng_initialize_primary(struct crng_state *crng)
{
memcpy(&crng->state[0], "expand 32-byte k", 16);
_extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0);
- if (crng_init_try_arch(crng) && trust_cpu) {
+ if (crng_init_try_arch_early(crng) && trust_cpu) {
invalidate_batched_entropy();
numa_crng_init();
crng_init = 2;