diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/compat.c | 24 | ||||
-rw-r--r-- | src/common/compat.h | 5 | ||||
-rw-r--r-- | src/common/crypto.c | 8 | ||||
-rw-r--r-- | src/common/crypto.h | 2 | ||||
-rw-r--r-- | src/common/util.c | 42 | ||||
-rw-r--r-- | src/common/util.h | 14 |
6 files changed, 62 insertions, 33 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index 3b15f8ad24..d7ce89479a 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -2059,30 +2059,6 @@ tor_lookup_hostname(const char *name, uint32_t *addr) return -1; } -/** Initialize the insecure libc RNG. */ -void -tor_init_weak_random(unsigned seed) -{ -#ifdef _WIN32 - srand(seed); -#else - srandom(seed); -#endif -} - -/** Return a randomly chosen value in the range 0..TOR_RAND_MAX. This - * entropy will not be cryptographically strong; do not rely on it - * for anything an adversary should not be able to predict. */ -long -tor_weak_random(void) -{ -#ifdef _WIN32 - return rand(); -#else - return random(); -#endif -} - /** Hold the result of our call to <b>uname</b>. */ static char uname_result[256]; /** True iff uname_result is set. */ diff --git a/src/common/compat.h b/src/common/compat.h index fa071e5558..f9eb4ba0be 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -581,11 +581,6 @@ typedef enum { SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08, } socks5_reply_status_t; -/* ===== Insecure rng */ -void tor_init_weak_random(unsigned seed); -long tor_weak_random(void); -#define TOR_RAND_MAX (RAND_MAX) - /* ===== OS compatibility */ const char *get_uname(void); diff --git a/src/common/crypto.c b/src/common/crypto.c index 70bd45299f..22d57c7c8a 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -2337,12 +2337,12 @@ crypto_dh_free(crypto_dh_t *dh) (OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,8,'c')) /** Set the seed of the weak RNG to a random value. */ -static void -seed_weak_rng(void) +void +crypto_seed_weak_rng(tor_weak_rng_t *rng) { unsigned seed; crypto_rand((void*)&seed, sizeof(seed)); - tor_init_weak_random(seed); + tor_init_weak_random(rng, seed); } /** Try to get <b>out_len</b> bytes of the strongest entropy we can generate, @@ -2426,7 +2426,7 @@ crypto_seed_rng(int startup) } memwipe(buf, 0, sizeof(buf)); - seed_weak_rng(); + if (rand_poll_ok || load_entropy_ok) return 0; else diff --git a/src/common/crypto.h b/src/common/crypto.h index 08efc801d3..12fcfae27e 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -256,6 +256,8 @@ int crypto_strongest_rand(uint8_t *out, size_t out_len); int crypto_rand_int(unsigned int max); uint64_t crypto_rand_uint64(uint64_t max); double crypto_rand_double(void); +struct tor_weak_rng_t; +void crypto_seed_weak_rng(struct tor_weak_rng_t *rng); char *crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix, const char *suffix); diff --git a/src/common/util.c b/src/common/util.c index 93e2ba8e14..49353a8ee1 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -4996,3 +4996,45 @@ tor_check_port_forwarding(const char *filename, } } +/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */ +void +tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed) +{ + rng->state = (uint32_t)(seed & 0x7fffffff); +} + +/** Return a randomly chosen value in the range 0..TOR_WEAK_RANDOM_MAX based + * on the RNG state of <b>rng</b>. This entropy will not be cryptographically + * strong; do not rely on it for anything an adversary should not be able to + * predict. */ +int32_t +tor_weak_random(tor_weak_rng_t *rng) +{ + /* Here's a linear congruential generator. OpenBSD and glibc use these + * parameters; they aren't too bad, and should have maximal period over the + * range 0..INT32_MAX. We don't want to use the platform rand() or random(), + * since some platforms have bad weak RNGs that only return values in the + * range 0..INT16_MAX, which just isn't enough. */ + rng->state = (rng->state * 1103515245 + 12345) & 0x7fffffff; + return (int32_t) rng->state; +} + +/** Return a random number in the range [0 , <b>top</b>). {That is, the range + * of integers i such that 0 <= i < top.} Chooses uniformly. Requires that + * top is greater than 0. This randomness is not cryptographically strong; do + * not rely on it for anything an adversary should not be able to predict. */ +int32_t +tor_weak_random_range(tor_weak_rng_t *rng, int32_t top) +{ + /* We don't want to just do tor_weak_random() % top, since random() is often + * implemented with an LCG whose modulus is a power of 2, and those are + * cyclic in their low-order bits. */ + int divisor, result; + tor_assert(top > 0); + divisor = TOR_WEAK_RANDOM_MAX / top; + do { + result = (int32_t)(tor_weak_random(rng) / divisor); + } while (result >= top); + return result; +} + diff --git a/src/common/util.h b/src/common/util.h index 911b1b5a37..ac88f1ca1c 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -494,6 +494,20 @@ int tor_terminate_process(process_handle_t *process_handle); void tor_process_handle_destroy(process_handle_t *process_handle, int also_terminate_process); +/* ===== Insecure rng */ +typedef struct tor_weak_rng_t { + uint32_t state; +} tor_weak_rng_t; + +#define TOR_WEAK_RNG_INIT {383745623} +#define TOR_WEAK_RANDOM_MAX (INT_MAX) +void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed); +int32_t tor_weak_random(tor_weak_rng_t *weak_rng); +int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top); +/** Randomly return true according to <b>rng</b> with probability 1 in + * <b>n</b> */ +#define tor_weak_random_one_in_n(rng, n) (0==tor_weak_random_range((rng),(n))) + #ifdef UTIL_PRIVATE /* Prototypes for private functions only used by util.c (and unit tests) */ |