/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: 26a821633e00d0fed1f4db9f17345c271f85a515 $") |
12 | | |
13 | | #include <freeradius-devel/util/rand.h> |
14 | | |
15 | 0 | #define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */ |
16 | 0 | #define RANDSIZ (1 << RANDSIZL) |
17 | | |
18 | 0 | #define ind(mm,x) ((mm)[(x >> 2) &(RANDSIZ-1)]) |
19 | 0 | #define rngstep(mix, a, b, mm, m, m2, r, x) \ |
20 | 0 | do { \ |
21 | 0 | x = *m; \ |
22 | 0 | a = ((a^(mix)) + *(m2++)) & 0xffffffff; \ |
23 | 0 | *(m++) = y = (ind(mm, x) + a + b) & 0xffffffff; \ |
24 | 0 | *(r++) = b = (ind(mm, y >> RANDSIZL) + x) & 0xffffffff; \ |
25 | 0 | } 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 | 0 | { |
48 | 0 | register uint32_t a, b, x, y, *m, *mm, *m2, *r, *mend; |
49 | |
|
50 | 0 | mm = ctx->randmem; |
51 | 0 | r = ctx->randrsl; |
52 | 0 | a = ctx->randa; |
53 | 0 | b = (ctx->randb + (++ctx->randc)) & 0xffffffff; |
54 | |
|
55 | 0 | for (m = mm, mend = m2 = m + (RANDSIZ / 2); m < mend; ) { |
56 | 0 | rngstep(a << 13, a, b, mm, m, m2, r, x); |
57 | 0 | rngstep(a >> 6 , a, b, mm, m, m2, r, x); |
58 | 0 | rngstep(a << 2 , a, b, mm, m, m2, r, x); |
59 | 0 | rngstep(a >> 16, a, b, mm, m, m2, r, x); |
60 | 0 | } |
61 | 0 | for (m2 = mm; m2 < mend; ) { |
62 | 0 | rngstep(a << 13, a, b, mm, m, m2, r, x); |
63 | 0 | rngstep(a >> 6 , a, b, mm, m, m2, r, x); |
64 | 0 | rngstep(a << 2 , a, b, mm, m, m2, r, x); |
65 | 0 | rngstep(a >> 16, a, b, mm, m, m2, r, x); |
66 | 0 | } |
67 | 0 | ctx->randb = b; |
68 | 0 | ctx->randa = a; |
69 | 0 | } |
70 | | |
71 | | |
72 | 0 | #define mix(a,b,c,d,e,f,g,h) \ |
73 | 0 | do { \ |
74 | 0 | a ^= b << 11; d += a; b += c; \ |
75 | 0 | b ^= c >> 2; e += b; c += d; \ |
76 | 0 | c ^= d << 8; f += c; d += e; \ |
77 | 0 | d ^= e >> 16; g += d; e += f; \ |
78 | 0 | e ^= f << 10; h += e; f += g; \ |
79 | 0 | f ^= g >> 4; a += f; g += h; \ |
80 | 0 | g ^= h << 8; b += g; h += a; \ |
81 | 0 | h ^= a >> 9; c += h; a += b; \ |
82 | 0 | } 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 | 0 | { |
87 | 0 | int i; |
88 | 0 | uint32_t a, b, c, d, e, f, g, h; |
89 | 0 | uint32_t *m, *r; |
90 | |
|
91 | 0 | ctx->randa = ctx->randb = ctx->randc = 0; |
92 | 0 | m = ctx->randmem; |
93 | 0 | r = ctx->randrsl; |
94 | 0 | a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */ |
95 | | |
96 | | /* scramble it */ |
97 | 0 | for (i = 0; i < 4; ++i) { |
98 | | /* coverity[overflow_const] */ |
99 | 0 | mix(a, b, c, d, e, f, g, h); |
100 | 0 | } |
101 | |
|
102 | 0 | if (flag) { |
103 | | /* initialize using the contents of r[] as the seed */ |
104 | 0 | for (i = 0; i < RANDSIZ; i += 8) { |
105 | 0 | a += r[i ]; b += r[i + 1]; c +=r [i + 2]; d += r[i + 3]; |
106 | 0 | e += r[i + 4]; f += r[i + 5]; g +=r [i + 6]; h += r[i + 7]; |
107 | 0 | mix(a, b, c, d, e, f, g, h); |
108 | 0 | m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; |
109 | 0 | m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; |
110 | 0 | } |
111 | | /* do a second pass to make all of the seed affect all of m */ |
112 | 0 | for (i = 0; i < RANDSIZ; i += 8) { |
113 | 0 | a += m[i ]; b += m[i + 1]; c += m[i + 2]; d += m[i + 3]; |
114 | 0 | e += m[i + 4]; f += m[i + 5]; g += m[i + 6]; h += m[i + 7]; |
115 | 0 | mix(a, b, c, d, e, f, g, h); |
116 | 0 | m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; |
117 | 0 | m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; |
118 | 0 | } |
119 | 0 | } else { |
120 | 0 | for (i = 0; i < RANDSIZ; i += 8) { |
121 | | /* fill in mm[] with messy stuff */ |
122 | 0 | mix(a, b, c, d, e, f, g, h); |
123 | 0 | m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; |
124 | 0 | m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; |
125 | 0 | } |
126 | 0 | } |
127 | |
|
128 | 0 | fr_isaac(ctx); /* fill in the first set of results */ |
129 | 0 | ctx->randcnt = RANDSIZ; /* prepare to use the first set of results */ |
130 | 0 | } |
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 |