X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_random.c;h=25ba4db2a81ac94c9172c82c428590288ca7e474;hb=0ea8e006d5f5ef84e31e000607bd24a23f8fc1ed;hp=b56523a4685a3810eb67f4584ccb5cf1449cce1f;hpb=c2d3d24cd9b4f552d7ca8ad6283f9819c1cfefc7;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index b56523a46..25ba4db2a 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -30,16 +30,32 @@ #include /** + * Create a cryptographically weak pseudo-random number in the interval of 0 to 1. + * + * @return number between 0 and 1. + */ +static double +weak_random () +{ + return ((double) RANDOM () / RAND_MAX); +} + + +/** + * Produce a random value. + * + * @param mode desired quality of the random number + * @param i the upper limit (exclusive) for the random number * @return a random value in the interval [0,i[. */ uint32_t -GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, - uint32_t i) +GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; #endif uint32_t ret; + uint32_t ul; GNUNET_assert (i > 0); @@ -50,14 +66,18 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif - gcry_randomize ((unsigned char *) &ret, - sizeof (uint32_t), - GCRY_STRONG_RANDOM); + ul = UINT32_MAX - (UINT32_MAX % i); + do + { + gcry_randomize ((unsigned char *) &ret, + sizeof (uint32_t), GCRY_STRONG_RANDOM); + } + while (ret >= ul); return ret % i; } else { - ret = i * ((double) RANDOM () / RAND_MAX); + ret = i * weak_random (); if (ret >= i) ret = i - 1; return ret; @@ -85,9 +105,9 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) ret = GNUNET_malloc (n * sizeof (unsigned int)); for (i = 0; i < n; i++) ret[i] = i; - for (i = 0; i < n; i++) + for (i = n - 1; i > 0; i--) { - x = GNUNET_CRYPTO_random_u32 (mode, n); + x = GNUNET_CRYPTO_random_u32 (mode, i+1); tmp = ret[x]; ret[x] = ret[i]; ret[i] = tmp; @@ -97,26 +117,35 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) /** * Random on unsigned 64-bit values. + * + * + * @param mode desired quality of the random number + * @param max value returned will be in range [0,max) (exclusive) + * @return random 64-bit number */ uint64_t -GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, - uint64_t u) +GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) { uint64_t ret; + uint64_t ul; - GNUNET_assert (u > 0); + GNUNET_assert (max > 0); if (mode == GNUNET_CRYPTO_QUALITY_STRONG) { - gcry_randomize ((unsigned char *) &ret, - sizeof (uint64_t), - GCRY_STRONG_RANDOM); - return ret % u; + ul = UINT64_MAX - (UINT64_MAX % max); + do + { + gcry_randomize ((unsigned char *) &ret, + sizeof (uint64_t), GCRY_STRONG_RANDOM); + } + while (ret >= ul); + return ret % max; } else { - ret = u * ((double) RANDOM () / RAND_MAX); - if (ret >= u) - ret = u - 1; + ret = max * weak_random (); + if (ret >= max) + ret = max - 1; return ret; } } @@ -135,8 +164,7 @@ GNUNET_CRYPTO_random_disable_entropy_gathering () /** * Initializer */ -void __attribute__ ((constructor)) -GNUNET_util_random_init() +void __attribute__ ((constructor)) GNUNET_util_random_init () { SRANDOM (time (NULL)); }