remove all WINCE ifdefs
[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 # elif defined __OpenBSD__
125 int RAND_poll(void)
126 {
127     u_int32_t rnd = 0, i;
128     unsigned char buf[ENTROPY_NEEDED];
129
130     for (i = 0; i < sizeof(buf); i++) {
131         if (i % 4 == 0)
132             rnd = arc4random();
133         buf[i] = rnd;
134         rnd >>= 8;
135     }
136     RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
137     memset(buf, 0, sizeof(buf));
138
139     return 1;
140 }
141 # else                          /* !defined(__OpenBSD__) */
142 int RAND_poll(void)
143 {
144     unsigned long l;
145     pid_t curr_pid = getpid();
146 #  if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD))
147     unsigned char tmpbuf[ENTROPY_NEEDED];
148     int n = 0;
149 #  endif
150 #  ifdef DEVRANDOM
151     static const char *randomfiles[] = { DEVRANDOM };
152     struct stat randomstats[OSSL_NELEM(randomfiles)];
153     int fd;
154     unsigned int i;
155 #  endif
156 #  if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
157     static const char *egdsockets[] = { DEVRANDOM_EGD, NULL };
158     const char **egdsocket = NULL;
159 #  endif
160
161 #  ifdef DEVRANDOM
162     memset(randomstats, 0, sizeof(randomstats));
163     /*
164      * Use a random entropy pool device. Linux, FreeBSD and OpenBSD have
165      * this. Use /dev/urandom if you can as /dev/random may block if it runs
166      * out of random entries.
167      */
168
169     for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < ENTROPY_NEEDED); i++) {
170         if ((fd = open(randomfiles[i], O_RDONLY
171 #   ifdef O_NONBLOCK
172                        | O_NONBLOCK
173 #   endif
174 #   ifdef O_BINARY
175                        | O_BINARY
176 #   endif
177 #   ifdef O_NOCTTY              /* If it happens to be a TTY (god forbid), do
178                                  * not make it our controlling tty */
179                        | O_NOCTTY
180 #   endif
181              )) >= 0) {
182             int usec = 10 * 1000; /* spend 10ms on each file */
183             int r;
184             unsigned int j;
185             struct stat *st = &randomstats[i];
186
187             /*
188              * Avoid using same input... Used to be O_NOFOLLOW above, but
189              * it's not universally appropriate...
190              */
191             if (fstat(fd, st) != 0) {
192                 close(fd);
193                 continue;
194             }
195             for (j = 0; j < i; j++) {
196                 if (randomstats[j].st_ino == st->st_ino &&
197                     randomstats[j].st_dev == st->st_dev)
198                     break;
199             }
200             if (j < i) {
201                 close(fd);
202                 continue;
203             }
204
205             do {
206                 int try_read = 0;
207
208 #   if defined(OPENSSL_SYS_LINUX)
209                 /* use poll() */
210                 struct pollfd pset;
211
212                 pset.fd = fd;
213                 pset.events = POLLIN;
214                 pset.revents = 0;
215
216                 if (poll(&pset, 1, usec / 1000) < 0)
217                     usec = 0;
218                 else
219                     try_read = (pset.revents & POLLIN) != 0;
220
221 #   else
222                 /* use select() */
223                 fd_set fset;
224                 struct timeval t;
225
226                 t.tv_sec = 0;
227                 t.tv_usec = usec;
228
229                 if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE) {
230                     /*
231                      * can't use select, so just try to read once anyway
232                      */
233                     try_read = 1;
234                 } else {
235                     FD_ZERO(&fset);
236                     FD_SET(fd, &fset);
237
238                     if (select(fd + 1, &fset, NULL, NULL, &t) >= 0) {
239                         usec = t.tv_usec;
240                         if (FD_ISSET(fd, &fset))
241                             try_read = 1;
242                     } else
243                         usec = 0;
244                 }
245 #   endif
246
247                 if (try_read) {
248                     r = read(fd, (unsigned char *)tmpbuf + n,
249                              ENTROPY_NEEDED - n);
250                     if (r > 0)
251                         n += r;
252                 } else
253                     r = -1;
254
255                 /*
256                  * Some Unixen will update t in select(), some won't.  For
257                  * those who won't, or if we didn't use select() in the first
258                  * place, give up here, otherwise, we will do this once again
259                  * for the remaining time.
260                  */
261                 if (usec == 10 * 1000)
262                     usec = 0;
263             }
264             while ((r > 0 ||
265                     (errno == EINTR || errno == EAGAIN)) && usec != 0
266                    && n < ENTROPY_NEEDED);
267
268             close(fd);
269         }
270     }
271 #  endif                        /* defined(DEVRANDOM) */
272
273 #  if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
274     /*
275      * Use an EGD socket to read entropy from an EGD or PRNGD entropy
276      * collecting daemon.
277      */
278
279     for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED;
280          egdsocket++) {
281         int r;
282
283         r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n,
284                                  ENTROPY_NEEDED - n);
285         if (r > 0)
286             n += r;
287     }
288 #  endif                        /* defined(DEVRANDOM_EGD) */
289
290 #  if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
291     if (n > 0) {
292         RAND_add(tmpbuf, sizeof tmpbuf, (double)n);
293         OPENSSL_cleanse(tmpbuf, n);
294     }
295 #  endif
296
297     /* put in some default random data, we need more than just this */
298     l = curr_pid;
299     RAND_add(&l, sizeof(l), 0.0);
300     l = getuid();
301     RAND_add(&l, sizeof(l), 0.0);
302
303     l = time(NULL);
304     RAND_add(&l, sizeof(l), 0.0);
305
306 #  if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
307     return 1;
308 #  else
309     return 0;
310 #  endif
311 }
312
313 # endif                         /* defined(__OpenBSD__) */
314 #endif                          /* !(defined(OPENSSL_SYS_WINDOWS) ||
315                                  * defined(OPENSSL_SYS_WIN32) ||
316                                  * defined(OPENSSL_SYS_VMS) ||
317                                  * defined(OPENSSL_SYS_VXWORKS) */
318
319 #if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
320 int RAND_poll(void)
321 {
322     return 0;
323 }
324 #endif