1- /* $NetBSD: arc4random.c,v 1.15 2012/08/18 14:42:46 dsl Exp $ */
1+ /* $NetBSD: arc4random.c,v 1.16 2012/08/18 15:04:53 dsl 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.15 2012/08/18 14:42:46 dsl Exp $" );
30+ __RCSID ("$NetBSD: arc4random.c,v 1.16 2012/08/18 15:04:53 dsl Exp $" );
3131#endif /* LIBC_SCCS and not lint */
3232
3333#include "namespace.h"
@@ -53,6 +53,21 @@ struct arc4_stream {
5353 uint8_t s [RSIZE ];
5454};
5555
56+ #ifdef _REENTRANT
57+ #define LOCK (rs ) { \
58+ int isthreaded = __isthreaded; \
59+ if (isthreaded) \
60+ mutex_lock(&(rs)->mtx);
61+ #define UNLOCK (rs ) \
62+ if (isthreaded) \
63+ mutex_unlock(&(rs)->mtx); \
64+ }
65+ #else
66+ #define LOCK (rs )
67+ #define UNLOCK(rs)
68+ #endif
69+
70+
5671/* XXX lint explodes with an internal error if only mtx is initialized! */
5772static struct arc4_stream rs = { .i = 0 , .mtx = MUTEX_INITIALIZER };
5873
@@ -160,99 +175,53 @@ arc4_getword(struct arc4_stream *as)
160175 return val ;
161176}
162177
163- static inline void
164- _arc4random_stir_unlocked (void )
165- {
166- if (__predict_false (!arc4_check_init (& rs ))) /* init() stirs */
167- arc4_stir (& rs );
168- }
169-
170178void
171179arc4random_stir (void )
172180{
173- #ifdef _REENTRANT
174- if (__isthreaded ) {
175- mutex_lock (& rs .mtx );
176- _arc4random_stir_unlocked ();
177- mutex_unlock (& rs .mtx );
178- return ;
179- }
180- #endif
181- _arc4random_stir_unlocked ();
182- }
183-
184- static inline void
185- _arc4random_addrandom_unlocked (u_char * dat , int datlen )
186- {
187- arc4_check_init (& rs );
188- arc4_addrandom (& rs , dat , datlen );
181+ LOCK (& rs );
182+ if (__predict_false (!arc4_check_init (& rs ))) /* init() stirs */
183+ arc4_stir (& rs );
184+ UNLOCK (& rs );
189185}
190186
191187void
192188arc4random_addrandom (u_char * dat , int datlen )
193189{
194- #ifdef _REENTRANT
195- if (__isthreaded ) {
196- mutex_lock (& rs .mtx );
197- _arc4random_addrandom_unlocked (dat , datlen );
198- mutex_unlock (& rs .mtx );
199- return ;
200- }
201- #endif
202- _arc4random_addrandom_unlocked (dat , datlen );
203- }
204-
205- static inline uint32_t
206- _arc4random_unlocked (void )
207- {
190+ LOCK (& rs );
208191 arc4_check_init (& rs );
209- return arc4_getword (& rs );
192+ arc4_addrandom (& rs , dat , datlen );
193+ UNLOCK (& rs );
210194}
211195
212196uint32_t
213197arc4random (void )
214198{
215199 uint32_t v ;
216- #ifdef _REENTRANT
217- if (__isthreaded ) {
218- mutex_lock (& rs .mtx );
219- v = _arc4random_unlocked ();
220- mutex_unlock (& rs .mtx );
221- return v ;
222- }
223- #endif
224- v = _arc4random_unlocked ();
200+
201+ LOCK (& rs );
202+ arc4_check_init (& rs );
203+ v = arc4_getword (& rs );
204+ UNLOCK (& rs );
225205 return v ;
226206}
227207
228- static void
229- _arc4random_buf_unlocked (void * buf , size_t len )
208+ void
209+ arc4random_buf (void * buf , size_t len )
230210{
231211 uint8_t * bp = buf ;
232212 uint8_t * ep = bp + len ;
213+ int skip ;
233214
215+ LOCK (& rs );
234216 arc4_check_init (& rs );
235217
236- bp [ 0 ] = arc4_getbyte (& rs ) % 3 ;
237- while (bp [ 0 ] -- )
218+ skip = arc4_getbyte (& rs ) % 3 ;
219+ while (skip -- )
238220 (void )arc4_getbyte (& rs );
239221
240222 while (bp < ep )
241223 * bp ++ = arc4_getbyte (& rs );
242- }
243-
244- void
245- arc4random_buf (void * buf , size_t len )
246- {
247- #ifdef _REENTRANT
248- if (__isthreaded ) {
249- mutex_lock (& rs .mtx );
250- _arc4random_buf_unlocked (buf , len );
251- mutex_unlock (& rs .mtx );
252- return ;
253- } else
254- #endif
255- _arc4random_buf_unlocked (buf , len );
224+ UNLOCK (& rs );
256225}
257226
258227/*-
@@ -271,54 +240,34 @@ arc4random_buf(void *buf, size_t len)
271240 * [2^32 % upper_bound, 2^32[ which maps back to
272241 * [0, upper_bound[ after reduction modulo upper_bound.
273242 */
274- static uint32_t
275- _arc4random_uniform_unlocked (uint32_t upper_bound )
243+ uint32_t
244+ arc4random_uniform (uint32_t upper_bound )
276245{
277246 uint32_t r , min ;
278247
279248 if (upper_bound < 2 )
280249 return 0 ;
281250
282- #if defined(ULONG_MAX ) && (ULONG_MAX > 0xFFFFFFFFUL )
283- min = (uint32_t )(0x100000000U % upper_bound );
284- #else
285251 /* calculate (2^32 % upper_bound) avoiding 64-bit math */
286- if (upper_bound > 0x80000000U )
287- /* 2^32 - upper_bound (only one "value area") */
288- min = 1 + ~upper_bound ;
289- else
290- /* ((2^32 - x) % x) == (2^32 % x) when x <= 2^31 */
291- min = (0xFFFFFFFFU - upper_bound + 1 ) % upper_bound ;
292- #endif
252+ /* ((2^32 - x) % x) == (2^32 % x) when x <= 2^31 */
253+ min = (0xFFFFFFFFU - upper_bound + 1 ) % upper_bound ;
254+
255+ LOCK (& rs );
256+ arc4_check_init (& rs );
257+
258+ if (arc4_getbyte (& rs ) & 1 )
259+ (void )arc4_getbyte (& rs );
293260
294261 /*
295262 * This could theoretically loop forever but each retry has
296263 * p > 0.5 (worst case, usually far better) of selecting a
297264 * number inside the range we need, so it should rarely need
298265 * to re-roll (at all).
299266 */
300- arc4_check_init (& rs );
301- if (arc4_getbyte (& rs ) & 1 )
302- (void )arc4_getbyte (& rs );
303267 do
304268 r = arc4_getword (& rs );
305269 while (r < min );
270+ UNLOCK (& rs );
306271
307272 return r % upper_bound ;
308273}
309-
310- uint32_t
311- arc4random_uniform (uint32_t upper_bound )
312- {
313- uint32_t v ;
314- #ifdef _REENTRANT
315- if (__isthreaded ) {
316- mutex_lock (& rs .mtx );
317- v = _arc4random_uniform_unlocked (upper_bound );
318- mutex_unlock (& rs .mtx );
319- return v ;
320- }
321- #endif
322- v = _arc4random_uniform_unlocked (upper_bound );
323- return v ;
324- }
0 commit comments