/src/freeradius-server/src/lib/util/isaac.c
Line | Count | Source (jump to first uncovered line) |
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: 34a829076fb450282b995ff0c58c4eaf88f8334f $") |
12 | | |
13 | | #include <freeradius-devel/util/rand.h> |
14 | | |
15 | 10.4k | #define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */ |
16 | 10.4k | #define RANDSIZ (1 << RANDSIZL) |
17 | | |
18 | 9.21k | #define ind(mm,x) ((mm)[(x >> 2) &(RANDSIZ-1)]) |
19 | 4.60k | #define rngstep(mix, a, b, mm, m, m2, r, x) \ |
20 | 4.60k | do { \ |
21 | 4.60k | x = *m; \ |
22 | 4.60k | a = ((a^(mix)) + *(m2++)) & 0xffffffff; \ |
23 | 4.60k | *(m++) = y = (ind(mm, x) + a + b) & 0xffffffff; \ |
24 | 4.60k | *(r++) = b = (ind(mm, y >> RANDSIZL) + x) & 0xffffffff; \ |
25 | 4.60k | } while (0) |
26 | | |
27 | | void fr_isaac(fr_randctx *ctx) |
28 | 18 | { |
29 | 18 | register uint32_t a, b, x, y, *m, *mm, *m2, *r, *mend; |
30 | | |
31 | 18 | mm = ctx->randmem; |
32 | 18 | r = ctx->randrsl; |
33 | 18 | a = ctx->randa; |
34 | 18 | b = (ctx->randb + (++ctx->randc)) & 0xffffffff; |
35 | | |
36 | 594 | for (m = mm, mend = m2 = m + (RANDSIZ / 2); m < mend; ) { |
37 | 576 | rngstep(a << 13, a, b, mm, m, m2, r, x); |
38 | 576 | rngstep(a >> 6 , a, b, mm, m, m2, r, x); |
39 | 576 | rngstep(a << 2 , a, b, mm, m, m2, r, x); |
40 | 576 | rngstep(a >> 16, a, b, mm, m, m2, r, x); |
41 | 576 | } |
42 | 594 | for (m2 = mm; m2 < mend; ) { |
43 | 576 | rngstep(a << 13, a, b, mm, m, m2, r, x); |
44 | 576 | rngstep(a >> 6 , a, b, mm, m, m2, r, x); |
45 | 576 | rngstep(a << 2 , a, b, mm, m, m2, r, x); |
46 | 576 | rngstep(a >> 16, a, b, mm, m, m2, r, x); |
47 | 576 | } |
48 | 18 | ctx->randb = b; |
49 | 18 | ctx->randa = a; |
50 | 18 | } |
51 | | |
52 | | |
53 | 1.22k | #define mix(a,b,c,d,e,f,g,h) \ |
54 | 1.22k | do { \ |
55 | 1.22k | a ^= b << 11; d += a; b += c; \ |
56 | 1.22k | b ^= c >> 2; e += b; c += d; \ |
57 | 1.22k | c ^= d << 8; f += c; d += e; \ |
58 | 1.22k | d ^= e >> 16; g += d; e += f; \ |
59 | 1.22k | e ^= f << 10; h += e; f += g; \ |
60 | 1.22k | f ^= g >> 4; a += f; g += h; \ |
61 | 1.22k | g ^= h << 8; b += g; h += a; \ |
62 | 1.22k | h ^= a >> 9; c += h; a += b; \ |
63 | 1.22k | } while (0) |
64 | | |
65 | | /* if (flag==1), then use the contents of randrsl[] to initialize mm[]. */ |
66 | | void fr_rand_init(fr_randctx *ctx, int flag) |
67 | 18 | { |
68 | 18 | int i; |
69 | 18 | uint32_t a, b, c, d, e, f, g, h; |
70 | 18 | uint32_t *m, *r; |
71 | | |
72 | 18 | ctx->randa = ctx->randb = ctx->randc = 0; |
73 | 18 | m = ctx->randmem; |
74 | 18 | r = ctx->randrsl; |
75 | 18 | a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */ |
76 | | |
77 | | /* scramble it */ |
78 | 90 | for (i = 0; i < 4; ++i) mix(a, b, c, d, e, f, g, h); |
79 | | |
80 | 18 | if (flag) { |
81 | | /* initialize using the contents of r[] as the seed */ |
82 | 594 | for (i = 0; i < RANDSIZ; i += 8) { |
83 | 576 | a += r[i ]; b += r[i + 1]; c +=r [i + 2]; d += r[i + 3]; |
84 | 576 | e += r[i + 4]; f += r[i + 5]; g +=r [i + 6]; h += r[i + 7]; |
85 | 576 | mix(a, b, c, d, e, f, g, h); |
86 | 576 | m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; |
87 | 576 | m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; |
88 | 576 | } |
89 | | /* do a second pass to make all of the seed affect all of m */ |
90 | 594 | for (i = 0; i < RANDSIZ; i += 8) { |
91 | 576 | a += m[i ]; b += m[i + 1]; c += m[i + 2]; d += m[i + 3]; |
92 | 576 | e += m[i + 4]; f += m[i + 5]; g += m[i + 6]; h += m[i + 7]; |
93 | 576 | mix(a, b, c, d, e, f, g, h); |
94 | 576 | m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; |
95 | 576 | m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; |
96 | 576 | } |
97 | 18 | } else { |
98 | 0 | for (i = 0; i < RANDSIZ; i += 8) { |
99 | | /* fill in mm[] with messy stuff */ |
100 | 0 | mix(a, b, c, d, e, f, g, h); |
101 | 0 | m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; |
102 | 0 | m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; |
103 | 0 | } |
104 | 0 | } |
105 | | |
106 | 18 | fr_isaac(ctx); /* fill in the first set of results */ |
107 | 18 | ctx->randcnt = RANDSIZ; /* prepare to use the first set of results */ |
108 | 18 | } |
109 | | |
110 | | |
111 | | #ifdef TEST |
112 | | /* |
113 | | * For testing. Output should be the same as |
114 | | * |
115 | | * http://burtleburtle.net/bob/rand/randvect.txt |
116 | | */ |
117 | | int main() |
118 | | { |
119 | | uint32_t i,j; |
120 | | fr_randctx ctx; |
121 | | |
122 | | ctx.randa = ctx.randb = ctx.randc = (uint32_t)0; |
123 | | |
124 | | for (i = 0; i < 256; ++i) ctx.randrsl[i] = (uint32_t)0; |
125 | | |
126 | | fr_rand_init(&ctx, 1); |
127 | | for (i = 0; i < 2; ++i) { |
128 | | fr_isaac(&ctx); |
129 | | for (j = 0; j < 256; ++j) { |
130 | | printf("%.8lx",ctx.randrsl[j]); |
131 | | if ((j & 7) == 7) printf("\n"); |
132 | | } |
133 | | } |
134 | | } |
135 | | #endif |