LCOV - code coverage report
Current view: top level - lib - rand-isaac.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 0 92 0.0 %
Date: 2018-01-30 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* Bob Jenkins's cryptographic random number generator, ISAAC.
       2             : 
       3             :    Copyright (C) 1999-2006 Free Software Foundation, Inc.
       4             :    Copyright (C) 1997, 1998, 1999 Colin Plumb.
       5             : 
       6             :    This program is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation, either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : 
      19             :    Written by Colin Plumb.  */
      20             : 
      21             : /*
      22             :  * --------------------------------------------------------------------
      23             :  * We need a source of random numbers for some data.
      24             :  * Cryptographically secure is desirable, but it's not life-or-death
      25             :  * so I can be a little bit experimental in the choice of RNGs here.
      26             :  *
      27             :  * This generator is based somewhat on RC4, but has analysis
      28             :  * <http://burtleburtle.net/bob/rand/isaacafa.html>
      29             :  * pointing to it actually being better.  I like it because it's nice
      30             :  * and fast, and because the author did good work analyzing it.
      31             :  * --------------------------------------------------------------------
      32             :  */
      33             : #include <config.h>
      34             : 
      35             : #include "rand-isaac.h"
      36             : 
      37             : #include <string.h>
      38             : #include <unistd.h>
      39             : 
      40             : #include "gethrxtime.h"
      41             : 
      42             : 
      43             : /* This index operation is more efficient on many processors */
      44             : #define ind(mm, x) \
      45             :   (* (uint32_t *) ((char *) (mm) \
      46             :                    + ((x) & (ISAAC_WORDS - 1) * sizeof (uint32_t))))
      47             : 
      48             : /*
      49             :  * The central step.  This uses two temporaries, x and y.  mm is the
      50             :  * whole state array, while m is a pointer to the current word.  off is
      51             :  * the offset from m to the word ISAAC_WORDS/2 words away in the mm array,
      52             :  * i.e. +/- ISAAC_WORDS/2.
      53             :  */
      54             : #define isaac_step(mix, a, b, mm, m, off, r) \
      55             : ( \
      56             :   a = ((a) ^ (mix)) + (m)[off], \
      57             :   x = *(m), \
      58             :   *(m) = y = ind (mm, x) + (a) + (b), \
      59             :   *(r) = b = ind (mm, (y) >> ISAAC_LOG) + x \
      60             : )
      61             : 
      62             : /* Use and update *S to generate random data to fill R.  */
      63             : void
      64           0 : isaac_refill (struct isaac_state *s, uint32_t r[ISAAC_WORDS])
      65             : {
      66             :   uint32_t a, b;                /* Caches of a and b */
      67             :   uint32_t x, y;                /* Temps needed by isaac_step macro */
      68           0 :   uint32_t *m = s->mm;       /* Pointer into state array */
      69             : 
      70           0 :   a = s->a;
      71           0 :   b = s->b + (++s->c);
      72             : 
      73             :   do
      74             :     {
      75           0 :       isaac_step (a << 13, a, b, s->mm, m, ISAAC_WORDS / 2, r);
      76           0 :       isaac_step (a >> 6, a, b, s->mm, m + 1, ISAAC_WORDS / 2, r + 1);
      77           0 :       isaac_step (a << 2, a, b, s->mm, m + 2, ISAAC_WORDS / 2, r + 2);
      78           0 :       isaac_step (a >> 16, a, b, s->mm, m + 3, ISAAC_WORDS / 2, r + 3);
      79           0 :       r += 4;
      80             :     }
      81           0 :   while ((m += 4) < s->mm + ISAAC_WORDS / 2);
      82             :   do
      83             :     {
      84           0 :       isaac_step (a << 13, a, b, s->mm, m, -ISAAC_WORDS / 2, r);
      85           0 :       isaac_step (a >> 6, a, b, s->mm, m + 1, -ISAAC_WORDS / 2, r + 1);
      86           0 :       isaac_step (a << 2, a, b, s->mm, m + 2, -ISAAC_WORDS / 2, r + 2);
      87           0 :       isaac_step (a >> 16, a, b, s->mm, m + 3, -ISAAC_WORDS / 2, r + 3);
      88           0 :       r += 4;
      89             :     }
      90           0 :   while ((m += 4) < s->mm + ISAAC_WORDS);
      91           0 :   s->a = a;
      92           0 :   s->b = b;
      93           0 : }
      94             : 
      95             : /*
      96             :  * The basic seed-scrambling step for initialization, based on Bob
      97             :  * Jenkins' 256-bit hash.
      98             :  */
      99             : #define mix(a,b,c,d,e,f,g,h) \
     100             :    (       a ^= b << 11, d += a, \
     101             :    b += c, b ^= c >>  2, e += b, \
     102             :    c += d, c ^= d <<  8, f += c, \
     103             :    d += e, d ^= e >> 16, g += d, \
     104             :    e += f, e ^= f << 10, h += e, \
     105             :    f += g, f ^= g >>  4, a += f, \
     106             :    g += h, g ^= h <<  8, b += g, \
     107             :    h += a, h ^= a >>  9, c += h, \
     108             :    a += b                        )
     109             : 
     110             : /* The basic ISAAC initialization pass.  */
     111             : static void
     112           0 : isaac_mix (struct isaac_state *s, uint32_t const seed[/* ISAAC_WORDS */])
     113             : {
     114             :   int i;
     115           0 :   uint32_t a = s->iv[0];
     116           0 :   uint32_t b = s->iv[1];
     117           0 :   uint32_t c = s->iv[2];
     118           0 :   uint32_t d = s->iv[3];
     119           0 :   uint32_t e = s->iv[4];
     120           0 :   uint32_t f = s->iv[5];
     121           0 :   uint32_t g = s->iv[6];
     122           0 :   uint32_t h = s->iv[7];
     123             : 
     124           0 :   for (i = 0; i < ISAAC_WORDS; i += 8)
     125             :     {
     126           0 :       a += seed[i];
     127           0 :       b += seed[i + 1];
     128           0 :       c += seed[i + 2];
     129           0 :       d += seed[i + 3];
     130           0 :       e += seed[i + 4];
     131           0 :       f += seed[i + 5];
     132           0 :       g += seed[i + 6];
     133           0 :       h += seed[i + 7];
     134             : 
     135           0 :       mix (a, b, c, d, e, f, g, h);
     136             : 
     137           0 :       s->mm[i] = a;
     138           0 :       s->mm[i + 1] = b;
     139           0 :       s->mm[i + 2] = c;
     140           0 :       s->mm[i + 3] = d;
     141           0 :       s->mm[i + 4] = e;
     142           0 :       s->mm[i + 5] = f;
     143           0 :       s->mm[i + 6] = g;
     144           0 :       s->mm[i + 7] = h;
     145             :     }
     146             : 
     147           0 :   s->iv[0] = a;
     148           0 :   s->iv[1] = b;
     149           0 :   s->iv[2] = c;
     150           0 :   s->iv[3] = d;
     151           0 :   s->iv[4] = e;
     152           0 :   s->iv[5] = f;
     153           0 :   s->iv[6] = g;
     154           0 :   s->iv[7] = h;
     155           0 : }
     156             : 
     157             : #if 0 /* Provided for reference only; not used in this code */
     158             : /*
     159             :  * Initialize the ISAAC RNG with the given seed material.
     160             :  * Its size MUST be a multiple of ISAAC_BYTES, and may be
     161             :  * stored in the s->mm array.
     162             :  *
     163             :  * This is a generalization of the original ISAAC initialization code
     164             :  * to support larger seed sizes.  For seed sizes of 0 and ISAAC_BYTES,
     165             :  * it is identical.
     166             :  */
     167             : static void
     168             : isaac_init (struct isaac_state *s, uint32_t const *seed, size_t seedsize)
     169             : {
     170             :   static uint32_t const iv[8] =
     171             :   {
     172             :     0x1367df5a, 0x95d90059, 0xc3163e4b, 0x0f421ad8,
     173             :     0xd92a4a78, 0xa51a3c49, 0xc4efea1b, 0x30609119};
     174             :   int i;
     175             : 
     176             : # if 0
     177             :   /* The initialization of iv is a precomputed form of: */
     178             :   for (i = 0; i < 7; i++)
     179             :     iv[i] = 0x9e3779b9;         /* the golden ratio */
     180             :   for (i = 0; i < 4; ++i)    /* scramble it */
     181             :     mix (iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]);
     182             : # endif
     183             :   s->a = s->b = s->c = 0;
     184             : 
     185             :   for (i = 0; i < 8; i++)
     186             :     s->iv[i] = iv[i];
     187             : 
     188             :   if (seedsize)
     189             :     {
     190             :       /* First pass (as in reference ISAAC code) */
     191             :       isaac_mix (s, seed);
     192             :       /* Second and subsequent passes (extension to ISAAC) */
     193             :       while (seedsize -= ISAAC_BYTES)
     194             :         {
     195             :           seed += ISAAC_WORDS;
     196             :           for (i = 0; i < ISAAC_WORDS; i++)
     197             :             s->mm[i] += seed[i];
     198             :           isaac_mix (s, s->mm);
     199             :         }
     200             :     }
     201             :   else
     202             :     {
     203             :       /* The no seed case (as in reference ISAAC code) */
     204             :       for (i = 0; i < ISAAC_WORDS; i++)
     205             :         s->mm[i] = 0;
     206             :     }
     207             : 
     208             :   /* Final pass */
     209             :   isaac_mix (s, s->mm);
     210             : }
     211             : #endif
     212             : 
     213             : /* Initialize *S to a somewhat-random value.  */
     214             : static void
     215           0 : isaac_seed_start (struct isaac_state *s)
     216             : {
     217             :   static uint32_t const iv[8] =
     218             :     {
     219             :       0x1367df5a, 0x95d90059, 0xc3163e4b, 0x0f421ad8,
     220             :       0xd92a4a78, 0xa51a3c49, 0xc4efea1b, 0x30609119
     221             :     };
     222             : 
     223             : #if 0
     224             :   /* The initialization of iv is a precomputed form of: */
     225             :   int i;
     226             :   for (i = 0; i < 7; i++)
     227             :     iv[i] = 0x9e3779b9;         /* the golden ratio */
     228             :   for (i = 0; i < 4; ++i)    /* scramble it */
     229             :     mix (iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]);
     230             : #endif
     231             : 
     232           0 :   memset (s->mm, 0, sizeof s->mm);
     233           0 :   memcpy (s->iv, iv, sizeof s->iv);
     234             : 
     235             :   /* s->c gets used for a data pointer during the seeding phase */
     236           0 :   s->a = s->b = s->c = 0;
     237           0 : }
     238             : 
     239             : /* Add a buffer of seed material.  */
     240             : static void
     241           0 : isaac_seed_data (struct isaac_state *s, void const *buffer, size_t size)
     242             : {
     243           0 :   unsigned char const *buf = buffer;
     244             :   unsigned char *p;
     245             :   size_t avail;
     246             :   size_t i;
     247             : 
     248           0 :   avail = sizeof s->mm - s->c;    /* s->c is used as a write pointer */
     249             : 
     250             :   /* Do any full buffers that are necessary */
     251           0 :   while (size > avail)
     252             :     {
     253           0 :       p = (unsigned char *) s->mm + s->c;
     254           0 :       for (i = 0; i < avail; i++)
     255           0 :         p[i] ^= buf[i];
     256           0 :       buf += avail;
     257           0 :       size -= avail;
     258           0 :       isaac_mix (s, s->mm);
     259           0 :       s->c = 0;
     260           0 :       avail = sizeof s->mm;
     261             :     }
     262             : 
     263             :   /* And the final partial block */
     264           0 :   p = (unsigned char *) s->mm + s->c;
     265           0 :   for (i = 0; i < size; i++)
     266           0 :     p[i] ^= buf[i];
     267           0 :   s->c = size;
     268           0 : }
     269             : 
     270             : 
     271             : /* End of seeding phase; get everything ready to produce output. */
     272             : static void
     273           0 : isaac_seed_finish (struct isaac_state *s)
     274             : {
     275           0 :   isaac_mix (s, s->mm);
     276           0 :   isaac_mix (s, s->mm);
     277             :   /* Now reinitialize c to start things off right */
     278           0 :   s->c = 0;
     279           0 : }
     280             : #define ISAAC_SEED(s,x) isaac_seed_data (s, &(x), sizeof (x))
     281             : 
     282             : /* Initialize *S to a somewhat-random value; this starts seeding,
     283             :    seeds with somewhat-random data, and finishes seeding.  */
     284             : void
     285           0 : isaac_seed (struct isaac_state *s)
     286             : {
     287           0 :   isaac_seed_start (s);
     288             : 
     289           0 :   { pid_t t = getpid ();   ISAAC_SEED (s, t); }
     290           0 :   { pid_t t = getppid ();  ISAAC_SEED (s, t); }
     291           0 :   { uid_t t = getuid ();   ISAAC_SEED (s, t); }
     292           0 :   { gid_t t = getgid ();   ISAAC_SEED (s, t); }
     293             : 
     294             :   {
     295           0 :     xtime_t t = gethrxtime ();
     296           0 :     ISAAC_SEED (s, t);
     297             :   }
     298             : 
     299           0 :   isaac_seed_finish (s);
     300           0 : }

Generated by: LCOV version 1.10