@ -1,7 +1,8 @@
/* $OpenBSD: arc4random.c,v 1.17 2008/01/01 00:43:39 kurt Exp $ */
/* $OpenBSD: arc4random.c,v 1.18 2008/03/16 19:47:43 otto Exp $ */
/*
/*
* Copyright ( c ) 1996 , David Mazieres < dm @ uun . org >
* Copyright ( c ) 1996 , David Mazieres < dm @ uun . org >
* Copyright ( c ) 2008 , Damien Miller < djm @ openbsd . org >
*
*
* Permission to use , copy , modify , and distribute this software for any
* Permission to use , copy , modify , and distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* purpose with or without fee is hereby granted , provided that the above
@ -34,6 +35,7 @@
*/
*/
# include <fcntl.h>
# include <fcntl.h>
# include <limits.h>
# include <stdlib.h>
# include <stdlib.h>
# include <unistd.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/types.h>
@ -188,6 +190,66 @@ arc4random(void)
return val ;
return val ;
}
}
void
arc4random_buf ( void * _buf , size_t n )
{
u_char * buf = ( u_char * ) _buf ;
_ARC4_LOCK ( ) ;
if ( ! rs_initialized | | arc4_stir_pid ! = getpid ( ) )
arc4_stir ( ) ;
while ( n - - ) {
if ( - - arc4_count < = 0 )
arc4_stir ( ) ;
buf [ n ] = arc4_getbyte ( ) ;
}
_ARC4_UNLOCK ( ) ;
}
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding " modulo bias " .
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [ 0 , 2 * * 32 % upper_bound ) . This
* guarantees the selected random number will be inside
* [ 2 * * 32 % upper_bound , 2 * * 32 ) which maps back to [ 0 , upper_bound )
* after reduction modulo upper_bound .
*/
u_int32_t
arc4random_uniform ( u_int32_t upper_bound )
{
u_int32_t r , min ;
if ( upper_bound < 2 )
return 0 ;
# if (ULONG_MAX > 0xffffffffUL)
min = 0x100000000UL % upper_bound ;
# else
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
if ( upper_bound > 0x80000000 )
min = 1 + ~ upper_bound ; /* 2**32 - upper_bound */
else {
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
min = ( ( 0xffffffff - ( upper_bound < < 2 ) ) + 1 ) % upper_bound ;
}
# endif
/*
* This could theoretically loop forever but each retry has
* p > 0.5 ( worst case , usually far better ) of selecting a
* number inside the range we need , so it should rarely need
* to re - roll .
*/
for ( ; ; ) {
r = arc4random ( ) ;
if ( r > = min )
break ;
}
return r % upper_bound ;
}
#if 0
#if 0
/*-------- Test code for i386 --------*/
/*-------- Test code for i386 --------*/
# include <stdio.h>
# include <stdio.h>