X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_random.c;h=25ba4db2a81ac94c9172c82c428590288ca7e474;hb=0ea8e006d5f5ef84e31e000607bd24a23f8fc1ed;hp=3f7ac4dd386c64d7e32af3e83736dac6c8f2f36c;hpb=0a217a8df1657b4334b55b0e4a6c7837a8dbcfd9;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index 3f7ac4dd3..25ba4db2a 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -30,15 +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[. */ -unsigned int -GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, unsigned int i) +uint32_t +GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; #endif - unsigned int ret; + uint32_t ret; + uint32_t ul; GNUNET_assert (i > 0); @@ -49,16 +66,18 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, unsigned int i) if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif - ret = rand (); /* in case gcry_randomize fails, - we at least get a pseudo- - random number this way */ - gcry_randomize ((unsigned char *) &ret, - sizeof (unsigned int), 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; @@ -80,15 +99,15 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) unsigned int *ret; unsigned int i; unsigned int tmp; - unsigned int x; + uint32_t x; GNUNET_assert (n > 0); - ret = GNUNET_malloc (n * sizeof (int)); + 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; @@ -98,25 +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 */ -unsigned long long -GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, - unsigned long long u) +uint64_t +GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) { - unsigned long long ret; + 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 (unsigned long long), 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; } } @@ -132,5 +161,12 @@ GNUNET_CRYPTO_random_disable_entropy_gathering () gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); } +/** + * Initializer + */ +void __attribute__ ((constructor)) GNUNET_util_random_init () +{ + SRANDOM (time (NULL)); +} /* end of crypto_random.c */