diff options
-rw-r--r-- | src/lib/libc/stdlib/Makefile.inc | 10 | ||||
-rw-r--r-- | src/lib/libc/stdlib/drand48.c | 10 | ||||
-rw-r--r-- | src/lib/libc/stdlib/lcong48.c | 10 | ||||
-rw-r--r-- | src/lib/libc/stdlib/lrand48.c | 4 | ||||
-rw-r--r-- | src/lib/libc/stdlib/mrand48.c | 4 | ||||
-rw-r--r-- | src/lib/libc/stdlib/rand.3 | 76 | ||||
-rw-r--r-- | src/lib/libc/stdlib/rand.c | 15 | ||||
-rw-r--r-- | src/lib/libc/stdlib/rand48.3 | 110 | ||||
-rw-r--r-- | src/lib/libc/stdlib/rand48.h | 3 | ||||
-rw-r--r-- | src/lib/libc/stdlib/random.3 | 110 | ||||
-rw-r--r-- | src/lib/libc/stdlib/random.c | 49 | ||||
-rw-r--r-- | src/lib/libc/stdlib/seed48.c | 13 | ||||
-rw-r--r-- | src/lib/libc/stdlib/srand48.c | 12 |
13 files changed, 267 insertions, 159 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc index 3a13d9ff1a..3e99fe112d 100644 --- a/src/lib/libc/stdlib/Makefile.inc +++ b/src/lib/libc/stdlib/Makefile.inc | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile.inc,v 1.56 2014/12/08 20:39:16 tedu Exp $ | 1 | # $OpenBSD: Makefile.inc,v 1.57 2014/12/08 21:45:20 deraadt Exp $ |
2 | 2 | ||
3 | # stdlib sources | 3 | # stdlib sources |
4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/stdlib ${LIBCSRCDIR}/stdlib | 4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/stdlib ${LIBCSRCDIR}/stdlib |
@@ -43,12 +43,14 @@ MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3 | |||
43 | MLINKS+=malloc.3 reallocarray.3 | 43 | MLINKS+=malloc.3 reallocarray.3 |
44 | MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 | 44 | MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 |
45 | MLINKS+=radixsort.3 sradixsort.3 | 45 | MLINKS+=radixsort.3 sradixsort.3 |
46 | MLINKS+=rand.3 srand.3 rand.3 rand_r.3 | 46 | MLINKS+=rand.3 srand.3 rand.3 rand_r.3 rand.3 srand_deterministic.3 |
47 | MLINKS+=random.3 initstate.3 random.3 setstate.3 | 47 | MLINKS+=random.3 initstate.3 random.3 setstate.3 |
48 | MLINKS+=random.3 srandom.3 random.3 srandomdev.3 | 48 | MLINKS+=random.3 srandom.3 random.3 srandomdev.3 random.3 srandom_deterministic.3 |
49 | MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 | 49 | MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 |
50 | MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3 | 50 | MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3 |
51 | MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3 | 51 | MLINKS+=rand48.3 srand48.3 rand48.3 srand48_deterministic.3 |
52 | MLINKS+=rand48.3 seed48.3 rand48.3 seed48_deterministic.3 | ||
53 | MLINKS+=rand48.3 lcong48.3 rand48.3 lcong48_deterministic.3 | ||
52 | MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3 | 54 | MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3 |
53 | MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3 | 55 | MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3 |
54 | MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3 | 56 | MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3 |
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c index b6c046c831..bbeedf8a8a 100644 --- a/src/lib/libc/stdlib/drand48.c +++ b/src/lib/libc/stdlib/drand48.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: drand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */ | 1 | /* $OpenBSD: drand48.c,v 1.4 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1993 Martin Birgmeier | 3 | * Copyright (c) 1993 Martin Birgmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -19,5 +19,13 @@ extern unsigned short __rand48_seed[3]; | |||
19 | double | 19 | double |
20 | drand48(void) | 20 | drand48(void) |
21 | { | 21 | { |
22 | if (__rand48_deterministic == 0) { | ||
23 | short rseed[3]; | ||
24 | |||
25 | arc4random_buf(rseed, sizeof rseed); | ||
26 | return ldexp((double) rseed[0], -48) + | ||
27 | ldexp((double) rseed[1], -32) + | ||
28 | ldexp((double) rseed[2], -16); | ||
29 | } | ||
22 | return erand48(__rand48_seed); | 30 | return erand48(__rand48_seed); |
23 | } | 31 | } |
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c index 2cf5c271ba..09726efb6e 100644 --- a/src/lib/libc/stdlib/lcong48.c +++ b/src/lib/libc/stdlib/lcong48.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: lcong48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */ | 1 | /* $OpenBSD: lcong48.c,v 1.4 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1993 Martin Birgmeier | 3 | * Copyright (c) 1993 Martin Birgmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -21,6 +21,14 @@ extern unsigned short __rand48_add; | |||
21 | void | 21 | void |
22 | lcong48(unsigned short p[7]) | 22 | lcong48(unsigned short p[7]) |
23 | { | 23 | { |
24 | lcong48_deterministic(p); | ||
25 | __rand48_deterministic = 0; | ||
26 | } | ||
27 | |||
28 | void | ||
29 | lcong48_deterministic(unsigned short p[7]) | ||
30 | { | ||
31 | __rand48_deterministic = 1; | ||
24 | __rand48_seed[0] = p[0]; | 32 | __rand48_seed[0] = p[0]; |
25 | __rand48_seed[1] = p[1]; | 33 | __rand48_seed[1] = p[1]; |
26 | __rand48_seed[2] = p[2]; | 34 | __rand48_seed[2] = p[2]; |
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c index 21beb858ca..22508594fc 100644 --- a/src/lib/libc/stdlib/lrand48.c +++ b/src/lib/libc/stdlib/lrand48.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: lrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */ | 1 | /* $OpenBSD: lrand48.c,v 1.4 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1993 Martin Birgmeier | 3 | * Copyright (c) 1993 Martin Birgmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -19,6 +19,8 @@ extern unsigned short __rand48_seed[3]; | |||
19 | long | 19 | long |
20 | lrand48(void) | 20 | lrand48(void) |
21 | { | 21 | { |
22 | if (__rand48_deterministic == 0) | ||
23 | return arc4random() & 0x7fffffff; | ||
22 | __dorand48(__rand48_seed); | 24 | __dorand48(__rand48_seed); |
23 | return ((long) __rand48_seed[2] << 15) + ((long) __rand48_seed[1] >> 1); | 25 | return ((long) __rand48_seed[2] << 15) + ((long) __rand48_seed[1] >> 1); |
24 | } | 26 | } |
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c index 977264aba5..7bfccbbf83 100644 --- a/src/lib/libc/stdlib/mrand48.c +++ b/src/lib/libc/stdlib/mrand48.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */ | 1 | /* $OpenBSD: mrand48.c,v 1.4 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1993 Martin Birgmeier | 3 | * Copyright (c) 1993 Martin Birgmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -19,6 +19,8 @@ extern unsigned short __rand48_seed[3]; | |||
19 | long | 19 | long |
20 | mrand48(void) | 20 | mrand48(void) |
21 | { | 21 | { |
22 | if (__rand48_deterministic == 0) | ||
23 | return arc4random(); | ||
22 | __dorand48(__rand48_seed); | 24 | __dorand48(__rand48_seed); |
23 | return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1]; | 25 | return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1]; |
24 | } | 26 | } |
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3 index 5d4bfe7ab6..c760161ba7 100644 --- a/src/lib/libc/stdlib/rand.3 +++ b/src/lib/libc/stdlib/rand.3 | |||
@@ -29,52 +29,65 @@ | |||
29 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 29 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | .\" SUCH DAMAGE. | 30 | .\" SUCH DAMAGE. |
31 | .\" | 31 | .\" |
32 | .\" $OpenBSD: rand.3,v 1.17 2014/11/25 17:41:12 millert Exp $ | 32 | .\" $OpenBSD: rand.3,v 1.18 2014/12/08 21:45:20 deraadt Exp $ |
33 | .\" | 33 | .\" |
34 | .Dd $Mdocdate: November 25 2014 $ | 34 | .Dd $Mdocdate: December 8 2014 $ |
35 | .Dt RAND 3 | 35 | .Dt RAND 3 |
36 | .Os | 36 | .Os |
37 | .Sh NAME | 37 | .Sh NAME |
38 | .Nm rand , | 38 | .Nm rand , |
39 | .Nm rand_r , | 39 | .Nm rand_r , |
40 | .Nm srand | 40 | .Nm srand , |
41 | .Nm srand_deterministic | ||
41 | .Nd bad pseudo-random number generator | 42 | .Nd bad pseudo-random number generator |
42 | .Sh SYNOPSIS | 43 | .Sh SYNOPSIS |
43 | .In stdlib.h | 44 | .In stdlib.h |
44 | .Ft void | 45 | .Ft void |
45 | .Fn srand "unsigned int seed" | 46 | .Fn srand "unsigned int seed" |
47 | .Ft void | ||
48 | .Fn srand_deterministic "unsigned int seed" | ||
46 | .Ft int | 49 | .Ft int |
47 | .Fn rand void | 50 | .Fn rand void |
48 | .Ft int | 51 | .Ft int |
49 | .Fn rand_r "unsigned int *seed" | 52 | .Fn rand_r "unsigned int *seed" |
50 | .Sh DESCRIPTION | 53 | .Sh DESCRIPTION |
51 | .Bf -symbolic | 54 | .Bf -symbolic |
52 | These interfaces are obsoleted by | 55 | Standards insist that this interface return deterministic results. |
53 | .Xr random 3 , | 56 | Unsafe usage is very common, so |
54 | which is also unsafe. | 57 | .Ox |
55 | Consider using | 58 | changed the subsystem to return non-deterministic results by default. |
56 | .Xr arc4random 3 . | ||
57 | .Ef | 59 | .Ef |
58 | .Pp | 60 | .Pp |
59 | The | 61 | To satisfy portable code, |
62 | .Fn srand | ||
63 | may be called to initialize the subsystem. | ||
64 | In | ||
65 | .Ox | ||
66 | the | ||
67 | .Ar seed | ||
68 | variable is ignored, and strong random number results will be provided from | ||
69 | .Xr arc4random 3. | ||
70 | In other systems, the | ||
71 | .Ar seed | ||
72 | variable primes a simplistic deterministic algorithm. | ||
73 | .Pp | ||
74 | If the standardized behavior is required | ||
75 | .Fn srand_deterministic | ||
76 | can be substituted for | ||
77 | .Fn srand , | ||
78 | then subsequent | ||
60 | .Fn rand | 79 | .Fn rand |
61 | function computes a sequence of pseudo-random integers in the range | 80 | calls will return results using the deterministic algorithm. |
62 | of 0 to | ||
63 | .Dv RAND_MAX | ||
64 | (as defined by the header file | ||
65 | .In stdlib.h ) . | ||
66 | .Pp | 81 | .Pp |
67 | The | 82 | The |
68 | .Fn srand | 83 | .Fn rand |
69 | function sets its argument as the seed for a new sequence of | 84 | function returns a result in the range of 0 to |
70 | pseudo-random numbers to be returned by | 85 | .Dv RAND_MAX . |
71 | .Fn rand . | 86 | By default, this result comes from |
72 | These sequences are repeatable by calling | 87 | .Xr arc4random 3 . |
73 | .Fn srand | 88 | If |
74 | with the same seed value. | 89 | .Fn srand_deterministic |
75 | .Pp | 90 | was called, the result will be computed using the deterministic algorithm. |
76 | If no seed value is provided, the functions are automatically | ||
77 | seeded with a value of 1. | ||
78 | .Pp | 91 | .Pp |
79 | The | 92 | The |
80 | .Fn rand_r | 93 | .Fn rand_r |
@@ -83,6 +96,7 @@ is a thread-safe version of | |||
83 | Storage for the seed must be provided through the | 96 | Storage for the seed must be provided through the |
84 | .Fa seed | 97 | .Fa seed |
85 | argument, and needs to have been initialized by the caller. | 98 | argument, and needs to have been initialized by the caller. |
99 | It always operates using the deterministic algorithm. | ||
86 | .Sh SEE ALSO | 100 | .Sh SEE ALSO |
87 | .Xr arc4random 3 , | 101 | .Xr arc4random 3 , |
88 | .Xr rand48 3 , | 102 | .Xr rand48 3 , |
@@ -90,15 +104,23 @@ argument, and needs to have been initialized by the caller. | |||
90 | .Sh STANDARDS | 104 | .Sh STANDARDS |
91 | The | 105 | The |
92 | .Fn rand | 106 | .Fn rand |
93 | and | 107 | function conforms to |
94 | .Fn srand | ||
95 | functions conform to | ||
96 | .St -ansiC . | 108 | .St -ansiC . |
97 | .Pp | 109 | .Pp |
98 | The | 110 | The |
99 | .Fn rand_r | 111 | .Fn rand_r |
100 | function conforms to | 112 | function conforms to |
101 | .St -p1003.1-2008 . | 113 | .St -p1003.1-2008 . |
114 | .Pp | ||
115 | The | ||
116 | .Fn srand | ||
117 | function does not conform to | ||
118 | .St -ansiC , | ||
119 | intentionally. | ||
120 | .Pp | ||
121 | The | ||
122 | .Fn srand_deterministic | ||
123 | function is an OpenBSD extension. | ||
102 | .Sh HISTORY | 124 | .Sh HISTORY |
103 | The functions | 125 | The functions |
104 | .Fn rand | 126 | .Fn rand |
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c index 6860dd4f71..618559fd9c 100644 --- a/src/lib/libc/stdlib/rand.c +++ b/src/lib/libc/stdlib/rand.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <sys/types.h> | 30 | #include <sys/types.h> |
31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
32 | 32 | ||
33 | static int rand_deterministic; | ||
33 | static u_int next = 1; | 34 | static u_int next = 1; |
34 | 35 | ||
35 | int | 36 | int |
@@ -47,6 +48,8 @@ __warn_references(rand_r, | |||
47 | int | 48 | int |
48 | rand(void) | 49 | rand(void) |
49 | { | 50 | { |
51 | if (rand_deterministic) | ||
52 | return (arc4random() % ((u_int)RAND_MAX + 1)); | ||
50 | return (rand_r(&next)); | 53 | return (rand_r(&next)); |
51 | } | 54 | } |
52 | 55 | ||
@@ -58,10 +61,12 @@ __warn_references(rand, | |||
58 | void | 61 | void |
59 | srand(u_int seed) | 62 | srand(u_int seed) |
60 | { | 63 | { |
61 | next = seed; | 64 | rand_deterministic = 0; |
62 | } | 65 | } |
63 | 66 | ||
64 | #if defined(APIWARN) | 67 | void |
65 | __warn_references(srand, | 68 | srand_deterministic(u_int seed) |
66 | "warning: srand() seed choices are invariably poor"); | 69 | { |
67 | #endif | 70 | rand_deterministic = 1; |
71 | next = seed; | ||
72 | } | ||
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3 index a4473185de..dce8c0dd18 100644 --- a/src/lib/libc/stdlib/rand48.3 +++ b/src/lib/libc/stdlib/rand48.3 | |||
@@ -9,9 +9,9 @@ | |||
9 | .\" of any kind. I shall in no event be liable for anything that happens | 9 | .\" of any kind. I shall in no event be liable for anything that happens |
10 | .\" to anyone/anything when using this software. | 10 | .\" to anyone/anything when using this software. |
11 | .\" | 11 | .\" |
12 | .\" $OpenBSD: rand48.3,v 1.16 2014/11/25 17:26:34 millert Exp $ | 12 | .\" $OpenBSD: rand48.3,v 1.17 2014/12/08 21:45:20 deraadt Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd $Mdocdate: November 25 2014 $ | 14 | .Dd $Mdocdate: December 8 2014 $ |
15 | .Dt RAND48 3 | 15 | .Dt RAND48 3 |
16 | .Os | 16 | .Os |
17 | .Sh NAME | 17 | .Sh NAME |
@@ -22,8 +22,11 @@ | |||
22 | .Nm mrand48 , | 22 | .Nm mrand48 , |
23 | .Nm jrand48 , | 23 | .Nm jrand48 , |
24 | .Nm srand48 , | 24 | .Nm srand48 , |
25 | .Nm srand48_deterministic , | ||
25 | .Nm seed48 , | 26 | .Nm seed48 , |
27 | .Nm seed48_deterministic , | ||
26 | .Nm lcong48 | 28 | .Nm lcong48 |
29 | .Nm lcong48_deterministic | ||
27 | .Nd pseudo-random number generators and initialization routines | 30 | .Nd pseudo-random number generators and initialization routines |
28 | .Sh SYNOPSIS | 31 | .Sh SYNOPSIS |
29 | .In stdlib.h | 32 | .In stdlib.h |
@@ -41,31 +44,56 @@ | |||
41 | .Fn jrand48 "unsigned short xseed[3]" | 44 | .Fn jrand48 "unsigned short xseed[3]" |
42 | .Ft void | 45 | .Ft void |
43 | .Fn srand48 "long seed" | 46 | .Fn srand48 "long seed" |
47 | .Ft void | ||
48 | .Fn srand48_deterministic "long seed" | ||
44 | .Ft "unsigned short *" | 49 | .Ft "unsigned short *" |
45 | .Fn seed48 "unsigned short xseed[3]" | 50 | .Fn seed48 "unsigned short xseed[3]" |
51 | .Ft "unsigned short *" | ||
52 | .Fn seed48_deterministic "unsigned short xseed[3]" | ||
46 | .Ft void | 53 | .Ft void |
47 | .Fn lcong48 "unsigned short p[7]" | 54 | .Fn lcong48 "unsigned short p[7]" |
55 | .Ft void | ||
56 | .Fn lcong48_deterministic "unsigned short p[7]" | ||
48 | .Sh DESCRIPTION | 57 | .Sh DESCRIPTION |
49 | .Bf -symbolic | 58 | .Bf -symbolic |
50 | This interface is not cryptographically secure, so consider using | 59 | Standards insist that this interface return deterministic results. |
51 | .Xr arc4random 3 | 60 | Unsafe usage is very common, so |
52 | instead. | 61 | .Ox |
62 | changed the subsystem to return non-deterministic results by default. | ||
53 | .Ef | 63 | .Ef |
54 | .Pp | 64 | .Pp |
55 | The | 65 | To satisfy portable code, |
56 | .Fn rand48 | 66 | .Fn srand48 , |
57 | family of functions generates pseudo-random numbers using a linear | 67 | .Fn seed48 , |
58 | congruential algorithm working on integers 48 bits in size. | 68 | or |
59 | The particular formula employed is | 69 | .Fn lcong48 |
60 | r(n+1) = (a * r(n) + c) mod m | 70 | should be called to initialize the subsystem. |
61 | where the default values are | 71 | In |
62 | for the multiplicand a = 0xfdeece66d = 25214903917 and | 72 | .Ox |
63 | the addend c = 0xb = 11. | 73 | the |
64 | The modulus is always fixed at m = 2 ** 48. | 74 | seeding parameters are ignored, and strong random number results will be |
65 | r(n) is called the seed of the random number generator. | 75 | provided from |
76 | .Xr arc4random 3. | ||
77 | In other systems, the | ||
78 | parameters prime a simplistic deterministic algorithm. | ||
66 | .Pp | 79 | .Pp |
67 | For all the six generator routines described next, the first | 80 | If the standardized behavior is required then |
68 | computational step is to perform a single iteration of the algorithm. | 81 | .Fn srand48_deterministic , |
82 | .Fn seed48_deterministic , | ||
83 | and | ||
84 | .Fn lcong48_deterministic | ||
85 | can be substituted for | ||
86 | .Fn srand48 , | ||
87 | .Fn seed48 , | ||
88 | and | ||
89 | .Fn lcong48 . | ||
90 | That will cause subsequent | ||
91 | calls to | ||
92 | .Fn drand48 , | ||
93 | .Fn lrand48 , | ||
94 | and | ||
95 | .Fn jrand48 | ||
96 | to return results using the deterministic algorithm. | ||
69 | .Pp | 97 | .Pp |
70 | .Fn drand48 | 98 | .Fn drand48 |
71 | and | 99 | and |
@@ -91,6 +119,21 @@ return values of type long in the range | |||
91 | [-2**31, 2**31-1]. | 119 | [-2**31, 2**31-1]. |
92 | The high-order (32) bits of r(n+1) are loaded into the returned value. | 120 | The high-order (32) bits of r(n+1) are loaded into the returned value. |
93 | .Pp | 121 | .Pp |
122 | In the deterministic mode, the | ||
123 | .Fn rand48 | ||
124 | family of functions generates numbers using a linear congruential | ||
125 | algorithm working on integers 48 bits in size. | ||
126 | The particular formula employed is | ||
127 | r(n+1) = (a * r(n) + c) mod m | ||
128 | where the default values are | ||
129 | for the multiplicand a = 0xfdeece66d = 25214903917 and | ||
130 | the addend c = 0xb = 11. | ||
131 | The modulus is always fixed at m = 2 ** 48. | ||
132 | r(n) is called the seed of the random number generator. | ||
133 | .Pp | ||
134 | For all the six generator routines described next, the first | ||
135 | computational step is to perform a single iteration of the algorithm. | ||
136 | .Pp | ||
94 | .Fn drand48 , | 137 | .Fn drand48 , |
95 | .Fn lrand48 , | 138 | .Fn lrand48 , |
96 | and | 139 | and |
@@ -110,7 +153,7 @@ holds the least significant bits. | |||
110 | .Pp | 153 | .Pp |
111 | All functions share the same multiplicand and addend. | 154 | All functions share the same multiplicand and addend. |
112 | .Pp | 155 | .Pp |
113 | .Fn srand48 | 156 | .Fn srand48_deterministic |
114 | is used to initialize the internal buffer r(n) of | 157 | is used to initialize the internal buffer r(n) of |
115 | .Fn drand48 , | 158 | .Fn drand48 , |
116 | .Fn lrand48 , | 159 | .Fn lrand48 , |
@@ -121,7 +164,7 @@ of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e. | |||
121 | Additionally, the constant multiplicand and addend of the algorithm are | 164 | Additionally, the constant multiplicand and addend of the algorithm are |
122 | reset to the default values given above. | 165 | reset to the default values given above. |
123 | .Pp | 166 | .Pp |
124 | .Fn seed48 | 167 | .Fn seed48_deterministic |
125 | also initializes the internal buffer r(n) of | 168 | also initializes the internal buffer r(n) of |
126 | .Fn drand48 , | 169 | .Fn drand48 , |
127 | .Fn lrand48 , | 170 | .Fn lrand48 , |
@@ -131,14 +174,14 @@ but here all 48 bits of the seed can be specified in an array of 3 shorts, | |||
131 | where the zeroth member specifies the lowest bits. | 174 | where the zeroth member specifies the lowest bits. |
132 | Again, the constant multiplicand and addend of the algorithm are | 175 | Again, the constant multiplicand and addend of the algorithm are |
133 | reset to the default values given above. | 176 | reset to the default values given above. |
134 | .Fn seed48 | 177 | .Fn seed48_deterministic |
135 | returns a pointer to an array of 3 shorts which contains the old seed. | 178 | returns a pointer to an array of 3 shorts which contains the old seed. |
136 | This array is statically allocated, so its contents are lost after | 179 | This array is statically allocated, so its contents are lost after |
137 | each new call to | 180 | each new call to |
138 | .Fn seed48 . | 181 | .Fn seed48_deterministic . |
139 | .Pp | 182 | .Pp |
140 | Finally, | 183 | Finally, |
141 | .Fn lcong48 | 184 | .Fn lcong48_deterministic |
142 | allows full control over the multiplicand and addend used in | 185 | allows full control over the multiplicand and addend used in |
143 | .Fn drand48 , | 186 | .Fn drand48 , |
144 | .Fn erand48 , | 187 | .Fn erand48 , |
@@ -169,14 +212,27 @@ The | |||
169 | .Fn drand48 , | 212 | .Fn drand48 , |
170 | .Fn erand48 , | 213 | .Fn erand48 , |
171 | .Fn jrand48 , | 214 | .Fn jrand48 , |
172 | .Fn lcong48 , | ||
173 | .Fn lrand48 , | 215 | .Fn lrand48 , |
174 | .Fn mrand48 , | 216 | .Fn mrand48 , |
175 | .Fn nrand48 , | ||
176 | .Fn seed48 , | ||
177 | and | 217 | and |
178 | .Fn srand48 | 218 | .Fn nrand48 , |
179 | functions conform to | 219 | functions conform to |
180 | .St -p1003.1-2008 . | 220 | .St -p1003.1-2008 . |
221 | .Pp | ||
222 | The | ||
223 | .Fn seed48 , | ||
224 | .Fn srand48 , | ||
225 | and | ||
226 | .Fn lcong48 | ||
227 | function do not conform to | ||
228 | .St -ansiC , | ||
229 | intentionally. | ||
230 | .Pp | ||
231 | The | ||
232 | .Fn seed48_deterministic , | ||
233 | .Fn srand48_deterministic , | ||
234 | and | ||
235 | .Fn lcong48_deterministic | ||
236 | functions are OpenBSD extensions. | ||
181 | .Sh AUTHORS | 237 | .Sh AUTHORS |
182 | .An Martin Birgmeier | 238 | .An Martin Birgmeier |
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h index afa49f65f3..ee70174744 100644 --- a/src/lib/libc/stdlib/rand48.h +++ b/src/lib/libc/stdlib/rand48.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * of any kind. I shall in no event be liable for anything that happens | 10 | * of any kind. I shall in no event be liable for anything that happens |
11 | * to anyone/anything when using this software. | 11 | * to anyone/anything when using this software. |
12 | * | 12 | * |
13 | * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $ | 13 | * $OpenBSD: rand48.h,v 1.4 2014/12/08 21:45:20 deraadt Exp $ |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #ifndef _RAND48_H_ | 16 | #ifndef _RAND48_H_ |
@@ -20,6 +20,7 @@ | |||
20 | #include <stdlib.h> | 20 | #include <stdlib.h> |
21 | 21 | ||
22 | void __dorand48(unsigned short[3]); | 22 | void __dorand48(unsigned short[3]); |
23 | extern int __rand48_deterministic; | ||
23 | 24 | ||
24 | #define RAND48_SEED_0 (0x330e) | 25 | #define RAND48_SEED_0 (0x330e) |
25 | #define RAND48_SEED_1 (0xabcd) | 26 | #define RAND48_SEED_1 (0xabcd) |
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3 index b3bc560ad3..ad92b60387 100644 --- a/src/lib/libc/stdlib/random.3 +++ b/src/lib/libc/stdlib/random.3 | |||
@@ -25,14 +25,15 @@ | |||
25 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 25 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | .\" SUCH DAMAGE. | 26 | .\" SUCH DAMAGE. |
27 | .\" | 27 | .\" |
28 | .\" $OpenBSD: random.3,v 1.26 2014/11/25 17:40:38 millert Exp $ | 28 | .\" $OpenBSD: random.3,v 1.27 2014/12/08 21:45:20 deraadt Exp $ |
29 | .\" | 29 | .\" |
30 | .Dd $Mdocdate: November 25 2014 $ | 30 | .Dd $Mdocdate: December 8 2014 $ |
31 | .Dt RANDOM 3 | 31 | .Dt RANDOM 3 |
32 | .Os | 32 | .Os |
33 | .Sh NAME | 33 | .Sh NAME |
34 | .Nm random , | 34 | .Nm random , |
35 | .Nm srandom , | 35 | .Nm srandom , |
36 | .Nm srandom_deterministic , | ||
36 | .Nm srandomdev , | 37 | .Nm srandomdev , |
37 | .Nm initstate , | 38 | .Nm initstate , |
38 | .Nm setstate | 39 | .Nm setstate |
@@ -44,6 +45,8 @@ | |||
44 | .Ft void | 45 | .Ft void |
45 | .Fn srandom "unsigned int seed" | 46 | .Fn srandom "unsigned int seed" |
46 | .Ft void | 47 | .Ft void |
48 | .Fn srandom_deterministic "unsigned int seed" | ||
49 | .Ft void | ||
47 | .Fn srandomdev void | 50 | .Fn srandomdev void |
48 | .Ft char * | 51 | .Ft char * |
49 | .Fn initstate "unsigned int seed" "char *state" "size_t n" | 52 | .Fn initstate "unsigned int seed" "char *state" "size_t n" |
@@ -51,58 +54,48 @@ | |||
51 | .Fn setstate "char *state" | 54 | .Fn setstate "char *state" |
52 | .Sh DESCRIPTION | 55 | .Sh DESCRIPTION |
53 | .Bf -symbolic | 56 | .Bf -symbolic |
54 | This interface is not cryptographically secure, so consider using | 57 | Standards insist that this interface return deterministic results. |
55 | .Xr arc4random 3 | 58 | Unsafe usage is very common, so |
56 | instead. | 59 | .Ox |
60 | changed the subsystem to return non-deterministic results by default. | ||
57 | .Ef | 61 | .Ef |
58 | .Pp | 62 | .Pp |
59 | The | 63 | To satisfy portable code, |
60 | .Fn random | ||
61 | function uses a non-linear additive feedback random number generator employing | ||
62 | a default table of size 31 long integers to return successive pseudo-random | ||
63 | numbers in the range from 0 to (2**31)\-1. | ||
64 | The period of this random number generator is very large, approximately | ||
65 | 16*((2**31)\-1). | ||
66 | .Pp | ||
67 | The | ||
68 | .Fn random | ||
69 | and | ||
70 | .Fn srandom | 64 | .Fn srandom |
71 | functions have (almost) the same calling sequence and initialization | 65 | or |
72 | properties as | 66 | .Fn srandomdev |
73 | .Xr rand 3 Ns / Ns Xr srand 3 . | 67 | may be called to initialize the subsystem. |
74 | The difference is that | 68 | In |
75 | .Xr rand | 69 | .Ox |
76 | produces a much less random sequence \(em in fact, the low dozen bits | 70 | the |
77 | generated by rand go through a cyclic pattern. | 71 | .Ar seed |
78 | All the bits generated by | 72 | variable is ignored, and strong random number results will be provided from |
73 | .Xr arc4random 3. | ||
74 | In other systems, the | ||
75 | .Ar seed | ||
76 | variable primes a simplistic deterministic algorithm. | ||
77 | .Pp | ||
78 | If the standardized behavior is required | ||
79 | .Fn srandom_deterministic | ||
80 | can be substituted for | ||
81 | .Fn srandom , | ||
82 | then subsequent | ||
79 | .Fn random | 83 | .Fn random |
80 | are usable. | 84 | calls will return results using the deterministic algorithm. |
81 | For example, | ||
82 | .Sq Li random()&01 | ||
83 | will produce a random binary | ||
84 | value. | ||
85 | .Pp | 85 | .Pp |
86 | Like | 86 | In non-deterministic (default) mode, the |
87 | .Xr rand 3 , | ||
88 | .Fn random | 87 | .Fn random |
89 | will by default produce a sequence of numbers that can be duplicated | 88 | function returns results from |
90 | by calling | 89 | .Xr arc4random 3 |
91 | .Fn srandom | 90 | in the range from 0 to (2**31)\-1. |
92 | with | ||
93 | .Ql 1 | ||
94 | as the seed. | ||
95 | .Pp | 91 | .Pp |
96 | The | 92 | In deterministic mode, the |
97 | .Fn srandomdev | 93 | .Fn random |
98 | routine switches to an algorithm using state derived from | 94 | function uses a non-linear additive feedback random number generator employing |
99 | random numbers obtained from the kernel. | 95 | a default table of size 31 long integers to return successive pseudo-random |
100 | Note that this particular seeding procedure can generate | 96 | numbers in the range from 0 to (2**31)\-1. |
101 | states which are impossible to reproduce by calling | 97 | The period of this random number generator is very large, approximately |
102 | .Fn srandom | 98 | 16*((2**31)\-1), but the results are a deterministic sequence from the seed. |
103 | with any value, since the succeeding terms in the | ||
104 | state buffer are no longer derived from the LC algorithm applied to | ||
105 | a fixed seed. | ||
106 | .Pp | 99 | .Pp |
107 | The | 100 | The |
108 | .Fn initstate | 101 | .Fn initstate |
@@ -151,9 +144,12 @@ and | |||
151 | is that the size of the state array does not have to be remembered after | 144 | is that the size of the state array does not have to be remembered after |
152 | it is initialized. | 145 | it is initialized. |
153 | .Pp | 146 | .Pp |
154 | With 256 bytes of state information, the period of the random number | 147 | Use of |
155 | generator is greater than 2**69 | 148 | .Fn srandom_deterministic , |
156 | which should be sufficient for most purposes. | 149 | .Fn initstate , |
150 | or | ||
151 | .Fn setstate | ||
152 | forces the subsystem into deterministic mode. | ||
157 | .Sh DIAGNOSTICS | 153 | .Sh DIAGNOSTICS |
158 | If | 154 | If |
159 | .Fn initstate | 155 | .Fn initstate |
@@ -169,7 +165,6 @@ messages are printed on the standard error output. | |||
169 | .Sh STANDARDS | 165 | .Sh STANDARDS |
170 | The | 166 | The |
171 | .Fn random , | 167 | .Fn random , |
172 | .Fn srandom , | ||
173 | .Fn initstate , | 168 | .Fn initstate , |
174 | and | 169 | and |
175 | .Fn setstate | 170 | .Fn setstate |
@@ -177,14 +172,21 @@ functions conform to | |||
177 | .St -xpg4.2 . | 172 | .St -xpg4.2 . |
178 | .Pp | 173 | .Pp |
179 | The | 174 | The |
175 | .Fn srandom | ||
176 | function does not conform to | ||
177 | .St -xpg4.2 , | ||
178 | intentionally. | ||
179 | .Pp | ||
180 | The | ||
180 | .Fn srandomdev | 181 | .Fn srandomdev |
181 | function is an extension. | 182 | function is an extension. |
183 | .Pp | ||
184 | The | ||
185 | .Fn srandom_deterministic | ||
186 | function is an OpenBSD extension. | ||
182 | .Sh HISTORY | 187 | .Sh HISTORY |
183 | These | 188 | These |
184 | functions appeared in | 189 | functions appeared in |
185 | .Bx 4.2 . | 190 | .Bx 4.2 . |
186 | .Sh AUTHORS | 191 | .Sh AUTHORS |
187 | .An Earl T. Cohen | 192 | .An Earl T. Cohen |
188 | .Sh BUGS | ||
189 | The historical implementation used to have very weak seeding. | ||
190 | As a result, the random sequence did not vary much with the seed. | ||
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c index e4ff07ea0c..cba088c751 100644 --- a/src/lib/libc/stdlib/random.c +++ b/src/lib/libc/stdlib/random.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: random.c,v 1.24 2014/10/13 20:54:13 chl Exp $ */ | 1 | /* $OpenBSD: random.c,v 1.25 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1983 Regents of the University of California. | 3 | * Copyright (c) 1983 Regents of the University of California. |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -176,7 +176,7 @@ static int rand_type = TYPE_3; | |||
176 | static int rand_deg = DEG_3; | 176 | static int rand_deg = DEG_3; |
177 | static int rand_sep = SEP_3; | 177 | static int rand_sep = SEP_3; |
178 | 178 | ||
179 | static int use_arc4random; | 179 | static int random_deterministic; |
180 | 180 | ||
181 | _THREAD_PRIVATE_MUTEX(random); | 181 | _THREAD_PRIVATE_MUTEX(random); |
182 | static long random_l(void); | 182 | static long random_l(void); |
@@ -203,7 +203,7 @@ srandom_l(unsigned int x) | |||
203 | int32_t test; | 203 | int32_t test; |
204 | div_t val; | 204 | div_t val; |
205 | 205 | ||
206 | use_arc4random = 0; | 206 | random_deterministic = 1; |
207 | if (rand_type == TYPE_0) | 207 | if (rand_type == TYPE_0) |
208 | state[0] = x; | 208 | state[0] = x; |
209 | else { | 209 | else { |
@@ -231,39 +231,23 @@ srandom_l(unsigned int x) | |||
231 | void | 231 | void |
232 | srandom(unsigned int x) | 232 | srandom(unsigned int x) |
233 | { | 233 | { |
234 | LOCK(); | 234 | random_deterministic = 0; |
235 | srandom_l(x); | ||
236 | UNLOCK(); | ||
237 | } | 235 | } |
238 | 236 | ||
239 | #if defined(APIWARN) | ||
240 | __warn_references(srandom, | ||
241 | "warning: srandom() seed choices are invariably poor"); | ||
242 | #endif | ||
243 | |||
244 | /* | ||
245 | * srandomdev: | ||
246 | * | ||
247 | * Many programs choose the seed value in a totally predictable manner. | ||
248 | * This often causes problems. We seed the generator using random data. | ||
249 | * Note that this particular seeding procedure can generate states | ||
250 | * which are impossible to reproduce by calling srandom() with any | ||
251 | * value, since the succeeding terms in the state buffer are no longer | ||
252 | * derived from the LC algorithm applied to a fixed seed. | ||
253 | */ | ||
254 | void | 237 | void |
255 | srandomdev(void) | 238 | srandomdev(void) |
256 | { | 239 | { |
240 | random_deterministic = 0; /* back to the default */ | ||
241 | } | ||
242 | |||
243 | void | ||
244 | srandom_deterministic(unsigned int x) | ||
245 | { | ||
257 | LOCK(); | 246 | LOCK(); |
258 | use_arc4random = 1; | 247 | srandom_l(x); |
259 | UNLOCK(); | 248 | UNLOCK(); |
260 | } | 249 | } |
261 | 250 | ||
262 | #if defined(APIWARN) | ||
263 | __warn_references(srandomdev, | ||
264 | "warning: srandomdev() usage; consider switching to arc4random()"); | ||
265 | #endif | ||
266 | |||
267 | /* | 251 | /* |
268 | * initstate: | 252 | * initstate: |
269 | * | 253 | * |
@@ -289,7 +273,7 @@ initstate(u_int seed, char *arg_state, size_t n) | |||
289 | char *ostate = (char *)(&state[-1]); | 273 | char *ostate = (char *)(&state[-1]); |
290 | 274 | ||
291 | LOCK(); | 275 | LOCK(); |
292 | use_arc4random = 0; | 276 | random_deterministic = 1; |
293 | if (rand_type == TYPE_0) | 277 | if (rand_type == TYPE_0) |
294 | state[-1] = rand_type; | 278 | state[-1] = rand_type; |
295 | else | 279 | else |
@@ -354,7 +338,7 @@ setstate(char *arg_state) | |||
354 | char *ostate = (char *)(&state[-1]); | 338 | char *ostate = (char *)(&state[-1]); |
355 | 339 | ||
356 | LOCK(); | 340 | LOCK(); |
357 | use_arc4random = 0; | 341 | random_deterministic = 1; |
358 | if (rand_type == TYPE_0) | 342 | if (rand_type == TYPE_0) |
359 | state[-1] = rand_type; | 343 | state[-1] = rand_type; |
360 | else | 344 | else |
@@ -405,7 +389,7 @@ random_l(void) | |||
405 | { | 389 | { |
406 | int32_t i; | 390 | int32_t i; |
407 | 391 | ||
408 | if (use_arc4random) | 392 | if (random_deterministic == 0) |
409 | return arc4random() & 0x7fffffff; | 393 | return arc4random() & 0x7fffffff; |
410 | 394 | ||
411 | if (rand_type == TYPE_0) | 395 | if (rand_type == TYPE_0) |
@@ -431,8 +415,3 @@ random(void) | |||
431 | UNLOCK(); | 415 | UNLOCK(); |
432 | return r; | 416 | return r; |
433 | } | 417 | } |
434 | |||
435 | #if defined(APIWARN) | ||
436 | __warn_references(random, | ||
437 | "warning: random() isn't random; consider using arc4random()"); | ||
438 | #endif | ||
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c index 583262f2d5..7acb4e6d1d 100644 --- a/src/lib/libc/stdlib/seed48.c +++ b/src/lib/libc/stdlib/seed48.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: seed48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */ | 1 | /* $OpenBSD: seed48.c,v 1.4 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1993 Martin Birgmeier | 3 | * Copyright (c) 1993 Martin Birgmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -21,8 +21,19 @@ extern unsigned short __rand48_add; | |||
21 | unsigned short * | 21 | unsigned short * |
22 | seed48(unsigned short xseed[3]) | 22 | seed48(unsigned short xseed[3]) |
23 | { | 23 | { |
24 | unsigned short *res; | ||
25 | |||
26 | res = seed48_deterministic(xseed); | ||
27 | __rand48_deterministic = 0; | ||
28 | return res; | ||
29 | } | ||
30 | |||
31 | unsigned short * | ||
32 | seed48_deterministic(unsigned short xseed[3]) | ||
33 | { | ||
24 | static unsigned short sseed[3]; | 34 | static unsigned short sseed[3]; |
25 | 35 | ||
36 | __rand48_deterministic = 1; | ||
26 | sseed[0] = __rand48_seed[0]; | 37 | sseed[0] = __rand48_seed[0]; |
27 | sseed[1] = __rand48_seed[1]; | 38 | sseed[1] = __rand48_seed[1]; |
28 | sseed[2] = __rand48_seed[2]; | 39 | sseed[2] = __rand48_seed[2]; |
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c index f76b6cca86..115b9e82aa 100644 --- a/src/lib/libc/stdlib/srand48.c +++ b/src/lib/libc/stdlib/srand48.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: srand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */ | 1 | /* $OpenBSD: srand48.c,v 1.4 2014/12/08 21:45:20 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1993 Martin Birgmeier | 3 | * Copyright (c) 1993 Martin Birgmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -18,9 +18,19 @@ extern unsigned short __rand48_seed[3]; | |||
18 | extern unsigned short __rand48_mult[3]; | 18 | extern unsigned short __rand48_mult[3]; |
19 | extern unsigned short __rand48_add; | 19 | extern unsigned short __rand48_add; |
20 | 20 | ||
21 | int __rand48_deterministic; | ||
22 | |||
21 | void | 23 | void |
22 | srand48(long seed) | 24 | srand48(long seed) |
23 | { | 25 | { |
26 | srand48_deterministic(seed); | ||
27 | __rand48_deterministic = 0; | ||
28 | } | ||
29 | |||
30 | void | ||
31 | srand48_deterministic(long seed) | ||
32 | { | ||
33 | __rand48_deterministic = 1; | ||
24 | __rand48_seed[0] = RAND48_SEED_0; | 34 | __rand48_seed[0] = RAND48_SEED_0; |
25 | __rand48_seed[1] = (unsigned short) seed; | 35 | __rand48_seed[1] = (unsigned short) seed; |
26 | __rand48_seed[2] = (unsigned short) (seed >> 16); | 36 | __rand48_seed[2] = (unsigned short) (seed >> 16); |