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.c155
1 files changed, 108 insertions, 47 deletions
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..4ca8735e75 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.13 2005/03/30 18:51:49 pat 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:
@@ -190,18 +190,28 @@ static long *end_ptr = &randtbl[DEG_3 + 1];
190 * for default usage relies on values produced by this routine. 190 * for default usage relies on values produced by this routine.
191 */ 191 */
192void 192void
193srandom(x) 193srandom(unsigned int x)
194 u_int x;
195{ 194{
196 register int i, j; 195 int i;
196 int32_t test;
197 div_t val;
197 198
198 if (rand_type == TYPE_0) 199 if (rand_type == TYPE_0)
199 state[0] = x; 200 state[0] = x;
200 else { 201 else {
201 j = 1;
202 state[0] = x; 202 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 203 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 204 /*
205 * Implement the following, without overflowing 31 bits:
206 *
207 * state[i] = (16807 * state[i - 1]) % 2147483647;
208 *
209 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
210 */
211 val = div(state[i-1], 127773);
212 test = 16807 * val.rem - 2836 * val.quot;
213 state[i] = test + (test < 0 ? 2147483647 : 0);
214 }
205 fptr = &state[rand_sep]; 215 fptr = &state[rand_sep];
206 rptr = &state[0]; 216 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 217 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +220,65 @@ srandom(x)
210} 220}
211 221
212/* 222/*
223 * srandomdev:
224 *
225 * Many programs choose the seed value in a totally predictable manner.
226 * This often causes problems. We seed the generator using the much more
227 * secure arandom(4) interface. Note that this particular seeding
228 * procedure can generate states which are impossible to reproduce by
229 * calling srandom() with any value, since the succeeding terms in the
230 * state buffer are no longer derived from the LC algorithm applied to
231 * a fixed seed.
232 */
233void
234srandomdev(void)
235{
236 int fd, i, mib[2], n;
237 size_t len;
238
239 if (rand_type == TYPE_0)
240 len = sizeof(state[0]);
241 else
242 len = rand_deg * sizeof(state[0]);
243
244 /*
245 * To get seed data, first try reading from /dev/arandom.
246 * If that fails, try the KERN_ARND sysctl() (one int at a time).
247 * As a last resort, call srandom().
248 */
249 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
250 read(fd, (void *) state, len) == (ssize_t) len) {
251 close(fd);
252 } else {
253 if (fd != -1)
254 close(fd);
255 mib[0] = CTL_KERN;
256 mib[1] = KERN_ARND;
257 n = len / sizeof(int);
258 len = sizeof(int);
259 for (i = 0; i < n; i++) {
260 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
261 NULL, 0) == -1)
262 break;
263 }
264 if (i != n) {
265 struct timeval tv;
266 u_int junk;
267
268 /* XXX - this could be better */
269 gettimeofday(&tv, NULL);
270 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
271 return;
272 }
273 }
274
275 if (rand_type != TYPE_0) {
276 fptr = &state[rand_sep];
277 rptr = &state[0];
278 }
279}
280
281/*
213 * initstate: 282 * initstate:
214 * 283 *
215 * Initialize the state information in the given array of n bytes for future 284 * Initialize the state information in the given array of n bytes for future
@@ -229,22 +298,16 @@ srandom(x)
229 * Returns a pointer to the old state. 298 * Returns a pointer to the old state.
230 */ 299 */
231char * 300char *
232initstate(seed, arg_state, n) 301initstate(u_int seed, char *arg_state, size_t n)
233 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */
236{ 302{
237 register char *ostate = (char *)(&state[-1]); 303 char *ostate = (char *)(&state[-1]);
238 304
239 if (rand_type == TYPE_0) 305 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 306 state[-1] = rand_type;
241 else 307 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 308 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 309 if (n < BREAK_0)
244 (void)fprintf(stderr, 310 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 311 if (n < BREAK_1) {
249 rand_type = TYPE_0; 312 rand_type = TYPE_0;
250 rand_deg = DEG_0; 313 rand_deg = DEG_0;
@@ -266,7 +329,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 329 rand_deg = DEG_4;
267 rand_sep = SEP_4; 330 rand_sep = SEP_4;
268 } 331 }
269 state = &(((long *)arg_state)[1]); /* first location */ 332 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 333 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 334 srandom(seed);
272 if (rand_type == TYPE_0) 335 if (rand_type == TYPE_0)
@@ -292,12 +355,11 @@ initstate(seed, arg_state, n)
292 * Returns a pointer to the old state information. 355 * Returns a pointer to the old state information.
293 */ 356 */
294char * 357char *
295setstate(arg_state) 358setstate(const char *arg_state)
296 char *arg_state;
297{ 359{
298 register long *new_state = (long *)arg_state; 360 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 361 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 362 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 363 char *ostate = (char *)(&state[-1]);
302 364
303 if (rand_type == TYPE_0) 365 if (rand_type == TYPE_0)
@@ -315,8 +377,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 377 rand_sep = seps[type];
316 break; 378 break;
317 default: 379 default:
318 (void)fprintf(stderr, 380 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 381 }
321 state = &new_state[1]; 382 state = &new_state[1];
322 if (rand_type != TYPE_0) { 383 if (rand_type != TYPE_0) {
@@ -345,9 +406,9 @@ setstate(arg_state)
345 * Returns a 31-bit random number. 406 * Returns a 31-bit random number.
346 */ 407 */
347long 408long
348random() 409random(void)
349{ 410{
350 long i; 411 int32_t i;
351 412
352 if (rand_type == TYPE_0) 413 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 414 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +421,5 @@ random()
360 } else if (++rptr >= end_ptr) 421 } else if (++rptr >= end_ptr)
361 rptr = state; 422 rptr = state;
362 } 423 }
363 return(i); 424 return((long)i);
364} 425}