OLD | NEW |
| (Empty) |
1 /* crypto/rand/rand_unix.c */ | |
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | |
3 * All rights reserved. | |
4 * | |
5 * This package is an SSL implementation written | |
6 * by Eric Young (eay@cryptsoft.com). | |
7 * The implementation was written so as to conform with Netscapes SSL. | |
8 * | |
9 * This library is free for commercial and non-commercial use as long as | |
10 * the following conditions are aheared to. The following conditions | |
11 * apply to all code found in this distribution, be it the RC4, RSA, | |
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
13 * included with this distribution is covered by the same copyright terms | |
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
15 * | |
16 * Copyright remains Eric Young's, and as such any Copyright notices in | |
17 * the code are not to be removed. | |
18 * If this package is used in a product, Eric Young should be given attribution | |
19 * as the author of the parts of the library used. | |
20 * This can be in the form of a textual message at program startup or | |
21 * in documentation (online or textual) provided with the package. | |
22 * | |
23 * Redistribution and use in source and binary forms, with or without | |
24 * modification, are permitted provided that the following conditions | |
25 * are met: | |
26 * 1. Redistributions of source code must retain the copyright | |
27 * notice, this list of conditions and the following disclaimer. | |
28 * 2. Redistributions in binary form must reproduce the above copyright | |
29 * notice, this list of conditions and the following disclaimer in the | |
30 * documentation and/or other materials provided with the distribution. | |
31 * 3. All advertising materials mentioning features or use of this software | |
32 * must display the following acknowledgement: | |
33 * "This product includes cryptographic software written by | |
34 * Eric Young (eay@cryptsoft.com)" | |
35 * The word 'cryptographic' can be left out if the rouines from the library | |
36 * being used are not cryptographic related :-). | |
37 * 4. If you include any Windows specific code (or a derivative thereof) from | |
38 * the apps directory (application code) you must include an acknowledgement: | |
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
40 * | |
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | |
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 * SUCH DAMAGE. | |
52 * | |
53 * The licence and distribution terms for any publically available version or | |
54 * derivative of this code cannot be changed. i.e. this code cannot simply be | |
55 * copied and put under another distribution licence | |
56 * [including the GNU Public Licence.] | |
57 */ | |
58 /* ==================================================================== | |
59 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. | |
60 * | |
61 * Redistribution and use in source and binary forms, with or without | |
62 * modification, are permitted provided that the following conditions | |
63 * are met: | |
64 * | |
65 * 1. Redistributions of source code must retain the above copyright | |
66 * notice, this list of conditions and the following disclaimer. | |
67 * | |
68 * 2. Redistributions in binary form must reproduce the above copyright | |
69 * notice, this list of conditions and the following disclaimer in | |
70 * the documentation and/or other materials provided with the | |
71 * distribution. | |
72 * | |
73 * 3. All advertising materials mentioning features or use of this | |
74 * software must display the following acknowledgment: | |
75 * "This product includes software developed by the OpenSSL Project | |
76 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
77 * | |
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
79 * endorse or promote products derived from this software without | |
80 * prior written permission. For written permission, please contact | |
81 * openssl-core@openssl.org. | |
82 * | |
83 * 5. Products derived from this software may not be called "OpenSSL" | |
84 * nor may "OpenSSL" appear in their names without prior written | |
85 * permission of the OpenSSL Project. | |
86 * | |
87 * 6. Redistributions of any form whatsoever must retain the following | |
88 * acknowledgment: | |
89 * "This product includes software developed by the OpenSSL Project | |
90 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
91 * | |
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
95 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
103 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
104 * ==================================================================== | |
105 * | |
106 * This product includes cryptographic software written by Eric Young | |
107 * (eay@cryptsoft.com). This product includes software written by Tim | |
108 * Hudson (tjh@cryptsoft.com). | |
109 * | |
110 */ | |
111 #include <stdio.h> | |
112 | |
113 #define USE_SOCKETS | |
114 #include "e_os.h" | |
115 #include "cryptlib.h" | |
116 #include <openssl/rand.h> | |
117 #include "rand_lcl.h" | |
118 | |
119 #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPEN
SSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defi
ned(OPENSSL_SYS_NETWARE)) | |
120 | |
121 #include <sys/types.h> | |
122 #include <sys/time.h> | |
123 #include <sys/times.h> | |
124 #include <sys/stat.h> | |
125 #include <fcntl.h> | |
126 #include <unistd.h> | |
127 #include <time.h> | |
128 #if defined(OPENSSL_SYS_LINUX) /* should actually be available virtually everywh
ere */ | |
129 # include <poll.h> | |
130 #endif | |
131 #include <limits.h> | |
132 #ifndef FD_SETSIZE | |
133 # define FD_SETSIZE (8*sizeof(fd_set)) | |
134 #endif | |
135 | |
136 #if defined(OPENSSL_SYS_VOS) | |
137 | |
138 /* The following algorithm repeatedly samples the real-time clock | |
139 (RTC) to generate a sequence of unpredictable data. The algorithm | |
140 relies upon the uneven execution speed of the code (due to factors | |
141 such as cache misses, interrupts, bus activity, and scheduling) and | |
142 upon the rather large relative difference between the speed of the | |
143 clock and the rate at which it can be read. | |
144 | |
145 If this code is ported to an environment where execution speed is | |
146 more constant or where the RTC ticks at a much slower rate, or the | |
147 clock can be read with fewer instructions, it is likely that the | |
148 results would be far more predictable. | |
149 | |
150 As a precaution, we generate 4 times the minimum required amount of | |
151 seed data. */ | |
152 | |
153 int RAND_poll(void) | |
154 { | |
155 short int code; | |
156 gid_t curr_gid; | |
157 pid_t curr_pid; | |
158 uid_t curr_uid; | |
159 int i, k; | |
160 struct timespec ts; | |
161 unsigned char v; | |
162 | |
163 #ifdef OPENSSL_SYS_VOS_HPPA | |
164 long duration; | |
165 extern void s$sleep (long *_duration, short int *_code); | |
166 #else | |
167 #ifdef OPENSSL_SYS_VOS_IA32 | |
168 long long duration; | |
169 extern void s$sleep2 (long long *_duration, short int *_code); | |
170 #else | |
171 #error "Unsupported Platform." | |
172 #endif /* OPENSSL_SYS_VOS_IA32 */ | |
173 #endif /* OPENSSL_SYS_VOS_HPPA */ | |
174 | |
175 /* Seed with the gid, pid, and uid, to ensure *some* | |
176 variation between different processes. */ | |
177 | |
178 curr_gid = getgid(); | |
179 RAND_add (&curr_gid, sizeof curr_gid, 1); | |
180 curr_gid = 0; | |
181 | |
182 curr_pid = getpid(); | |
183 RAND_add (&curr_pid, sizeof curr_pid, 1); | |
184 curr_pid = 0; | |
185 | |
186 curr_uid = getuid(); | |
187 RAND_add (&curr_uid, sizeof curr_uid, 1); | |
188 curr_uid = 0; | |
189 | |
190 for (i=0; i<(ENTROPY_NEEDED*4); i++) | |
191 { | |
192 /* burn some cpu; hope for interrupts, cache | |
193 collisions, bus interference, etc. */ | |
194 for (k=0; k<99; k++) | |
195 ts.tv_nsec = random (); | |
196 | |
197 #ifdef OPENSSL_SYS_VOS_HPPA | |
198 /* sleep for 1/1024 of a second (976 us). */ | |
199 duration = 1; | |
200 s$sleep (&duration, &code); | |
201 #else | |
202 #ifdef OPENSSL_SYS_VOS_IA32 | |
203 /* sleep for 1/65536 of a second (15 us). */ | |
204 duration = 1; | |
205 s$sleep2 (&duration, &code); | |
206 #endif /* OPENSSL_SYS_VOS_IA32 */ | |
207 #endif /* OPENSSL_SYS_VOS_HPPA */ | |
208 | |
209 /* get wall clock time. */ | |
210 clock_gettime (CLOCK_REALTIME, &ts); | |
211 | |
212 /* take 8 bits */ | |
213 v = (unsigned char) (ts.tv_nsec % 256); | |
214 RAND_add (&v, sizeof v, 1); | |
215 v = 0; | |
216 } | |
217 return 1; | |
218 } | |
219 #elif defined __OpenBSD__ | |
220 int RAND_poll(void) | |
221 { | |
222 u_int32_t rnd = 0, i; | |
223 unsigned char buf[ENTROPY_NEEDED]; | |
224 | |
225 for (i = 0; i < sizeof(buf); i++) { | |
226 if (i % 4 == 0) | |
227 rnd = arc4random(); | |
228 buf[i] = rnd; | |
229 rnd >>= 8; | |
230 } | |
231 RAND_add(buf, sizeof(buf), ENTROPY_NEEDED); | |
232 memset(buf, 0, sizeof(buf)); | |
233 | |
234 return 1; | |
235 } | |
236 #else /* !defined(__OpenBSD__) */ | |
237 int RAND_poll(void) | |
238 { | |
239 unsigned long l; | |
240 pid_t curr_pid = getpid(); | |
241 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) | |
242 unsigned char tmpbuf[ENTROPY_NEEDED]; | |
243 int n = 0; | |
244 #endif | |
245 #ifdef DEVRANDOM | |
246 static const char *randomfiles[] = { DEVRANDOM }; | |
247 struct stat randomstats[sizeof(randomfiles)/sizeof(randomfiles[0])]; | |
248 int fd; | |
249 unsigned int i; | |
250 #endif | |
251 #ifdef DEVRANDOM_EGD | |
252 static const char *egdsockets[] = { DEVRANDOM_EGD, NULL }; | |
253 const char **egdsocket = NULL; | |
254 #endif | |
255 | |
256 #ifdef DEVRANDOM | |
257 memset(randomstats,0,sizeof(randomstats)); | |
258 /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD | |
259 * have this. Use /dev/urandom if you can as /dev/random may block | |
260 * if it runs out of random entries. */ | |
261 | |
262 for (i = 0; (i < sizeof(randomfiles)/sizeof(randomfiles[0])) && | |
263 (n < ENTROPY_NEEDED); i++) | |
264 { | |
265 if ((fd = open(randomfiles[i], O_RDONLY | |
266 #ifdef O_NONBLOCK | |
267 |O_NONBLOCK | |
268 #endif | |
269 #ifdef O_BINARY | |
270 |O_BINARY | |
271 #endif | |
272 #ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do not make it | |
273 our controlling tty */ | |
274 |O_NOCTTY | |
275 #endif | |
276 )) >= 0) | |
277 { | |
278 int usec = 10*1000; /* spend 10ms on each file */ | |
279 int r; | |
280 unsigned int j; | |
281 struct stat *st=&randomstats[i]; | |
282 | |
283 /* Avoid using same input... Used to be O_NOFOLLOW | |
284 * above, but it's not universally appropriate... */ | |
285 if (fstat(fd,st) != 0) { close(fd); continue; } | |
286 for (j=0;j<i;j++) | |
287 { | |
288 if (randomstats[j].st_ino==st->st_ino && | |
289 randomstats[j].st_dev==st->st_dev) | |
290 break; | |
291 } | |
292 if (j<i) { close(fd); continue; } | |
293 | |
294 do | |
295 { | |
296 int try_read = 0; | |
297 | |
298 #if defined(OPENSSL_SYS_BEOS_R5) | |
299 /* select() is broken in BeOS R5, so we simply | |
300 * try to read something and snooze if we could
n't */ | |
301 try_read = 1; | |
302 | |
303 #elif defined(OPENSSL_SYS_LINUX) | |
304 /* use poll() */ | |
305 struct pollfd pset; | |
306 | |
307 pset.fd = fd; | |
308 pset.events = POLLIN; | |
309 pset.revents = 0; | |
310 | |
311 if (poll(&pset, 1, usec / 1000) < 0) | |
312 usec = 0; | |
313 else | |
314 try_read = (pset.revents & POLLIN) != 0; | |
315 | |
316 #else | |
317 /* use select() */ | |
318 fd_set fset; | |
319 struct timeval t; | |
320 | |
321 t.tv_sec = 0; | |
322 t.tv_usec = usec; | |
323 | |
324 if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE
) | |
325 { | |
326 /* can't use select, so just try to read
once anyway */ | |
327 try_read = 1; | |
328 } | |
329 else | |
330 { | |
331 FD_ZERO(&fset); | |
332 FD_SET(fd, &fset); | |
333 | |
334 if (select(fd+1,&fset,NULL,NULL,&t) >= 0
) | |
335 { | |
336 usec = t.tv_usec; | |
337 if (FD_ISSET(fd, &fset)) | |
338 try_read = 1; | |
339 } | |
340 else | |
341 usec = 0; | |
342 } | |
343 #endif | |
344 | |
345 if (try_read) | |
346 { | |
347 r = read(fd,(unsigned char *)tmpbuf+n, E
NTROPY_NEEDED-n); | |
348 if (r > 0) | |
349 n += r; | |
350 #if defined(OPENSSL_SYS_BEOS_R5) | |
351 if (r == 0) | |
352 snooze(t.tv_usec); | |
353 #endif | |
354 } | |
355 else | |
356 r = -1; | |
357 | |
358 /* Some Unixen will update t in select(), some | |
359 won't. For those who won't, or if we | |
360 didn't use select() in the first place, | |
361 give up here, otherwise, we will do | |
362 this once again for the remaining | |
363 time. */ | |
364 if (usec == 10*1000) | |
365 usec = 0; | |
366 } | |
367 while ((r > 0 || | |
368 (errno == EINTR || errno == EAGAIN)) && usec != 0
&& n < ENTROPY_NEEDED); | |
369 | |
370 close(fd); | |
371 } | |
372 } | |
373 #endif /* defined(DEVRANDOM) */ | |
374 | |
375 #ifdef DEVRANDOM_EGD | |
376 /* Use an EGD socket to read entropy from an EGD or PRNGD entropy | |
377 * collecting daemon. */ | |
378 | |
379 for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED; egdsocket
++) | |
380 { | |
381 int r; | |
382 | |
383 r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf+n, | |
384 ENTROPY_NEEDED-n); | |
385 if (r > 0) | |
386 n += r; | |
387 } | |
388 #endif /* defined(DEVRANDOM_EGD) */ | |
389 | |
390 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) | |
391 if (n > 0) | |
392 { | |
393 RAND_add(tmpbuf,sizeof tmpbuf,(double)n); | |
394 OPENSSL_cleanse(tmpbuf,n); | |
395 } | |
396 #endif | |
397 | |
398 /* put in some default random data, we need more than just this */ | |
399 l=curr_pid; | |
400 RAND_add(&l,sizeof(l),0.0); | |
401 l=getuid(); | |
402 RAND_add(&l,sizeof(l),0.0); | |
403 | |
404 l=time(NULL); | |
405 RAND_add(&l,sizeof(l),0.0); | |
406 | |
407 #if defined(OPENSSL_SYS_BEOS) | |
408 { | |
409 system_info sysInfo; | |
410 get_system_info(&sysInfo); | |
411 RAND_add(&sysInfo,sizeof(sysInfo),0); | |
412 } | |
413 #endif | |
414 | |
415 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) | |
416 return 1; | |
417 #else | |
418 return 0; | |
419 #endif | |
420 } | |
421 | |
422 #endif /* defined(__OpenBSD__) */ | |
423 #endif /* !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || define
d(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) |
| defined(OPENSSL_SYS_NETWARE)) */ | |
424 | |
425 | |
426 #if defined(OPENSSL_SYS_VXWORKS) | |
427 int RAND_poll(void) | |
428 { | |
429 return 0; | |
430 } | |
431 #endif | |
OLD | NEW |