Module Name: src Committed By: tls Date: Sat Feb 27 00:54:59 UTC 2016
Modified Files: src/sys/arch/x86/include: via_padlock.h src/sys/arch/x86/x86: cpu_rng.c via_padlock.c Log Message: Remove callout-based RNG support in VIA crypto driver; add VIA RNG backend for cpu_rng. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/include/via_padlock.h cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/x86/cpu_rng.c cvs rdiff -u -r1.24 -r1.25 src/sys/arch/x86/x86/via_padlock.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/via_padlock.h diff -u src/sys/arch/x86/include/via_padlock.h:1.8 src/sys/arch/x86/include/via_padlock.h:1.9 --- src/sys/arch/x86/include/via_padlock.h:1.8 Mon Apr 13 16:03:51 2015 +++ src/sys/arch/x86/include/via_padlock.h Sat Feb 27 00:54:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: via_padlock.h,v 1.8 2015/04/13 16:03:51 riastradh Exp $ */ +/* $NetBSD: via_padlock.h,v 1.9 2016/02/27 00:54:59 tls Exp $ */ /*- * Copyright (c) 2003 Jason Wright @@ -59,11 +59,6 @@ struct via_padlock_softc { uint8_t op_iv[16]; /* 128 bit aligned */ void *op_buf; - int sc_rnd_hz; - struct callout sc_rnd_co; - krndsource_t sc_rnd_source; - bool sc_rnd_attached; - /* normal softc stuff */ int32_t sc_cid; bool sc_cid_attached; @@ -74,8 +69,6 @@ struct via_padlock_softc { #define VIAC3_SESSION(sid) ((sid) & 0x0fffffff) #define VIAC3_SID(crd,ses) (((crd) << 28) | ((ses) & 0x0fffffff)) -#define VIAC3_RNG_BUFSIZ 16 - #endif /* _KERNEL */ #if defined(_KERNEL) || defined(_KMEMUSER) Index: src/sys/arch/x86/x86/cpu_rng.c diff -u src/sys/arch/x86/x86/cpu_rng.c:1.2 src/sys/arch/x86/x86/cpu_rng.c:1.3 --- src/sys/arch/x86/x86/cpu_rng.c:1.2 Sat Feb 27 00:43:55 2016 +++ src/sys/arch/x86/x86/cpu_rng.c Sat Feb 27 00:54:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu_rng.c,v 1.2 2016/02/27 00:43:55 tls Exp $ */ +/* $NetBSD: cpu_rng.c,v 1.3 2016/02/27 00:54:59 tls Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -29,6 +29,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* + * 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 t...@openbsd.org mailing list. + */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/cpu.h> @@ -42,7 +48,8 @@ static enum { CPU_RNG_NONE = 0, CPU_RNG_RDRAND, - CPU_RNG_RDSEED } cpu_rng_mode __read_mostly = CPU_RNG_NONE; + CPU_RNG_RDSEED, + CPU_RNG_VIA } cpu_rng_mode __read_mostly = CPU_RNG_NONE; bool cpu_rng_init(void) @@ -56,6 +63,10 @@ cpu_rng_init(void) 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; } @@ -121,6 +132,49 @@ exhausted: return cpu_rng_rdrand(out); } +static size_t +cpu_rng_via(cpu_rng_t *out) +{ + uint32_t creg0, rndsts; + + /* + * Sadly, we have to monkey with the coprocessor enable and fault + * registers, which are really for the FPU, in order to read + * from the RNG. + * + * Don't remove CR0_TS from the call below -- comments in the Linux + * driver indicate that the xstorerng instruction can generate + * spurious DNA faults though no FPU or SIMD state is changed + * even if such a fault is generated. + * + * XXX can this really happen if we don't use "rep xstorrng"? + * + */ + kpreempt_disable(); + x86_disable_intr(); + creg0 = rcr0(); + lcr0(creg0 & ~(CR0_EM|CR0_TS)); /* Permit access to SIMD/FPU path */ + /* + * The VIA RNG has an output queue of 8-byte values. Read one. + * This is atomic, so if the FPU were already enabled, we could skip + * all the preemption and interrupt frobbing. If we had bread, + * we could have a ham sandwich, if we had any ham. + */ + __asm __volatile("xstorerng" + : "=a" (rndsts), "+D" (out) : "d" (0) : "memory"); + /* Put CR0 back how it was */ + lcr0(creg0); + x86_enable_intr(); + kpreempt_enable(); + + /* + * The Cryptography Research paper on the VIA RNG estimates + * 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; +} + size_t cpu_rng(cpu_rng_t *out) { @@ -131,6 +185,8 @@ cpu_rng(cpu_rng_t *out) return cpu_rng_rdseed(out); case CPU_RNG_RDRAND: return cpu_rng_rdrand(out); + case CPU_RNG_VIA: + return cpu_rng_via(out); default: panic("cpu_rng: unknown mode %d", (int)cpu_rng_mode); } Index: src/sys/arch/x86/x86/via_padlock.c diff -u src/sys/arch/x86/x86/via_padlock.c:1.24 src/sys/arch/x86/x86/via_padlock.c:1.25 --- src/sys/arch/x86/x86/via_padlock.c:1.24 Mon Apr 13 16:03:51 2015 +++ src/sys/arch/x86/x86/via_padlock.c Sat Feb 27 00:54:59 2016 @@ -1,5 +1,5 @@ /* $OpenBSD: via.c,v 1.8 2006/11/17 07:47:56 tom Exp $ */ -/* $NetBSD: via_padlock.c,v 1.24 2015/04/13 16:03:51 riastradh Exp $ */ +/* $NetBSD: via_padlock.c,v 1.25 2016/02/27 00:54:59 tls Exp $ */ /*- * Copyright (c) 2003 Jason Wright @@ -20,7 +20,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: via_padlock.c,v 1.24 2015/04/13 16:03:51 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: via_padlock.c,v 1.25 2016/02/27 00:54:59 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -28,7 +28,6 @@ __KERNEL_RCSID(0, "$NetBSD: via_padlock. #include <sys/kernel.h> #include <sys/device.h> #include <sys/module.h> -#include <sys/rndsource.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/cpu.h> @@ -72,64 +71,6 @@ static __inline void via_padlock_cbc(voi void *); static void -via_c3_rnd(void *arg) -{ - struct via_padlock_softc *sc = arg; - - uint32_t creg0, len = VIAC3_RNG_BUFSIZ; - uint32_t buffer[VIAC3_RNG_BUFSIZ/4 + 1]; /* CPU goes 3 bytes beyond */ - uint32_t eax, ecx, edi; /* XXX write-only, but necessary it seems */ - - /* - * Sadly, we have to monkey with the coprocessor enable and fault - * registers, which are really for the FPU, in order to read - * from the RNG. - * - * Don't remove CR0_TS from the call below -- comments in the Linux - * driver indicate that the xstorerng instruction can generate - * spurious DNA faults though no FPU or SIMD state is changed - * even if such a fault is generated. - * - */ - kpreempt_disable(); - x86_disable_intr(); - creg0 = rcr0(); - lcr0(creg0 & ~(CR0_EM|CR0_TS)); /* Permit access to SIMD/FPU path */ - /* - * Collect the random data from the C3 RNG into our buffer. - * We turn on maximum whitening (is this actually desirable - * if we will feed the data to SHA1?) (%edx[0,1] = "11"). - */ - __asm __volatile("rep xstorerng" - : "=a" (eax), "=c" (ecx), "=D" (edi) - : "d" (3), "D" (buffer), "c" (len) - : "memory", "cc"); - /* Put CR0 back how it was */ - lcr0(creg0); - x86_enable_intr(); - kpreempt_enable(); - rnd_add_data(&sc->sc_rnd_source, buffer, len, len * NBBY); - callout_reset(&sc->sc_rnd_co, sc->sc_rnd_hz, via_c3_rnd, sc); -} - -static void -via_c3_rnd_init(struct via_padlock_softc *sc) -{ - sc->sc_rnd_attached = true; - - if (hz >= 100) { - sc->sc_rnd_hz = 10 * hz / 100; - } else { - sc->sc_rnd_hz = 10; - } - rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), - RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE); - callout_init(&sc->sc_rnd_co, 0); - /* Call once to prime the pool early and set callout. */ - via_c3_rnd(sc); -} - -static void via_c3_ace_init(struct via_padlock_softc *sc) { /* @@ -608,7 +549,6 @@ via_padlock_attach_intr(device_t self) aprint_normal("%s:", device_xname(self)); if (cpu_feature[4] & CPUID_VIA_HAS_RNG) { - via_c3_rnd_init(sc); aprint_normal(" RNG"); } if (cpu_feature[4] & CPUID_VIA_HAS_ACE) { @@ -623,12 +563,6 @@ via_padlock_detach(device_t self, int fl { struct via_padlock_softc *sc = device_private(self); - if (sc->sc_rnd_attached) { - callout_halt(&sc->sc_rnd_co, NULL); - callout_destroy(&sc->sc_rnd_co); - rnd_detach_source(&sc->sc_rnd_source); - sc->sc_rnd_attached = false; - } if (sc->sc_cid_attached) { crypto_unregister(sc->sc_cid, CRYPTO_AES_CBC); crypto_unregister(sc->sc_cid, CRYPTO_MD5_HMAC_96);