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/libkern/arc4random.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  * THE BEER-WARE LICENSE
    3  *
    4  * <dan@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
    5  * can do whatever you want with this stuff.  If we meet some day, and you
    6  * think this stuff is worth it, you can buy me a beer in return.
    7  *
    8  * Dan Moschuk
    9  *
   10  * $FreeBSD: src/sys/libkern/arc4random.c,v 1.3.2.2 2001/09/17 07:06:50 silby Exp $
   11  * $DragonFly: src/sys/libkern/arc4random.c,v 1.3 2006/09/03 17:31:55 dillon Exp $
   12  */
   13 
   14 #include <sys/types.h>
   15 #include <sys/random.h>
   16 #include <sys/libkern.h>
   17 #include <sys/time.h>
   18 
   19 #define ARC4_MAXRUNS 16384
   20 #define ARC4_RESEED_SECONDS 300
   21 #define ARC4_KEYBYTES 32 /* 256 bit key */
   22 
   23 static u_int8_t arc4_i, arc4_j;
   24 static int arc4_initialized = 0;
   25 static int arc4_numruns = 0;
   26 static u_int8_t arc4_sbox[256];
   27 static struct timeval arc4_tv_nextreseed;
   28 
   29 static u_int8_t arc4_randbyte(void);
   30 
   31 static __inline void
   32 arc4_swap(u_int8_t *a, u_int8_t *b)
   33 {
   34         u_int8_t c;
   35 
   36         c = *a;
   37         *a = *b;
   38         *b = c;
   39 }       
   40 
   41 /*
   42  * Stir our S-box.
   43  */
   44 static void
   45 arc4_randomstir (void)
   46 {
   47         u_int8_t key[256];
   48         int r, n;
   49 
   50         /*
   51          * XXX read_random() returns unsafe numbers if the entropy
   52          * device is not loaded -- MarkM.
   53          */
   54         r = read_random_unlimited(key, ARC4_KEYBYTES);
   55         /* If r == 0 || -1, just use what was on the stack. */
   56         if (r > 0)
   57         {
   58                 for (n = r; n < sizeof(key); n++)
   59                         key[n] = key[n % r];
   60         }
   61 
   62         for (n = 0; n < 256; n++)
   63         {
   64                 arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
   65                 arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
   66         }
   67 
   68         /* Reset for next reseed cycle. */
   69         getmicrotime(&arc4_tv_nextreseed);
   70         arc4_tv_nextreseed.tv_sec += ARC4_RESEED_SECONDS;
   71         arc4_numruns = 0;
   72 }
   73 
   74 /*
   75  * Initialize our S-box to its beginning defaults.
   76  */
   77 static void
   78 arc4_init(void)
   79 {
   80         int n;
   81 
   82         arc4_i = arc4_j = 0;
   83         for (n = 0; n < 256; n++)
   84                 arc4_sbox[n] = (u_int8_t) n;
   85 
   86         arc4_randomstir();
   87         arc4_initialized = 1;
   88 
   89         /*
   90          * Throw away the first N words of output, as suggested in the
   91          * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
   92          * by Fluher, Mantin, and Shamir.  (N = 256 in our case.)
   93          */
   94         for (n = 0; n < 256*4; n++)
   95                 arc4_randbyte();
   96 }
   97 
   98 /*
   99  * Generate a random byte.
  100  */
  101 static u_int8_t
  102 arc4_randbyte(void)
  103 {
  104         u_int8_t arc4_t;
  105 
  106         arc4_i = (arc4_i + 1) % 256;
  107         arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
  108 
  109         arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
  110 
  111         arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
  112         return arc4_sbox[arc4_t];
  113 }
  114 
  115 u_int32_t
  116 karc4random(void)
  117 {
  118         u_int32_t ret;
  119         struct timeval tv_now;
  120 
  121         /* Initialize array if needed. */
  122         if (!arc4_initialized)
  123                 arc4_init();
  124 
  125         getmicrotime(&tv_now);
  126         if ((++arc4_numruns > ARC4_MAXRUNS) || 
  127             (tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
  128         {
  129                 arc4_randomstir();
  130         }
  131 
  132         ret = arc4_randbyte();
  133         ret |= arc4_randbyte() << 8;
  134         ret |= arc4_randbyte() << 16;
  135         ret |= arc4_randbyte() << 24;
  136 
  137         return ret;
  138 }
  139 
  140 void
  141 karc4rand(void *ptr, size_t len)
  142 {
  143         uint8_t *p;
  144         struct timeval tv_now;
  145 
  146         p = ptr;
  147 
  148         /* Initialize array if needed. */
  149         if (!arc4_initialized)
  150                 arc4_init();
  151 
  152         getmicrotime(&tv_now);
  153         if ((++arc4_numruns > ARC4_MAXRUNS) ||
  154             (tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
  155         {
  156                 arc4_randomstir();
  157         }
  158 
  159         while (len--)
  160                 *p++ = arc4_randbyte();
  161 }

Cache object: 08536471cc169fa39d00277d47f7d6cc


[ 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.