diff options
Diffstat (limited to 'win32/isaac.c')
-rw-r--r-- | win32/isaac.c | 192 |
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 | ------------------------------------------------------------------------------ | ||
3 | readable.c: My random number generator, ISAAC. | ||
4 | (c) Bob Jenkins, March 1996, Public Domain | ||
5 | You 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 | |||
23 | typedef 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 | |||
33 | static 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 | |||
77 | static 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 | */ | ||
122 | static 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 | */ | ||
153 | ssize_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 | } | ||