• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(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 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 #ifdef __VOS__
RAND_poll(void)137 int RAND_poll(void)
138 {
139 	unsigned char buf[ENTROPY_NEEDED];
140 	pid_t curr_pid;
141 	uid_t curr_uid;
142 	static int first=1;
143 	int i;
144 	long rnd = 0;
145 	struct timespec ts;
146 	unsigned seed;
147 
148 /* The VOS random() function starts from a static seed so its
149    initial value is predictable.  If random() returns the
150    initial value, reseed it with dynamic data.  The VOS
151    real-time clock has a granularity of 1 nsec so it should be
152    reasonably difficult to predict its exact value.  Do not
153    gratuitously reseed the PRNG because other code in this
154    process or thread may be using it.  */
155 
156 	if (first) {
157 		first = 0;
158 		rnd = random ();
159 		if (rnd == 1804289383) {
160 			clock_gettime (CLOCK_REALTIME, &ts);
161 			curr_pid = getpid();
162 			curr_uid = getuid();
163 			seed = ts.tv_sec ^ ts.tv_nsec ^ curr_pid ^ curr_uid;
164 			srandom (seed);
165 		}
166 	}
167 
168 	for (i = 0; i < sizeof(buf); i++) {
169 		if (i % 4 == 0)
170 			rnd = random();
171 		buf[i] = rnd;
172 		rnd >>= 8;
173 	}
174 	RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
175 	memset(buf, 0, sizeof(buf));
176 
177 	return 1;
178 }
179 #elif defined __OpenBSD__
RAND_poll(void)180 int RAND_poll(void)
181 {
182 	u_int32_t rnd = 0, i;
183 	unsigned char buf[ENTROPY_NEEDED];
184 
185 	for (i = 0; i < sizeof(buf); i++) {
186 		if (i % 4 == 0)
187 			rnd = arc4random();
188 		buf[i] = rnd;
189 		rnd >>= 8;
190 	}
191 	RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
192 	memset(buf, 0, sizeof(buf));
193 
194 	return 1;
195 }
196 #else /* !defined(__OpenBSD__) */
RAND_poll(void)197 int RAND_poll(void)
198 {
199 	unsigned long l;
200 	pid_t curr_pid = getpid();
201 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD)
202 	unsigned char tmpbuf[ENTROPY_NEEDED];
203 	int n = 0;
204 #endif
205 #ifdef DEVRANDOM
206 	static const char *randomfiles[] = { DEVRANDOM };
207 	struct stat randomstats[sizeof(randomfiles)/sizeof(randomfiles[0])];
208 	int fd;
209 	unsigned int i;
210 #endif
211 #ifdef DEVRANDOM_EGD
212 	static const char *egdsockets[] = { DEVRANDOM_EGD, NULL };
213 	const char **egdsocket = NULL;
214 #endif
215 
216 #ifdef DEVRANDOM
217 	memset(randomstats,0,sizeof(randomstats));
218 	/* Use a random entropy pool device. Linux, FreeBSD and OpenBSD
219 	 * have this. Use /dev/urandom if you can as /dev/random may block
220 	 * if it runs out of random entries.  */
221 
222 	for (i = 0; (i < sizeof(randomfiles)/sizeof(randomfiles[0])) &&
223 			(n < ENTROPY_NEEDED); i++)
224 		{
225 		if ((fd = open(randomfiles[i], O_RDONLY
226 #ifdef O_NONBLOCK
227 			|O_NONBLOCK
228 #endif
229 #ifdef O_BINARY
230 			|O_BINARY
231 #endif
232 #ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do not make it
233 		   our controlling tty */
234 			|O_NOCTTY
235 #endif
236 			)) >= 0)
237 			{
238 			int usec = 10*1000; /* spend 10ms on each file */
239 			int r;
240 			unsigned int j;
241 			struct stat *st=&randomstats[i];
242 
243 			/* Avoid using same input... Used to be O_NOFOLLOW
244 			 * above, but it's not universally appropriate... */
245 			if (fstat(fd,st) != 0)	{ close(fd); continue; }
246 			for (j=0;j<i;j++)
247 				{
248 				if (randomstats[j].st_ino==st->st_ino &&
249 				    randomstats[j].st_dev==st->st_dev)
250 					break;
251 				}
252 			if (j<i)		{ close(fd); continue; }
253 
254 			do
255 				{
256 				int try_read = 0;
257 
258 #if defined(OPENSSL_SYS_BEOS_R5)
259 				/* select() is broken in BeOS R5, so we simply
260 				 *  try to read something and snooze if we couldn't */
261 				try_read = 1;
262 
263 #elif defined(OPENSSL_SYS_LINUX)
264 				/* use poll() */
265 				struct pollfd pset;
266 
267 				pset.fd = fd;
268 				pset.events = POLLIN;
269 				pset.revents = 0;
270 
271 				if (poll(&pset, 1, usec / 1000) < 0)
272 					usec = 0;
273 				else
274 					try_read = (pset.revents & POLLIN) != 0;
275 
276 #else
277 				/* use select() */
278 				fd_set fset;
279 				struct timeval t;
280 
281 				t.tv_sec = 0;
282 				t.tv_usec = usec;
283 
284 				if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE)
285 					{
286 					/* can't use select, so just try to read once anyway */
287 					try_read = 1;
288 					}
289 				else
290 					{
291 					FD_ZERO(&fset);
292 					FD_SET(fd, &fset);
293 
294 					if (select(fd+1,&fset,NULL,NULL,&t) >= 0)
295 						{
296 						usec = t.tv_usec;
297 						if (FD_ISSET(fd, &fset))
298 							try_read = 1;
299 						}
300 					else
301 						usec = 0;
302 					}
303 #endif
304 
305 				if (try_read)
306 					{
307 					r = read(fd,(unsigned char *)tmpbuf+n, ENTROPY_NEEDED-n);
308 					if (r > 0)
309 						n += r;
310 #if defined(OPENSSL_SYS_BEOS_R5)
311 					if (r == 0)
312 						snooze(t.tv_usec);
313 #endif
314 					}
315 				else
316 					r = -1;
317 
318 				/* Some Unixen will update t in select(), some
319 				   won't.  For those who won't, or if we
320 				   didn't use select() in the first place,
321 				   give up here, otherwise, we will do
322 				   this once again for the remaining
323 				   time. */
324 				if (usec == 10*1000)
325 					usec = 0;
326 				}
327 			while ((r > 0 ||
328 			       (errno == EINTR || errno == EAGAIN)) && usec != 0 && n < ENTROPY_NEEDED);
329 
330 			close(fd);
331 			}
332 		}
333 #endif /* defined(DEVRANDOM) */
334 
335 #ifdef DEVRANDOM_EGD
336 	/* Use an EGD socket to read entropy from an EGD or PRNGD entropy
337 	 * collecting daemon. */
338 
339 	for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED; egdsocket++)
340 		{
341 		int r;
342 
343 		r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf+n,
344 					 ENTROPY_NEEDED-n);
345 		if (r > 0)
346 			n += r;
347 		}
348 #endif /* defined(DEVRANDOM_EGD) */
349 
350 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD)
351 	if (n > 0)
352 		{
353 		RAND_add(tmpbuf,sizeof tmpbuf,(double)n);
354 		OPENSSL_cleanse(tmpbuf,n);
355 		}
356 #endif
357 
358 	/* put in some default random data, we need more than just this */
359 	l=curr_pid;
360 	RAND_add(&l,sizeof(l),0.0);
361 	l=getuid();
362 	RAND_add(&l,sizeof(l),0.0);
363 
364 	l=time(NULL);
365 	RAND_add(&l,sizeof(l),0.0);
366 
367 #if defined(OPENSSL_SYS_BEOS)
368 	{
369 	system_info sysInfo;
370 	get_system_info(&sysInfo);
371 	RAND_add(&sysInfo,sizeof(sysInfo),0);
372 	}
373 #endif
374 
375 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD)
376 	return 1;
377 #else
378 	return 0;
379 #endif
380 }
381 
382 #endif /* defined(__OpenBSD__) */
383 #endif /* !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE)) */
384 
385 
386 #if defined(OPENSSL_SYS_VXWORKS)
RAND_poll(void)387 int RAND_poll(void)
388 	{
389 	return 0;
390 	}
391 #endif
392