X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_random.c;h=25ba4db2a81ac94c9172c82c428590288ca7e474;hb=0ea8e006d5f5ef84e31e000607bd24a23f8fc1ed;hp=50af9f2519a366fb48f5882d9587966d16f9dfd9;hpb=fe947a9704bed14c2fc74b2f2069596fe884cbad;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index 50af9f251..25ba4db2a 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -29,6 +29,18 @@ #include "gnunet_crypto_lib.h" #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. * @@ -37,13 +49,13 @@ * @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); @@ -54,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; @@ -89,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; @@ -108,22 +124,26 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) * @return random 64-bit number */ uint64_t -GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, - uint64_t max) +GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) { uint64_t ret; + uint64_t ul; GNUNET_assert (max > 0); if (mode == GNUNET_CRYPTO_QUALITY_STRONG) { - gcry_randomize ((unsigned char *) &ret, - sizeof (uint64_t), - GCRY_STRONG_RANDOM); + 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 = max * ((double) RANDOM () / RAND_MAX); + ret = max * weak_random (); if (ret >= max) ret = max - 1; return ret; @@ -144,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)); }