Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/random/randomdev.c
Show First 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
if (error == ERESTART || error == EINTR) | if (error == ERESTART || error == EINTR) | ||||
error = 0; | error = 0; | ||||
} | } | ||||
free(random_buf, M_ENTROPY); | free(random_buf, M_ENTROPY); | ||||
return (error); | return (error); | ||||
} | } | ||||
/*- | /*- | ||||
* Kernel API version of read_random(). | * Kernel API version of read_random(). This is similar to read_random_uio(), | ||||
* This is similar to random_alg_read(), | * except it doesn't interface with uio(9). It cannot assumed that random_buf | ||||
* except it doesn't interface with uio(9). | * is a multiple of RANDOM_BLOCKSIZE bytes. | ||||
* It cannot assumed that random_buf is a multiple of | * | ||||
* RANDOM_BLOCKSIZE bytes. | * If the tunable 'kern.random.initial_seeding.bypass_before_seeding' is set | ||||
* non-zero, silently fail to emit random data (matching the pre-r346250 | |||||
* behavior). If read_random is called prior to seeding and bypassed because | |||||
* of this tunable, the condition is reported in the read-only sysctl | |||||
* 'kern.random.initial_seeding.read_random_bypassed_before_seeding'. | |||||
*/ | */ | ||||
void | void | ||||
READ_RANDOM(void *random_buf, u_int len) | READ_RANDOM(void *random_buf, u_int len) | ||||
{ | { | ||||
u_int read_directly_len; | u_int read_directly_len; | ||||
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__)); | KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__)); | ||||
p_random_alg_context->ra_pre_read(); | p_random_alg_context->ra_pre_read(); | ||||
if (len == 0) | |||||
return; | |||||
/* (Un)Blocking logic */ | /* (Un)Blocking logic */ | ||||
if (!p_random_alg_context->ra_seeded()) | if (__predict_false(!p_random_alg_context->ra_seeded())) { | ||||
if (random_bypass_before_seeding) { | |||||
if (!read_random_bypassed_before_seeding) { | |||||
if (!random_bypass_disable_warnings) | |||||
printf("read_random: WARNING: bypassing" | |||||
" request for random data because " | |||||
"the random device is not yet " | |||||
"seeded and the knob " | |||||
"'bypass_before_seeding' was " | |||||
"enabled.\n"); | |||||
read_random_bypassed_before_seeding = true; | |||||
} | |||||
/* Avoid potentially leaking stack garbage */ | |||||
memset(random_buf, 0, len); | |||||
return; | |||||
} | |||||
(void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE); | (void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE); | ||||
} | |||||
read_rate_increment(roundup2(len, sizeof(uint32_t))); | read_rate_increment(roundup2(len, sizeof(uint32_t))); | ||||
if (len == 0) | |||||
return; | |||||
/* | /* | ||||
* The underlying generator expects multiples of | * The underlying generator expects multiples of | ||||
* RANDOM_BLOCKSIZE. | * RANDOM_BLOCKSIZE. | ||||
*/ | */ | ||||
read_directly_len = rounddown(len, RANDOM_BLOCKSIZE); | read_directly_len = rounddown(len, RANDOM_BLOCKSIZE); | ||||
if (read_directly_len > 0) | if (read_directly_len > 0) | ||||
p_random_alg_context->ra_read(random_buf, read_directly_len); | p_random_alg_context->ra_read(random_buf, read_directly_len); | ||||
if (read_directly_len < len) { | if (read_directly_len < len) { | ||||
▲ Show 20 Lines • Show All 208 Lines • Show Last 20 Lines |