Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random

Pull random updates from Ted Ts'o:
 "Some changes to trust cpu-based hwrng (such as RDRAND) for
  initializing hashed pointers and (optionally, controlled by a config
  option) to initialize the CRNG to avoid boot hangs"

* tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random:
  random: Make crng state queryable
  random: remove preempt disabled region
  random: add a config option to trust the CPU's hwrng
  vsprintf: Add command line option debug_boot_weak_hash
  vsprintf: Use hw RNG for ptr_key
  random: Return nbytes filled from hw RNG
  random: Fix whitespace pre random-bytes work
This commit is contained in:
Linus Torvalds
2018-08-15 21:16:02 -07:00
5 changed files with 85 additions and 16 deletions

View File

@@ -554,3 +554,17 @@ config ADI
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)
{
int i;
int arch_init = 1;
unsigned long rv;
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);
for (i = 4; i < 16; i++) {
if (!arch_get_random_seed_long(&rv) &&
!arch_get_random_long(&rv))
!arch_get_random_long(&rv)) {
rv = random_get_entropy();
arch_init = 0;
}
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;
}
@@ -1122,8 +1131,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
} sample;
long delta, delta2, delta3;
preempt_disable();
sample.jiffies = jiffies;
sample.cycles = random_get_entropy();
sample.num = num;
@@ -1161,8 +1168,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
* and limit entropy entimate to 12 bits.
*/
credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
preempt_enable();
}
void add_input_randomness(unsigned int type, unsigned int code,
@@ -1658,6 +1663,21 @@ int wait_for_random_bytes(void)
}
EXPORT_SYMBOL(wait_for_random_bytes);
/*
* Returns whether or not the urandom pool has been seeded and thus guaranteed
* to supply cryptographically secure random numbers. This applies to: the
* /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
* ,u64,int,long} family of functions.
*
* Returns: true if the urandom pool has been seeded.
* false if the urandom pool has not been seeded.
*/
bool rng_is_initialized(void)
{
return crng_ready();
}
EXPORT_SYMBOL(rng_is_initialized);
/*
* Add a callback function that will be invoked when the nonblocking
* pool is initialised.
@@ -1725,30 +1745,31 @@ EXPORT_SYMBOL(del_random_ready_callback);
* key known by the NSA). So it's useful if we need the speed, but
* only if we're willing to trust the hardware manufacturer not to
* have put in a back door.
*
* Return number of bytes filled in.
*/
void get_random_bytes_arch(void *buf, int nbytes)
int __must_check get_random_bytes_arch(void *buf, int nbytes)
{
int left = nbytes;
char *p = buf;
trace_get_random_bytes_arch(nbytes, _RET_IP_);
while (nbytes) {
trace_get_random_bytes_arch(left, _RET_IP_);
while (left) {
unsigned long v;
int chunk = min(nbytes, (int)sizeof(unsigned long));
int chunk = min_t(int, left, sizeof(unsigned long));
if (!arch_get_random_long(&v))
break;
memcpy(p, &v, chunk);
p += chunk;
nbytes -= chunk;
left -= chunk;
}
if (nbytes)
get_random_bytes(p, nbytes);
return nbytes - left;
}
EXPORT_SYMBOL(get_random_bytes_arch);
/*
* init_std_data - initialize pool with system data
*