diff --git a/sys/conf/files.x86 b/sys/conf/files.x86 --- a/sys/conf/files.x86 +++ b/sys/conf/files.x86 @@ -311,6 +311,7 @@ dev/nvram/nvram.c optional nvram isa dev/random/ivy.c optional rdrand_rng !random_loadable dev/random/nehemiah.c optional padlock_rng !random_loadable +dev/random/rdseed.c optional rdrand_rng !random_loadable dev/qat_c2xxx/qat.c optional qat_c2xxx dev/qat_c2xxx/qat_ae.c optional qat_c2xxx dev/qat_c2xxx/qat_c2xxx.c optional qat_c2xxx diff --git a/sys/dev/random/ivy.c b/sys/dev/random/ivy.c --- a/sys/dev/random/ivy.c +++ b/sys/dev/random/ivy.c @@ -1,6 +1,6 @@ /*- + * Copyright (c) 2013, 2025, David E. O'Brien * Copyright (c) 2013 The FreeBSD Foundation - * Copyright (c) 2013 David E. O'Brien * Copyright (c) 2012 Konstantin Belousov * All rights reserved. * @@ -99,25 +99,6 @@ return (true); } -static bool -x86_rdseed_store(u_long *buf) -{ - u_long rndval; - int retry; - - retry = RETRY_COUNT; - __asm __volatile( - "1:\n\t" - "rdseed %1\n\t" /* read randomness into rndval */ - "jc 2f\n\t" /* CF is set on success, exit retry loop */ - "dec %0\n\t" /* otherwise, retry-- */ - "jne 1b\n\t" /* and loop if retries are not exhausted */ - "2:" - : "+r" (retry), "=r" (rndval) : : "cc"); - *buf = rndval; - return (retry != 0); -} - static bool x86_unimpl_store(u_long *buf __unused) { @@ -130,9 +111,7 @@ has_rdrand = (cpu_feature2 & CPUID2_RDRAND); has_rdseed = (cpu_stdext_feature & CPUID_STDEXT_RDSEED); - if (has_rdseed) - return (x86_rdseed_store); - else if (has_rdrand) + if (has_rdrand) return (x86_rdrand_store); else return (x86_unimpl_store); @@ -162,14 +141,14 @@ switch (type) { case MOD_LOAD: - if (has_rdrand || has_rdseed) { + if (has_rdrand && !has_rdseed) { random_source_register(&random_ivy); printf("random: fast provider: \"%s\"\n", random_ivy.rs_ident); } break; case MOD_UNLOAD: - if (has_rdrand || has_rdseed) + if (has_rdrand && !has_rdseed) random_source_deregister(&random_ivy); break; diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -666,6 +666,7 @@ [RANDOM_PURE_GLXSB] = "PURE_GLXSB", [RANDOM_PURE_HIFN] = "PURE_HIFN", [RANDOM_PURE_RDRAND] = "PURE_RDRAND", + [RANDOM_PURE_RDSEED] = "PURE_RDSEED", [RANDOM_PURE_NEHEMIAH] = "PURE_NEHEMIAH", [RANDOM_PURE_RNDTEST] = "PURE_RNDTEST", [RANDOM_PURE_VIRTIO] = "PURE_VIRTIO", diff --git a/sys/dev/random/ivy.c b/sys/dev/random/rdseed.c copy from sys/dev/random/ivy.c copy to sys/dev/random/rdseed.c --- a/sys/dev/random/ivy.c +++ b/sys/dev/random/rdseed.c @@ -1,6 +1,6 @@ /*- + * Copyright (c) 2013, 2025, David E. O'Brien * Copyright (c) 2013 The FreeBSD Foundation - * Copyright (c) 2013 David E. O'Brien * Copyright (c) 2012 Konstantin Belousov * All rights reserved. * @@ -48,56 +48,17 @@ #define RETRY_COUNT 10 -static bool has_rdrand, has_rdseed; -static u_int random_ivy_read(void *, u_int); +static bool has_rdseed; +static u_int random_rdseed_read(void *, u_int); -static const struct random_source random_ivy = { - .rs_ident = "Intel Secure Key RNG", - .rs_source = RANDOM_PURE_RDRAND, - .rs_read = random_ivy_read +static struct random_source random_rdseed = { + .rs_ident = "Intel Secure Key Seed", + .rs_source = RANDOM_PURE_RDSEED, + .rs_read = random_rdseed_read }; -SYSCTL_NODE(_kern_random, OID_AUTO, rdrand, CTLFLAG_RW | CTLFLAG_MPSAFE, 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 -x86_rdrand_store(u_long *buf) -{ - u_long rndval, seed_iterations, i; - 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; - __asm __volatile( - "1:\n\t" - "rdrand %1\n\t" /* read randomness into rndval */ - "jc 2f\n\t" /* CF is set on success, exit retry loop */ - "dec %0\n\t" /* otherwise, retry-- */ - "jne 1b\n\t" /* and loop if retries are not exhausted */ - "2:" - : "+r" (retry), "=r" (rndval) : : "cc"); - if (retry == 0) - return (false); - } - *buf = rndval; - return (true); -} +SYSCTL_NODE(_kern_random, OID_AUTO, rdseed, CTLFLAG_RW, 0, + "rdseed (x86) entropy source"); static bool x86_rdseed_store(u_long *buf) @@ -125,22 +86,19 @@ panic("%s called", __func__); } -DEFINE_IFUNC(static, bool, x86_rng_store, (u_long *buf)) +DEFINE_IFUNC(static, bool, x86_seed_store, (u_long *buf)) { - has_rdrand = (cpu_feature2 & CPUID2_RDRAND); has_rdseed = (cpu_stdext_feature & CPUID_STDEXT_RDSEED); if (has_rdseed) return (x86_rdseed_store); - else if (has_rdrand) - return (x86_rdrand_store); else return (x86_unimpl_store); } /* It is required that buf length is a multiple of sizeof(u_long). */ static u_int -random_ivy_read(void *buf, u_int c) +random_rdseed_read(void *buf, u_int c) { u_long *b, rndval; u_int count; @@ -148,7 +106,7 @@ KASSERT(c % sizeof(*b) == 0, ("partial read %d", c)); b = buf; for (count = c; count > 0; count -= sizeof(*b)) { - if (!x86_rng_store(&rndval)) + if (!x86_seed_store(&rndval)) break; *b++ = rndval; } @@ -156,21 +114,21 @@ } static int -rdrand_modevent(module_t mod, int type, void *unused) +rdseed_modevent(module_t mod, int type, void *unused) { int error = 0; switch (type) { case MOD_LOAD: - if (has_rdrand || has_rdseed) { - random_source_register(&random_ivy); - printf("random: fast provider: \"%s\"\n", random_ivy.rs_ident); + if (has_rdseed) { + random_source_register(&random_rdseed); + printf("random: fast provider: \"%s\"\n", random_rdseed.rs_ident); } break; case MOD_UNLOAD: - if (has_rdrand || has_rdseed) - random_source_deregister(&random_ivy); + if (has_rdseed) + random_source_deregister(&random_rdseed); break; case MOD_SHUTDOWN: @@ -185,12 +143,38 @@ return (error); } -static moduledata_t rdrand_mod = { - "rdrand", - rdrand_modevent, +static moduledata_t rdseed_mod = { + "rdseed", + rdseed_modevent, 0 }; -DECLARE_MODULE(rdrand, rdrand_mod, SI_SUB_RANDOM, SI_ORDER_FOURTH); -MODULE_VERSION(rdrand, 1); -MODULE_DEPEND(rdrand, random_harvestq, 1, 1, 1); +DECLARE_MODULE(rdseed, rdseed_mod, SI_SUB_RANDOM, SI_ORDER_FOURTH); +MODULE_VERSION(rdseed, 1); +MODULE_DEPEND(rdseed, random_harvestq, 1, 1, 1); + +/* + * Intel's RDSEED Entropy Assessment Report min-entropy claim is 0.6 Shannons + * per bit of data output. Rrefer to the following Entropy Source Validation + * (ESV) certificates: + * + * E#87: Junos OS Physical Entropy Source - Broadwell EP 10-Core Die + * Broadwell-EP-10 FCLGA2011 Intel(R) Xeon(R) E5-2620 V4 Processor + * https://csrc.nist.gov/projects/cryptographic-module-validation-program/entropy-validations/certificate/87 + * (URLs below omitted for brevity but follow same format.) + * + * E#121: Junos OS Physical Entropy Source - Intel Atom C3000 Series + * (Denverton) 16 Core Die with FCBGA1310 Package + * + * E#122: Junos OS Physical Entropy Source - Intel Xeon D-1500 Family + * (Broadwell) 8 Core Die with FCBGA1667 Package + * + * E#123: Junos OS Physical Entropy Source - Intel Xeon D-2100 Series + * (Skylake) 18 Core Die with FCBGA2518 Package + * + * E#141: Junos OS Physical Entropy Source - Intel Xeon D-10 Series + * (Ice Lake-D-10) Die with FCBGA2227 Package + * + * E#169: Junos OS Physical Entropy Source - Intel Xeon AWS-1000 v4 and + * E5 v4 (Broadwell EP) 15 Core Die with FCLGA2011 Package + */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -346,6 +346,7 @@ rc4 \ ${_rdma} \ ${_rdrand_rng} \ + ${_rdseed_rng} \ re \ rl \ ${_rockchip} \ @@ -822,6 +823,7 @@ _padlock= padlock _padlock_rng= padlock_rng _rdrand_rng= rdrand_rng +_rdseed_rng= rdseed_rng .endif _pchtherm = pchtherm _s3= s3 diff --git a/sys/modules/rdrand_rng/Makefile b/sys/modules/rdrand_rng/Makefile --- a/sys/modules/rdrand_rng/Makefile +++ b/sys/modules/rdrand_rng/Makefile @@ -6,9 +6,4 @@ CFLAGS+= -I${SRCTOP}/sys -# ld.bfd doesn't support ifuncs invoked non-PIC -.if ${MACHINE_CPUARCH} == "i386" -CFLAGS.gcc= -fPIC -.endif - .include diff --git a/sys/modules/rdseed_rng/Makefile b/sys/modules/rdseed_rng/Makefile new file mode 100644 --- /dev/null +++ b/sys/modules/rdseed_rng/Makefile @@ -0,0 +1,9 @@ +.PATH: ${SRCTOP}/sys/dev/random + +KMOD= rdseed_rng +SRCS= rdseed.c +SRCS+= bus_if.h device_if.h + +CFLAGS+= -I${SRCTOP}/sys + +.include diff --git a/sys/sys/random.h b/sys/sys/random.h --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -94,6 +94,7 @@ RANDOM_PURE_GLXSB, RANDOM_PURE_HIFN, RANDOM_PURE_RDRAND, + RANDOM_PURE_RDSEED, RANDOM_PURE_NEHEMIAH, RANDOM_PURE_RNDTEST, RANDOM_PURE_VIRTIO,