summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib/random.c')
-rw-r--r--src/lib/libc/stdlib/random.c95
1 files changed, 74 insertions, 21 deletions
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..5ce7c90ee9 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -32,12 +32,15 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)random.c 5.9 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: random.c,v 1.9 2000/04/04 14:27:00 millert Exp $";
36static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#include <sys/types.h>
39#include <sys/time.h>
40#include <fcntl.h>
39#include <stdio.h> 41#include <stdio.h>
40#include <stdlib.h> 42#include <stdlib.h>
43#include <unistd.h>
41 44
42/* 45/*
43 * random.c: 46 * random.c:
@@ -136,12 +139,12 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
136 139
137static long randtbl[DEG_3 + 1] = { 140static long randtbl[DEG_3 + 1] = {
138 TYPE_3, 141 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 142 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 143 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 144 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 145 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 146 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 147 0xf3bec5da,
145}; 148};
146 149
147/* 150/*
@@ -193,15 +196,26 @@ void
193srandom(x) 196srandom(x)
194 u_int x; 197 u_int x;
195{ 198{
196 register int i, j; 199 register long int test;
200 register int i;
201 ldiv_t val;
197 202
198 if (rand_type == TYPE_0) 203 if (rand_type == TYPE_0)
199 state[0] = x; 204 state[0] = x;
200 else { 205 else {
201 j = 1;
202 state[0] = x; 206 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 207 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 208 /*
209 * Implement the following, without overflowing 31 bits:
210 *
211 * state[i] = (16807 * state[i - 1]) % 2147483647;
212 *
213 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
214 */
215 val = ldiv(state[i-1], 127773);
216 test = 16807 * val.rem - 2836 * val.quot;
217 state[i] = test + (test < 0 ? 2147483647 : 0);
218 }
205 fptr = &state[rand_sep]; 219 fptr = &state[rand_sep];
206 rptr = &state[0]; 220 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 221 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +224,49 @@ srandom(x)
210} 224}
211 225
212/* 226/*
227 * srandomdev:
228 *
229 * Many programs choose the seed value in a totally predictable manner.
230 * This often causes problems. We seed the generator using the much more
231 * secure arandom(4) interface. Note that this particular seeding
232 * procedure can generate states which are impossible to reproduce by
233 * calling srandom() with any value, since the succeeding terms in the
234 * state buffer are no longer derived from the LC algorithm applied to
235 * a fixed seed.
236 */
237void
238srandomdev()
239{
240 int fd;
241 size_t len;
242
243 if (rand_type == TYPE_0)
244 len = sizeof(state[0]);
245 else
246 len = rand_deg * sizeof(state[0]);
247
248 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
249 read(fd, (void *) state, len) == (ssize_t) len) {
250 close(fd);
251 } else {
252 struct timeval tv;
253 u_int junk;
254
255 /* XXX - this could be better */
256 gettimeofday(&tv, NULL);
257 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
258 if (fd != -1)
259 close(fd);
260 return;
261 }
262
263 if (rand_type != TYPE_0) {
264 fptr = &state[rand_sep];
265 rptr = &state[0];
266 }
267}
268
269/*
213 * initstate: 270 * initstate:
214 * 271 *
215 * Initialize the state information in the given array of n bytes for future 272 * Initialize the state information in the given array of n bytes for future
@@ -232,7 +289,7 @@ char *
232initstate(seed, arg_state, n) 289initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 290 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 291 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 292 size_t n; /* # bytes of state info */
236{ 293{
237 register char *ostate = (char *)(&state[-1]); 294 register char *ostate = (char *)(&state[-1]);
238 295
@@ -240,11 +297,8 @@ initstate(seed, arg_state, n)
240 state[-1] = rand_type; 297 state[-1] = rand_type;
241 else 298 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 299 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 300 if (n < BREAK_0)
244 (void)fprintf(stderr, 301 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 302 if (n < BREAK_1) {
249 rand_type = TYPE_0; 303 rand_type = TYPE_0;
250 rand_deg = DEG_0; 304 rand_deg = DEG_0;
@@ -293,7 +347,7 @@ initstate(seed, arg_state, n)
293 */ 347 */
294char * 348char *
295setstate(arg_state) 349setstate(arg_state)
296 char *arg_state; 350 const char *arg_state;
297{ 351{
298 register long *new_state = (long *)arg_state; 352 register long *new_state = (long *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 353 register int type = new_state[0] % MAX_TYPES;
@@ -315,8 +369,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 369 rand_sep = seps[type];
316 break; 370 break;
317 default: 371 default:
318 (void)fprintf(stderr, 372 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 373 }
321 state = &new_state[1]; 374 state = &new_state[1];
322 if (rand_type != TYPE_0) { 375 if (rand_type != TYPE_0) {