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.c142
1 files changed, 106 insertions, 36 deletions
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..49a5ed1c3e 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -32,12 +32,16 @@
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.11 2003/02/28 21:27:44 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/param.h>
39#include <sys/sysctl.h>
40#include <sys/time.h>
41#include <fcntl.h>
39#include <stdio.h> 42#include <stdio.h>
40#include <stdlib.h> 43#include <stdlib.h>
44#include <unistd.h>
41 45
42/* 46/*
43 * random.c: 47 * random.c:
@@ -55,10 +59,10 @@ static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"
55 * congruential generator. If the amount of state information is less than 59 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used. 60 * 32 bytes, a simple linear congruential R.N.G. is used.
57 * 61 *
58 * Internally, the state information is treated as an array of longs; the 62 * Internally, the state information is treated as an array of int32_t; the
59 * zeroeth element of the array is the type of R.N.G. being used (small 63 * zeroeth element of the array is the type of R.N.G. being used (small
60 * integer); the remainder of the array is the state information for the 64 * integer); the remainder of the array is the state information for the
61 * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of 65 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
62 * state information, which will allow a degree seven polynomial. (Note: 66 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information 67 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details). 68 * stored in it -- see setstate() for details).
@@ -134,14 +138,14 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. 138 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */ 139 */
136 140
137static long randtbl[DEG_3 + 1] = { 141static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3, 142 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 143 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 144 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 145 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 146 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 147 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 148 0xf3bec5da,
145}; 149};
146 150
147/* 151/*
@@ -158,8 +162,8 @@ static long randtbl[DEG_3 + 1] = {
158 * in the initialization of randtbl) because the state table pointer is set 162 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below). 163 * to point to randtbl[1] (as explained below).
160 */ 164 */
161static long *fptr = &randtbl[SEP_3 + 1]; 165static int32_t *fptr = &randtbl[SEP_3 + 1];
162static long *rptr = &randtbl[1]; 166static int32_t *rptr = &randtbl[1];
163 167
164/* 168/*
165 * The following things are the pointer to the state information table, the 169 * The following things are the pointer to the state information table, the
@@ -171,11 +175,11 @@ static long *rptr = &randtbl[1];
171 * this is more efficient than indexing every time to find the address of 175 * this is more efficient than indexing every time to find the address of
172 * the last element to see if the front and rear pointers have wrapped. 176 * the last element to see if the front and rear pointers have wrapped.
173 */ 177 */
174static long *state = &randtbl[1]; 178static int32_t *state = &randtbl[1];
179static int32_t *end_ptr = &randtbl[DEG_3 + 1];
175static int rand_type = TYPE_3; 180static int rand_type = TYPE_3;
176static int rand_deg = DEG_3; 181static int rand_deg = DEG_3;
177static int rand_sep = SEP_3; 182static int rand_sep = SEP_3;
178static long *end_ptr = &randtbl[DEG_3 + 1];
179 183
180/* 184/*
181 * srandom: 185 * srandom:
@@ -191,17 +195,28 @@ static long *end_ptr = &randtbl[DEG_3 + 1];
191 */ 195 */
192void 196void
193srandom(x) 197srandom(x)
194 u_int x; 198 unsigned int x;
195{ 199{
196 register int i, j; 200 int i;
201 int32_t test;
202 div_t val;
197 203
198 if (rand_type == TYPE_0) 204 if (rand_type == TYPE_0)
199 state[0] = x; 205 state[0] = x;
200 else { 206 else {
201 j = 1;
202 state[0] = x; 207 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 208 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 209 /*
210 * Implement the following, without overflowing 31 bits:
211 *
212 * state[i] = (16807 * state[i - 1]) % 2147483647;
213 *
214 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
215 */
216 val = div(state[i-1], 127773);
217 test = 16807 * val.rem - 2836 * val.quot;
218 state[i] = test + (test < 0 ? 2147483647 : 0);
219 }
205 fptr = &state[rand_sep]; 220 fptr = &state[rand_sep];
206 rptr = &state[0]; 221 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 222 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +225,65 @@ srandom(x)
210} 225}
211 226
212/* 227/*
228 * srandomdev:
229 *
230 * Many programs choose the seed value in a totally predictable manner.
231 * This often causes problems. We seed the generator using the much more
232 * secure arandom(4) interface. Note that this particular seeding
233 * procedure can generate states which are impossible to reproduce by
234 * calling srandom() with any value, since the succeeding terms in the
235 * state buffer are no longer derived from the LC algorithm applied to
236 * a fixed seed.
237 */
238void
239srandomdev()
240{
241 int fd, i, mib[2], n;
242 size_t len;
243
244 if (rand_type == TYPE_0)
245 len = sizeof(state[0]);
246 else
247 len = rand_deg * sizeof(state[0]);
248
249 /*
250 * To get seed data, first try reading from /dev/arandom.
251 * If that fails, try the KERN_ARND sysctl() (one int at a time).
252 * As a last resort, call srandom().
253 */
254 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
255 read(fd, (void *) state, len) == (ssize_t) len) {
256 close(fd);
257 } else {
258 if (fd != -1)
259 close(fd);
260 mib[0] = CTL_KERN;
261 mib[1] = KERN_ARND;
262 n = len / sizeof(int);
263 len = sizeof(int);
264 for (i = 0; i < n; i++) {
265 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
266 NULL, 0) == -1)
267 break;
268 }
269 if (i != n) {
270 struct timeval tv;
271 u_int junk;
272
273 /* XXX - this could be better */
274 gettimeofday(&tv, NULL);
275 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
276 return;
277 }
278 }
279
280 if (rand_type != TYPE_0) {
281 fptr = &state[rand_sep];
282 rptr = &state[0];
283 }
284}
285
286/*
213 * initstate: 287 * initstate:
214 * 288 *
215 * Initialize the state information in the given array of n bytes for future 289 * Initialize the state information in the given array of n bytes for future
@@ -232,19 +306,16 @@ char *
232initstate(seed, arg_state, n) 306initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 307 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 308 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 309 size_t n; /* # bytes of state info */
236{ 310{
237 register char *ostate = (char *)(&state[-1]); 311 char *ostate = (char *)(&state[-1]);
238 312
239 if (rand_type == TYPE_0) 313 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 314 state[-1] = rand_type;
241 else 315 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 316 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 317 if (n < BREAK_0)
244 (void)fprintf(stderr, 318 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 319 if (n < BREAK_1) {
249 rand_type = TYPE_0; 320 rand_type = TYPE_0;
250 rand_deg = DEG_0; 321 rand_deg = DEG_0;
@@ -266,7 +337,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 337 rand_deg = DEG_4;
267 rand_sep = SEP_4; 338 rand_sep = SEP_4;
268 } 339 }
269 state = &(((long *)arg_state)[1]); /* first location */ 340 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 341 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 342 srandom(seed);
272 if (rand_type == TYPE_0) 343 if (rand_type == TYPE_0)
@@ -293,11 +364,11 @@ initstate(seed, arg_state, n)
293 */ 364 */
294char * 365char *
295setstate(arg_state) 366setstate(arg_state)
296 char *arg_state; 367 const char *arg_state;
297{ 368{
298 register long *new_state = (long *)arg_state; 369 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 370 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 371 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 372 char *ostate = (char *)(&state[-1]);
302 373
303 if (rand_type == TYPE_0) 374 if (rand_type == TYPE_0)
@@ -315,8 +386,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 386 rand_sep = seps[type];
316 break; 387 break;
317 default: 388 default:
318 (void)fprintf(stderr, 389 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 390 }
321 state = &new_state[1]; 391 state = &new_state[1];
322 if (rand_type != TYPE_0) { 392 if (rand_type != TYPE_0) {
@@ -347,7 +417,7 @@ setstate(arg_state)
347long 417long
348random() 418random()
349{ 419{
350 long i; 420 int32_t i;
351 421
352 if (rand_type == TYPE_0) 422 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 423 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +430,5 @@ random()
360 } else if (++rptr >= end_ptr) 430 } else if (++rptr >= end_ptr)
361 rptr = state; 431 rptr = state;
362 } 432 }
363 return(i); 433 return((long)i);
364} 434}