Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Simplify Intel RDRAND/RDSEED and VIA C3 RNG API.
details: https://anonhg.NetBSD.org/src/rev/ab32b0fa0ba6
branches: trunk
changeset: 1009656:ab32b0fa0ba6
user: riastradh <riastradh%NetBSD.org@localhost>
date: Thu Apr 30 03:29:19 2020 +0000
description:
Simplify Intel RDRAND/RDSEED and VIA C3 RNG API.
Push it all into MD x86 code to keep it simpler, until we have other
examples on other CPUs. Simplify RDSEED-to-RDRAND fallback.
Eliminate cpu_earlyrng in favour of just using entropy_extract, which
is available early now.
diffstat:
sys/arch/amd64/amd64/machdep.c | 6 +-
sys/arch/i386/i386/machdep.c | 6 +-
sys/arch/x86/include/cpu_rng.h | 10 +-
sys/arch/x86/x86/cpu_rng.c | 208 ++++++++++++++++++++++++----------------
sys/arch/x86/x86/pmap.c | 10 +-
5 files changed, 138 insertions(+), 102 deletions(-)
diffs (truncated from 446 to 300 lines):
diff -r a8a31eeb02b8 -r ab32b0fa0ba6 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c Thu Apr 30 03:28:18 2020 +0000
+++ b/sys/arch/amd64/amd64/machdep.c Thu Apr 30 03:29:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.349 2020/04/28 21:35:35 jmcneill Exp $ */
+/* $NetBSD: machdep.c,v 1.350 2020/04/30 03:29:19 riastradh Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -110,7 +110,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.349 2020/04/28 21:35:35 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.350 2020/04/30 03:29:19 riastradh Exp $");
#include "opt_modular.h"
#include "opt_user_ldt.h"
@@ -167,6 +167,7 @@
#include <sys/sysctl.h>
#include <machine/cpu.h>
+#include <machine/cpu_rng.h>
#include <machine/cpufunc.h>
#include <machine/gdt.h>
#include <machine/intr.h>
@@ -1682,6 +1683,7 @@
uvm_lwp_setuarea(&lwp0, lwp0uarea);
cpu_probe(&cpu_info_primary);
+ cpu_rng_init();
#ifdef SVS
svs_init();
#endif
diff -r a8a31eeb02b8 -r ab32b0fa0ba6 sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c Thu Apr 30 03:28:18 2020 +0000
+++ b/sys/arch/i386/i386/machdep.c Thu Apr 30 03:29:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.827 2020/04/25 15:26:17 bouyer Exp $ */
+/* $NetBSD: machdep.c,v 1.828 2020/04/30 03:29:19 riastradh Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009, 2017
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.827 2020/04/25 15:26:17 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.828 2020/04/30 03:29:19 riastradh Exp $");
#include "opt_beep.h"
#include "opt_compat_freebsd.h"
@@ -122,6 +122,7 @@
#include <x86/efi.h>
#include <machine/cpu.h>
+#include <machine/cpu_rng.h>
#include <machine/cpufunc.h>
#include <machine/cpuvar.h>
#include <machine/gdt.h>
@@ -1142,6 +1143,7 @@
uvm_lwp_setuarea(&lwp0, lwp0uarea);
cpu_probe(&cpu_info_primary);
+ cpu_rng_init();
cpu_init_msrs(&cpu_info_primary, true);
#ifndef XEN
cpu_speculation_init(&cpu_info_primary);
diff -r a8a31eeb02b8 -r ab32b0fa0ba6 sys/arch/x86/include/cpu_rng.h
--- a/sys/arch/x86/include/cpu_rng.h Thu Apr 30 03:28:18 2020 +0000
+++ b/sys/arch/x86/include/cpu_rng.h Thu Apr 30 03:29:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_rng.h,v 1.2 2018/07/21 06:09:13 maxv Exp $ */
+/* $NetBSD: cpu_rng.h,v 1.3 2020/04/30 03:29:19 riastradh Exp $ */
#ifndef _X86_CPU_RNG_H_
#define _X86_CPU_RNG_H_
@@ -32,12 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/types.h>
-
-typedef uint64_t cpu_rng_t;
-
-bool cpu_rng_init(void);
-size_t cpu_rng(cpu_rng_t *);
-void cpu_earlyrng(void *, size_t);
+void cpu_rng_init(void);
#endif /* _X86_CPU_RNG_H_ */
diff -r a8a31eeb02b8 -r ab32b0fa0ba6 sys/arch/x86/x86/cpu_rng.c
--- a/sys/arch/x86/x86/cpu_rng.c Thu Apr 30 03:28:18 2020 +0000
+++ b/sys/arch/x86/x86/cpu_rng.c Thu Apr 30 03:29:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_rng.c,v 1.10 2019/11/01 15:01:27 taca Exp $ */
+/* $NetBSD: cpu_rng.c,v 1.11 2020/04/30 03:29:20 riastradh Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,11 +33,24 @@
* The VIA RNG code in this file is inspired by Jason Wright and
* Theo de Raadt's OpenBSD version but has been rewritten in light of
* comments from Henric Jungheim on the tech%openbsd.org@localhost mailing list.
+ *
+ * For reference on Intel RDRAND/RDSEED, see the Intel Digital Random
+ * Number Generator Software Implementation Guide (`Intel DRNG SIG'),
+ * Revision 2.1, October 17, 2018.
+ * https://software.intel.com/sites/default/files/managed/98/4a/DRNG_Software_Implementation_Guide_2.1.pdf
+ *
+ * For reference on AMD RDRAND/RDSEED, which are designed to be
+ * compatible with Intel RDRAND/RDSEED, see the somewhat less detailed
+ * AMD Random Number Generator documentation, 2017-06-27.
+ * https://www.amd.com/system/files/TechDocs/amd-random-number-generator.pdf
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/cpu.h>
+#include <sys/rnd.h>
+#include <sys/rndpool.h>
+#include <sys/rndsource.h>
#include <sys/sha2.h>
#include <x86/specialreg.h>
@@ -45,41 +58,66 @@
#include <machine/cpufunc.h>
#include <machine/cpuvar.h>
#include <machine/cpu_rng.h>
+#include <machine/limits.h>
-static enum {
+static enum cpu_rng_mode {
CPU_RNG_NONE = 0,
CPU_RNG_RDRAND,
CPU_RNG_RDSEED,
+ CPU_RNG_RDSEED_RDRAND,
CPU_RNG_VIA
} cpu_rng_mode __read_mostly = CPU_RNG_NONE;
-static bool has_rdrand;
+static const char *const cpu_rng_name[] = {
+ [CPU_RNG_RDRAND] = "rdrand",
+ [CPU_RNG_RDSEED] = "rdseed",
+ [CPU_RNG_RDSEED_RDRAND] = "rdrand/rdseed",
+ [CPU_RNG_VIA] = "via",
+};
-bool
-cpu_rng_init(void)
-{
+static struct krndsource cpu_rng_source __read_mostly;
- if (cpu_feature[5] & CPUID_SEF_RDSEED) {
- cpu_rng_mode = CPU_RNG_RDSEED;
- aprint_normal("cpu_rng: RDSEED\n");
- return true;
- } else if (cpu_feature[1] & CPUID2_RDRAND) {
- cpu_rng_mode = CPU_RNG_RDRAND;
- aprint_normal("cpu_rng: RDRAND\n");
- return true;
- } else if (cpu_feature[4] & CPUID_VIA_HAS_RNG) {
- cpu_rng_mode = CPU_RNG_VIA;
- aprint_normal("cpu_rng: VIA\n");
- return true;
- }
- return false;
+static enum cpu_rng_mode
+cpu_rng_detect(void)
+{
+ bool has_rdseed = (cpu_feature[5] & CPUID_SEF_RDSEED);
+ bool has_rdrand = (cpu_feature[1] & CPUID2_RDRAND);
+ bool has_viarng = (cpu_feature[4] & CPUID_VIA_HAS_RNG);
+
+ if (has_rdseed && has_rdrand)
+ return CPU_RNG_RDSEED_RDRAND;
+ else if (has_rdseed)
+ return CPU_RNG_RDSEED;
+ else if (has_rdrand)
+ return CPU_RNG_RDRAND;
+ else if (has_viarng)
+ return CPU_RNG_VIA;
+ else
+ return CPU_RNG_NONE;
}
static size_t
-cpu_rng_rdrand(cpu_rng_t *out)
+cpu_rng_rdrand(uint64_t *out)
{
uint8_t rndsts;
+ /*
+ * XXX The Intel DRNG SIG recommends (Sec. 5.2.1 `Retry
+ * recommendations', p. 22) that we retry up to ten times
+ * before giving up and panicking because something must be
+ * seriously awry with the CPU.
+ *
+ * XXX The Intel DRNG SIG also recommends (Sec. 5.2.6
+ * `Generating Seeds from RDRAND', p. 28) drawing 1024 64-bit
+ * samples (or, 512 128-bit samples) in order to guarantee that
+ * the CPU has drawn an independent sample from the physical
+ * entropy source, since the AES CTR_DRBG behind RDRAND will be
+ * used to generate at most 511 128-bit samples before it is
+ * reseeded from the physical entropy source. It is unclear
+ * whether the same considerations about RDSEED starvation
+ * apply to this advice.
+ */
+
#ifdef __i386__
uint32_t lo, hi;
@@ -102,19 +140,27 @@
}
static size_t
-cpu_rng_rdseed(cpu_rng_t *out)
+cpu_rng_rdseed(uint64_t *out)
{
uint8_t rndsts;
+ /*
+ * XXX The Intel DRNG SIG recommends (Sec. 5.3.1 `Retry
+ * recommendations', p. 22) that we consider retrying up to 100
+ * times, separated by PAUSE, but offers no guarantees about
+ * success after that many retries. In particular, userland
+ * threads could starve the kernel by issuing RDSEED.
+ */
+
#ifdef __i386__
uint32_t lo, hi;
__asm __volatile("rdseed %0; setc %1" : "=r"(lo), "=qm"(rndsts));
if (rndsts != 1)
- goto exhausted;
+ return 0;
__asm __volatile("rdseed %0; setc %1" : "=r"(hi), "=qm"(rndsts));
if (rndsts != 1)
- goto exhausted;
+ return 0;
*out = (uint64_t)lo | ((uint64_t)hi << 32);
explicit_memset(&lo, 0, sizeof(lo));
@@ -123,24 +169,24 @@
__asm __volatile("rdseed %0; setc %1" : "=r"(*out), "=qm"(rndsts));
#endif
if (rndsts != 1)
- goto exhausted;
+ return 0;
return sizeof(*out) * NBBY;
-
- /*
- * Userspace could have exhausted RDSEED, but the
- * CPU-internal generator feeding RDRAND is guaranteed
- * to be seeded even in this case.
- */
-exhausted:
- if (has_rdrand)
- return cpu_rng_rdrand(out);
- else
- return 0;
}
static size_t
-cpu_rng_via(cpu_rng_t *out)
+cpu_rng_rdseed_rdrand(uint64_t *out)
+{
+ size_t n = cpu_rng_rdseed(out);
+
+ if (n == 0)
+ n = cpu_rng_rdrand(out);
+
+ return n;
+}
+
+static size_t
+cpu_rng_via(uint64_t *out)
{
uint32_t creg0, rndsts;
@@ -179,72 +225,64 @@
* 0.75 bits of entropy per output bit and advises users to
* be "even more conservative".
*/
- return rndsts & 0xf ? 0 : sizeof(cpu_rng_t) * NBBY / 2;
+ return (rndsts & 0xf) ? 0 : sizeof(uint64_t) * NBBY/2;
}
-size_t
-cpu_rng(cpu_rng_t *out)
+static size_t
+cpu_rng(enum cpu_rng_mode mode, uint64_t *out)
{
- switch (cpu_rng_mode) {
+ switch (mode) {
case CPU_RNG_NONE:
return 0;
case CPU_RNG_RDSEED:
Home |
Main Index |
Thread Index |
Old Index