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$
   11  */
   12 
   13 #include <sys/types.h>
   14 #include <sys/random.h>
   15 #include <sys/libkern.h>
   16 #include <sys/time.h>
   17 
   18 #define ARC4_MAXRUNS 16384
   19 #define ARC4_RESEED_SECONDS 300
   20 #define ARC4_KEYBYTES 32 /* 256 bit key */
   21 
   22 static u_int8_t arc4_i, arc4_j;
   23 static int arc4_initialized = 0;
   24 static int arc4_numruns = 0;
   25 static u_int8_t arc4_sbox[256];
   26 static struct timeval arc4_tv_nextreseed;
   27 
   28 static u_int8_t arc4_randbyte(void);
   29 
   30 static __inline void
   31 arc4_swap(u_int8_t *a, u_int8_t *b)
   32 {
   33         u_int8_t c;
   34 
   35         c = *a;
   36         *a = *b;
   37         *b = c;
   38 }       
   39 
   40 /*
   41  * Stir our S-box.
   42  */
   43 static void
   44 arc4_randomstir (void)
   45 {
   46         u_int8_t key[256];
   47         int r, n;
   48 
   49         /*
   50          * XXX read_random() returns unsafe numbers if the entropy
   51          * device is not loaded -- MarkM.
   52          */
   53         r = read_random_unlimited(key, ARC4_KEYBYTES);
   54         /* If r == 0 || -1, just use what was on the stack. */
   55         if (r > 0)
   56         {
   57                 for (n = r; n < sizeof(key); n++)
   58                         key[n] = key[n % r];
   59         }
   60 
   61         for (n = 0; n < 256; n++)
   62         {
   63                 arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
   64                 arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
   65         }
   66 
   67         /* Reset for next reseed cycle. */
   68         getmicrotime(&arc4_tv_nextreseed);
   69         arc4_tv_nextreseed.tv_sec += ARC4_RESEED_SECONDS;
   70         arc4_numruns = 0;
   71 }
   72 
   73 /*
   74  * Initialize our S-box to its beginning defaults.
   75  */
   76 static void
   77 arc4_init(void)
   78 {
   79         int n;
   80 
   81         arc4_i = arc4_j = 0;
   82         for (n = 0; n < 256; n++)
   83                 arc4_sbox[n] = (u_int8_t) n;
   84 
   85         arc4_randomstir();
   86         arc4_initialized = 1;
   87 
   88         /*
   89          * Throw away the first N words of output, as suggested in the
   90          * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
   91          * by Fluher, Mantin, and Shamir.  (N = 256 in our case.)
   92          */
   93         for (n = 0; n < 256*4; n++)
   94                 arc4_randbyte();
   95 }
   96 
   97 /*
   98  * Generate a random byte.
   99  */
  100 static u_int8_t
  101 arc4_randbyte(void)
  102 {
  103         u_int8_t arc4_t;
  104 
  105         arc4_i = (arc4_i + 1) % 256;
  106         arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
  107 
  108         arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
  109 
  110         arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
  111         return arc4_sbox[arc4_t];
  112 }
  113 
  114 u_int32_t
  115 arc4random(void)
  116 {
  117         u_int32_t ret;
  118         struct timeval tv_now;
  119 
  120         /* Initialize array if needed. */
  121         if (!arc4_initialized)
  122                 arc4_init();
  123 
  124         getmicrotime(&tv_now);
  125         if ((++arc4_numruns > ARC4_MAXRUNS) || 
  126             (tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
  127         {
  128                 arc4_randomstir();
  129         }
  130 
  131         ret = arc4_randbyte();
  132         ret |= arc4_randbyte() << 8;
  133         ret |= arc4_randbyte() << 16;
  134         ret |= arc4_randbyte() << 24;
  135 
  136         return ret;
  137 }

Cache object: 3bb1cf231a5df0ffd9a96fdd761e0ff2


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