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.c148
1 files changed, 107 insertions, 41 deletions
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..4807d2f27d 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -10,11 +10,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 13 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software 14 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 15 * without specific prior written permission.
20 * 16 *
@@ -32,12 +28,16 @@
32 */ 28 */
33 29
34#if defined(LIBC_SCCS) && !defined(lint) 30#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)random.c 5.9 (Berkeley) 2/23/91";*/ 31static char *rcsid = "$OpenBSD: random.c,v 1.12 2003/06/02 20:18:38 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 */ 32#endif /* LIBC_SCCS and not lint */
38 33
34#include <sys/param.h>
35#include <sys/sysctl.h>
36#include <sys/time.h>
37#include <fcntl.h>
39#include <stdio.h> 38#include <stdio.h>
40#include <stdlib.h> 39#include <stdlib.h>
40#include <unistd.h>
41 41
42/* 42/*
43 * random.c: 43 * random.c:
@@ -55,10 +55,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 55 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used. 56 * 32 bytes, a simple linear congruential R.N.G. is used.
57 * 57 *
58 * Internally, the state information is treated as an array of longs; the 58 * 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 59 * 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 60 * 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 61 * 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: 62 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information 63 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details). 64 * stored in it -- see setstate() for details).
@@ -134,14 +134,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. 134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */ 135 */
136 136
137static long randtbl[DEG_3 + 1] = { 137static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3, 138 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 139 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 140 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 141 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 142 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 143 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 144 0xf3bec5da,
145}; 145};
146 146
147/* 147/*
@@ -158,8 +158,8 @@ static long randtbl[DEG_3 + 1] = {
158 * in the initialization of randtbl) because the state table pointer is set 158 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below). 159 * to point to randtbl[1] (as explained below).
160 */ 160 */
161static long *fptr = &randtbl[SEP_3 + 1]; 161static int32_t *fptr = &randtbl[SEP_3 + 1];
162static long *rptr = &randtbl[1]; 162static int32_t *rptr = &randtbl[1];
163 163
164/* 164/*
165 * The following things are the pointer to the state information table, the 165 * The following things are the pointer to the state information table, the
@@ -171,11 +171,11 @@ static long *rptr = &randtbl[1];
171 * this is more efficient than indexing every time to find the address of 171 * 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. 172 * the last element to see if the front and rear pointers have wrapped.
173 */ 173 */
174static long *state = &randtbl[1]; 174static int32_t *state = &randtbl[1];
175static int32_t *end_ptr = &randtbl[DEG_3 + 1];
175static int rand_type = TYPE_3; 176static int rand_type = TYPE_3;
176static int rand_deg = DEG_3; 177static int rand_deg = DEG_3;
177static int rand_sep = SEP_3; 178static int rand_sep = SEP_3;
178static long *end_ptr = &randtbl[DEG_3 + 1];
179 179
180/* 180/*
181 * srandom: 181 * srandom:
@@ -191,17 +191,28 @@ static long *end_ptr = &randtbl[DEG_3 + 1];
191 */ 191 */
192void 192void
193srandom(x) 193srandom(x)
194 u_int x; 194 unsigned int x;
195{ 195{
196 register int i, j; 196 int i;
197 int32_t test;
198 div_t val;
197 199
198 if (rand_type == TYPE_0) 200 if (rand_type == TYPE_0)
199 state[0] = x; 201 state[0] = x;
200 else { 202 else {
201 j = 1;
202 state[0] = x; 203 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 204 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 205 /*
206 * Implement the following, without overflowing 31 bits:
207 *
208 * state[i] = (16807 * state[i - 1]) % 2147483647;
209 *
210 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
211 */
212 val = div(state[i-1], 127773);
213 test = 16807 * val.rem - 2836 * val.quot;
214 state[i] = test + (test < 0 ? 2147483647 : 0);
215 }
205 fptr = &state[rand_sep]; 216 fptr = &state[rand_sep];
206 rptr = &state[0]; 217 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 218 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +221,65 @@ srandom(x)
210} 221}
211 222
212/* 223/*
224 * srandomdev:
225 *
226 * Many programs choose the seed value in a totally predictable manner.
227 * This often causes problems. We seed the generator using the much more
228 * secure arandom(4) interface. Note that this particular seeding
229 * procedure can generate states which are impossible to reproduce by
230 * calling srandom() with any value, since the succeeding terms in the
231 * state buffer are no longer derived from the LC algorithm applied to
232 * a fixed seed.
233 */
234void
235srandomdev()
236{
237 int fd, i, mib[2], n;
238 size_t len;
239
240 if (rand_type == TYPE_0)
241 len = sizeof(state[0]);
242 else
243 len = rand_deg * sizeof(state[0]);
244
245 /*
246 * To get seed data, first try reading from /dev/arandom.
247 * If that fails, try the KERN_ARND sysctl() (one int at a time).
248 * As a last resort, call srandom().
249 */
250 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
251 read(fd, (void *) state, len) == (ssize_t) len) {
252 close(fd);
253 } else {
254 if (fd != -1)
255 close(fd);
256 mib[0] = CTL_KERN;
257 mib[1] = KERN_ARND;
258 n = len / sizeof(int);
259 len = sizeof(int);
260 for (i = 0; i < n; i++) {
261 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
262 NULL, 0) == -1)
263 break;
264 }
265 if (i != n) {
266 struct timeval tv;
267 u_int junk;
268
269 /* XXX - this could be better */
270 gettimeofday(&tv, NULL);
271 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
272 return;
273 }
274 }
275
276 if (rand_type != TYPE_0) {
277 fptr = &state[rand_sep];
278 rptr = &state[0];
279 }
280}
281
282/*
213 * initstate: 283 * initstate:
214 * 284 *
215 * Initialize the state information in the given array of n bytes for future 285 * Initialize the state information in the given array of n bytes for future
@@ -232,19 +302,16 @@ char *
232initstate(seed, arg_state, n) 302initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 303 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 304 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 305 size_t n; /* # bytes of state info */
236{ 306{
237 register char *ostate = (char *)(&state[-1]); 307 char *ostate = (char *)(&state[-1]);
238 308
239 if (rand_type == TYPE_0) 309 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 310 state[-1] = rand_type;
241 else 311 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 312 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 313 if (n < BREAK_0)
244 (void)fprintf(stderr, 314 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 315 if (n < BREAK_1) {
249 rand_type = TYPE_0; 316 rand_type = TYPE_0;
250 rand_deg = DEG_0; 317 rand_deg = DEG_0;
@@ -266,7 +333,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 333 rand_deg = DEG_4;
267 rand_sep = SEP_4; 334 rand_sep = SEP_4;
268 } 335 }
269 state = &(((long *)arg_state)[1]); /* first location */ 336 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 337 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 338 srandom(seed);
272 if (rand_type == TYPE_0) 339 if (rand_type == TYPE_0)
@@ -293,11 +360,11 @@ initstate(seed, arg_state, n)
293 */ 360 */
294char * 361char *
295setstate(arg_state) 362setstate(arg_state)
296 char *arg_state; 363 const char *arg_state;
297{ 364{
298 register long *new_state = (long *)arg_state; 365 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 366 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 367 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 368 char *ostate = (char *)(&state[-1]);
302 369
303 if (rand_type == TYPE_0) 370 if (rand_type == TYPE_0)
@@ -315,8 +382,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 382 rand_sep = seps[type];
316 break; 383 break;
317 default: 384 default:
318 (void)fprintf(stderr, 385 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 386 }
321 state = &new_state[1]; 387 state = &new_state[1];
322 if (rand_type != TYPE_0) { 388 if (rand_type != TYPE_0) {
@@ -347,7 +413,7 @@ setstate(arg_state)
347long 413long
348random() 414random()
349{ 415{
350 long i; 416 int32_t i;
351 417
352 if (rand_type == TYPE_0) 418 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 419 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +426,5 @@ random()
360 } else if (++rptr >= end_ptr) 426 } else if (++rptr >= end_ptr)
361 rptr = state; 427 rptr = state;
362 } 428 }
363 return(i); 429 return((long)i);
364} 430}