diff options
author | Ron Yorston <rmy@pobox.com> | 2018-02-23 09:09:35 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-02-23 09:09:35 +0000 |
commit | 7288179d1218f8e0308455d4d58346aec268eb2e (patch) | |
tree | 9c5381f96accfd5c85d05f66e239ddce1557d4fd | |
parent | f46f3503fca50bfb397ed32d805158099a416f64 (diff) | |
download | busybox-w32-7288179d1218f8e0308455d4d58346aec268eb2e.tar.gz busybox-w32-7288179d1218f8e0308455d4d58346aec268eb2e.tar.bz2 busybox-w32-7288179d1218f8e0308455d4d58346aec268eb2e.zip |
win32: make /dev/urandom more random
-rw-r--r-- | include/mingw.h | 2 | ||||
-rw-r--r-- | win32/Kbuild | 1 | ||||
-rw-r--r-- | win32/isaac.c | 240 | ||||
-rw-r--r-- | win32/mingw.c | 3 |
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 | ||
482 | ULONGLONG CompatGetTickCount64(void); | 482 | ULONGLONG CompatGetTickCount64(void); |
483 | #define GetTickCount64 CompatGetTickCount64 | 483 | #define GetTickCount64 CompatGetTickCount64 |
484 | |||
485 | ssize_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 | |||
8 | lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o | 8 | lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o |
9 | lib-$(CONFIG_PLATFORM_MINGW32) += fsync.o | 9 | lib-$(CONFIG_PLATFORM_MINGW32) += fsync.o |
10 | lib-$(CONFIG_PLATFORM_MINGW32) += ioctl.o | 10 | lib-$(CONFIG_PLATFORM_MINGW32) += ioctl.o |
11 | lib-$(CONFIG_PLATFORM_MINGW32) += isaac.o | ||
11 | lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o | 12 | lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o |
12 | lib-$(CONFIG_PLATFORM_MINGW32) += process.o | 13 | lib-$(CONFIG_PLATFORM_MINGW32) += process.o |
13 | lib-$(CONFIG_PLATFORM_MINGW32) += regex.o | 14 | lib-$(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 | ------------------------------------------------------------------------------ | ||
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 | |||
22 | /* external results */ | ||
23 | static uint32_t randrsl[256]; | ||
24 | |||
25 | /* internal state */ | ||
26 | static uint32_t mm[256]; | ||
27 | static uint32_t aa=0, bb=0, cc=0; | ||
28 | |||
29 | |||
30 | static 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 | |||
74 | static 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 | */ | ||
126 | static 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 | */ | ||
190 | ssize_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 | } |