Undo commit de02ec2
[openssl.git] / crypto / rand / rand_unix.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11
12 #define USE_SOCKETS
13 #include "e_os.h"
14 #include "internal/cryptlib.h"
15 #include <openssl/rand.h>
16 #include "rand_lcl.h"
17
18 #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI))
19
20 # include <sys/types.h>
21 # include <sys/time.h>
22 # include <sys/times.h>
23 # include <sys/stat.h>
24 # include <fcntl.h>
25 # include <unistd.h>
26 # include <time.h>
27 # if defined(OPENSSL_SYS_LINUX) /* should actually be available virtually
28                                  * everywhere */
29 #  include <poll.h>
30 # endif
31 # include <limits.h>
32 # ifndef FD_SETSIZE
33 #  define FD_SETSIZE (8*sizeof(fd_set))
34 # endif
35
36 # if defined(OPENSSL_SYS_VOS)
37
38 /*
39  * The following algorithm repeatedly samples the real-time clock (RTC) to
40  * generate a sequence of unpredictable data.  The algorithm relies upon the
41  * uneven execution speed of the code (due to factors such as cache misses,
42  * interrupts, bus activity, and scheduling) and upon the rather large
43  * relative difference between the speed of the clock and the rate at which
44  * it can be read.
45  *
46  * If this code is ported to an environment where execution speed is more
47  * constant or where the RTC ticks at a much slower rate, or the clock can be
48  * read with fewer instructions, it is likely that the results would be far
49  * more predictable.
50  *
51  * As a precaution, we generate 4 times the minimum required amount of seed
52  * data.
53  */
54
55 int RAND_poll(void)
56 {
57     short int code;
58     gid_t curr_gid;
59     pid_t curr_pid;
60     uid_t curr_uid;
61     int i, k;
62     struct timespec ts;
63     unsigned char v;
64
65 #  ifdef OPENSSL_SYS_VOS_HPPA
66     long duration;
67     extern void s$sleep(long *_duration, short int *_code);
68 #  else
69 #   ifdef OPENSSL_SYS_VOS_IA32
70     long long duration;
71     extern void s$sleep2(long long *_duration, short int *_code);
72 #   else
73 #    error "Unsupported Platform."
74 #   endif                       /* OPENSSL_SYS_VOS_IA32 */
75 #  endif                        /* OPENSSL_SYS_VOS_HPPA */
76
77     /*
78      * Seed with the gid, pid, and uid, to ensure *some* variation between
79      * different processes.
80      */
81
82     curr_gid = getgid();
83     RAND_add(&curr_gid, sizeof curr_gid, 1);
84     curr_gid = 0;
85
86     curr_pid = getpid();
87     RAND_add(&curr_pid, sizeof curr_pid, 1);
88     curr_pid = 0;
89
90     curr_uid = getuid();
91     RAND_add(&curr_uid, sizeof curr_uid, 1);
92     curr_uid = 0;
93
94     for (i = 0; i < (ENTROPY_NEEDED * 4); i++) {
95         /*
96          * burn some cpu; hope for interrupts, cache collisions, bus
97          * interference, etc.
98          */
99         for (k = 0; k < 99; k++)
100             ts.tv_nsec = random();
101
102 #  ifdef OPENSSL_SYS_VOS_HPPA
103         /* sleep for 1/1024 of a second (976 us).  */
104         duration = 1;
105         s$sleep(&duration, &code);
106 #  else
107 #   ifdef OPENSSL_SYS_VOS_IA32
108         /* sleep for 1/65536 of a second (15 us).  */
109         duration = 1;
110         s$sleep2(&duration, &code);
111 #   endif                       /* OPENSSL_SYS_VOS_IA32 */
112 #  endif                        /* OPENSSL_SYS_VOS_HPPA */
113
114         /* get wall clock time.  */
115         clock_gettime(CLOCK_REALTIME, &ts);
116
117         /* take 8 bits */
118         v = (unsigned char)(ts.tv_nsec % 256);
119         RAND_add(&v, sizeof v, 1);
120         v = 0;
121     }
122     return 1;
123 }
124 # else
125 int RAND_poll(void)
126 {
127     unsigned long l;
128     pid_t curr_pid = getpid();
129 #  if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD))
130     unsigned char tmpbuf[ENTROPY_NEEDED];
131     int n = 0;
132 #  endif
133 #  ifdef DEVRANDOM
134     static const char *randomfiles[] = { DEVRANDOM };
135     struct stat randomstats[OSSL_NELEM(randomfiles)];
136     int fd;
137     unsigned int i;
138 #  endif
139 #  if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
140     static const char *egdsockets[] = { DEVRANDOM_EGD, NULL };
141     const char **egdsocket = NULL;
142 #  endif
143
144 #  ifdef DEVRANDOM
145     memset(randomstats, 0, sizeof(randomstats));
146     /*
147      * Use a random entropy pool device. Linux, FreeBSD and OpenBSD have
148      * this. Use /dev/urandom if you can as /dev/random may block if it runs
149      * out of random entries.
150      */
151
152     for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < ENTROPY_NEEDED); i++) {
153         if ((fd = open(randomfiles[i], O_RDONLY
154 #   ifdef O_NONBLOCK
155                        | O_NONBLOCK
156 #   endif
157 #   ifdef O_BINARY
158                        | O_BINARY
159 #   endif
160 #   ifdef O_NOCTTY              /* If it happens to be a TTY (god forbid), do
161                                  * not make it our controlling tty */
162                        | O_NOCTTY
163 #   endif
164              )) >= 0) {
165             int usec = 10 * 1000; /* spend 10ms on each file */
166             int r;
167             unsigned int j;
168             struct stat *st = &randomstats[i];
169
170             /*
171              * Avoid using same input... Used to be O_NOFOLLOW above, but
172              * it's not universally appropriate...
173              */
174             if (fstat(fd, st) != 0) {
175                 close(fd);
176                 continue;
177             }
178             for (j = 0; j < i; j++) {
179                 if (randomstats[j].st_ino == st->st_ino &&
180                     randomstats[j].st_dev == st->st_dev)
181                     break;
182             }
183             if (j < i) {
184                 close(fd);
185                 continue;
186             }
187
188             do {
189                 int try_read = 0;
190
191 #   if defined(OPENSSL_SYS_LINUX)
192                 /* use poll() */
193                 struct pollfd pset;
194
195                 pset.fd = fd;
196                 pset.events = POLLIN;
197                 pset.revents = 0;
198
199                 if (poll(&pset, 1, usec / 1000) < 0)
200                     usec = 0;
201                 else
202                     try_read = (pset.revents & POLLIN) != 0;
203
204 #   else
205                 /* use select() */
206                 fd_set fset;
207                 struct timeval t;
208
209                 t.tv_sec = 0;
210                 t.tv_usec = usec;
211
212                 if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE) {
213                     /*
214                      * can't use select, so just try to read once anyway
215                      */
216                     try_read = 1;
217                 } else {
218                     FD_ZERO(&fset);
219                     FD_SET(fd, &fset);
220
221                     if (select(fd + 1, &fset, NULL, NULL, &t) >= 0) {
222                         usec = t.tv_usec;
223                         if (FD_ISSET(fd, &fset))
224                             try_read = 1;
225                     } else
226                         usec = 0;
227                 }
228 #   endif
229
230                 if (try_read) {
231                     r = read(fd, (unsigned char *)tmpbuf + n,
232                              ENTROPY_NEEDED - n);
233                     if (r > 0)
234                         n += r;
235                 } else
236                     r = -1;
237
238                 /*
239                  * Some Unixen will update t in select(), some won't.  For
240                  * those who won't, or if we didn't use select() in the first
241                  * place, give up here, otherwise, we will do this once again
242                  * for the remaining time.
243                  */
244                 if (usec == 10 * 1000)
245                     usec = 0;
246             }
247             while ((r > 0 ||
248                     (errno == EINTR || errno == EAGAIN)) && usec != 0
249                    && n < ENTROPY_NEEDED);
250
251             close(fd);
252         }
253     }
254 #  endif                        /* defined(DEVRANDOM) */
255
256 #  if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
257     /*
258      * Use an EGD socket to read entropy from an EGD or PRNGD entropy
259      * collecting daemon.
260      */
261
262     for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED;
263          egdsocket++) {
264         int r;
265
266         r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n,
267                                  ENTROPY_NEEDED - n);
268         if (r > 0)
269             n += r;
270     }
271 #  endif                        /* defined(DEVRANDOM_EGD) */
272
273 #  if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
274     if (n > 0) {
275         RAND_add(tmpbuf, sizeof tmpbuf, (double)n);
276         OPENSSL_cleanse(tmpbuf, n);
277     }
278 #  endif
279
280     /* put in some default random data, we need more than just this */
281     l = curr_pid;
282     RAND_add(&l, sizeof(l), 0.0);
283     l = getuid();
284     RAND_add(&l, sizeof(l), 0.0);
285
286     l = time(NULL);
287     RAND_add(&l, sizeof(l), 0.0);
288
289 #  if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
290     return 1;
291 #  else
292     return 0;
293 #  endif
294 }
295
296 # endif                         /* defined(__OpenBSD__) */
297 #endif                          /* !(defined(OPENSSL_SYS_WINDOWS) ||
298                                  * defined(OPENSSL_SYS_WIN32) ||
299                                  * defined(OPENSSL_SYS_VMS) ||
300                                  * defined(OPENSSL_SYS_VXWORKS) */
301
302 #if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
303 int RAND_poll(void)
304 {
305     return 0;
306 }
307 #endif