aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-02-23 09:09:35 +0000
committerRon Yorston <rmy@pobox.com>2018-02-23 09:09:35 +0000
commit7288179d1218f8e0308455d4d58346aec268eb2e (patch)
tree9c5381f96accfd5c85d05f66e239ddce1557d4fd
parentf46f3503fca50bfb397ed32d805158099a416f64 (diff)
downloadbusybox-w32-7288179d1218f8e0308455d4d58346aec268eb2e.tar.gz
busybox-w32-7288179d1218f8e0308455d4d58346aec268eb2e.tar.bz2
busybox-w32-7288179d1218f8e0308455d4d58346aec268eb2e.zip
win32: make /dev/urandom more random
-rw-r--r--include/mingw.h2
-rw-r--r--win32/Kbuild1
-rw-r--r--win32/isaac.c240
-rw-r--r--win32/mingw.c3
4 files changed, 244 insertions, 2 deletions
diff --git a/include/mingw.h b/include/mingw.h
index 46be4dc23..8f7e529ba 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -481,3 +481,5 @@ int err_win_to_posix(DWORD winerr);
481 481
482ULONGLONG CompatGetTickCount64(void); 482ULONGLONG CompatGetTickCount64(void);
483#define GetTickCount64 CompatGetTickCount64 483#define GetTickCount64 CompatGetTickCount64
484
485ssize_t get_random_bytes(void *buf, ssize_t count);
diff --git a/win32/Kbuild b/win32/Kbuild
index 8248c994f..00950e0f7 100644
--- a/win32/Kbuild
+++ b/win32/Kbuild
@@ -8,6 +8,7 @@ lib-$(CONFIG_PLATFORM_MINGW32) += env.o
8lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o 8lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o
9lib-$(CONFIG_PLATFORM_MINGW32) += fsync.o 9lib-$(CONFIG_PLATFORM_MINGW32) += fsync.o
10lib-$(CONFIG_PLATFORM_MINGW32) += ioctl.o 10lib-$(CONFIG_PLATFORM_MINGW32) += ioctl.o
11lib-$(CONFIG_PLATFORM_MINGW32) += isaac.o
11lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o 12lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o
12lib-$(CONFIG_PLATFORM_MINGW32) += process.o 13lib-$(CONFIG_PLATFORM_MINGW32) += process.o
13lib-$(CONFIG_PLATFORM_MINGW32) += regex.o 14lib-$(CONFIG_PLATFORM_MINGW32) += regex.o
diff --git a/win32/isaac.c b/win32/isaac.c
new file mode 100644
index 000000000..8e9da9baf
--- /dev/null
+++ b/win32/isaac.c
@@ -0,0 +1,240 @@
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
22/* external results */
23static uint32_t randrsl[256];
24
25/* internal state */
26static uint32_t mm[256];
27static uint32_t aa=0, bb=0, cc=0;
28
29
30static void isaac(void)
31{
32 register uint32_t i,x,y;
33
34 cc = cc + 1; /* cc just gets incremented once per 256 results */
35 bb = bb + cc; /* then combined with bb */
36
37 for (i=0; i<256; ++i)
38 {
39 x = mm[i];
40 switch (i%4)
41 {
42 case 0: aa = aa^(aa<<13); break;
43 case 1: aa = aa^(aa>>6); break;
44 case 2: aa = aa^(aa<<2); break;
45 case 3: aa = aa^(aa>>16); break;
46 }
47 aa = mm[(i+128)%256] + aa;
48 mm[i] = y = mm[(x>>2)%256] + aa + bb;
49 randrsl[i] = bb = mm[(y>>10)%256] + x;
50
51 /* Note that bits 2..9 are chosen from x but 10..17 are chosen
52 from y. The only important thing here is that 2..9 and 10..17
53 don't overlap. 2..9 and 10..17 were then chosen for speed in
54 the optimized version (rand.c) */
55 /* See http://burtleburtle.net/bob/rand/isaac.html
56 for further explanations and analysis. */
57 }
58}
59
60
61/* if (flag!=0), then use the contents of randrsl[] to initialize mm[]. */
62#define mix(a,b,c,d,e,f,g,h) \
63{ \
64 a^=b<<11; d+=a; b+=c; \
65 b^=c>>2; e+=b; c+=d; \
66 c^=d<<8; f+=c; d+=e; \
67 d^=e>>16; g+=d; e+=f; \
68 e^=f<<10; h+=e; f+=g; \
69 f^=g>>4; a+=f; g+=h; \
70 g^=h<<8; b+=g; h+=a; \
71 h^=a>>9; c+=h; a+=b; \
72}
73
74static void randinit(int flag)
75{
76 int i;
77 uint32_t a,b,c,d,e,f,g,h;
78 aa=bb=cc=0;
79 a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
80
81 for (i=0; i<4; ++i) /* scramble it */
82 {
83 mix(a,b,c,d,e,f,g,h);
84 }
85
86 for (i=0; i<256; i+=8) /* fill in mm[] with messy stuff */
87 {
88 if (flag) /* use all the information in the seed */
89 {
90 a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
91 e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
92 }
93 mix(a,b,c,d,e,f,g,h);
94 mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
95 mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
96 }
97
98 if (flag)
99 { /* do a second pass to make all of the seed affect all of mm */
100 for (i=0; i<256; i+=8)
101 {
102 a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
103 e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
104 mix(a,b,c,d,e,f,g,h);
105 mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
106 mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
107 }
108 }
109
110 isaac(); /* fill in the first set of results */
111}
112
113/* call 'fn' to put data in 'dt' then copy it to generator state */
114#define GET_DATA(fn, dt) \
115 fn(&dt); \
116 u = (uint32_t *)&dt; \
117 for (j=0; j<sizeof(dt)/sizeof(uint32_t); ++j) { \
118 randrsl[i++] = *u++; \
119 }
120
121/*
122 * Stuff a few bytes of random-ish data into the generator state.
123 * This is unlikely to be very robust: don't rely on it for
124 * anything that needs to be secure.
125 */
126static void get_entropy(void)
127{
128 int i, j, len;
129 SYSTEMTIME tm;
130 MEMORYSTATUS ms;
131 SYSTEM_INFO si;
132 LARGE_INTEGER pc;
133 uint32_t *u;
134 char *env, *s;
135 md5_ctx_t ctx;
136 unsigned char buf[16];
137
138 i = 0;
139 randrsl[i++] = (uint32_t)GetCurrentProcessId();
140 randrsl[i++] = (uint32_t)GetCurrentThreadId();
141 randrsl[i++] = (uint32_t)GetTickCount();
142
143 GET_DATA(GetLocalTime, tm)
144 GET_DATA(GlobalMemoryStatus, ms)
145 GET_DATA(GetSystemInfo, si)
146 GET_DATA(QueryPerformanceCounter, pc)
147
148 env = GetEnvironmentStringsA();
149
150 /* get length of environment: it ends with two nuls */
151 for (s=env,len=0; *s && *(s+1); ++s,++len)
152 ;
153
154 md5_begin(&ctx);
155 md5_hash(&ctx, env, len);
156 md5_end(&ctx, buf);
157
158 FreeEnvironmentStringsA(env);
159
160 u = (uint32_t *)buf;
161 for (j=0; j<sizeof(buf)/sizeof(uint32_t); ++j) {
162 randrsl[i++] = *u++;
163 }
164
165#if 0
166 {
167 unsigned char *p = (unsigned char *)randrsl;
168
169 for (j=0; j<i*sizeof(uint32_t); ++j) {
170 fprintf(stderr, "%02x", *p++);
171 if ((j&31) == 31) {
172 fprintf(stderr, "\n");
173 }
174 else if ((j&3) == 3) {
175 fprintf(stderr, " ");
176 }
177 }
178 fprintf(stderr, "\n");
179 }
180#endif
181}
182
183#define RAND_BYTES sizeof(randrsl)
184#define RAND_WORDS (sizeof(randrsl)/sizeof(randrsl[0]))
185
186/*
187 * Place 'count' random bytes in the buffer 'buf'. You're responsible
188 * for ensuring the buffer is big enough.
189 */
190ssize_t get_random_bytes(void *buf, ssize_t count)
191{
192 static int initialised = 0;
193 static int rand_index = 0;
194 int i;
195 ssize_t save_count = count;
196 unsigned char *ptr = (unsigned char *)randrsl;
197
198 if (buf == NULL || count < 0) {
199 errno = EINVAL;
200 return -1;
201 }
202
203 if (!initialised) {
204 aa = bb = cc = (uint32_t)0;
205 for (i=0; i<RAND_WORDS; ++i)
206 mm[i] = randrsl[i] = (uint32_t)0;
207
208 get_entropy();
209 randinit(1);
210 isaac();
211 rand_index = 0;
212 initialised = 1;
213 }
214
215 while (count > 0) {
216 int bytes_left = RAND_BYTES - rand_index;
217
218 if (bytes_left >= count) {
219 /* we have enough random bytes */
220 memcpy(buf, ptr+rand_index, count);
221 rand_index += count;
222 count = 0;
223 }
224 else {
225 /* insufficient bytes, use what we have */
226 memcpy(buf, ptr+rand_index, bytes_left);
227 buf += bytes_left;
228 count -= bytes_left;
229 rand_index += bytes_left;
230 }
231
232 if (rand_index >= RAND_BYTES) {
233 /* generate more */
234 isaac();
235 rand_index = 0;
236 }
237 }
238
239 return save_count;
240}
diff --git a/win32/mingw.c b/win32/mingw.c
index 595042d85..86f649674 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -210,8 +210,7 @@ ssize_t mingw_read(int fd, void *buf, size_t count)
210 return count; 210 return count;
211 } 211 }
212 else if (fd == rand_fd) { 212 else if (fd == rand_fd) {
213 memset(buf, 0x5A, count); 213 return get_random_bytes(buf, count);
214 return count;
215 } 214 }
216 return read(fd, buf, count); 215 return read(fd, buf, count);
217} 216}