1- /* $NetBSD: arc4random.c,v 1.9 2005/12/24 21:11:16 perry Exp $ */
1+ /* $NetBSD: arc4random.c,v 1.10 2011/02/04 22:07:07 christos Exp $ */
22/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */
33
44/*
2727
2828#include <sys/cdefs.h>
2929#if defined(LIBC_SCCS ) && !defined(lint )
30- __RCSID ("$NetBSD: arc4random.c,v 1.9 2005/12/24 21:11:16 perry Exp $" );
30+ __RCSID ("$NetBSD: arc4random.c,v 1.10 2011/02/04 22:07:07 christos Exp $" );
3131#endif /* LIBC_SCCS and not lint */
3232
3333#include "namespace.h"
@@ -44,9 +44,9 @@ __weak_alias(arc4random,_arc4random)
4444#endif
4545
4646struct arc4_stream {
47- u_int8_t i ;
48- u_int8_t j ;
49- u_int8_t s [256 ];
47+ uint8_t i ;
48+ uint8_t j ;
49+ uint8_t s [256 ];
5050};
5151
5252static int rs_initialized ;
@@ -55,12 +55,11 @@ static struct arc4_stream rs;
5555static inline void arc4_init (struct arc4_stream * );
5656static inline void arc4_addrandom (struct arc4_stream * , u_char * , int );
5757static void arc4_stir (struct arc4_stream * );
58- static inline u_int8_t arc4_getbyte (struct arc4_stream * );
59- static inline u_int32_t arc4_getword (struct arc4_stream * );
58+ static inline uint8_t arc4_getbyte (struct arc4_stream * );
59+ static inline uint32_t arc4_getword (struct arc4_stream * );
6060
6161static inline void
62- arc4_init (as )
63- struct arc4_stream * as ;
62+ arc4_init (struct arc4_stream * as )
6463{
6564 int n ;
6665
@@ -71,13 +70,10 @@ arc4_init(as)
7170}
7271
7372static inline void
74- arc4_addrandom (as , dat , datlen )
75- struct arc4_stream * as ;
76- u_char * dat ;
77- int datlen ;
73+ arc4_addrandom (struct arc4_stream * as , u_char * dat , int datlen )
7874{
7975 int n ;
80- u_int8_t si ;
76+ uint8_t si ;
8177
8278 as -> i -- ;
8379 for (n = 0 ; n < 256 ; n ++ ) {
@@ -91,8 +87,7 @@ arc4_addrandom(as, dat, datlen)
9187}
9288
9389static void
94- arc4_stir (as )
95- struct arc4_stream * as ;
90+ arc4_stir (struct arc4_stream * as )
9691{
9792 int fd ;
9893 struct {
@@ -140,11 +135,10 @@ arc4_stir(as)
140135 arc4_getbyte (as );
141136}
142137
143- static inline u_int8_t
144- arc4_getbyte (as )
145- struct arc4_stream * as ;
138+ static inline uint8_t
139+ arc4_getbyte (struct arc4_stream * as )
146140{
147- u_int8_t si , sj ;
141+ uint8_t si , sj ;
148142
149143 as -> i = (as -> i + 1 );
150144 si = as -> s [as -> i ];
@@ -155,11 +149,10 @@ arc4_getbyte(as)
155149 return (as -> s [(si + sj ) & 0xff ]);
156150}
157151
158- static inline u_int32_t
159- arc4_getword (as )
160- struct arc4_stream * as ;
152+ static inline uint32_t
153+ arc4_getword (struct arc4_stream * as )
161154{
162- u_int32_t val ;
155+ uint32_t val ;
163156 val = arc4_getbyte (as ) << 24 ;
164157 val |= arc4_getbyte (as ) << 16 ;
165158 val |= arc4_getbyte (as ) << 8 ;
@@ -168,7 +161,7 @@ arc4_getword(as)
168161}
169162
170163void
171- arc4random_stir ()
164+ arc4random_stir (void )
172165{
173166 if (!rs_initialized ) {
174167 arc4_init (& rs );
@@ -178,23 +171,89 @@ arc4random_stir()
178171}
179172
180173void
181- arc4random_addrandom (dat , datlen )
182- u_char * dat ;
183- int datlen ;
174+ arc4random_addrandom (u_char * dat , int datlen )
184175{
185176 if (!rs_initialized )
186177 arc4random_stir ();
187178 arc4_addrandom (& rs , dat , datlen );
188179}
189180
190- u_int32_t
191- arc4random ()
181+ uint32_t
182+ arc4random (void )
192183{
193184 if (!rs_initialized )
194185 arc4random_stir ();
195186 return arc4_getword (& rs );
196187}
197188
189+ void
190+ arc4random_buf (void * buf , size_t len )
191+ {
192+ uint8_t * bp = buf ;
193+ uint8_t * ep = bp + len ;
194+
195+ bp [0 ] = arc4_getbyte (& rs ) % 3 ;
196+ while (bp [0 ]-- )
197+ (void )arc4_getbyte (& rs );
198+
199+ while (bp < ep )
200+ * bp ++ = arc4_getbyte (& rs );
201+ }
202+
203+ /*-
204+ * Written by Damien Miller.
205+ * With simplifications by Jinmei Tatuya.
206+ */
207+
208+ /*
209+ * Calculate a uniformly distributed random number less than
210+ * upper_bound avoiding "modulo bias".
211+ *
212+ * Uniformity is achieved by generating new random numbers
213+ * until the one returned is outside the range
214+ * [0, 2^32 % upper_bound[. This guarantees the selected
215+ * random number will be inside the range
216+ * [2^32 % upper_bound, 2^32[ which maps back to
217+ * [0, upper_bound[ after reduction modulo upper_bound.
218+ */
219+ uint32_t
220+ arc4random_uniform (uint32_t upper_bound )
221+ {
222+ uint32_t r , min ;
223+
224+ if (upper_bound < 2 )
225+ return 0 ;
226+
227+ #if defined(ULONG_MAX ) && (ULONG_MAX > 0xFFFFFFFFUL )
228+ min = 0x100000000UL % upper_bound ;
229+ #else
230+ /* calculate (2^32 % upper_bound) avoiding 64-bit math */
231+ if (upper_bound > 0x80000000U )
232+ /* 2^32 - upper_bound (only one "value area") */
233+ min = 1 + ~upper_bound ;
234+ else
235+ /* ((2^32 - x) % x) == (2^32 % x) when x <= 2^31 */
236+ min = (0xFFFFFFFFU - upper_bound + 1 ) % upper_bound ;
237+ #endif
238+
239+ /*
240+ * This could theoretically loop forever but each retry has
241+ * p > 0.5 (worst case, usually far better) of selecting a
242+ * number inside the range we need, so it should rarely need
243+ * to re-roll (at all).
244+ */
245+ if (!rs_initialized )
246+ arc4random_stir ();
247+ if (arc4_getbyte (& rs ) & 1 )
248+ (void )arc4_getbyte (& rs );
249+ do
250+ r = arc4_getword (& rs );
251+ while (r < min );
252+
253+ return r % upper_bound ;
254+ }
255+
256+
198257#if 0
199258/*-------- Test code for i386 --------*/
200259#include <stdio.h>
0 commit comments