Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/random/ivy.c
Show All 34 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/random.h> | #include <sys/random.h> | ||||
#include <sys/sysctl.h> | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
#include <x86/ifunc.h> | #include <x86/ifunc.h> | ||||
#include <dev/random/randomdev.h> | #include <dev/random/randomdev.h> | ||||
#define RETRY_COUNT 10 | #define RETRY_COUNT 10 | ||||
static bool has_rdrand, has_rdseed; | static bool has_rdrand, has_rdseed; | ||||
static u_int random_ivy_read(void *, u_int); | static u_int random_ivy_read(void *, u_int); | ||||
static struct random_source random_ivy = { | static struct random_source random_ivy = { | ||||
.rs_ident = "Intel Secure Key RNG", | .rs_ident = "Intel Secure Key RNG", | ||||
.rs_source = RANDOM_PURE_RDRAND, | .rs_source = RANDOM_PURE_RDRAND, | ||||
.rs_read = random_ivy_read | .rs_read = random_ivy_read | ||||
}; | }; | ||||
SYSCTL_NODE(_kern_random, OID_AUTO, rdrand, CTLFLAG_RW, 0, | |||||
"rdrand (ivy) entropy source"); | |||||
static bool acquire_independent_seed_samples = false; | |||||
SYSCTL_BOOL(_kern_random_rdrand, OID_AUTO, rdrand_independent_seed, | |||||
CTLFLAG_RWTUN, &acquire_independent_seed_samples, 0, | |||||
"If non-zero, use more expensive and slow, but safer, seeded samples " | |||||
"where RDSEED is not present."); | |||||
static bool | static bool | ||||
x86_rdrand_store(u_long *buf) | x86_rdrand_store(u_long *buf) | ||||
{ | { | ||||
u_long rndval; | u_long rndval, seed_iterations, i; | ||||
int retry; | int retry; | ||||
/* Per [1], "§ 5.2.6 Generating Seeds from RDRAND," | |||||
* machines lacking RDSEED will guarantee RDRAND is reseeded every 8kB | |||||
* of generated output. | |||||
* | |||||
* [1]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide#inpage-nav-6-8 | |||||
*/ | |||||
if (acquire_independent_seed_samples) | |||||
seed_iterations = 8 * 1024 / sizeof(*buf); | |||||
else | |||||
seed_iterations = 1; | |||||
for (i = 0; i < seed_iterations; i++) { | |||||
retry = RETRY_COUNT; | retry = RETRY_COUNT; | ||||
__asm __volatile( | __asm __volatile( | ||||
"1:\n\t" | "1:\n\t" | ||||
"rdrand %1\n\t" /* read randomness into rndval */ | "rdrand %1\n\t" /* read randomness into rndval */ | ||||
"jc 2f\n\t" /* CF is set on success, exit retry loop */ | "jc 2f\n\t" /* CF is set on success, exit retry loop */ | ||||
"dec %0\n\t" /* otherwise, retry-- */ | "dec %0\n\t" /* otherwise, retry-- */ | ||||
"jne 1b\n\t" /* and loop if retries are not exhausted */ | "jne 1b\n\t" /* and loop if retries are not exhausted */ | ||||
"2:" | "2:" | ||||
: "+r" (retry), "=r" (rndval) : : "cc"); | : "+r" (retry), "=r" (rndval) : : "cc"); | ||||
if (retry == 0) | |||||
return (false); | |||||
} | |||||
*buf = rndval; | *buf = rndval; | ||||
return (retry != 0); | return (true); | ||||
} | } | ||||
static bool | static bool | ||||
x86_rdseed_store(u_long *buf) | x86_rdseed_store(u_long *buf) | ||||
{ | { | ||||
u_long rndval; | u_long rndval; | ||||
int retry; | int retry; | ||||
▲ Show 20 Lines • Show All 89 Lines • Show Last 20 Lines |