The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/random/ivy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2013 The FreeBSD Foundation
    3  * Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
    4  * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Portions of this software were developed by Konstantin Belousov
    8  * under sponsorship from the FreeBSD Foundation.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer
   15  *    in this position and unchanged.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/conf.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/module.h>
   42 #include <sys/random.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/systm.h>
   45 
   46 #include <machine/md_var.h>
   47 #include <machine/specialreg.h>
   48 #include <x86/ifunc.h>
   49 
   50 #include <dev/random/randomdev.h>
   51 
   52 #define RETRY_COUNT     10
   53 
   54 static bool has_rdrand, has_rdseed;
   55 static u_int random_ivy_read(void *, u_int);
   56 
   57 static struct random_source random_ivy = {
   58         .rs_ident = "Intel Secure Key RNG",
   59         .rs_source = RANDOM_PURE_RDRAND,
   60         .rs_read = random_ivy_read
   61 };
   62 
   63 SYSCTL_NODE(_kern_random, OID_AUTO, rdrand, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
   64     "rdrand (ivy) entropy source");
   65 static bool acquire_independent_seed_samples = false;
   66 SYSCTL_BOOL(_kern_random_rdrand, OID_AUTO, rdrand_independent_seed,
   67     CTLFLAG_RWTUN, &acquire_independent_seed_samples, 0,
   68     "If non-zero, use more expensive and slow, but safer, seeded samples "
   69     "where RDSEED is not present.");
   70 
   71 static bool
   72 x86_rdrand_store(u_long *buf)
   73 {
   74         u_long rndval, seed_iterations, i;
   75         int retry;
   76 
   77         /* Per [1], "ยง 5.2.6 Generating Seeds from RDRAND,"
   78          * machines lacking RDSEED will guarantee RDRAND is reseeded every 8kB
   79          * of generated output.
   80          *
   81          * [1]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide#inpage-nav-6-8
   82          */
   83         if (acquire_independent_seed_samples)
   84                 seed_iterations = 8 * 1024 / sizeof(*buf);
   85         else
   86                 seed_iterations = 1;
   87 
   88         for (i = 0; i < seed_iterations; i++) {
   89                 retry = RETRY_COUNT;
   90                 __asm __volatile(
   91                     "1:\n\t"
   92                     "rdrand     %1\n\t" /* read randomness into rndval */
   93                     "jc         2f\n\t" /* CF is set on success, exit retry loop */
   94                     "dec        %0\n\t" /* otherwise, retry-- */
   95                     "jne        1b\n\t" /* and loop if retries are not exhausted */
   96                     "2:"
   97                     : "+r" (retry), "=r" (rndval) : : "cc");
   98                 if (retry == 0)
   99                         return (false);
  100         }
  101         *buf = rndval;
  102         return (true);
  103 }
  104 
  105 static bool
  106 x86_rdseed_store(u_long *buf)
  107 {
  108         u_long rndval;
  109         int retry;
  110 
  111         retry = RETRY_COUNT;
  112         __asm __volatile(
  113             "1:\n\t"
  114             "rdseed     %1\n\t" /* read randomness into rndval */
  115             "jc         2f\n\t" /* CF is set on success, exit retry loop */
  116             "dec        %0\n\t" /* otherwise, retry-- */
  117             "jne        1b\n\t" /* and loop if retries are not exhausted */
  118             "2:"
  119             : "+r" (retry), "=r" (rndval) : : "cc");
  120         *buf = rndval;
  121         return (retry != 0);
  122 }
  123 
  124 static bool
  125 x86_unimpl_store(u_long *buf __unused)
  126 {
  127 
  128         panic("%s called", __func__);
  129 }
  130 
  131 DEFINE_IFUNC(static, bool, x86_rng_store, (u_long *buf))
  132 {
  133         has_rdrand = (cpu_feature2 & CPUID2_RDRAND);
  134         has_rdseed = (cpu_stdext_feature & CPUID_STDEXT_RDSEED);
  135 
  136         if (has_rdseed)
  137                 return (x86_rdseed_store);
  138         else if (has_rdrand)
  139                 return (x86_rdrand_store);
  140         else
  141                 return (x86_unimpl_store);
  142 }
  143 
  144 /* It is required that buf length is a multiple of sizeof(u_long). */
  145 static u_int
  146 random_ivy_read(void *buf, u_int c)
  147 {
  148         u_long *b, rndval;
  149         u_int count;
  150 
  151         KASSERT(c % sizeof(*b) == 0, ("partial read %d", c));
  152         b = buf;
  153         for (count = c; count > 0; count -= sizeof(*b)) {
  154                 if (!x86_rng_store(&rndval))
  155                         break;
  156                 *b++ = rndval;
  157         }
  158         return (c - count);
  159 }
  160 
  161 static int
  162 rdrand_modevent(module_t mod, int type, void *unused)
  163 {
  164         int error = 0;
  165 
  166         switch (type) {
  167         case MOD_LOAD:
  168                 if (has_rdrand || has_rdseed) {
  169                         random_source_register(&random_ivy);
  170                         printf("random: fast provider: \"%s\"\n", random_ivy.rs_ident);
  171                 }
  172                 break;
  173 
  174         case MOD_UNLOAD:
  175                 if (has_rdrand || has_rdseed)
  176                         random_source_deregister(&random_ivy);
  177                 break;
  178 
  179         case MOD_SHUTDOWN:
  180                 break;
  181 
  182         default:
  183                 error = EOPNOTSUPP;
  184                 break;
  185 
  186         }
  187 
  188         return (error);
  189 }
  190 
  191 static moduledata_t rdrand_mod = {
  192         "rdrand",
  193         rdrand_modevent,
  194         0
  195 };
  196 
  197 DECLARE_MODULE(rdrand, rdrand_mod, SI_SUB_RANDOM, SI_ORDER_FOURTH);
  198 MODULE_VERSION(rdrand, 1);
  199 MODULE_DEPEND(rdrand, random_harvestq, 1, 1, 1);

Cache object: 43c7c02ef924d1730228d3c760fbb14e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.