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 | |||||