Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/x86 Add RDSEED and RDRAND backends for cpu_rng ...



details:   https://anonhg.NetBSD.org/src/rev/e173a42be62d
branches:  trunk
changeset: 813933:e173a42be62d
user:      tls <tls%NetBSD.org@localhost>
date:      Sat Feb 27 00:43:55 2016 +0000

description:
Add RDSEED and RDRAND backends for cpu_rng on amd64 and i386.

diffstat:

 sys/arch/x86/x86/cpu_rng.c |  81 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 76 insertions(+), 5 deletions(-)

diffs (109 lines):

diff -r 974064701128 -r e173a42be62d sys/arch/x86/x86/cpu_rng.c
--- a/sys/arch/x86/x86/cpu_rng.c        Sat Feb 27 00:13:21 2016 +0000
+++ b/sys/arch/x86/x86/cpu_rng.c        Sat Feb 27 00:43:55 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_rng.c,v 1.1 2016/02/27 00:09:45 tls Exp $ */
+/* $NetBSD: cpu_rng.c,v 1.2 2016/02/27 00:43:55 tls Exp $ */
 
 /*-
  * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -42,24 +42,95 @@
 static enum {
        CPU_RNG_NONE = 0,
        CPU_RNG_RDRAND,
-       CPU_RNG_RDSEED,
-       CPU_RNG_VIA } cpu_rng_mode __read_mostly = CPU_RNG_NONE;
+       CPU_RNG_RDSEED } cpu_rng_mode __read_mostly = CPU_RNG_NONE;
 
 bool
 cpu_rng_init(void)
 {
+
+       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;
+       }
        return false;
 }
 
+static inline size_t
+cpu_rng_rdrand(cpu_rng_t *out)
+{
+       uint8_t rndsts;
+
+#ifdef __i386__
+       uint32_t lo, hi;
+
+       __asm __volatile("rdrand %0; setc %1" : "=r"(lo), "=qm"(rndsts));
+       if (rndsts != 1)
+               return 0;
+       __asm __volatile("rdrand %0; setc %1" : "=r"(hi), "=qm"(rndsts));
+
+       *out = (uint64_t)lo | ((uint64_t)hi << 32);
+       explicit_memset(&lo, 0, sizeof(lo));
+       explicit_memset(&hi, 0, sizeof(hi));
+       if (rndsts != 1)
+               return sizeof(lo) * NBBY;
+#else
+       __asm __volatile("rdrand %0; setc %1" : "=r"(*out), "=qm"(rndsts));
+       if (rndsts != 1)
+               return 0;
+#endif
+       return sizeof(*out) * NBBY;
+}
+
+static inline size_t
+cpu_rng_rdseed(cpu_rng_t *out)
+{
+       uint8_t rndsts;
+
+#ifdef __i386__
+       uint32_t lo, hi;
+       
+       __asm __volatile("rdseed %0; setc %1" : "=r"(lo), "=qm"(rndsts));
+        if (rndsts != 1)
+               goto exhausted;
+       __asm __volatile("rdseed %0; setc %1" : "=r"(hi), "=qm"(rndsts));
+       if (rndsts != 1)
+               goto exhausted;
+
+       *out = (uint64_t)lo | ((uint64_t)hi << 32);
+       explicit_memset(&lo, 0, sizeof(lo));
+       explicit_memset(&hi, 0, sizeof(hi));
+#else
+       __asm __volatile("rdseed %0; setc %1" : "=r"(*out), "=qm"(rndsts));
+#endif
+       if (rndsts != 1)
+               goto exhausted;
+
+       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:
+       return cpu_rng_rdrand(out);
+}
+
 size_t
 cpu_rng(cpu_rng_t *out)
 {
        switch (cpu_rng_mode) {
        case CPU_RNG_NONE:
+               return 0;
        case CPU_RNG_RDSEED:
+               return cpu_rng_rdseed(out);
        case CPU_RNG_RDRAND:
-       case CPU_RNG_VIA:
-               return 0;
+               return cpu_rng_rdrand(out);
        default:
                panic("cpu_rng: unknown mode %d", (int)cpu_rng_mode);
        }



Home | Main Index | Thread Index | Old Index