summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-06-29 18:57:59 -0400
committerNick Mathewson <nickm@torproject.org>2010-06-29 18:57:59 -0400
commit485cab869d292becb62a43b2e33a399ebc671303 (patch)
tree7052a37a6c36d67cb7d48524766103890545e487
parentbea55766af461e4ca78a4919912f3aa9de978bdc (diff)
parentb111a7cd9c5e09bedf57a67f9044a2974222cd11 (diff)
downloadtor-485cab869d292becb62a43b2e33a399ebc671303.tar.gz
tor-485cab869d292becb62a43b2e33a399ebc671303.zip
Merge remote branch 'public/rand_double2'
-rw-r--r--src/common/crypto.c20
-rw-r--r--src/common/crypto.h1
-rw-r--r--src/or/circuitbuild.c6
-rw-r--r--src/test/test_crypto.c4
4 files changed, 29 insertions, 2 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 06b6aa4b51..1d75555b2f 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -2067,6 +2067,26 @@ crypto_rand_uint64(uint64_t max)
}
}
+/** Return a pseudorandom double d, chosen uniformly from the range
+ * 0.0 <= d < 1.0.
+ */
+double
+crypto_rand_double(void)
+{
+ /* We just use an unsigned int here; we don't really care about getting
+ * more than 32 bits of resolution */
+ unsigned int uint;
+ crypto_rand((char*)&uint, sizeof(uint));
+#if SIZEOF_INT == 4
+#define UINT_MAX_AS_DOUBLE 4294967296.0
+#elif SIZEOF_INT == 8
+#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
+#else
+#error SIZEOF_INT is neither 4 nor 8
+#endif
+ return ((double)uint) / UINT_MAX_AS_DOUBLE;
+}
+
/** Generate and return a new random hostname starting with <b>prefix</b>,
* ending with <b>suffix</b>, and containing no less than
* <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 1b004dd4b8..a30e5bcbae 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -210,6 +210,7 @@ int crypto_seed_rng(int startup);
int crypto_rand(char *to, size_t n);
int crypto_rand_int(unsigned int max);
uint64_t crypto_rand_uint64(uint64_t max);
+double crypto_rand_double(void);
char *crypto_random_hostname(int min_rand_len, int max_rand_len,
const char *prefix, const char *suffix);
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 1e51ffbe76..1d654f04c0 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -815,18 +815,20 @@ build_time_t
circuit_build_times_generate_sample(circuit_build_times_t *cbt,
double q_lo, double q_hi)
{
- uint64_t r = crypto_rand_uint64(UINT64_MAX-1);
+ double randval = crypto_rand_double();
build_time_t ret;
double u;
/* Generate between [q_lo, q_hi) */
+ /*XXXX This is what nextafter is supposed to be for; we should use it on the
+ * platforms that support it. */
q_hi -= 1.0/(INT32_MAX);
tor_assert(q_lo >= 0);
tor_assert(q_hi < 1);
tor_assert(q_lo < q_hi);
- u = q_lo + ((q_hi-q_lo)*r)/(1.0*UINT64_MAX);
+ u = q_lo + (q_hi-q_lo)*randval;
tor_assert(0 <= u && u < 1.0);
/* circuit_build_times_calculate_timeout returns <= INT32_MAX */
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 7aca098bc7..b475914b1b 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -57,6 +57,7 @@ test_crypto_rng(void)
{
int i, j, allok;
char data1[100], data2[100];
+ double d;
/* Try out RNG. */
test_assert(! crypto_seed_rng(0));
@@ -76,6 +77,9 @@ test_crypto_rng(void)
big = crypto_rand_uint64(U64_LITERAL(5));
if (big >= 5)
allok = 0;
+ d = crypto_rand_double();
+ test_assert(d >= 0);
+ test_assert(d < 1.0);
host = crypto_random_hostname(3,8,"www.",".onion");
if (strcmpstart(host,"www.") ||
strcmpend(host,".onion") ||