History

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.

Mark Rutland committed 6 years ago

Commit 253d3191 parent 5cbe0f12 files · +41 −1Browse files

Unified · Split

2 files
  1. drivers/char/random.c +19 −1
  2. include/linux/random.h +22 −0
drivers/char/random.c+19−1
@@ -799,6 +799,24 @@ static bool crng_init_try_arch(struct crng_state *crng) · 798 unmodified lines
799 return arch_init;799 return arch_init;
800}800}
801 801
802static bool __init crng_init_try_arch_early(struct crng_state *crng)
803{
804 int i;
805 bool arch_init = true;
806 unsigned long rv;
807
808 for (i = 4; i < 16; i++) {
809 if (!arch_get_random_seed_long_early(&rv) &&
810 !arch_get_random_long_early(&rv)) {
811 rv = random_get_entropy();
812 arch_init = false;
813 }
814 crng->state[i] ^= rv;
815 }
816
817 return arch_init;
818}
819
802static void crng_initialize_secondary(struct crng_state *crng)820static void crng_initialize_secondary(struct crng_state *crng)
803{821{
804 memcpy(&crng->state[0], "expand 32-byte k", 16);822 memcpy(&crng->state[0], "expand 32-byte k", 16);
@@ -811,7 +829,7 @@ static void __init crng_initialize_primary(struct crng_state *crng) · 6 unmodified lines
811{829{
812 memcpy(&crng->state[0], "expand 32-byte k", 16);830 memcpy(&crng->state[0], "expand 32-byte k", 16);
813 _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0);831 _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0);
814 if (crng_init_try_arch(crng) && trust_cpu) {832 if (crng_init_try_arch_early(crng) && trust_cpu) {
815 invalidate_batched_entropy();833 invalidate_batched_entropy();
816 numa_crng_init();834 numa_crng_init();
817 crng_init = 2;835 crng_init = 2;
include/linux/random.h+22−0
@@ -7,6 +7,8 @@ · 6 unmodified lines
7#ifndef _LINUX_RANDOM_H7#ifndef _LINUX_RANDOM_H
8#define _LINUX_RANDOM_H8#define _LINUX_RANDOM_H
9 9
10#include <linux/bug.h>
11#include <linux/kernel.h>
10#include <linux/list.h>12#include <linux/list.h>
11#include <linux/once.h>13#include <linux/once.h>
12 14
@@ -185,6 +187,26 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v) · 172 unmodified lines
185}187}
186#endif188#endif
187 189
190/*
191 * Called from the boot CPU during startup; not valid to call once
192 * secondary CPUs are up and preemption is possible.
193 */
194#ifndef arch_get_random_seed_long_early
195static inline bool __init arch_get_random_seed_long_early(unsigned long *v)
196{
197 WARN_ON(system_state != SYSTEM_BOOTING);
198 return arch_get_random_seed_long(v);
199}
200#endif
201
202#ifndef arch_get_random_long_early
203static inline bool __init arch_get_random_long_early(unsigned long *v)
204{
205 WARN_ON(system_state != SYSTEM_BOOTING);
206 return arch_get_random_long(v);
207}
208#endif
209
188/* Pseudo random number generator from numerical recipes. */210/* Pseudo random number generator from numerical recipes. */
189static inline u32 next_pseudo_random32(u32 seed)211static inline u32 next_pseudo_random32(u32 seed)
190{212{