diff --git a/src/common/crypto.c b/src/common/crypto.c index f05be2e8bf..1c4eda90fd 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -2317,6 +2317,25 @@ crypto_rand_int(unsigned int max) } } +/** Return a pseudorandom integer, chosen uniformly from the values between + * min and max inclusive. + * + * min MUST be between 0 and max - 1. + * max MUST be bigger than min and <= to INT_MAX. + */ +int +crypto_rand_int_range(unsigned int min, unsigned int max) +{ + tor_assert(min <= max); + tor_assert(max <= INT_MAX); + + /* The overflow is avoided here because crypto_rand_int() returns a value + * between 0 and (max - min - 1) with max being <= INT_MAX and min <= max. + * This is why we add 1 to the maximum value so we can actually get max as + * a return value. */ + return min + crypto_rand_int(max - min + 1); +} + /** Return a pseudorandom 64-bit integer, chosen uniformly from the values * between 0 and max-1. */ uint64_t @@ -2379,7 +2398,7 @@ crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix, if (min_rand_len > max_rand_len) min_rand_len = max_rand_len; - randlen = min_rand_len + crypto_rand_int(max_rand_len - min_rand_len + 1); + randlen = crypto_rand_int_range(min_rand_len, max_rand_len); prefixlen = strlen(prefix); resultlen = prefixlen + strlen(suffix) + randlen + 16; diff --git a/src/common/crypto.h b/src/common/crypto.h index b9c26a4551..3de3c7ea28 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -254,6 +254,7 @@ int crypto_seed_rng(int startup); MOCK_DECL(int,crypto_rand,(char *to, size_t n)); int crypto_strongest_rand(uint8_t *out, size_t out_len); int crypto_rand_int(unsigned int max); +int crypto_rand_int_range(unsigned int min, unsigned int max); uint64_t crypto_rand_uint64(uint64_t max); double crypto_rand_double(void); struct tor_weak_rng_t; diff --git a/src/common/tortls.c b/src/common/tortls.c index 32106eb2df..7809c1adaa 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -659,7 +659,8 @@ tor_tls_create_certificate(crypto_pk_t *rsa, * than having it start right now. Don't choose quite uniformly, since * then we might pick a time where we're about to expire. Lastly, be * sure to start on a day boundary. */ - start_time = time(NULL) - crypto_rand_int(cert_lifetime) + 2*24*3600; + time_t now = time(NULL); + start_time = crypto_rand_int_range(now - cert_lifetime, now) + 2*24*3600; start_time -= start_time % (24*3600); tor_assert(rsa); diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 9663f34002..9f07d5ad69 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -440,7 +440,8 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, * don't all select them on the same day, and b) avoid leaving a * precise timestamp in the state file about when we first picked * this guard. For details, see the Jan 2010 or-dev thread. */ - entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); + time_t now = time(NULL); + entry->chosen_on_date = crypto_rand_int_range(now - 3600*24*30, now); entry->chosen_by_version = tor_strdup(VERSION); /* Are we picking this guard because all of our current guards are @@ -1439,8 +1440,9 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg) } } else { if (state_version) { + time_t now = time(NULL); + e->chosen_on_date = crypto_rand_int_range(now - 3600*24*30, now); e->chosen_by_version = tor_strdup(state_version); - e->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); } } if (e->path_bias_disabled && !e->bad_since) diff --git a/src/or/main.c b/src/or/main.c index 39c0f5c89e..b9009db151 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1623,7 +1623,7 @@ run_scheduled_events(time_t now) time_to.check_for_correct_dns < now && ! router_my_exit_policy_is_reject_star()) { if (!time_to.check_for_correct_dns) { - time_to.check_for_correct_dns = now + 60 + crypto_rand_int(120); + time_to.check_for_correct_dns = crypto_rand_int_range(now, now + 120) + 60; } else { dns_launch_correctness_checks(); time_to.check_for_correct_dns = now + 12*3600 + diff --git a/src/or/rendservice.c b/src/or/rendservice.c index cf0352cd3e..4b2331ffca 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -3133,9 +3133,8 @@ intro_point_should_expire_now(rend_intro_point_t *intro, /* This intro point has been published, but we haven't picked an * expiration time for it. Pick one now. */ int intro_point_lifetime_seconds = - INTRO_POINT_LIFETIME_MIN_SECONDS + - crypto_rand_int(INTRO_POINT_LIFETIME_MAX_SECONDS - - INTRO_POINT_LIFETIME_MIN_SECONDS); + crypto_rand_int_range(INTRO_POINT_LIFETIME_MIN_SECONDS, + INTRO_POINT_LIFETIME_MAX_SECONDS); /* Start the expiration timer now, rather than when the intro * point was first published. There shouldn't be much of a time @@ -3337,9 +3336,8 @@ rend_services_introduce(void) intro->time_to_expire = -1; intro->time_expiring = -1; intro->max_introductions = - INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS + - crypto_rand_int(INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS - - INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); + crypto_rand_int_range(INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS, + INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS); smartlist_add(service->intro_nodes, intro); log_info(LD_REND, "Picked router %s as an intro point for %s.", safe_str_client(node_describe(node)), diff --git a/src/or/router.c b/src/or/router.c index b8bfd3cf6f..afe533ff9a 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -683,7 +683,9 @@ router_initialize_tls_context(void) if (!lifetime) { /* we should guess a good ssl cert lifetime */ /* choose between 5 and 365 days, and round to the day */ - lifetime = 5*24*3600 + crypto_rand_int(361*24*3600); + unsigned int five_days = 5*24*3600; + unsigned int one_year = 365*24*3600; + lifetime = crypto_rand_int_range(five_days, one_year); lifetime -= lifetime % (24*3600); if (crypto_rand_int(2)) {