static void bench_cell_ops(void) { const int iters = 1<<16; int i; /* benchmarks for cell ops at relay. */ or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t)); cell_t *cell = tor_malloc(sizeof(cell_t)); int outbound; uint64_t start, end; crypto_rand((char*)cell->payload, sizeof(cell->payload)); /* Mock-up or_circuit_t */ or_circ->base_.magic = OR_CIRCUIT_MAGIC; or_circ->base_.purpose = CIRCUIT_PURPOSE_OR; /* Initialize crypto */ char key1[CIPHER_KEY_LEN], key2[CIPHER_KEY_LEN]; crypto_rand(key1, sizeof(key1)); crypto_rand(key2, sizeof(key2)); or_circ->p_crypto = crypto_cipher_new(key1); or_circ->n_crypto = crypto_cipher_new(key2); or_circ->p_digest = crypto_digest_new(); or_circ->n_digest = crypto_digest_new(); reset_perftime(); for (outbound = 0; outbound <= 1; ++outbound) { cell_direction_t d = outbound ? CELL_DIRECTION_OUT : CELL_DIRECTION_IN; start = perftime(); for (i = 0; i < iters; ++i) { char recognized = 0; crypt_path_t *layer_hint = NULL; relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized); } end = perftime(); printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n", outbound?"Out":" In", NANOCOUNT(start,end,iters), NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE)); } crypto_digest_free(or_circ->p_digest); crypto_digest_free(or_circ->n_digest); crypto_cipher_free(or_circ->p_crypto); crypto_cipher_free(or_circ->n_crypto); tor_free(or_circ); tor_free(cell); }
/** 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); }
/** Implement the server side of the CREATE_FAST abbreviated handshake. The * client has provided DIGEST_LEN key bytes in <b>key_in</b> ("x"). We * generate a reply of DIGEST_LEN*2 bytes in <b>key_out</b>, consisting of a * new random "y", followed by H(x|y) to check for correctness. We set * <b>key_out_len</b> bytes of key material in <b>key_out</b>. * Return 0 on success, <0 on failure. **/ int fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */ uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */ uint8_t *key_out, size_t key_out_len) { uint8_t tmp[DIGEST_LEN+DIGEST_LEN]; uint8_t *out = NULL; size_t out_len; int r = -1; crypto_rand((char*)handshake_reply_out, DIGEST_LEN); memcpy(tmp, key_in, DIGEST_LEN); memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN); out_len = key_out_len+DIGEST_LEN; out = tor_malloc(out_len); if (BUG(crypto_expand_key_material_TAP(tmp, sizeof(tmp), out, out_len))) { goto done; // LCOV_EXCL_LINE } memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN); memcpy(key_out, out+DIGEST_LEN, key_out_len); r = 0; done: memwipe(tmp, 0, sizeof(tmp)); memwipe(out, 0, out_len); tor_free(out); return r; }
/* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to * <b>intro_circ</b>. Return the public key advertised in the cell. */ static crypto_pk_t * helper_establish_intro_v2(or_circuit_t *intro_circ) { crypto_pk_t *key1 = NULL; int retval; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; char circ_nonce[DIGEST_LEN] = {0}; tt_assert(intro_circ); /* Prepare the circuit for the incoming ESTABLISH_INTRO */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Send legacy establish_intro */ key1 = pk_generate(0); /* Use old circ_nonce why not */ cell_len = rend_service_encode_establish_intro_cell( (char*)cell_body, sizeof(cell_body), key1, circ_nonce); tt_int_op(cell_len, OP_GT, 0); /* Receive legacy establish_intro */ retval = hs_intro_received_establish_intro(intro_circ, cell_body, (size_t) cell_len); tt_int_op(retval, OP_EQ, 0); done: return key1; }
/* Helper function: Send a well-formed v3 ESTABLISH_INTRO cell to * <b>intro_circ</b>. Return the cell. */ static trn_cell_establish_intro_t * helper_establish_intro_v3(or_circuit_t *intro_circ) { int retval; char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; trn_cell_establish_intro_t *cell = NULL; tt_assert(intro_circ); /* Prepare the circuit for the incoming ESTABLISH_INTRO */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we * attempt to parse it. */ cell_len = new_establish_intro_cell(circ_nonce, &cell); tt_i64_op(cell_len, OP_GT, 0); tt_assert(cell); cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), cell); tt_int_op(cell_len, OP_GT, 0); /* Receive the cell */ retval = hs_intro_received_establish_intro(intro_circ, cell_body, (size_t) cell_len); tt_int_op(retval, OP_EQ, 0); done: return cell; }
/* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should * fail. */ static void test_establish_intro_wrong_sig(void *arg) { int retval; char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void) arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); tt_i64_op(cell_len, OP_GT, 0); /* Mutate the last byte (signature)! :) */ cell_body[cell_len - 1]++; /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, (size_t)cell_len); expect_log_msg_containing("Failed to verify ESTABLISH_INTRO cell."); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: circuit_free_(TO_CIRCUIT(intro_circ)); }
/* Try sending an ESTABLISH_INTRO cell on a circuit that is already an intro * point. Should fail. */ static void test_establish_intro_wrong_purpose(void *arg) { int retval; ssize_t cell_len = 0; char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void)arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); memcpy(intro_circ->rend_circ_nonce, circ_nonce, DIGEST_LEN); /* Set a bad circuit purpose!! :) */ circuit_change_purpose(TO_CIRCUIT(intro_circ), CIRCUIT_PURPOSE_INTRO_POINT); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); tt_i64_op(cell_len, OP_GT, 0); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("Rejecting ESTABLISH_INTRO on non-OR circuit."); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: circuit_free_(TO_CIRCUIT(intro_circ)); }
static void bench_cell_aes(void) { uint64_t start, end; const int len = 509; const int iters = (1<<16); const int max_misalign = 15; char *b = tor_malloc(len+max_misalign); crypto_cipher_t *c; int i, misalign; char key[CIPHER_KEY_LEN]; crypto_rand(key, sizeof(key)); c = crypto_cipher_new(key); reset_perftime(); for (misalign = 0; misalign <= max_misalign; ++misalign) { start = perftime(); for (i = 0; i < iters; ++i) { crypto_cipher_crypt_inplace(c, b+misalign, len); } end = perftime(); printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign, NANOCOUNT(start, end, iters*len)); } crypto_cipher_free(c); tor_free(b); }
/** We simulate a failure to create an ESTABLISH_INTRO cell */ static void test_gen_establish_intro_cell_bad(void *arg) { (void) arg; ssize_t cell_len = 0; trn_cell_establish_intro_t *cell = NULL; char circ_nonce[DIGEST_LEN] = {0}; hs_service_intro_point_t *ip = NULL; MOCK(ed25519_sign_prefixed, mock_ed25519_sign_prefixed); crypto_rand(circ_nonce, sizeof(circ_nonce)); setup_full_capture_of_logs(LOG_WARN); /* Easiest way to make that function fail is to mock the ed25519_sign_prefixed() function and make it fail. */ cell = trn_cell_establish_intro_new(); tt_assert(cell); ip = service_intro_point_new(NULL); cell_len = hs_cell_build_establish_intro(circ_nonce, ip, NULL); service_intro_point_free(ip); expect_log_msg_containing("Unable to make signature for " "ESTABLISH_INTRO cell."); teardown_capture_of_logs(); tt_i64_op(cell_len, OP_EQ, -1); done: trn_cell_establish_intro_free(cell); UNMOCK(ed25519_sign_prefixed); }
/** Implement the server side of the CREATE_FAST abbreviated handshake. The * client has provided DIGEST_LEN key bytes in <b>key_in</b> ("x"). We * generate a reply of DIGEST_LEN*2 bytes in <b>key_out</b>, consisting of a * new random "y", followed by H(x|y) to check for correctness. We set * <b>key_out_len</b> bytes of key material in <b>key_out</b>. * Return 0 on success, <0 on failure. **/ int fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */ char *handshake_reply_out, /* DIGEST_LEN*2 bytes */ char *key_out, size_t key_out_len) { char tmp[DIGEST_LEN+DIGEST_LEN]; char *out = NULL; size_t out_len; int r = -1; if (crypto_rand(handshake_reply_out, DIGEST_LEN)<0) return -1; memcpy(tmp, key_in, DIGEST_LEN); memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN); out_len = key_out_len+DIGEST_LEN; out = tor_malloc(out_len); if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) { goto done; } memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN); memcpy(key_out, out+DIGEST_LEN, key_out_len); r = 0; done: memset(tmp, 0, sizeof(tmp)); memset(out, 0, out_len); tor_free(out); return r; }
/** Test base32 decoding. */ static void test_crypto_base32_decode(void) { char plain[60], encoded[96 + 1], decoded[60]; int res; crypto_rand(plain, 60); /* Encode and decode a random string. */ base32_encode(encoded, 96 + 1, plain, 60); res = base32_decode(decoded, 60, encoded, 96); test_eq(res, 0); test_memeq(plain, decoded, 60); /* Encode, uppercase, and decode a random string. */ base32_encode(encoded, 96 + 1, plain, 60); tor_strupper(encoded); res = base32_decode(decoded, 60, encoded, 96); test_eq(res, 0); test_memeq(plain, decoded, 60); /* Change encoded string and decode. */ if (encoded[0] == 'A' || encoded[0] == 'a') encoded[0] = 'B'; else encoded[0] = 'A'; res = base32_decode(decoded, 60, encoded, 96); test_eq(res, 0); test_memneq(plain, decoded, 60); /* Bad encodings. */ encoded[0] = '!'; res = base32_decode(decoded, 60, encoded, 96); test_assert(res < 0); done: ; }
/** Send the establish-rendezvous cell along a rendezvous circuit. if * it fails, mark the circ for close and return -1. else return 0. */ static int rend_client_send_establish_rendezvous(origin_circuit_t *circ) { tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); tor_assert(circ->rend_data); log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell"); crypto_rand(circ->rend_data->rend_cookie, REND_COOKIE_LEN); /* Set timestamp_dirty, because circuit_expire_building expects it, * and the rend cookie also means we've used the circ. */ circ->base_.timestamp_dirty = time(NULL); /* We've attempted to use this circuit. Probe it if we fail */ pathbias_count_use_attempt(circ); if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), RELAY_COMMAND_ESTABLISH_RENDEZVOUS, circ->rend_data->rend_cookie, REND_COOKIE_LEN, circ->cpath->prev)<0) { /* circ is already marked for close */ log_warn(LD_GENERAL, "Couldn't send ESTABLISH_RENDEZVOUS cell"); return -1; } return 0; }
static void test_routerlist_launch_descriptor_downloads(void *arg) { smartlist_t *downloadable = smartlist_new(); time_t now = time(NULL); char *cp; (void)arg; for (int i = 0; i < 100; i++) { cp = tor_malloc(DIGEST256_LEN); tt_assert(cp); crypto_rand(cp, DIGEST256_LEN); smartlist_add(downloadable, cp); } MOCK(initiate_descriptor_downloads, mock_initiate_descriptor_downloads); launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, downloadable, NULL, now); tt_int_op(3, ==, count); UNMOCK(initiate_descriptor_downloads); done: SMARTLIST_FOREACH(downloadable, char *, cp1, tor_free(cp1)); smartlist_free(downloadable); }
static void test_buffers_tls_read_mocked(void *arg) { uint8_t *mem; buf_t *buf; (void)arg; mem = tor_malloc(64*1024); crypto_rand((char*)mem, 64*1024); tls_read_ptr = mem; n_remaining = 64*1024; MOCK(tor_tls_read, mock_tls_read); buf = buf_new(); next_reply_val[0] = 1024; tt_int_op(128, ==, read_to_buf_tls(NULL, 128, buf)); next_reply_val[0] = 5000; next_reply_val[1] = 5000; tt_int_op(6000, ==, read_to_buf_tls(NULL, 6000, buf)); done: UNMOCK(tor_tls_read); tor_free(mem); buf_free(buf); }
/** Run AES performance benchmarks. */ static void bench_aes(void) { int len, i; char *b1, *b2; crypto_cipher_t *c; uint64_t start, end; const int bytes_per_iter = (1<<24); reset_perftime(); char key[CIPHER_KEY_LEN]; crypto_rand(key, sizeof(key)); c = crypto_cipher_new(key); for (len = 1; len <= 8192; len *= 2) { int iters = bytes_per_iter / len; b1 = tor_malloc_zero(len); b2 = tor_malloc_zero(len); start = perftime(); for (i = 0; i < iters; ++i) { crypto_cipher_encrypt(c, b1, b2, len); } end = perftime(); tor_free(b1); tor_free(b2); printf("%d bytes: %.2f nsec per byte\n", len, NANOCOUNT(start, end, iters*len)); } crypto_cipher_free(c); }
/** Send the establish-rendezvous cell along a rendezvous circuit. if * it fails, mark the circ for close and return -1. else return 0. */ static int rend_client_send_establish_rendezvous(origin_circuit_t *circ) { tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); tor_assert(circ->rend_data); log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell"); if (crypto_rand(circ->rend_data->rend_cookie, REND_COOKIE_LEN) < 0) { log_warn(LD_BUG, "Internal error: Couldn't produce random cookie."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return -1; } /* Set timestamp_dirty, because circuit_expire_building expects it, * and the rend cookie also means we've used the circ. */ circ->base_.timestamp_dirty = time(NULL); if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), RELAY_COMMAND_ESTABLISH_RENDEZVOUS, circ->rend_data->rend_cookie, REND_COOKIE_LEN, circ->cpath->prev)<0) { /* circ is already marked for close */ log_warn(LD_GENERAL, "Couldn't send ESTABLISH_RENDEZVOUS cell"); return -1; } return 0; }
/** Return a filename with a random suffix, relative to our testing temporary * directory. If name is NULL, return the name of the testing temporary * directory, without any suffix. */ const char * get_fname_rnd(const char *name) { char rnd[256], rnd32[256]; crypto_rand(rnd, RAND_PATH_BYTES); base32_encode(rnd32, sizeof(rnd32), rnd, RAND_PATH_BYTES); return get_fname_suffix(name, rnd32); }
int randombytes(char *out, size_t num_bytes) { if (crypto_rand(out, num_bytes) < 0) { DRBG_RET(DRBG_ENTROPY_FAIL); } DRBG_RET(DRBG_OK); }
/** * Initialize the system that tells which ewma tick we are in. */ STATIC void cell_ewma_initialize_ticks(void) { if (ewma_ticks_initialized) return; monotime_coarse_get(&start_of_current_tick); crypto_rand((char*)¤t_tick_num, sizeof(current_tick_num)); ewma_ticks_initialized = 1; }
/** * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If * <b>extra_strong</b> is true, this key is possibly going to get used more * than once, so use a better-than-usual RNG. Return 0 on success, -1 on * failure. * * This function does not adjust the output of the RNG at all; the will caller * will need to clear or set the appropriate bits to make curve25519 work. */ int curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong) { if (extra_strong) crypto_strongest_rand(out, CURVE25519_SECKEY_LEN); else crypto_rand((char*)out, CURVE25519_SECKEY_LEN); return 0; }
/** Create the state needed to perform a CREATE_FAST handshake. Return 0 * on success, -1 on failure. */ int fast_onionskin_create(fast_handshake_state_t **handshake_state_out, uint8_t *handshake_out) { fast_handshake_state_t *s; *handshake_state_out = s = tor_malloc(sizeof(fast_handshake_state_t)); crypto_rand((char*)s->state, sizeof(s->state)); memcpy(handshake_out, s->state, DIGEST_LEN); return 0; }
static void add_bytes_to_buf(generic_buffer_t *buf, size_t n_bytes) { char b[3000]; while (n_bytes) { size_t this_add = n_bytes > sizeof(b) ? sizeof(b) : n_bytes; crypto_rand(b, this_add); generic_buffer_add(buf, b, this_add); n_bytes -= this_add; } }
/** 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: ; }
/** Run unit tests for digest set code (implemented as a hashtable or as a * bloom filter) */ static void test_container_digestset(void *arg) { smartlist_t *included = smartlist_new(); char d[DIGEST_LEN]; int i; int ok = 1; int false_positives = 0; digestset_t *set = NULL; (void)arg; for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); smartlist_add(included, tor_memdup(d, DIGEST_LEN)); } set = digestset_new(1000); SMARTLIST_FOREACH(included, const char *, cp, if (digestset_contains(set, cp)) ok = 0); tt_assert(ok); SMARTLIST_FOREACH(included, const char *, cp, digestset_add(set, cp)); SMARTLIST_FOREACH(included, const char *, cp, if (!digestset_contains(set, cp)) ok = 0); tt_assert(ok); for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); if (digestset_contains(set, d)) ++false_positives; } tt_int_op(50, OP_GT, false_positives); /* Should be far lower. */ done: if (set) digestset_free(set); SMARTLIST_FOREACH(included, char *, cp, tor_free(cp)); smartlist_free(included); }
static circuit_t * dummy_or_circuit_new(int n_p_cells, int n_n_cells) { or_circuit_t *circ = or_circuit_new(0, NULL); int i; cell_t cell; for (i=0; i < n_p_cells; ++i) { crypto_rand((void*)&cell, sizeof(cell)); cell_queue_append_packed_copy(TO_CIRCUIT(circ), &circ->p_chan_cells, 0, &cell, 1, 0); } for (i=0; i < n_n_cells; ++i) { crypto_rand((void*)&cell, sizeof(cell)); cell_queue_append_packed_copy(TO_CIRCUIT(circ), &TO_CIRCUIT(circ)->n_chan_cells, 1, &cell, 1, 0); } TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_OR; return TO_CIRCUIT(circ); }
static workqueue_entry_t * add_work(threadpool_t *tp) { int add_rsa = opt_ratio_rsa == 0 || tor_weak_random_range(&weak_rng, opt_ratio_rsa) == 0; if (add_rsa) { rsa_work_t *w = tor_malloc_zero(sizeof(*w)); w->serial = n_sent++; crypto_rand((char*)w->msg, 20); w->msglen = 20; ++rsa_sent; return threadpool_queue_work(tp, workqueue_do_rsa, handle_reply, w); } else { ecdh_work_t *w = tor_malloc_zero(sizeof(*w)); w->serial = n_sent++; /* Not strictly right, but this is just for benchmarks. */ crypto_rand((char*)w->u.pk.public_key, 32); ++ecdh_sent; return threadpool_queue_work(tp, workqueue_do_ecdh, handle_reply, w); } }
/** * Initialize a new ed25519 secret key in <b>seckey_out</b>. If * <b>extra_strong</b>, take the RNG inputs directly from the operating * system. Return 0 on success, -1 on failure. */ int ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out, int extra_strong) { int r; uint8_t seed[32]; if (! extra_strong || crypto_strongest_rand(seed, sizeof(seed)) < 0) crypto_rand((char*)seed, sizeof(seed)); r = get_ed_impl()->seckey_expand(seckey_out->seckey, seed); memwipe(seed, 0, sizeof(seed)); return r < 0 ? -1 : 0; }
/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we * parse it from the receiver side. */ static void test_gen_establish_intro_cell(void *arg) { (void) arg; ssize_t ret; char circ_nonce[DIGEST_LEN] = {0}; uint8_t buf[RELAY_PAYLOAD_SIZE]; trn_cell_establish_intro_t *cell_in = NULL; crypto_rand(circ_nonce, sizeof(circ_nonce)); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ { /* We only need the auth key pair here. */ hs_service_intro_point_t *ip = service_intro_point_new(NULL); /* Auth key pair is generated in the constructor so we are all set for * using this IP object. */ ret = hs_cell_build_establish_intro(circ_nonce, ip, buf); service_intro_point_free(ip); tt_u64_op(ret, OP_GT, 0); } /* Check the contents of the cell */ { /* First byte is the auth key type: make sure its correct */ tt_int_op(buf[0], OP_EQ, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); /* Next two bytes is auth key len */ tt_int_op(ntohs(get_uint16(buf+1)), OP_EQ, ED25519_PUBKEY_LEN); /* Skip to the number of extensions: no extensions */ tt_int_op(buf[35], OP_EQ, 0); /* Skip to the sig len. Make sure it's the size of an ed25519 sig */ tt_int_op(ntohs(get_uint16(buf+35+1+32)), OP_EQ, ED25519_SIG_LEN); } /* Parse it as the receiver */ { ret = trn_cell_establish_intro_parse(&cell_in, buf, sizeof(buf)); tt_u64_op(ret, OP_GT, 0); ret = verify_establish_intro_cell(cell_in, (const uint8_t *) circ_nonce, sizeof(circ_nonce)); tt_u64_op(ret, OP_EQ, 0); } done: trn_cell_establish_intro_free(cell_in); }
static void test_buffers_zlib_impl(int finalize_with_nil) { char *msg = NULL; char *contents = NULL; char *expanded = NULL; buf_t *buf = NULL; tor_zlib_state_t *zlib_state = NULL; size_t out_len, in_len; int done; buf = buf_new_with_capacity(128); /* will round up */ zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION); msg = tor_malloc(512); crypto_rand(msg, 512); tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), OP_EQ, 0); tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), OP_EQ, 0); tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), OP_EQ, 0); done = !finalize_with_nil; tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, done), OP_EQ, 0); if (finalize_with_nil) { tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0); } in_len = buf_datalen(buf); contents = tor_malloc(in_len); tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0); tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len, contents, in_len, ZLIB_METHOD, 1, LOG_WARN)); tt_int_op(out_len, OP_GE, 128); tt_mem_op(msg, OP_EQ, expanded, 128); tt_int_op(out_len, OP_GE, 512); tt_mem_op(msg, OP_EQ, expanded, 512); tt_int_op(out_len, OP_EQ, 512+9); tt_mem_op("all done", OP_EQ, expanded+512, 9); done: buf_free(buf); tor_zlib_free(zlib_state); tor_free(contents); tor_free(expanded); tor_free(msg); }
/** Select and create the temporary directory we'll use to run our unit tests. * Store it in <b>temp_dir</b>. Exit immediately if we can't create it. * idempotent. */ static void setup_directory(void) { static int is_setup = 0; int r; char rnd[256], rnd32[256]; if (is_setup) return; /* Due to base32 limitation needs to be a multiple of 5. */ #define RAND_PATH_BYTES 5 crypto_rand(rnd, RAND_PATH_BYTES); base32_encode(rnd32, sizeof(rnd32), rnd, RAND_PATH_BYTES); #ifdef _WIN32 { char buf[MAX_PATH]; const char *tmp = buf; const char *extra_backslash = ""; /* If this fails, we're probably screwed anyway */ if (!GetTempPathA(sizeof(buf),buf)) tmp = "c:\\windows\\temp\\"; if (strcmpend(tmp, "\\")) { /* According to MSDN, it should be impossible for GetTempPath to give us * an answer that doesn't end with \. But let's make sure. */ extra_backslash = "\\"; } tor_snprintf(temp_dir, sizeof(temp_dir), "%s%stor_test_%d_%s", tmp, extra_backslash, (int)getpid(), rnd32); r = mkdir(temp_dir); } #else tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d_%s", (int) getpid(), rnd32); r = mkdir(temp_dir, 0700); if (!r) { /* undo sticky bit so tests don't get confused. */ r = chown(temp_dir, getuid(), getgid()); } #endif if (r) { fprintf(stderr, "Can't create directory %s:", temp_dir); perror(""); exit(1); } is_setup = 1; temp_dir_setup_in_pid = getpid(); }