aboutsummaryrefslogtreecommitdiff
path: root/win32/isaac.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/isaac.c')
-rw-r--r--win32/isaac.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/win32/isaac.c b/win32/isaac.c
new file mode 100644
index 000000000..19b96de94
--- /dev/null
+++ b/win32/isaac.c
@@ -0,0 +1,192 @@
1/*
2------------------------------------------------------------------------------
3readable.c: My random number generator, ISAAC.
4(c) Bob Jenkins, March 1996, Public Domain
5You may use this code in any way you wish, and it is free. No warrantee.
6* May 2008 -- made it not depend on standard.h
7------------------------------------------------------------------------------
8
9 The original version of this file was downloaded from Bob Jenkins website:
10
11 http://burtleburtle.net/bob/rand/isaacafa.html
12
13 The isaac and randinit functions have been slightly modified to silence
14 warnings in modern compilers; the get_entropy and get_random_bytes have
15 been added.
16
17 These changes were made by R M Yorston and are also dedicated to the
18 public domain.
19*/
20#include "libbb.h"
21#include <ntsecapi.h>
22
23typedef struct {
24 /* external results */
25 uint32_t randrsl[256];
26
27 /* internal state */
28 uint32_t mm[256];
29 uint32_t aa, bb, cc;
30} isaac_t;
31
32
33static void isaac(isaac_t *t)
34{
35 register uint32_t i,x,y;
36
37 t->cc = t->cc + 1; /* cc just gets incremented once per 256 results */
38 t->bb = t->bb + t->cc; /* then combined with bb */
39
40 for (i=0; i<256; ++i)
41 {
42 x = t->mm[i];
43 switch (i%4)
44 {
45 case 0: t->aa = t->aa^(t->aa<<13); break;
46 case 1: t->aa = t->aa^(t->aa>>6); break;
47 case 2: t->aa = t->aa^(t->aa<<2); break;
48 case 3: t->aa = t->aa^(t->aa>>16); break;
49 }
50 t->aa = t->mm[(i+128)%256] + t->aa;
51 t->mm[i] = y = t->mm[(x>>2)%256] + t->aa + t->bb;
52 t->randrsl[i] = t->bb = t->mm[(y>>10)%256] + x;
53
54 /* Note that bits 2..9 are chosen from x but 10..17 are chosen
55 from y. The only important thing here is that 2..9 and 10..17
56 don't overlap. 2..9 and 10..17 were then chosen for speed in
57 the optimized version (rand.c) */
58 /* See http://burtleburtle.net/bob/rand/isaac.html
59 for further explanations and analysis. */
60 }
61}
62
63
64/* if (flag!=0), then use the contents of randrsl[] to initialize mm[]. */
65#define mix(a,b,c,d,e,f,g,h) \
66{ \
67 a^=b<<11; d+=a; b+=c; \
68 b^=c>>2; e+=b; c+=d; \
69 c^=d<<8; f+=c; d+=e; \
70 d^=e>>16; g+=d; e+=f; \
71 e^=f<<10; h+=e; f+=g; \
72 f^=g>>4; a+=f; g+=h; \
73 g^=h<<8; b+=g; h+=a; \
74 h^=a>>9; c+=h; a+=b; \
75}
76
77static void randinit(isaac_t *t, int flag)
78{
79 int i;
80 uint32_t a,b,c,d,e,f,g,h;
81 t->aa = t->bb = t->cc = 0;
82 a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
83
84 for (i=0; i<4; ++i) /* scramble it */
85 {
86 mix(a,b,c,d,e,f,g,h);
87 }
88
89 for (i=0; i<256; i+=8) /* fill in mm[] with messy stuff */
90 {
91 if (flag) /* use all the information in the seed */
92 {
93 a+=t->randrsl[i ]; b+=t->randrsl[i+1]; c+=t->randrsl[i+2];
94 d+=t->randrsl[i+3]; e+=t->randrsl[i+4]; f+=t->randrsl[i+5];
95 g+=t->randrsl[i+6]; h+=t->randrsl[i+7];
96 }
97 mix(a,b,c,d,e,f,g,h);
98 t->mm[i ]=a; t->mm[i+1]=b; t->mm[i+2]=c; t->mm[i+3]=d;
99 t->mm[i+4]=e; t->mm[i+5]=f; t->mm[i+6]=g; t->mm[i+7]=h;
100 }
101
102 if (flag)
103 { /* do a second pass to make all of the seed affect all of mm */
104 for (i=0; i<256; i+=8)
105 {
106 a+=t->mm[i ]; b+=t->mm[i+1]; c+=t->mm[i+2]; d+=t->mm[i+3];
107 e+=t->mm[i+4]; f+=t->mm[i+5]; g+=t->mm[i+6]; h+=t->mm[i+7];
108 mix(a,b,c,d,e,f,g,h);
109 t->mm[i ]=a; t->mm[i+1]=b; t->mm[i+2]=c; t->mm[i+3]=d;
110 t->mm[i+4]=e; t->mm[i+5]=f; t->mm[i+6]=g; t->mm[i+7]=h;
111 }
112 }
113
114 isaac(t); /* fill in the first set of results */
115}
116
117/*
118 * Stuff a few bytes of random-ish data into the generator state.
119 * This is unlikely to be very robust: don't rely on it for
120 * anything that needs to be secure.
121 */
122static void get_entropy(isaac_t *t)
123{
124 if (!RtlGenRandom(t->randrsl, sizeof(uint32_t)*256))
125 GetSystemTimeAsFileTime((FILETIME *)t->randrsl);
126
127#if 0
128 {
129 unsigned char *p = (unsigned char *)t->randrsl;
130 int j;
131
132 for (j=0; j<256; ++j) {
133 fprintf(stderr, "%02x", p[j]);
134 if ((j&31) == 31) {
135 fprintf(stderr, "\n");
136 }
137 else if ((j&3) == 3) {
138 fprintf(stderr, " ");
139 }
140 }
141 fprintf(stderr, "\n");
142 }
143#endif
144}
145
146#define RAND_BYTES sizeof(t->randrsl)
147#define RAND_WORDS (sizeof(t->randrsl)/sizeof(t->randrsl[0]))
148
149/*
150 * Place 'count' random bytes in the buffer 'buf'. You're responsible
151 * for ensuring the buffer is big enough.
152 */
153ssize_t get_random_bytes(void *buf, ssize_t count)
154{
155 static isaac_t *t = NULL;
156 static int rand_index = 0;
157 ssize_t save_count = count;
158 unsigned char *ptr;
159
160 if (buf == NULL || count < 0) {
161 errno = EINVAL;
162 return -1;
163 }
164
165 if (!t) {
166 t = xzalloc(sizeof(isaac_t));
167
168 get_entropy(t);
169 randinit(t, 1);
170 isaac(t);
171 rand_index = 0;
172 }
173
174 ptr = (unsigned char *)t->randrsl;
175 while (count > 0) {
176 int bytes_left = RAND_BYTES - rand_index;
177 ssize_t delta = MIN(bytes_left, count);
178
179 memcpy(buf, ptr+rand_index, delta);
180 buf += delta;
181 count -= delta;
182 rand_index += delta;
183
184 if (rand_index >= RAND_BYTES) {
185 /* generate more */
186 isaac(t);
187 rand_index = 0;
188 }
189 }
190
191 return save_count;
192}