tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Patch: CPU RNG framework with stub x86 implementation
As requested - here's just "cpu_rng" itself for review. I believe this
version addresses all comments received so far except that I _like_ the
construct "size_t cnt = <constant>; type_t foo[x]" so I've retained
that.
On the other hand, I _dislike_ needless forward declarations so I've
moved a small amount of code in kern_rndq.c to avoid another one of
those.
If this looks OK, I'll commit it and the next thing for review will be
the RDRAND backend; then RDSEED, then VIA. I have no hardware with RDSEED
nor a VIA RNG to test, so I'd appreciate help with that.
The RDRAND backend (unsurprisingly) passes the in-kernel statistical
test on both i386 and amd64.
Thor
Index: arch/amd64/include/Makefile
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/amd64/include/Makefile,v
retrieving revision 1.18
diff -u -p -r1.18 Makefile
--- arch/amd64/include/Makefile 23 Jul 2014 18:19:43 -0000 1.18
+++ arch/amd64/include/Makefile 8 Jan 2016 13:50:42 -0000
@@ -4,7 +4,7 @@ INCSDIR= /usr/include/amd64
INCS= ansi.h aout_machdep.h asm.h \
bootinfo.h bswap.h byte_swap.h \
- cdefs.h cpu.h \
+ cdefs.h cpu.h cpu_rng.h\
disklabel.h \
elf_machdep.h endian.h endian_machdep.h \
float.h fpu.h frame.h frame_regs.h \
Index: arch/amd64/include/types.h
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/amd64/include/types.h,v
retrieving revision 1.48
diff -u -p -r1.48 types.h
--- arch/amd64/include/types.h 27 Aug 2015 12:30:50 -0000 1.48
+++ arch/amd64/include/types.h 8 Jan 2016 13:50:42 -0000
@@ -93,6 +93,7 @@ typedef unsigned char __cpu_simple_lock
#define __HAVE_TLS_VARIANT_II
#define __HAVE_COMMON___TLS_GET_ADDR
#define __HAVE_INTR_CONTROL
+#define __HAVE_CPU_RNG
#ifdef _KERNEL_OPT
#define __HAVE_RAS
Index: arch/i386/include/Makefile
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/i386/include/Makefile,v
retrieving revision 1.43
diff -u -p -r1.43 Makefile
--- arch/i386/include/Makefile 23 Jul 2014 18:19:44 -0000 1.43
+++ arch/i386/include/Makefile 8 Jan 2016 13:50:42 -0000
@@ -4,7 +4,7 @@ INCSDIR= /usr/include/i386
INCS= ansi.h aout_machdep.h apmvar.h asm.h \
bioscall.h bootinfo.h bswap.h byte_swap.h \
- cdefs.h cpu.h cputypes.h \
+ cdefs.h cpu.h cpu_rng.h cputypes.h \
disklabel.h \
elf_machdep.h endian.h endian_machdep.h \
fenv.h float.h frame.h freebsd_machdep.h \
Index: arch/i386/include/types.h
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/i386/include/types.h,v
retrieving revision 1.83
diff -u -p -r1.83 types.h
--- arch/i386/include/types.h 27 Aug 2015 12:30:51 -0000 1.83
+++ arch/i386/include/types.h 8 Jan 2016 13:50:42 -0000
@@ -109,6 +109,8 @@ typedef unsigned char __cpu_simple_lock
#define __HAVE_SYSCALL_INTERN
#define __HAVE_MINIMAL_EMUL
#define __HAVE_OLD_DISKLABEL
+#define __HAVE_CPU_RNG
+
#if defined(_KERNEL)
/*
* Processors < i586 do not have cmpxchg8b, and we compile for i486
Index: arch/x86/conf/files.x86
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.85
diff -u -p -r1.85 files.x86
--- arch/x86/conf/files.x86 11 Nov 2015 08:20:22 -0000 1.85
+++ arch/x86/conf/files.x86 8 Jan 2016 13:50:42 -0000
@@ -27,6 +27,7 @@ define ipmibus {}
device cpu: cpufeaturebus
attach cpu at cpubus
file arch/x86/x86/cpu.c cpu
+file arch/x86/x86/cpu_rng.c cpu
device acpicpu: acpi
attach acpicpu at cpufeaturebus
Index: arch/x86/include/Makefile
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/x86/include/Makefile,v
retrieving revision 1.19
diff -u -p -r1.19 Makefile
--- arch/x86/include/Makefile 11 Feb 2014 20:17:16 -0000 1.19
+++ arch/x86/include/Makefile 8 Jan 2016 13:50:42 -0000
@@ -7,6 +7,7 @@ INCS= aout_machdep.h \
cacheinfo.h \
cpu.h \
cpu_extended_state.h \
+ cpu_rng.h \
cpu_ucode.h \
cputypes.h \
cpuvar.h \
Index: kern/kern_rndq.c
===================================================================
RCS file: /Volumes/NB/repo/src/sys/kern/kern_rndq.c,v
retrieving revision 1.74
diff -u -p -r1.74 kern_rndq.c
--- kern/kern_rndq.c 1 Jan 2016 16:09:00 -0000 1.74
+++ kern/kern_rndq.c 8 Jan 2016 13:50:42 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_rndq.c,v 1.72 2015/08/05 16:51:09 riastradh Exp $ */
+/* $NetBSD: kern_rndq.c,v 1.74 2016/01/01 16:09:00 tls Exp $ */
/*-
* Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.72 2015/08/05 16:51:09 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.74 2016/01/01 16:09:00 tls Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -59,6 +59,10 @@ __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,
#include <compat/sys/rnd.h>
#endif
+#if defined(__HAVE_CPU_RNG)
+#include <machine/cpu_rng.h>
+#endif
+
#if defined(__HAVE_CPU_COUNTER)
#include <machine/cpu_counter.h>
#endif
@@ -189,17 +193,6 @@ rnd_printf(const char *fmt, ...)
rnd_printing = 0;
}
-void
-rnd_init_softint(void)
-{
-
- rnd_process = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
- rnd_intr, NULL);
- rnd_wakeup = softint_establish(SOFTINT_CLOCK|SOFTINT_MPSAFE,
- rnd_wake, NULL);
- rnd_schedule_process();
-}
-
/*
* Generate a 32-bit counter.
*/
@@ -404,6 +397,49 @@ rnd_dv_estimate(krndsource_t *rs, uint32
return ret;
}
+#if defined(__HAVE_CPU_RNG)
+static struct {
+ kmutex_t lock; /* unfortunately, must protect krndsource */
+ void * intr;
+ krndsource_t source;
+} rnd_cpu __cacheline_aligned;
+
+static void
+rnd_cpu_get(size_t bytes, void *priv)
+{
+ krndsource_t *cpusrcp = priv;
+ KASSERT(cpusrcp == &rnd_cpu.source);
+
+ if (__predict_true(rnd_cpu.intr != NULL)) {
+ rnd_schedule_softint(rnd_cpu.intr);
+ }
+}
+
+static void
+rnd_cpu_intr(void *priv)
+{
+ size_t entropy = 0;
+ size_t cnt = 2 * RND_ENTROPY_THRESHOLD / sizeof(cpu_rng_t);
+ cpu_rng_t buf[cnt];
+ krndsource_t *cpusrcp = &rnd_cpu.source;
+
+ if (RND_ENABLED(cpusrcp)) {
+ cpu_rng_t *bufp;
+
+ mutex_spin_enter(&rnd_cpu.lock);
+ for (bufp = buf; bufp < buf + cnt; bufp++) {
+ entropy += cpu_rng(bufp);
+ }
+ if (__predict_true(entropy)) {
+ rnd_add_data(cpusrcp, buf, sizeof(buf), entropy);
+ explicit_memset(buf, 0, sizeof(buf));
+ }
+ mutex_spin_exit(&rnd_cpu.lock);
+ }
+}
+
+#endif
+
#if defined(__HAVE_CPU_COUNTER)
static struct {
kmutex_t lock;
@@ -463,6 +499,21 @@ rnd_skew_intr(void *arg)
}
#endif
+void
+rnd_init_softint(void)
+{
+
+ rnd_process = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
+ rnd_intr, NULL);
+ rnd_wakeup = softint_establish(SOFTINT_CLOCK|SOFTINT_MPSAFE,
+ rnd_wake, NULL);
+#ifdef __HAVE_CPU_RNG
+ rnd_cpu.intr = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
+ rnd_cpu_intr, NULL);
+#endif
+ rnd_schedule_process();
+}
+
/*
* Entropy was just added to the pool. If we crossed the threshold for
* the first time, set rnd_initial_entropy = 1.
@@ -542,6 +593,21 @@ rnd_init(void)
}
/*
+ * Attach CPU RNG if available.
+ */
+#if defined(__HAVE_CPU_RNG)
+ if (cpu_rng_init()) {
+ /* IPL_VM because taken while rnd_global.lock is held. */
+ mutex_init(&rnd_cpu.lock, MUTEX_DEFAULT, IPL_VM);
+ rndsource_setcb(&rnd_cpu.source, rnd_cpu_get, &rnd_cpu.source);
+ rnd_attach_source(&rnd_cpu.source, "cpurng",
+ RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE|
+ RND_FLAG_HASCB|RND_FLAG_HASENABLE);
+ rnd_cpu_intr(NULL);
+ }
+#endif
+
+ /*
* If we have a cycle counter, take its error with respect
* to the callout mechanism as a source of entropy, ala
* TrueRand.
@@ -572,7 +638,7 @@ rnd_init(void)
mutex_spin_exit(&rnd_global.lock);
rnd_printf("rnd: seeded with %d bits\n",
MIN(boot_rsp->entropy, RND_POOLBITS / 2));
- memset(boot_rsp, 0, sizeof(*boot_rsp));
+ explicit_memset(boot_rsp, 0, sizeof(*boot_rsp));
}
rnd_attach_source(&rnd_printf_source, "printf", RND_TYPE_UNKNOWN,
RND_FLAG_NO_ESTIMATE);
@@ -621,7 +687,7 @@ static void
rnd_sample_free(rnd_sample_t *c)
{
- memset(c, 0, sizeof(*c));
+ explicit_memset(c, 0, sizeof(*c));
pool_cache_put(rnd_mempc, c);
}
@@ -996,7 +1062,7 @@ rnd_hwrng_test(rnd_sample_t *sample)
return 1;
}
source->test_cnt = -1;
- memset(source->test, 0, sizeof(*source->test));
+ explicit_memset(source->test, 0, sizeof(*source->test));
}
return 0;
}
@@ -1201,10 +1267,10 @@ rnd_extract_data(void *p, uint32_t len,
"STATISTICAL TEST!\n");
continue;
}
- memset(&rnd_rt, 0, sizeof(rnd_rt));
+ explicit_memset(&rnd_rt, 0, sizeof(rnd_rt));
rndpool_add_data(&rnd_global.pool, rnd_testbits,
sizeof(rnd_testbits), entropy_count);
- memset(rnd_testbits, 0, sizeof(rnd_testbits));
+ explicit_memset(rnd_testbits, 0, sizeof(rnd_testbits));
rnd_printf_verbose("rnd: statistical RNG test done,"
" entropy = %d.\n",
rndpool_get_entropy_count(&rnd_global.pool));
@@ -1319,7 +1385,7 @@ rnd_seed(void *base, size_t len)
rndpool_add_data(&rnd_global.pool, boot_rsp->data,
sizeof(boot_rsp->data),
MIN(boot_rsp->entropy, RND_POOLBITS / 2));
- memset(boot_rsp, 0, sizeof(*boot_rsp));
+ explicit_memset(boot_rsp, 0, sizeof(*boot_rsp));
mutex_spin_exit(&rnd_global.lock);
} else {
rnd_printf_verbose("rnd: not ready, deferring seed feed.\n");
Home |
Main Index |
Thread Index |
Old Index