random: add a config option to trust the CPU's hwrng

This gives the user building their own kernel (or a Linux
distribution) the option of deciding whether or not to trust the CPU's
hardware random number generator (e.g., RDRAND for x86 CPU's) as being
correctly implemented and not having a back door introduced (perhaps
courtesy of a Nation State's law enforcement or intelligence
agencies).

This will prevent getrandom(2) from blocking, if there is a
willingness to trust the CPU manufacturer.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Theodore Ts'o 2018-07-17 18:24:27 -04:00
parent 3672476eda
commit 39a8883a2b
2 changed files with 24 additions and 1 deletions

View File

@ -554,3 +554,17 @@ config ADI
endmenu endmenu
config RANDOM_TRUST_CPU
bool "Trust the CPU manufacturer to initialize Linux's CRNG"
depends on X86 || S390 || PPC
default n
help
Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or
RDRAND, IBM for the S390 and Power PC architectures) is trustworthy
for the purposes of initializing Linux's CRNG. Since this is not
something that can be independently audited, this amounts to trusting
that CPU manufacturer (perhaps with the insistence or mandate
of a Nation State's intelligence or law enforcement agencies)
has not installed a hidden back door to compromise the CPU's
random number generation facilities.

View File

@ -782,6 +782,7 @@ static void invalidate_batched_entropy(void);
static void crng_initialize(struct crng_state *crng) static void crng_initialize(struct crng_state *crng)
{ {
int i; int i;
int arch_init = 1;
unsigned long rv; unsigned long rv;
memcpy(&crng->state[0], "expand 32-byte k", 16); memcpy(&crng->state[0], "expand 32-byte k", 16);
@ -792,10 +793,18 @@ static void crng_initialize(struct crng_state *crng)
_get_random_bytes(&crng->state[4], sizeof(__u32) * 12); _get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
for (i = 4; i < 16; i++) { for (i = 4; i < 16; i++) {
if (!arch_get_random_seed_long(&rv) && if (!arch_get_random_seed_long(&rv) &&
!arch_get_random_long(&rv)) !arch_get_random_long(&rv)) {
rv = random_get_entropy(); rv = random_get_entropy();
arch_init = 0;
}
crng->state[i] ^= rv; crng->state[i] ^= rv;
} }
#ifdef CONFIG_RANDOM_TRUST_CPU
if (arch_init) {
crng_init = 2;
pr_notice("random: crng done (trusting CPU's manufacturer)\n");
}
#endif
crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
} }