summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorderaadt <>2014-12-08 21:45:20 +0000
committerderaadt <>2014-12-08 21:45:20 +0000
commit1e2b0be5bee045db1b0abb1f87801004db563bb8 (patch)
treebf17a76201de02c2ce50358a383001a6b6c5cc64
parent4b0b4fc5d98edef87738071b3784e13573327bab (diff)
downloadopenbsd-1e2b0be5bee045db1b0abb1f87801004db563bb8.tar.gz
openbsd-1e2b0be5bee045db1b0abb1f87801004db563bb8.tar.bz2
openbsd-1e2b0be5bee045db1b0abb1f87801004db563bb8.zip
Change rand(), random(), drand48(), lrand48(), mrand48(), and srand48()
to returning strong random by default, source from arc4random(3). Parameters to the seeding functions are ignored, and the subsystems remain in strong random mode. If you wish the standardized deterministic mode, call srand_deterministic(), srandom_determistic(), srand48_deterministic(), seed48_deterministic() or lcong48_deterministic() instead. The re-entrant functions rand_r(), erand48(), nrand48(), jrand48() are unaffected by this change and remain in deterministic mode (for now). Verified as a good roadmap forward by auditing 8800 pieces of software. Roughly 60 pieces of software will need adaptation to request the deterministic mode. Violates POSIX and C89, which violate best practice in this century. ok guenther tedu millert
-rw-r--r--src/lib/libc/stdlib/Makefile.inc10
-rw-r--r--src/lib/libc/stdlib/drand48.c10
-rw-r--r--src/lib/libc/stdlib/lcong48.c10
-rw-r--r--src/lib/libc/stdlib/lrand48.c4
-rw-r--r--src/lib/libc/stdlib/mrand48.c4
-rw-r--r--src/lib/libc/stdlib/rand.376
-rw-r--r--src/lib/libc/stdlib/rand.c15
-rw-r--r--src/lib/libc/stdlib/rand48.3110
-rw-r--r--src/lib/libc/stdlib/rand48.h3
-rw-r--r--src/lib/libc/stdlib/random.3110
-rw-r--r--src/lib/libc/stdlib/random.c49
-rw-r--r--src/lib/libc/stdlib/seed48.c13
-rw-r--r--src/lib/libc/stdlib/srand48.c12
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
43MLINKS+=malloc.3 reallocarray.3 43MLINKS+=malloc.3 reallocarray.3
44MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 44MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
45MLINKS+=radixsort.3 sradixsort.3 45MLINKS+=radixsort.3 sradixsort.3
46MLINKS+=rand.3 srand.3 rand.3 rand_r.3 46MLINKS+=rand.3 srand.3 rand.3 rand_r.3 rand.3 srand_deterministic.3
47MLINKS+=random.3 initstate.3 random.3 setstate.3 47MLINKS+=random.3 initstate.3 random.3 setstate.3
48MLINKS+=random.3 srandom.3 random.3 srandomdev.3 48MLINKS+=random.3 srandom.3 random.3 srandomdev.3 random.3 srandom_deterministic.3
49MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 49MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
50MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3 50MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
51MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3 51MLINKS+=rand48.3 srand48.3 rand48.3 srand48_deterministic.3
52MLINKS+=rand48.3 seed48.3 rand48.3 seed48_deterministic.3
53MLINKS+=rand48.3 lcong48.3 rand48.3 lcong48_deterministic.3
52MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3 54MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3
53MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3 55MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3
54MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3 56MLINKS+=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];
19double 19double
20drand48(void) 20drand48(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;
21void 21void
22lcong48(unsigned short p[7]) 22lcong48(unsigned short p[7])
23{ 23{
24 lcong48_deterministic(p);
25 __rand48_deterministic = 0;
26}
27
28void
29lcong48_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];
19long 19long
20lrand48(void) 20lrand48(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];
19long 19long
20mrand48(void) 20mrand48(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
52These interfaces are obsoleted by 55Standards insist that this interface return deterministic results.
53.Xr random 3 , 56Unsafe usage is very common, so
54which is also unsafe. 57.Ox
55Consider using 58changed the subsystem to return non-deterministic results by default.
56.Xr arc4random 3 .
57.Ef 59.Ef
58.Pp 60.Pp
59The 61To satisfy portable code,
62.Fn srand
63may be called to initialize the subsystem.
64In
65.Ox
66the
67.Ar seed
68variable is ignored, and strong random number results will be provided from
69.Xr arc4random 3.
70In other systems, the
71.Ar seed
72variable primes a simplistic deterministic algorithm.
73.Pp
74If the standardized behavior is required
75.Fn srand_deterministic
76can be substituted for
77.Fn srand ,
78then subsequent
60.Fn rand 79.Fn rand
61function computes a sequence of pseudo-random integers in the range 80calls will return results using the deterministic algorithm.
62of 0 to
63.Dv RAND_MAX
64(as defined by the header file
65.In stdlib.h ) .
66.Pp 81.Pp
67The 82The
68.Fn srand 83.Fn rand
69function sets its argument as the seed for a new sequence of 84function returns a result in the range of 0 to
70pseudo-random numbers to be returned by 85.Dv RAND_MAX .
71.Fn rand . 86By default, this result comes from
72These sequences are repeatable by calling 87.Xr arc4random 3 .
73.Fn srand 88If
74with the same seed value. 89.Fn srand_deterministic
75.Pp 90was called, the result will be computed using the deterministic algorithm.
76If no seed value is provided, the functions are automatically
77seeded with a value of 1.
78.Pp 91.Pp
79The 92The
80.Fn rand_r 93.Fn rand_r
@@ -83,6 +96,7 @@ is a thread-safe version of
83Storage for the seed must be provided through the 96Storage for the seed must be provided through the
84.Fa seed 97.Fa seed
85argument, and needs to have been initialized by the caller. 98argument, and needs to have been initialized by the caller.
99It 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
91The 105The
92.Fn rand 106.Fn rand
93and 107function conforms to
94.Fn srand
95functions conform to
96.St -ansiC . 108.St -ansiC .
97.Pp 109.Pp
98The 110The
99.Fn rand_r 111.Fn rand_r
100function conforms to 112function conforms to
101.St -p1003.1-2008 . 113.St -p1003.1-2008 .
114.Pp
115The
116.Fn srand
117function does not conform to
118.St -ansiC ,
119intentionally.
120.Pp
121The
122.Fn srand_deterministic
123function is an OpenBSD extension.
102.Sh HISTORY 124.Sh HISTORY
103The functions 125The 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
33static int rand_deterministic;
33static u_int next = 1; 34static u_int next = 1;
34 35
35int 36int
@@ -47,6 +48,8 @@ __warn_references(rand_r,
47int 48int
48rand(void) 49rand(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,
58void 61void
59srand(u_int seed) 62srand(u_int seed)
60{ 63{
61 next = seed; 64 rand_deterministic = 0;
62} 65}
63 66
64#if defined(APIWARN) 67void
65__warn_references(srand, 68srand_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
50This interface is not cryptographically secure, so consider using 59Standards insist that this interface return deterministic results.
51.Xr arc4random 3 60Unsafe usage is very common, so
52instead. 61.Ox
62changed the subsystem to return non-deterministic results by default.
53.Ef 63.Ef
54.Pp 64.Pp
55The 65To satisfy portable code,
56.Fn rand48 66.Fn srand48 ,
57family of functions generates pseudo-random numbers using a linear 67.Fn seed48 ,
58congruential algorithm working on integers 48 bits in size. 68or
59The particular formula employed is 69.Fn lcong48
60r(n+1) = (a * r(n) + c) mod m 70should be called to initialize the subsystem.
61where the default values are 71In
62for the multiplicand a = 0xfdeece66d = 25214903917 and 72.Ox
63the addend c = 0xb = 11. 73the
64The modulus is always fixed at m = 2 ** 48. 74seeding parameters are ignored, and strong random number results will be
65r(n) is called the seed of the random number generator. 75provided from
76.Xr arc4random 3.
77In other systems, the
78parameters prime a simplistic deterministic algorithm.
66.Pp 79.Pp
67For all the six generator routines described next, the first 80If the standardized behavior is required then
68computational step is to perform a single iteration of the algorithm. 81.Fn srand48_deterministic ,
82.Fn seed48_deterministic ,
83and
84.Fn lcong48_deterministic
85can be substituted for
86.Fn srand48 ,
87.Fn seed48 ,
88and
89.Fn lcong48 .
90That will cause subsequent
91calls to
92.Fn drand48 ,
93.Fn lrand48 ,
94and
95.Fn jrand48
96to return results using the deterministic algorithm.
69.Pp 97.Pp
70.Fn drand48 98.Fn drand48
71and 99and
@@ -91,6 +119,21 @@ return values of type long in the range
91[-2**31, 2**31-1]. 119[-2**31, 2**31-1].
92The high-order (32) bits of r(n+1) are loaded into the returned value. 120The high-order (32) bits of r(n+1) are loaded into the returned value.
93.Pp 121.Pp
122In the deterministic mode, the
123.Fn rand48
124family of functions generates numbers using a linear congruential
125algorithm working on integers 48 bits in size.
126The particular formula employed is
127r(n+1) = (a * r(n) + c) mod m
128where the default values are
129for the multiplicand a = 0xfdeece66d = 25214903917 and
130the addend c = 0xb = 11.
131The modulus is always fixed at m = 2 ** 48.
132r(n) is called the seed of the random number generator.
133.Pp
134For all the six generator routines described next, the first
135computational step is to perform a single iteration of the algorithm.
136.Pp
94.Fn drand48 , 137.Fn drand48 ,
95.Fn lrand48 , 138.Fn lrand48 ,
96and 139and
@@ -110,7 +153,7 @@ holds the least significant bits.
110.Pp 153.Pp
111All functions share the same multiplicand and addend. 154All functions share the same multiplicand and addend.
112.Pp 155.Pp
113.Fn srand48 156.Fn srand48_deterministic
114is used to initialize the internal buffer r(n) of 157is 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.
121Additionally, the constant multiplicand and addend of the algorithm are 164Additionally, the constant multiplicand and addend of the algorithm are
122reset to the default values given above. 165reset to the default values given above.
123.Pp 166.Pp
124.Fn seed48 167.Fn seed48_deterministic
125also initializes the internal buffer r(n) of 168also 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,
131where the zeroth member specifies the lowest bits. 174where the zeroth member specifies the lowest bits.
132Again, the constant multiplicand and addend of the algorithm are 175Again, the constant multiplicand and addend of the algorithm are
133reset to the default values given above. 176reset to the default values given above.
134.Fn seed48 177.Fn seed48_deterministic
135returns a pointer to an array of 3 shorts which contains the old seed. 178returns a pointer to an array of 3 shorts which contains the old seed.
136This array is statically allocated, so its contents are lost after 179This array is statically allocated, so its contents are lost after
137each new call to 180each new call to
138.Fn seed48 . 181.Fn seed48_deterministic .
139.Pp 182.Pp
140Finally, 183Finally,
141.Fn lcong48 184.Fn lcong48_deterministic
142allows full control over the multiplicand and addend used in 185allows 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 ,
177and 217and
178.Fn srand48 218.Fn nrand48 ,
179functions conform to 219functions conform to
180.St -p1003.1-2008 . 220.St -p1003.1-2008 .
221.Pp
222The
223.Fn seed48 ,
224.Fn srand48 ,
225and
226.Fn lcong48
227function do not conform to
228.St -ansiC ,
229intentionally.
230.Pp
231The
232.Fn seed48_deterministic ,
233.Fn srand48_deterministic ,
234and
235.Fn lcong48_deterministic
236functions 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
22void __dorand48(unsigned short[3]); 22void __dorand48(unsigned short[3]);
23extern 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
54This interface is not cryptographically secure, so consider using 57Standards insist that this interface return deterministic results.
55.Xr arc4random 3 58Unsafe usage is very common, so
56instead. 59.Ox
60changed the subsystem to return non-deterministic results by default.
57.Ef 61.Ef
58.Pp 62.Pp
59The 63To satisfy portable code,
60.Fn random
61function uses a non-linear additive feedback random number generator employing
62a default table of size 31 long integers to return successive pseudo-random
63numbers in the range from 0 to (2**31)\-1.
64The period of this random number generator is very large, approximately
6516*((2**31)\-1).
66.Pp
67The
68.Fn random
69and
70.Fn srandom 64.Fn srandom
71functions have (almost) the same calling sequence and initialization 65or
72properties as 66.Fn srandomdev
73.Xr rand 3 Ns / Ns Xr srand 3 . 67may be called to initialize the subsystem.
74The difference is that 68In
75.Xr rand 69.Ox
76produces a much less random sequence \(em in fact, the low dozen bits 70the
77generated by rand go through a cyclic pattern. 71.Ar seed
78All the bits generated by 72variable is ignored, and strong random number results will be provided from
73.Xr arc4random 3.
74In other systems, the
75.Ar seed
76variable primes a simplistic deterministic algorithm.
77.Pp
78If the standardized behavior is required
79.Fn srandom_deterministic
80can be substituted for
81.Fn srandom ,
82then subsequent
79.Fn random 83.Fn random
80are usable. 84calls will return results using the deterministic algorithm.
81For example,
82.Sq Li random()&01
83will produce a random binary
84value.
85.Pp 85.Pp
86Like 86In non-deterministic (default) mode, the
87.Xr rand 3 ,
88.Fn random 87.Fn random
89will by default produce a sequence of numbers that can be duplicated 88function returns results from
90by calling 89.Xr arc4random 3
91.Fn srandom 90in the range from 0 to (2**31)\-1.
92with
93.Ql 1
94as the seed.
95.Pp 91.Pp
96The 92In deterministic mode, the
97.Fn srandomdev 93.Fn random
98routine switches to an algorithm using state derived from 94function uses a non-linear additive feedback random number generator employing
99random numbers obtained from the kernel. 95a default table of size 31 long integers to return successive pseudo-random
100Note that this particular seeding procedure can generate 96numbers in the range from 0 to (2**31)\-1.
101states which are impossible to reproduce by calling 97The period of this random number generator is very large, approximately
102.Fn srandom 9816*((2**31)\-1), but the results are a deterministic sequence from the seed.
103with any value, since the succeeding terms in the
104state buffer are no longer derived from the LC algorithm applied to
105a fixed seed.
106.Pp 99.Pp
107The 100The
108.Fn initstate 101.Fn initstate
@@ -151,9 +144,12 @@ and
151is that the size of the state array does not have to be remembered after 144is that the size of the state array does not have to be remembered after
152it is initialized. 145it is initialized.
153.Pp 146.Pp
154With 256 bytes of state information, the period of the random number 147Use of
155generator is greater than 2**69 148.Fn srandom_deterministic ,
156which should be sufficient for most purposes. 149.Fn initstate ,
150or
151.Fn setstate
152forces the subsystem into deterministic mode.
157.Sh DIAGNOSTICS 153.Sh DIAGNOSTICS
158If 154If
159.Fn initstate 155.Fn initstate
@@ -169,7 +165,6 @@ messages are printed on the standard error output.
169.Sh STANDARDS 165.Sh STANDARDS
170The 166The
171.Fn random , 167.Fn random ,
172.Fn srandom ,
173.Fn initstate , 168.Fn initstate ,
174and 169and
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
179The 174The
175.Fn srandom
176function does not conform to
177.St -xpg4.2 ,
178intentionally.
179.Pp
180The
180.Fn srandomdev 181.Fn srandomdev
181function is an extension. 182function is an extension.
183.Pp
184The
185.Fn srandom_deterministic
186function is an OpenBSD extension.
182.Sh HISTORY 187.Sh HISTORY
183These 188These
184functions appeared in 189functions 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
189The historical implementation used to have very weak seeding.
190As 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;
176static int rand_deg = DEG_3; 176static int rand_deg = DEG_3;
177static int rand_sep = SEP_3; 177static int rand_sep = SEP_3;
178 178
179static int use_arc4random; 179static int random_deterministic;
180 180
181_THREAD_PRIVATE_MUTEX(random); 181_THREAD_PRIVATE_MUTEX(random);
182static long random_l(void); 182static 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)
231void 231void
232srandom(unsigned int x) 232srandom(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 */
254void 237void
255srandomdev(void) 238srandomdev(void)
256{ 239{
240 random_deterministic = 0; /* back to the default */
241}
242
243void
244srandom_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;
21unsigned short * 21unsigned short *
22seed48(unsigned short xseed[3]) 22seed48(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
31unsigned short *
32seed48_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];
18extern unsigned short __rand48_mult[3]; 18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add; 19extern unsigned short __rand48_add;
20 20
21int __rand48_deterministic;
22
21void 23void
22srand48(long seed) 24srand48(long seed)
23{ 25{
26 srand48_deterministic(seed);
27 __rand48_deterministic = 0;
28}
29
30void
31srand48_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);