The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
isaac.c
Go to the documentation of this file.
1 /** Bob Jenkin's random number generator
2  *
3  * Bob's random number generator, ISAAC. Public Domain.
4  *
5  * http://burtleburtle.net/bob/rand/isaac.html
6  *
7  * @file src/lib/util/isaac.c
8  *
9  * @author Bob Jenkins.
10  */
11 RCSID("$Id: 26a821633e00d0fed1f4db9f17345c271f85a515 $")
12 
13 #include <freeradius-devel/util/rand.h>
14 
15 #define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */
16 #define RANDSIZ (1 << RANDSIZL)
17 
18 #define ind(mm,x) ((mm)[(x >> 2) &(RANDSIZ-1)])
19 #define rngstep(mix, a, b, mm, m, m2, r, x) \
20 do { \
21  x = *m; \
22  a = ((a^(mix)) + *(m2++)) & 0xffffffff; \
23  *(m++) = y = (ind(mm, x) + a + b) & 0xffffffff; \
24  *(r++) = b = (ind(mm, y >> RANDSIZL) + x) & 0xffffffff; \
25 } while (0)
26 
27 #ifdef ISAAC_PLUS
28 /*
29  * https://eprint.iacr.org/2006/438.pdf
30  *
31  * - replace shift by rotate
32  * - replace "a+b" with "a^b"
33  * - change "x+s" to "x+(s^a)"
34  */
35 #define rotr(x, n) (((x) << n) | ((x) >> (32 - n)))
36 #define ind(mm,x) ((mm)[rotr(x, 2) & (RANDSIZ-1)])
37 #define rngstep(mix, a, b, mm, m, m2, r, x) \
38 do { \
39  x = *m; \
40  a = ((a^(mix)) + *(m2++)) & 0xffffffff; \
41  *(m++) = y = (ind(mm, x) + (a ^ b)) & 0xffffffff; \
42  *(r++) = b = ((ind(mm, y >> RANDSIZL) ^ a) + x) & 0xffffffff; \
43 } while (0)
44 #endif
45 
46 void fr_isaac(fr_randctx *ctx)
47 {
48  register uint32_t a, b, x, y, *m, *mm, *m2, *r, *mend;
49 
50  mm = ctx->randmem;
51  r = ctx->randrsl;
52  a = ctx->randa;
53  b = (ctx->randb + (++ctx->randc)) & 0xffffffff;
54 
55  for (m = mm, mend = m2 = m + (RANDSIZ / 2); m < mend; ) {
56  rngstep(a << 13, a, b, mm, m, m2, r, x);
57  rngstep(a >> 6 , a, b, mm, m, m2, r, x);
58  rngstep(a << 2 , a, b, mm, m, m2, r, x);
59  rngstep(a >> 16, a, b, mm, m, m2, r, x);
60  }
61  for (m2 = mm; m2 < mend; ) {
62  rngstep(a << 13, a, b, mm, m, m2, r, x);
63  rngstep(a >> 6 , a, b, mm, m, m2, r, x);
64  rngstep(a << 2 , a, b, mm, m, m2, r, x);
65  rngstep(a >> 16, a, b, mm, m, m2, r, x);
66  }
67  ctx->randb = b;
68  ctx->randa = a;
69 }
70 
71 
72 #define mix(a,b,c,d,e,f,g,h) \
73 do { \
74  a ^= b << 11; d += a; b += c; \
75  b ^= c >> 2; e += b; c += d; \
76  c ^= d << 8; f += c; d += e; \
77  d ^= e >> 16; g += d; e += f; \
78  e ^= f << 10; h += e; f += g; \
79  f ^= g >> 4; a += f; g += h; \
80  g ^= h << 8; b += g; h += a; \
81  h ^= a >> 9; c += h; a += b; \
82 } while (0)
83 
84 /* if (flag==1), then use the contents of randrsl[] to initialize mm[]. */
85 void fr_isaac_init(fr_randctx *ctx, int flag)
86 {
87  int i;
88  uint32_t a, b, c, d, e, f, g, h;
89  uint32_t *m, *r;
90 
91  ctx->randa = ctx->randb = ctx->randc = 0;
92  m = ctx->randmem;
93  r = ctx->randrsl;
94  a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */
95 
96  /* scramble it */
97  for (i = 0; i < 4; ++i) {
98  /* coverity[overflow_const] */
99  mix(a, b, c, d, e, f, g, h);
100  }
101 
102  if (flag) {
103  /* initialize using the contents of r[] as the seed */
104  for (i = 0; i < RANDSIZ; i += 8) {
105  a += r[i ]; b += r[i + 1]; c +=r [i + 2]; d += r[i + 3];
106  e += r[i + 4]; f += r[i + 5]; g +=r [i + 6]; h += r[i + 7];
107  mix(a, b, c, d, e, f, g, h);
108  m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
109  m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
110  }
111  /* do a second pass to make all of the seed affect all of m */
112  for (i = 0; i < RANDSIZ; i += 8) {
113  a += m[i ]; b += m[i + 1]; c += m[i + 2]; d += m[i + 3];
114  e += m[i + 4]; f += m[i + 5]; g += m[i + 6]; h += m[i + 7];
115  mix(a, b, c, d, e, f, g, h);
116  m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
117  m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
118  }
119  } else {
120  for (i = 0; i < RANDSIZ; i += 8) {
121  /* fill in mm[] with messy stuff */
122  mix(a, b, c, d, e, f, g, h);
123  m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
124  m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
125  }
126  }
127 
128  fr_isaac(ctx); /* fill in the first set of results */
129  ctx->randcnt = RANDSIZ; /* prepare to use the first set of results */
130 }
131 
132 
133 #ifdef TEST
134 /*
135  * For testing. Output should be the same as
136  *
137  * http://burtleburtle.net/bob/rand/randvect.txt
138  */
139 int main()
140 {
141  uint32_t i,j;
142  fr_randctx ctx;
143 
144  ctx.randa = ctx.randb = ctx.randc = (uint32_t)0;
145 
146  for (i = 0; i < 256; ++i) ctx.randrsl[i] = (uint32_t)0;
147 
148  fr_isaac_init(&ctx, 1);
149  for (i = 0; i < 2; ++i) {
150  fr_isaac(&ctx);
151  for (j = 0; j < 256; ++j) {
152  printf("%.8lx",ctx.randrsl[j]);
153  if ((j & 7) == 7) printf("\n");
154  }
155  }
156 }
157 #endif
#define RCSID(id)
Definition: build.h:481
size_t y
Definition: dbuff.c:67
int main(int argc, char **argv)
Definition: dhcpclient.c:521
void fr_isaac_init(fr_randctx *ctx, int flag)
Definition: isaac.c:85
#define RANDSIZ
Definition: isaac.c:16
void fr_isaac(fr_randctx *ctx)
Definition: isaac.c:46
#define rngstep(mix, a, b, mm, m, m2, r, x)
Definition: isaac.c:19
#define mix(a, b, c, d, e, f, g, h)
Definition: isaac.c:72
unsigned int uint32_t
Definition: merged_model.c:33
uint32_t randb
Definition: rand.h:43
uint32_t randmem[256]
Definition: rand.h:41
uint32_t randrsl[256]
Definition: rand.h:40
uint32_t randc
Definition: rand.h:44
uint32_t randcnt
Definition: rand.h:39
uint32_t randa
Definition: rand.h:42