static int halfstream_insert(origin_circuit_t *circ, edge_connection_t *edgeconn, streamid_t *streams, int num, int random) { int inserted = 0; /* Insert num random elements */ while (inserted < num) { streamid_t id; if (random) id = (streamid_t)crypto_rand_int(65535)+1; else id = get_unique_stream_id_by_circ(circ); edgeconn->stream_id = id; /* Ensure it isn't there */ if (connection_half_edge_find_stream_id(circ->half_streams, id)) { continue; } connection_half_edge_add(edgeconn, circ); if (streams) streams[inserted] = id; inserted++; } return inserted; }
/** * Shuffle the build times array. * * Adapted from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle */ static void circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, build_time_t *raw_times, uint32_t num_times) { uint32_t n = num_times; if (num_times > CBT_NCIRCUITS_TO_OBSERVE) { log_notice(LD_CIRC, "The number of circuit times that this Tor version " "uses to calculate build times is less than the number stored " "in your state file. Decreasing the circuit time history from " "%lu to %d.", (unsigned long)num_times, CBT_NCIRCUITS_TO_OBSERVE); } if (n > INT_MAX-1) { log_warn(LD_CIRC, "For some insane reasons, you had %lu circuit build " "observations in your state file. That's far too many; probably " "there's a bug here.", (unsigned long)n); n = INT_MAX-1; } /* This code can only be run on a compact array */ while (n-- > 1) { int k = crypto_rand_int(n + 1); /* 0 <= k <= n. */ build_time_t tmp = raw_times[k]; raw_times[k] = raw_times[n]; raw_times[n] = tmp; } /* Since the times are now shuffled, take a random CBT_NCIRCUITS_TO_OBSERVE * subset (ie the first CBT_NCIRCUITS_TO_OBSERVE values) */ for (n = 0; n < MIN(num_times, CBT_NCIRCUITS_TO_OBSERVE); n++) { circuit_build_times_add_time(cbt, raw_times[n]); } }
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b> * and <b>p_conn</b>. Add it to the global circuit list. */ origin_circuit_t * origin_circuit_new(void) { origin_circuit_t *circ; /* never zero, since a global ID of 0 is treated specially by the * controller */ static uint32_t n_circuits_allocated = 1; circ = tor_malloc_zero(sizeof(origin_circuit_t)); circ->_base.magic = ORIGIN_CIRCUIT_MAGIC; circ->next_stream_id = crypto_rand_int(1<<16); circ->global_identifier = n_circuits_allocated++; circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT; circ->remaining_relay_early_cells -= crypto_rand_int(2); init_circuit_base(TO_CIRCUIT(circ)); return circ; }
/** Run unit tests for our random number generation function and its wrappers. */ static void test_crypto_rng(void *arg) { int i, j, allok; char data1[100], data2[100]; double d; char *h=NULL; /* Try out RNG. */ (void)arg; tt_assert(! crypto_seed_rng()); crypto_rand(data1, 100); crypto_rand(data2, 100); tt_mem_op(data1,OP_NE, data2,100); allok = 1; for (i = 0; i < 100; ++i) { uint64_t big; char *host; j = crypto_rand_int(100); if (j < 0 || j >= 100) allok = 0; big = crypto_rand_uint64(UINT64_C(1)<<40); if (big >= (UINT64_C(1)<<40)) allok = 0; big = crypto_rand_uint64(UINT64_C(5)); if (big >= 5) allok = 0; d = crypto_rand_double(); tt_assert(d >= 0); tt_assert(d < 1.0); host = crypto_random_hostname(3,8,"www.",".onion"); if (strcmpstart(host,"www.") || strcmpend(host,".onion") || strlen(host) < 13 || strlen(host) > 18) allok = 0; tor_free(host); } /* Make sure crypto_random_hostname clips its inputs properly. */ h = crypto_random_hostname(20000, 9000, "www.", ".onion"); tt_assert(! strcmpstart(h,"www.")); tt_assert(! strcmpend(h,".onion")); tt_int_op(63+4+6, OP_EQ, strlen(h)); tt_assert(allok); done: tor_free(h); }
/** Run unit tests for our random number generation function and its wrappers. */ static void test_crypto_rng(void) { int i, j, allok; char data1[100], data2[100]; double d; /* Try out RNG. */ test_assert(! crypto_seed_rng(0)); crypto_rand(data1, 100); crypto_rand(data2, 100); test_memneq(data1,data2,100); allok = 1; for (i = 0; i < 100; ++i) { uint64_t big; char *host; j = crypto_rand_int(100); if (j < 0 || j >= 100) allok = 0; big = crypto_rand_uint64(U64_LITERAL(1)<<40); if (big >= (U64_LITERAL(1)<<40)) allok = 0; 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") || strlen(host) < 13 || strlen(host) > 18) allok = 0; tor_free(host); } test_assert(allok); done: ; }