Coverage Report

Created: 2024-08-28 06:17

/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