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