Пример #1
0
Файл: test.c Проект: ageis/tor
/** Run unit tests for the onion handshake code. */
static void
test_onion_handshake(void *arg)
{
  /* client-side */
  crypto_dh_t *c_dh = NULL;
  char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
  char c_keys[40];
  /* server-side */
  char s_buf[TAP_ONIONSKIN_REPLY_LEN];
  char s_keys[40];
  int i;
  /* shared */
  crypto_pk_t *pk = NULL, *pk2 = NULL;

  (void)arg;
  pk = pk_generate(0);
  pk2 = pk_generate(1);

  /* client handshake 1. */
  memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
  tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));

  for (i = 1; i <= 3; ++i) {
    crypto_pk_t *k1, *k2;
    if (i==1) {
      /* server handshake: only one key known. */
      k1 = pk;  k2 = NULL;
    } else if (i==2) {
      /* server handshake: try the right key first. */
      k1 = pk;  k2 = pk2;
    } else {
      /* server handshake: try the right key second. */
      k1 = pk2; k2 = pk;
    }

    memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
    memset(s_keys, 0, 40);
    tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2,
                                                  s_buf, s_keys, 40));

    /* client handshake 2 */
    memset(c_keys, 0, 40);
    tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys,
                                                40, NULL));

    tt_mem_op(c_keys,OP_EQ, s_keys, 40);
    memset(s_buf, 0, 40);
    tt_mem_op(c_keys,OP_NE, s_buf, 40);
  }
 done:
  crypto_dh_free(c_dh);
  crypto_pk_free(pk);
  crypto_pk_free(pk2);
}
Пример #2
0
Файл: onion.c Проект: adoll/tor
/** Release all storage held in <b>keys</b>, but do not free <b>keys</b>
 * itself (as it's likely to be stack-allocated.) */
void
release_server_onion_keys(server_onion_keys_t *keys)
{
  if (! keys)
    return;

  crypto_pk_free(keys->onion_key);
  crypto_pk_free(keys->last_onion_key);
  ntor_key_map_free(keys->curve25519_key_map);
  tor_free(keys->junk_keypair);
  memset(keys, 0, sizeof(server_onion_keys_t));
}
Пример #3
0
static void
free_state(void *arg)
{
  state_t *st = arg;
  crypto_pk_free(st->rsa);
  tor_free(st);
}
Пример #4
0
static void
test_routerkeys_rsa_ed_crosscert(void *arg)
{
  (void)arg;
  ed25519_public_key_t ed;
  crypto_pk_t *rsa = pk_generate(2);

  uint8_t *cc = NULL;
  ssize_t cc_len;
  time_t expires_in = 1470846177;

  tt_int_op(0, OP_EQ, ed25519_public_from_base64(&ed,
                        "ThisStringCanContainAnythingSoNoKeyHereNowX"));
  cc_len = tor_make_rsa_ed25519_crosscert(&ed, rsa, expires_in, &cc);

  tt_int_op(cc_len, OP_GT, 0);
  tt_int_op(cc_len, OP_GT, 37); /* key, expires, siglen */
  tt_mem_op(cc, OP_EQ, ed.pubkey, 32);
  time_t expires_out = 3600 * ntohl(get_uint32(cc+32));
  tt_int_op(expires_out, OP_GE, expires_in);
  tt_int_op(expires_out, OP_LE, expires_in + 3600);

  tt_int_op(cc_len, OP_EQ, 37 + get_uint8(cc+36));

  tt_int_op(0, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_in - 10));

  /* Now try after it has expired */
  tt_int_op(-4, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_out + 1));

  /* Truncated object */
  tt_int_op(-2, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len - 2, rsa, &ed,
                                                  expires_in - 10));

  /* Key not as expected */
  cc[0] ^= 3;
  tt_int_op(-3, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_in - 10));
  cc[0] ^= 3;

  /* Bad signature */
  cc[40] ^= 3;
  tt_int_op(-5, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                   expires_in - 10));
  cc[40] ^= 3;

  /* Signature of wrong data */
  cc[0] ^= 3;
  ed.pubkey[0] ^= 3;
  tt_int_op(-6, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_in - 10));
  cc[0] ^= 3;
  ed.pubkey[0] ^= 3;

 done:
  crypto_pk_free(rsa);
  tor_free(cc);
}
Пример #5
0
static int
workqueue_do_shutdown(void *state, void *work)
{
  (void)state;
  (void)work;
  crypto_pk_free(((state_t*)state)->rsa);
  tor_free(state);
  return WQ_RPL_SHUTDOWN;
}
Пример #6
0
/** Free the storage held by the service descriptor <b>desc</b>.
 */
void
rend_service_descriptor_free(rend_service_descriptor_t *desc)
{
  if (!desc)
    return;
  if (desc->pk)
    crypto_pk_free(desc->pk);
  if (desc->intro_nodes) {
    SMARTLIST_FOREACH(desc->intro_nodes, rend_intro_point_t *, intro,
      rend_intro_point_free(intro););
Пример #7
0
/** Set <b>out</b> to the hex-encoded fingerprint of <b>pkey</b>. */
static int
get_digest(EVP_PKEY *pkey, char *out)
{
  int r = 1;
  crypto_pk_t *pk = _crypto_new_pk_from_rsa(EVP_PKEY_get1_RSA(pkey));
  if (pk) {
    r = crypto_pk_get_digest(pk, out);
    crypto_pk_free(pk);
  }
  return r;
}
Пример #8
0
/** Set <b>out</b> to the hex-encoded fingerprint of <b>pkey</b>. */
static int
get_fingerprint(EVP_PKEY *pkey, char *out)
{
  int r = 1;
  crypto_pk_t *pk = crypto_new_pk_from_rsa_(EVP_PKEY_get1_RSA(pkey));
  if (pk) {
    r = crypto_pk_get_fingerprint(pk, out, 0);
    crypto_pk_free(pk);
  }
  return r;
}
Пример #9
0
static int
recv_certs_cleanup(const struct testcase_t *test, void *obj)
{
  (void)test;
  certs_data_t *d = obj;
  UNMOCK(tor_tls_cert_matches_key);
  UNMOCK(connection_or_send_netinfo);
  UNMOCK(connection_or_close_for_error);

  if (d) {
    tor_free(d->cell);
    certs_cell_free(d->ccell);
    connection_free_(TO_CONN(d->c));
    circuitmux_free(d->chan->base_.cmux);
    tor_free(d->chan);
    crypto_pk_free(d->key1);
    crypto_pk_free(d->key2);
    tor_free(d);
  }
  return 1;
}
Пример #10
0
static RSA *
generate_key(int bits)
{
  RSA *rsa = NULL;
  crypto_pk_t *env = crypto_pk_new();
  if (crypto_pk_generate_key_with_bits(env,bits)<0)
    goto done;
  rsa = _crypto_pk_get_rsa(env);
  rsa = RSAPrivateKey_dup(rsa);
 done:
  crypto_pk_free(env);
  return rsa;
}
Пример #11
0
static void
test_routerkeys_cross_certify_tap(void *args)
{
  (void)args;
  uint8_t *cc = NULL;
  int cc_len;
  ed25519_public_key_t master_key;
  crypto_pk_t *onion_key = pk_generate(2), *id_key = pk_generate(1);
  char digest[20];
  char buf[128];
  int n;

  tt_int_op(0, OP_EQ, ed25519_public_from_base64(&master_key,
                               "IAlreadyWroteTestsForRouterdescsUsingTheseX"));

  cc = make_tap_onion_key_crosscert(onion_key,
                                    &master_key,
                                    id_key, &cc_len);
  tt_assert(cc);
  tt_assert(cc_len);

  n = crypto_pk_public_checksig(onion_key, buf, sizeof(buf),
                                (char*)cc, cc_len);
  tt_int_op(n,OP_GT,0);
  tt_int_op(n,OP_EQ,52);

  crypto_pk_get_digest(id_key, digest);
  tt_mem_op(buf,OP_EQ,digest,20);
  tt_mem_op(buf+20,OP_EQ,master_key.pubkey,32);

  tt_int_op(0, OP_EQ, check_tap_onion_key_crosscert(cc, cc_len,
                                    onion_key, &master_key, (uint8_t*)digest));

 done:
  tor_free(cc);
  crypto_pk_free(id_key);
  crypto_pk_free(onion_key);
}
Пример #12
0
/* If no distribution option was set, then check_bridge_distribution_setting()
 * should have set it to "any". */
static void
test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
{
  const char* needle = "bridge-distribution-request any";
  or_options_t* options = get_options_mutable();
  routerinfo_t* router = NULL;
  curve25519_keypair_t ntor_keypair;
  ed25519_keypair_t signing_keypair;
  char* desc = NULL;
  char* found = NULL;
  (void)arg;

  NS_MOCK(router_get_my_routerinfo);

  options->ORPort_set = 1;
  options->BridgeRelay = 1;

  /* Generate keys which router_dump_router_to_string() expects to exist. */
  tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair, 0));
  tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair, 0));

  /* Set up part of our routerinfo_t so that we don't trigger any other
   * assertions in router_dump_router_to_string(). */
  router = (routerinfo_t*)router_get_my_routerinfo();
  tt_ptr_op(router, !=, NULL);

  /* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using
   * get_current_curve25519_keypair(), but we don't initialise static data in
   * this test. */
  router->onion_curve25519_pkey = &ntor_keypair.pubkey;

  /* Generate our server descriptor and ensure that the substring
   * "bridge-distribution-request any" occurs somewhere within it. */
  crypto_pk_t *onion_pkey = router_get_rsa_onion_pkey(router->onion_pkey,
                                                      router->onion_pkey_len);
  desc = router_dump_router_to_string(router,
                                      router->identity_pkey,
                                      onion_pkey,
                                      &ntor_keypair,
                                      &signing_keypair);
  crypto_pk_free(onion_pkey);
  tt_ptr_op(desc, !=, NULL);
  found = strstr(desc, needle);
  tt_ptr_op(found, !=, NULL);

 done:
  NS_UNMOCK(router_get_my_routerinfo);

  tor_free(desc);
}
Пример #13
0
static const routerinfo_t*
NS(router_get_my_routerinfo)(void)
{
  crypto_pk_t* ident_key;
  crypto_pk_t* tap_key;
  time_t now;

  if (!mock_routerinfo) {
    /* Mock the published timestamp, otherwise router_dump_router_to_string()
     * will poop its pants. */
    time(&now);

    /* We'll need keys, or router_dump_router_to_string() would return NULL. */
    ident_key = pk_generate(0);
    tap_key = pk_generate(0);

    tor_assert(ident_key != NULL);
    tor_assert(tap_key != NULL);

    mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
    mock_routerinfo->nickname = tor_strdup("ConlonNancarrow");
    mock_routerinfo->addr = 123456789;
    mock_routerinfo->or_port = 443;
    mock_routerinfo->platform = tor_strdup("unittest");
    mock_routerinfo->cache_info.published_on = now;
    mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key);
    router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey,
                              &mock_routerinfo->onion_pkey_len);
    mock_routerinfo->bandwidthrate = 9001;
    mock_routerinfo->bandwidthburst = 9002;
    crypto_pk_free(ident_key);
    crypto_pk_free(tap_key);
  }

  return mock_routerinfo;
}
Пример #14
0
static void *
new_state(void *arg)
{
  state_t *st;
  (void)arg;

  st = tor_malloc(sizeof(*st));
  /* Every thread gets its own keys. not a problem for benchmarking */
  st->rsa = crypto_pk_new();
  if (crypto_pk_generate_key_with_bits(st->rsa, 1024) < 0) {
    crypto_pk_free(st->rsa);
    tor_free(st);
    return NULL;
  }
  curve25519_secret_key_generate(&st->ecdh, 0);
  st->magic = 13371337;
  return st;
}
Пример #15
0
/** Free all resources allocated for <b>tok</b> */
void
token_clear(directory_token_t *tok)
{
  if (tok->key)
    crypto_pk_free(tok->key);
}
Пример #16
0
/** Respond to an ESTABLISH_INTRO cell by checking the signed data and
 * setting the circuit's purpose and service pk digest.
 */
int
rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,
                         size_t request_len)
{
  crypto_pk_t *pk = NULL;
  char buf[DIGEST_LEN+9];
  char expected_digest[DIGEST_LEN];
  char pk_digest[DIGEST_LEN];
  size_t asn1len;
  or_circuit_t *c;
  char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
  int reason = END_CIRC_REASON_INTERNAL;

  log_info(LD_REND,
           "Received an ESTABLISH_INTRO request on circuit %u",
           (unsigned) circ->p_circ_id);

  if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
         "Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit.");
    reason = END_CIRC_REASON_TORPROTOCOL;
    goto err;
  }
  if (request_len < 2+DIGEST_LEN)
    goto truncated;
  /* First 2 bytes: length of asn1-encoded key. */
  asn1len = ntohs(get_uint16(request));

  /* Next asn1len bytes: asn1-encoded key. */
  if (request_len < 2+DIGEST_LEN+asn1len)
    goto truncated;
  pk = crypto_pk_asn1_decode((char*)(request+2), asn1len);
  if (!pk) {
    reason = END_CIRC_REASON_TORPROTOCOL;
    log_warn(LD_PROTOCOL, "Couldn't decode public key.");
    goto err;
  }

  /* Next 20 bytes: Hash of rend_circ_nonce | "INTRODUCE" */
  memcpy(buf, circ->rend_circ_nonce, DIGEST_LEN);
  memcpy(buf+DIGEST_LEN, "INTRODUCE", 9);
  if (crypto_digest(expected_digest, buf, DIGEST_LEN+9) < 0) {
    log_warn(LD_BUG, "Internal error computing digest.");
    goto err;
  }
  if (tor_memneq(expected_digest, request+2+asn1len, DIGEST_LEN)) {
    log_warn(LD_PROTOCOL, "Hash of session info was not as expected.");
    reason = END_CIRC_REASON_TORPROTOCOL;
    goto err;
  }
  /* Rest of body: signature of previous data */
  note_crypto_pk_op(REND_MID);
  if (crypto_pk_public_checksig_digest(pk,
                                       (char*)request, 2+asn1len+DIGEST_LEN,
                                       (char*)(request+2+DIGEST_LEN+asn1len),
                                       request_len-(2+DIGEST_LEN+asn1len))<0) {
    log_warn(LD_PROTOCOL,
             "Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
    reason = END_CIRC_REASON_TORPROTOCOL;
    goto err;
  }

  /* The request is valid.  First, compute the hash of Bob's PK.*/
  if (crypto_pk_get_digest(pk, pk_digest)<0) {
    log_warn(LD_BUG, "Internal error: couldn't hash public key.");
    goto err;
  }

  crypto_pk_free(pk); /* don't need it anymore */
  pk = NULL; /* so we don't free it again if err */

  base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
                pk_digest, REND_SERVICE_ID_LEN);

  /* Close any other intro circuits with the same pk. */
  c = NULL;
  while ((c = circuit_get_intro_point((const uint8_t *)pk_digest))) {
    log_info(LD_REND, "Replacing old circuit for service %s",
             safe_str(serviceid));
    circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
    /* Now it's marked, and it won't be returned next time. */
  }

  /* Acknowledge the request. */
  if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
                                   RELAY_COMMAND_INTRO_ESTABLISHED,
                                   "", 0, NULL)<0) {
    log_info(LD_GENERAL, "Couldn't send INTRO_ESTABLISHED cell.");
    goto err;
  }

  /* Now, set up this circuit. */
  circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
  circuit_set_intro_point_digest(circ, (uint8_t *)pk_digest);

  log_info(LD_REND,
           "Established introduction point on circuit %u for service %s",
           (unsigned) circ->p_circ_id, safe_str(serviceid));

  return 0;
 truncated:
  log_warn(LD_PROTOCOL, "Rejecting truncated ESTABLISH_INTRO cell.");
  reason = END_CIRC_REASON_TORPROTOCOL;
 err:
  if (pk) crypto_pk_free(pk);
  circuit_mark_for_close(TO_CIRCUIT(circ), reason);
  return -1;
}
Пример #17
0
static void
test_routerkeys_write_fingerprint(void *arg)
{
  crypto_pk_t *key = pk_generate(2);
  or_options_t *options = get_options_mutable();
  const char *ddir = get_fname("write_fingerprint");
  char *cp = NULL, *cp2 = NULL;
  char fp[FINGERPRINT_LEN+1];

  (void)arg;

  tt_assert(key);

  options->ORPort_set = 1; /* So that we can get the server ID key */
  tor_free(options->DataDirectory);
  options->DataDirectory = tor_strdup(ddir);
  options->Nickname = tor_strdup("haflinger");
  set_server_identity_key(key);
  set_client_identity_key(crypto_pk_dup_key(key));

  tt_int_op(0, OP_EQ, check_private_dir(ddir, CPD_CREATE, NULL));
  tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),OP_EQ,0);

  /* Write fingerprint file */
  tt_int_op(0, OP_EQ, router_write_fingerprint(0));
  cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"),
                        0, NULL);
  crypto_pk_get_fingerprint(key, fp, 0);
  tor_asprintf(&cp2, "haflinger %s\n", fp);
  tt_str_op(cp, OP_EQ, cp2);
  tor_free(cp);
  tor_free(cp2);

  /* Write hashed-fingerprint file */
  tt_int_op(0, OP_EQ, router_write_fingerprint(1));
  cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"),
                        0, NULL);
  crypto_pk_get_hashed_fingerprint(key, fp);
  tor_asprintf(&cp2, "haflinger %s\n", fp);
  tt_str_op(cp, OP_EQ, cp2);
  tor_free(cp);
  tor_free(cp2);

  /* Replace outdated file */
  write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"),
                    "junk goes here", 0);
  tt_int_op(0, OP_EQ, router_write_fingerprint(1));
  cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"),
                        0, NULL);
  crypto_pk_get_hashed_fingerprint(key, fp);
  tor_asprintf(&cp2, "haflinger %s\n", fp);
  tt_str_op(cp, OP_EQ, cp2);
  tor_free(cp);
  tor_free(cp2);

 done:
  crypto_pk_free(key);
  set_client_identity_key(NULL);
  tor_free(cp);
  tor_free(cp2);
}
Пример #18
0
/** Run unit tests for our public key crypto functions */
static void
test_crypto_pk(void)
{
  crypto_pk_t *pk1 = NULL, *pk2 = NULL;
  char *encoded = NULL;
  char data1[1024], data2[1024], data3[1024];
  size_t size;
  int i, j, p, len;

  /* Public-key ciphers */
  pk1 = pk_generate(0);
  pk2 = crypto_pk_new();
  test_assert(pk1 && pk2);
  test_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size));
  test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size));
  test_eq(0, crypto_pk_cmp_keys(pk1, pk2));

  /* comparison between keys and NULL */
  tt_int_op(crypto_pk_cmp_keys(NULL, pk1), <, 0);
  tt_int_op(crypto_pk_cmp_keys(NULL, NULL), ==, 0);
  tt_int_op(crypto_pk_cmp_keys(pk1, NULL), >, 0);

  test_eq(128, crypto_pk_keysize(pk1));
  test_eq(1024, crypto_pk_num_bits(pk1));
  test_eq(128, crypto_pk_keysize(pk2));
  test_eq(1024, crypto_pk_num_bits(pk2));

  test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1),
                                        "Hello whirled.", 15,
                                        PK_PKCS1_OAEP_PADDING));
  test_eq(128, crypto_pk_public_encrypt(pk1, data2, sizeof(data1),
                                        "Hello whirled.", 15,
                                        PK_PKCS1_OAEP_PADDING));
  /* oaep padding should make encryption not match */
  test_memneq(data1, data2, 128);
  test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data1, 128,
                                        PK_PKCS1_OAEP_PADDING,1));
  test_streq(data3, "Hello whirled.");
  memset(data3, 0, 1024);
  test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128,
                                        PK_PKCS1_OAEP_PADDING,1));
  test_streq(data3, "Hello whirled.");
  /* Can't decrypt with public key. */
  test_eq(-1, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data2, 128,
                                        PK_PKCS1_OAEP_PADDING,1));
  /* Try again with bad padding */
  memcpy(data2+1, "XYZZY", 5);  /* This has fails ~ once-in-2^40 */
  test_eq(-1, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128,
                                        PK_PKCS1_OAEP_PADDING,1));

  /* File operations: save and load private key */
  test_assert(! crypto_pk_write_private_key_to_filename(pk1,
                                                        get_fname("pkey1")));
  /* failing case for read: can't read. */
  test_assert(crypto_pk_read_private_key_from_filename(pk2,
                                                   get_fname("xyzzy")) < 0);
  write_str_to_file(get_fname("xyzzy"), "foobar", 6);
  /* Failing case for read: no key. */
  test_assert(crypto_pk_read_private_key_from_filename(pk2,
                                                   get_fname("xyzzy")) < 0);
  test_assert(! crypto_pk_read_private_key_from_filename(pk2,
                                                         get_fname("pkey1")));
  test_eq(15, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data1, 128,
                                        PK_PKCS1_OAEP_PADDING,1));

  /* Now try signing. */
  strlcpy(data1, "Ossifrage", 1024);
  test_eq(128, crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10));
  test_eq(10,
          crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128));
  test_streq(data3, "Ossifrage");
  /* Try signing digests. */
  test_eq(128, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2),
                                             data1, 10));
  test_eq(20,
          crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128));
  test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128));
  test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128));

  /*XXXX test failed signing*/

  /* Try encoding */
  crypto_pk_free(pk2);
  pk2 = NULL;
  i = crypto_pk_asn1_encode(pk1, data1, 1024);
  test_assert(i>0);
  pk2 = crypto_pk_asn1_decode(data1, i);
  test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);

  /* Try with hybrid encryption wrappers. */
  crypto_rand(data1, 1024);
  for (i = 0; i < 2; ++i) {
    for (j = 85; j < 140; ++j) {
      memset(data2,0,1024);
      memset(data3,0,1024);
      p = (i==0)?PK_PKCS1_PADDING:PK_PKCS1_OAEP_PADDING;
      len = crypto_pk_public_hybrid_encrypt(pk1,data2,sizeof(data2),
                                            data1,j,p,0);
      test_assert(len>=0);
      len = crypto_pk_private_hybrid_decrypt(pk1,data3,sizeof(data3),
                                             data2,len,p,1);
      test_eq(len,j);
      test_memeq(data1,data3,j);
    }
  }

  /* Try copy_full */
  crypto_pk_free(pk2);
  pk2 = crypto_pk_copy_full(pk1);
  test_assert(pk2 != NULL);
  test_neq_ptr(pk1, pk2);
  test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);

 done:
  if (pk1)
    crypto_pk_free(pk1);
  if (pk2)
    crypto_pk_free(pk2);
  tor_free(encoded);
}
Пример #19
0
/** Deallocate space associated with circ.
 */
static void
circuit_free(circuit_t *circ)
{
  void *mem;
  size_t memlen;
  if (!circ)
    return;

  if (CIRCUIT_IS_ORIGIN(circ)) {
    origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
    mem = ocirc;
    memlen = sizeof(origin_circuit_t);
    tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
    if (ocirc->build_state) {
        extend_info_free(ocirc->build_state->chosen_exit);
        circuit_free_cpath_node(ocirc->build_state->pending_final_cpath);
        cpath_ref_decref(ocirc->build_state->service_pending_final_cpath_ref);
    }
    tor_free(ocirc->build_state);

    circuit_free_cpath(ocirc->cpath);

    crypto_pk_free(ocirc->intro_key);
    rend_data_free(ocirc->rend_data);

    tor_free(ocirc->dest_address);
    if (ocirc->socks_username) {
      memwipe(ocirc->socks_username, 0x12, ocirc->socks_username_len);
      tor_free(ocirc->socks_username);
    }
    if (ocirc->socks_password) {
      memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len);
      tor_free(ocirc->socks_password);
    }
  } else {
    or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
    /* Remember cell statistics for this circuit before deallocating. */
    if (get_options()->CellStatistics)
      rep_hist_buffer_stats_add_circ(circ, time(NULL));
    mem = ocirc;
    memlen = sizeof(or_circuit_t);
    tor_assert(circ->magic == OR_CIRCUIT_MAGIC);

    crypto_cipher_free(ocirc->p_crypto);
    crypto_digest_free(ocirc->p_digest);
    crypto_cipher_free(ocirc->n_crypto);
    crypto_digest_free(ocirc->n_digest);

    if (ocirc->rend_splice) {
      or_circuit_t *other = ocirc->rend_splice;
      tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC);
      other->rend_splice = NULL;
    }

    /* remove from map. */
    circuit_set_p_circid_orconn(ocirc, 0, NULL);

    /* Clear cell queue _after_ removing it from the map.  Otherwise our
     * "active" checks will be violated. */
    cell_queue_clear(&ocirc->p_conn_cells);
  }

  extend_info_free(circ->n_hop);
  tor_free(circ->n_conn_onionskin);

  /* Remove from map. */
  circuit_set_n_circid_orconn(circ, 0, NULL);

  /* Clear cell queue _after_ removing it from the map.  Otherwise our
   * "active" checks will be violated. */
  cell_queue_clear(&circ->n_conn_cells);

  memwipe(mem, 0xAA, memlen); /* poison memory */
  tor_free(mem);
}
Пример #20
0
/** Test utility function: checks that the <b>plaintext_len</b>-byte string at
 * <b>plaintext</b> is at least superficially parseable.
 */
static void
do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase)
{
  crypto_pk_t *k = NULL;
  ssize_t r;
  uint8_t *cell = NULL;
  size_t cell_len;
  rend_intro_cell_t *parsed_req = NULL;
  char *err_msg = NULL;
  char digest[DIGEST_LEN];

  /* Get a key */
  k = crypto_pk_new();
  tt_assert(k);
  r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_1, -1);
  tt_assert(!r);

  /* Get digest for future comparison */
  r = crypto_pk_get_digest(k, digest);
  tt_assert(r >= 0);

  /* Make a cell out of it */
  memmgr_init_check_shared_mem(SHARED_SIZE, UIO_DEVICE, BASE_ADDRESS);
  char* plaintext_buf = memmgr_alloc(plaintext_len);
  memcpy(plaintext_buf, plaintext, plaintext_len);


  r = make_intro_from_plaintext(
      plaintext_buf, plaintext_len,
      k, (void **)(&cell));
  tt_assert(r > 0);
  tt_assert(cell);
  cell_len = r;
  memmgr_free(plaintext_buf);

  /* Do early parsing */
  parsed_req = rend_service_begin_parse_intro(cell, cell_len, 2, &err_msg);
  tt_assert(parsed_req);
  tt_assert(!err_msg);
  tt_mem_op(parsed_req->pk,OP_EQ, digest, DIGEST_LEN);
  tt_assert(parsed_req->ciphertext);
  tt_assert(parsed_req->ciphertext_len > 0);

  if (phase == EARLY_PARSE_ONLY)
    goto done;

  printf("\nHere");

  /* Do decryption */
  r = rend_service_decrypt_intro(parsed_req, k, &err_msg);
  tt_assert(!r);
  tt_assert(!err_msg);
  tt_assert(parsed_req->plaintext);
  tt_assert(parsed_req->plaintext_len > 0);

  if (phase == DECRYPT_ONLY)
    goto done;

  /* Do late parsing */
  r = rend_service_parse_intro_plaintext(parsed_req, &err_msg);
  tt_assert(!r);
  tt_assert(!err_msg);
  tt_assert(parsed_req->parsed);

 done:
//  tor_free(cell);
  memmgr_assert(cell);
  memmgr_free(cell);
  crypto_pk_free(k);
  rend_service_free_intro(parsed_req);
  tor_free(err_msg);
}
Пример #21
0
/** Implement a cpuworker.  'data' is an fdarray as returned by socketpair.
 * Read and writes from fdarray[1].  Reads requests, writes answers.
 *
 *   Request format:
 *          Task type           [1 byte, always CPUWORKER_TASK_ONION]
 *          Opaque tag          TAG_LEN
 *          Onionskin challenge ONIONSKIN_CHALLENGE_LEN
 *   Response format:
 *          Success/failure     [1 byte, boolean.]
 *          Opaque tag          TAG_LEN
 *          Onionskin challenge ONIONSKIN_REPLY_LEN
 *          Negotiated keys     KEY_LEN*2+DIGEST_LEN*2
 *
 *  (Note: this _should_ be by addr/port, since we're concerned with specific
 * connections, not with routers (where we'd use identity).)
 */
static void
cpuworker_main(void *data)
{
  char question[ONIONSKIN_CHALLENGE_LEN];
  uint8_t question_type;
  tor_socket_t *fdarray = data;
  tor_socket_t fd;

  /* variables for onion processing */
  char keys[CPATH_KEY_MATERIAL_LEN];
  char reply_to_proxy[ONIONSKIN_REPLY_LEN];
  char buf[LEN_ONION_RESPONSE];
  char tag[TAG_LEN];
  crypto_pk_t *onion_key = NULL, *last_onion_key = NULL;

  fd = fdarray[1]; /* this side is ours */
#ifndef TOR_IS_MULTITHREADED
  tor_close_socket(fdarray[0]); /* this is the side of the socketpair the
                                 * parent uses */
  tor_free_all(1); /* so the child doesn't hold the parent's fd's open */
  handle_signals(0); /* ignore interrupts from the keyboard, etc */
#endif
  tor_free(data);

  dup_onion_keys(&onion_key, &last_onion_key);

  for (;;) {
    ssize_t r;

    if ((r = recv(fd, (void *)&question_type, 1, 0)) != 1) {
//      log_fn(LOG_ERR,"read type failed. Exiting.");
      if (r == 0) {
        log_info(LD_OR,
                 "CPU worker exiting because Tor process closed connection "
                 "(either rotated keys or died).");
      } else {
        log_info(LD_OR,
                 "CPU worker exiting because of error on connection to Tor "
                 "process.");
        log_info(LD_OR,"(Error on %d was %s)",
                 fd, tor_socket_strerror(tor_socket_errno(fd)));
      }
      goto end;
    }
    tor_assert(question_type == CPUWORKER_TASK_ONION);

    if (read_all(fd, tag, TAG_LEN, 1) != TAG_LEN) {
      log_err(LD_BUG,"read tag failed. Exiting.");
      goto end;
    }

    if (read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) !=
        ONIONSKIN_CHALLENGE_LEN) {
      log_err(LD_BUG,"read question failed. Exiting.");
      goto end;
    }

    if (question_type == CPUWORKER_TASK_ONION) {
      if (onion_skin_server_handshake(question, onion_key, last_onion_key,
          reply_to_proxy, keys, CPATH_KEY_MATERIAL_LEN) < 0) {
        /* failure */
        log_debug(LD_OR,"onion_skin_server_handshake failed.");
        *buf = 0; /* indicate failure in first byte */
        memcpy(buf+1,tag,TAG_LEN);
        /* send all zeros as answer */
        memset(buf+1+TAG_LEN, 0, LEN_ONION_RESPONSE-(1+TAG_LEN));
      } else {
        /* success */
        log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
        buf[0] = 1; /* 1 means success */
        memcpy(buf+1,tag,TAG_LEN);
        memcpy(buf+1+TAG_LEN,reply_to_proxy,ONIONSKIN_REPLY_LEN);
        memcpy(buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,keys,CPATH_KEY_MATERIAL_LEN);
      }
      if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) {
        log_err(LD_BUG,"writing response buf failed. Exiting.");
        goto end;
      }
      log_debug(LD_OR,"finished writing response.");
    }
  }
 end:
  if (onion_key)
    crypto_pk_free(onion_key);
  if (last_onion_key)
    crypto_pk_free(last_onion_key);
  tor_close_socket(fd);
  crypto_thread_cleanup();
  spawn_exit();
}
Пример #22
0
/* Test good certs cells */
static void
test_link_handshake_certs_ok(void *arg)
{
  (void) arg;

  or_connection_t *c1 = or_connection_new(CONN_TYPE_OR, AF_INET);
  or_connection_t *c2 = or_connection_new(CONN_TYPE_OR, AF_INET);
  var_cell_t *cell1 = NULL, *cell2 = NULL;
  certs_cell_t *cc1 = NULL, *cc2 = NULL;
  channel_tls_t *chan1 = NULL, *chan2 = NULL;
  crypto_pk_t *key1 = NULL, *key2 = NULL;

  scheduler_init();

  MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key);
  MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell);
  MOCK(connection_or_send_netinfo, mock_send_netinfo);

  key1 = pk_generate(2);
  key2 = pk_generate(3);

  /* We need to make sure that our TLS certificates are set up before we can
   * actually generate a CERTS cell.
   */
  tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER,
                                 key1, key2, 86400), ==, 0);

  c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
  c1->link_proto = 3;
  tt_int_op(connection_init_or_handshake_state(c1, 1), ==, 0);

  c2->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
  c2->link_proto = 3;
  tt_int_op(connection_init_or_handshake_state(c2, 0), ==, 0);

  tt_int_op(0, ==, connection_or_send_certs_cell(c1));
  tt_assert(mock_got_var_cell);
  cell1 = mock_got_var_cell;

  tt_int_op(0, ==, connection_or_send_certs_cell(c2));
  tt_assert(mock_got_var_cell);
  cell2 = mock_got_var_cell;

  tt_int_op(cell1->command, ==, CELL_CERTS);
  tt_int_op(cell1->payload_len, >, 1);

  tt_int_op(cell2->command, ==, CELL_CERTS);
  tt_int_op(cell2->payload_len, >, 1);

  tt_int_op(cell1->payload_len, ==,
            certs_cell_parse(&cc1, cell1->payload, cell1->payload_len));
  tt_int_op(cell2->payload_len, ==,
            certs_cell_parse(&cc2, cell2->payload, cell2->payload_len));

  tt_int_op(2, ==, cc1->n_certs);
  tt_int_op(2, ==, cc2->n_certs);

  tt_int_op(certs_cell_get_certs(cc1, 0)->cert_type, ==,
            CERTTYPE_RSA1024_ID_AUTH);
  tt_int_op(certs_cell_get_certs(cc1, 1)->cert_type, ==,
            CERTTYPE_RSA1024_ID_ID);

  tt_int_op(certs_cell_get_certs(cc2, 0)->cert_type, ==,
            CERTTYPE_RSA1024_ID_LINK);
  tt_int_op(certs_cell_get_certs(cc2, 1)->cert_type, ==,
            CERTTYPE_RSA1024_ID_ID);

  chan1 = tor_malloc_zero(sizeof(*chan1));
  channel_tls_common_init(chan1);
  c1->chan = chan1;
  chan1->conn = c1;
  c1->base_.address = tor_strdup("C1");
  c1->tls = tor_tls_new(-1, 0);
  c1->link_proto = 4;
  c1->base_.conn_array_index = -1;
  crypto_pk_get_digest(key2, c1->identity_digest);

  channel_tls_process_certs_cell(cell2, chan1);

  tt_assert(c1->handshake_state->received_certs_cell);
  tt_assert(c1->handshake_state->auth_cert == NULL);
  tt_assert(c1->handshake_state->id_cert);
  tt_assert(! tor_mem_is_zero(
                  (char*)c1->handshake_state->authenticated_peer_id, 20));

  chan2 = tor_malloc_zero(sizeof(*chan2));
  channel_tls_common_init(chan2);
  c2->chan = chan2;
  chan2->conn = c2;
  c2->base_.address = tor_strdup("C2");
  c2->tls = tor_tls_new(-1, 1);
  c2->link_proto = 4;
  c2->base_.conn_array_index = -1;
  crypto_pk_get_digest(key1, c2->identity_digest);

  channel_tls_process_certs_cell(cell1, chan2);

  tt_assert(c2->handshake_state->received_certs_cell);
  tt_assert(c2->handshake_state->auth_cert);
  tt_assert(c2->handshake_state->id_cert);
  tt_assert(tor_mem_is_zero(
                (char*)c2->handshake_state->authenticated_peer_id, 20));

 done:
  UNMOCK(tor_tls_cert_matches_key);
  UNMOCK(connection_or_write_var_cell_to_buf);
  UNMOCK(connection_or_send_netinfo);
  connection_free_(TO_CONN(c1));
  connection_free_(TO_CONN(c2));
  tor_free(cell1);
  tor_free(cell2);
  certs_cell_free(cc1);
  certs_cell_free(cc2);
  if (chan1)
    circuitmux_free(chan1->base_.cmux);
  tor_free(chan1);
  if (chan2)
    circuitmux_free(chan2->base_.cmux);
  tor_free(chan2);
  crypto_pk_free(key1);
  crypto_pk_free(key2);
}
Пример #23
0
void
construct_consensus(char **consensus_text_md)
{
  networkstatus_t *vote = NULL;
  networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL;
  networkstatus_voter_info_t *voter = NULL;
  authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL;
  crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL;
  crypto_pk_t *sign_skey_leg=NULL;
  time_t now = time(NULL);
  smartlist_t *votes = NULL;
  int n_vrs;

  tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3,
                                          &sign_skey_1, &sign_skey_2,
                                          &sign_skey_3));
  sign_skey_leg = pk_generate(4);

  dir_common_construct_vote_1(&vote, cert1, sign_skey_1,
                              &dir_common_gen_routerstatus_for_v3ns,
                              &v1, &n_vrs, now, 1);
  networkstatus_vote_free(vote);
  tt_assert(v1);
  tt_int_op(n_vrs, ==, 4);
  tt_int_op(smartlist_len(v1->routerstatus_list), ==, 4);

  dir_common_construct_vote_2(&vote, cert2, sign_skey_2,
                              &dir_common_gen_routerstatus_for_v3ns,
                              &v2, &n_vrs, now, 1);
  networkstatus_vote_free(vote);
  tt_assert(v2);
  tt_int_op(n_vrs, ==, 4);
  tt_int_op(smartlist_len(v2->routerstatus_list), ==, 4);

  dir_common_construct_vote_3(&vote, cert3, sign_skey_3,
                              &dir_common_gen_routerstatus_for_v3ns,
                              &v3, &n_vrs, now, 1);

  tt_assert(v3);
  tt_int_op(n_vrs, ==, 4);
  tt_int_op(smartlist_len(v3->routerstatus_list), ==, 4);
  networkstatus_vote_free(vote);
  votes = smartlist_new();
  smartlist_add(votes, v1);
  smartlist_add(votes, v2);
  smartlist_add(votes, v3);

  *consensus_text_md = networkstatus_compute_consensus(votes, 3,
                                                   cert1->identity_key,
                                                   sign_skey_1,
                                                   "AAAAAAAAAAAAAAAAAAAA",
                                                   sign_skey_leg,
                                                   FLAV_MICRODESC);

  tt_assert(*consensus_text_md);

 done:
  tor_free(voter);
  networkstatus_vote_free(v1);
  networkstatus_vote_free(v2);
  networkstatus_vote_free(v3);
  smartlist_free(votes);
  authority_cert_free(cert1);
  authority_cert_free(cert2);
  authority_cert_free(cert3);
  crypto_pk_free(sign_skey_1);
  crypto_pk_free(sign_skey_2);
  crypto_pk_free(sign_skey_3);
  crypto_pk_free(sign_skey_leg);
}
Пример #24
0
static void
bench_onion_TAP(void)
{
  const int iters = 1<<9;
  int i;
  crypto_pk_t *key, *key2;
  uint64_t start, end;
  char os[TAP_ONIONSKIN_CHALLENGE_LEN];
  char or[TAP_ONIONSKIN_REPLY_LEN];
  crypto_dh_t *dh_out;

  key = crypto_pk_new();
  key2 = crypto_pk_new();
  if (crypto_pk_generate_key_with_bits(key, 1024) < 0)
    goto done;
  if (crypto_pk_generate_key_with_bits(key2, 1024) < 0)
    goto done;

  reset_perftime();
  start = perftime();
  for (i = 0; i < iters; ++i) {
    onion_skin_TAP_create(key, &dh_out, os);
    crypto_dh_free(dh_out);
  }
  end = perftime();
  printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3);

  onion_skin_TAP_create(key, &dh_out, os);
  start = perftime();
  for (i = 0; i < iters; ++i) {
    char key_out[CPATH_KEY_MATERIAL_LEN];
    onion_skin_TAP_server_handshake(os, key, NULL, or,
                                    key_out, sizeof(key_out));
  }
  end = perftime();
  printf("Server-side, key guessed right: %f usec\n",
         NANOCOUNT(start, end, iters)/1e3);

  start = perftime();
  for (i = 0; i < iters; ++i) {
    char key_out[CPATH_KEY_MATERIAL_LEN];
    onion_skin_TAP_server_handshake(os, key2, key, or,
                                    key_out, sizeof(key_out));
  }
  end = perftime();
  printf("Server-side, key guessed wrong: %f usec.\n",
         NANOCOUNT(start, end, iters)/1e3);

  start = perftime();
  for (i = 0; i < iters; ++i) {
    crypto_dh_t *dh;
    char key_out[CPATH_KEY_MATERIAL_LEN];
    int s;
    dh = crypto_dh_dup(dh_out);
    s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out),
                                        NULL);
    crypto_dh_free(dh);
    tor_assert(s == 0);
  }
  end = perftime();
  printf("Client-side, part 2: %f usec.\n",
         NANOCOUNT(start, end, iters)/1e3);

 done:
  crypto_pk_free(key);
  crypto_pk_free(key2);
}
Пример #25
0
static void
test_add_onion_helper_keyarg(void *arg)
{
  crypto_pk_t *pk = NULL;
  crypto_pk_t *pk2 = NULL;
  const char *key_new_alg = NULL;
  char *key_new_blob = NULL;
  char *err_msg = NULL;
  char *encoded = NULL;
  char *arg_str = NULL;

  (void) arg;

  /* Test explicit RSA1024 key generation. */
  pk = add_onion_helper_keyarg("NEW:RSA1024", 0, &key_new_alg, &key_new_blob,
                               &err_msg);
  tt_assert(pk);
  tt_str_op(key_new_alg, OP_EQ, "RSA1024");
  tt_assert(key_new_blob);
  tt_assert(!err_msg);

  /* Test "BEST" key generation (Assumes BEST = RSA1024). */
  crypto_pk_free(pk);
  tor_free(key_new_blob);
  pk = add_onion_helper_keyarg("NEW:BEST", 0, &key_new_alg, &key_new_blob,
                               &err_msg);
  tt_assert(pk);
  tt_str_op(key_new_alg, OP_EQ, "RSA1024");
  tt_assert(key_new_blob);
  tt_assert(!err_msg);

  /* Test discarding the private key. */
  crypto_pk_free(pk);
  tor_free(key_new_blob);
  pk = add_onion_helper_keyarg("NEW:BEST", 1, &key_new_alg, &key_new_blob,
                               &err_msg);
  tt_assert(pk);
  tt_assert(!key_new_alg);
  tt_assert(!key_new_blob);
  tt_assert(!err_msg);

  /* Test generating a invalid key type. */
  crypto_pk_free(pk);
  pk = add_onion_helper_keyarg("NEW:RSA512", 0, &key_new_alg, &key_new_blob,
                               &err_msg);
  tt_assert(!pk);
  tt_assert(!key_new_alg);
  tt_assert(!key_new_blob);
  tt_assert(err_msg);

  /* Test loading a RSA1024 key. */
  tor_free(err_msg);
  pk = pk_generate(0);
  tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk, &encoded));
  tor_asprintf(&arg_str, "RSA1024:%s", encoded);
  pk2 = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob,
                                &err_msg);
  tt_assert(pk2);
  tt_assert(!key_new_alg);
  tt_assert(!key_new_blob);
  tt_assert(!err_msg);
  tt_assert(crypto_pk_cmp_keys(pk, pk2) == 0);

  /* Test loading a invalid key type. */
  tor_free(arg_str);
  crypto_pk_free(pk); pk = NULL;
  tor_asprintf(&arg_str, "RSA512:%s", encoded);
  pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob,
                               &err_msg);
  tt_assert(!pk);
  tt_assert(!key_new_alg);
  tt_assert(!key_new_blob);
  tt_assert(err_msg);

  /* Test loading a invalid key. */
  tor_free(arg_str);
  crypto_pk_free(pk); pk = NULL;
  tor_free(err_msg);
  encoded[strlen(encoded)/2] = '\0';
  tor_asprintf(&arg_str, "RSA1024:%s", encoded);
  pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob,
                               &err_msg);
  tt_assert(!pk);
  tt_assert(!key_new_alg);
  tt_assert(!key_new_blob);
  tt_assert(err_msg);

 done:
  crypto_pk_free(pk);
  crypto_pk_free(pk2);
  tor_free(key_new_blob);
  tor_free(err_msg);
  tor_free(encoded);
  tor_free(arg_str);
}
Пример #26
0
void scalliontor_readCPUWorkerCallback(int sockd, short ev_types, void * arg) {
	/* adapted from cpuworker_main.
	 *
	 * these are blocking calls in Tor. we need to cope, so the approach we
	 * take is that if the first read would block, its ok. after that, we
	 * continue through the state machine until we are able to read and write
	 * everything we need to, then reset and start with the next question.
	 *
	 * this is completely nonblocking with the state machine.
	 */
	vtor_cpuworker_tp cpuw = arg;
	g_assert(cpuw);

	if(cpuw->state == CPUW_NONE) {
		cpuw->state = CPUW_READTYPE;
	}

	int ioResult = 0;
	int action = 0;

enter:

	switch(cpuw->state) {
		case CPUW_READTYPE: {
			ioResult = 0;

			/* get the type of question */
			ioResult = recv(cpuw->fd, &(cpuw->question_type), 1, 0);

			action = scalliontor_checkIOResult(cpuw, ioResult);
			if(action == -1) goto kill;
			else if(action == 0) goto exit;

			/* we got our initial question type */
			tor_assert(cpuw->question_type == CPUWORKER_TASK_ONION);

			cpuw->state = CPUW_READTAG;
			goto enter;
		}

		case CPUW_READTAG: {
			ioResult = 0;
			action = 1;
			int bytesNeeded = TAG_LEN;

			while(action > 0 && cpuw->offset < bytesNeeded) {
				ioResult = recv(cpuw->fd, cpuw->tag+cpuw->offset, bytesNeeded-cpuw->offset, 0);

				action = scalliontor_checkIOResult(cpuw, ioResult);
				if(action == -1) goto kill;
				else if(action == 0) goto exit;

				/* read some bytes */
				cpuw->offset += action;
			}

			/* we got what we needed, assert this */
			if (cpuw->offset != TAG_LEN) {
			  log_err(LD_BUG,"read tag failed. Exiting.");
			  goto kill;
			}

			cpuw->state = CPUW_READCHALLENGE;
			cpuw->offset = 0;
			goto enter;
		}

		case CPUW_READCHALLENGE: {
			ioResult = 0;
			action = 1;
			int bytesNeeded = ONIONSKIN_CHALLENGE_LEN;

			while(action > 0 && cpuw->offset < bytesNeeded) {
				ioResult = recv(cpuw->fd, cpuw->question+cpuw->offset, bytesNeeded-cpuw->offset, 0);

				action = scalliontor_checkIOResult(cpuw, ioResult);
				if(action == -1) goto kill;
				else if(action == 0) goto exit;

				/* read some bytes */
				cpuw->offset += action;
			}

			/* we got what we needed, assert this */
			if (cpuw->offset != ONIONSKIN_CHALLENGE_LEN) {
			  log_err(LD_BUG,"read question failed. got %i bytes, expecting %i bytes. Exiting.", cpuw->offset, ONIONSKIN_CHALLENGE_LEN);
			  goto kill;
			}

			cpuw->state = CPUW_PROCESS;
			cpuw->offset = 0;
			goto enter;
		}

		case CPUW_PROCESS: {
			if (cpuw->question_type != CPUWORKER_TASK_ONION) {
				log_debug(LD_OR,"unknown CPU worker question type. ignoring...");
				cpuw->state = CPUW_READTYPE;
				cpuw->offset = 0;
				goto exit;
			}


			int r = onion_skin_server_handshake(cpuw->question, cpuw->onion_key, cpuw->last_onion_key,
					  cpuw->reply_to_proxy, cpuw->keys, CPATH_KEY_MATERIAL_LEN);

			if (r < 0) {
				/* failure */
				log_debug(LD_OR,"onion_skin_server_handshake failed.");
				*(cpuw->buf) = 0; /* indicate failure in first byte */
				memcpy(cpuw->buf+1,cpuw->tag,TAG_LEN);
				/* send all zeros as answer */
				memset(cpuw->buf+1+TAG_LEN, 0, LEN_ONION_RESPONSE-(1+TAG_LEN));
			} else {
				/* success */
				log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
				cpuw->buf[0] = 1; /* 1 means success */
				memcpy(cpuw->buf+1,cpuw->tag,TAG_LEN);
				memcpy(cpuw->buf+1+TAG_LEN,cpuw->reply_to_proxy,ONIONSKIN_REPLY_LEN);
				memcpy(cpuw->buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,cpuw->keys,CPATH_KEY_MATERIAL_LEN);
			}

			cpuw->state = CPUW_WRITERESPONSE;
			cpuw->offset = 0;
			goto enter;
		}

		case CPUW_WRITERESPONSE: {
			ioResult = 0;
			action = 1;
			int bytesNeeded = LEN_ONION_RESPONSE;

			while(action > 0 && cpuw->offset < bytesNeeded) {
				ioResult = send(cpuw->fd, cpuw->buf+cpuw->offset, bytesNeeded-cpuw->offset, 0);

				action = scalliontor_checkIOResult(cpuw, ioResult);
				if(action == -1) goto kill;
				else if(action == 0) goto exit;

				/* wrote some bytes */
				cpuw->offset += action;
			}

			/* we wrote what we needed, assert this */
			if (cpuw->offset != LEN_ONION_RESPONSE) {
				log_err(LD_BUG,"writing response buf failed. Exiting.");
				goto kill;
			}

			log_debug(LD_OR,"finished writing response.");

			cpuw->state = CPUW_READTYPE;
			cpuw->offset = 0;
			goto enter;
		}

		default: {
			log_err(LD_BUG,"unknown CPU worker state. Exiting.");
			goto kill;
		}
	}

exit:
	return;

kill:
	if(cpuw != NULL) {
		if (cpuw->onion_key)
			crypto_pk_free(cpuw->onion_key);
		if (cpuw->last_onion_key)
			crypto_pk_free(cpuw->last_onion_key);
		tor_close_socket(cpuw->fd);
		event_del(&(cpuw->read_event));
		free(cpuw);
	}
}
Пример #27
0
/** Process an AUTHENTICATE cell from an OR connection.
 *
 * If it's ill-formed or we weren't supposed to get one or we're not doing a
 * v3 handshake, then mark the connection.  If it does not authenticate the
 * other side of the connection successfully (because it isn't signed right,
 * we didn't get a CERTS cell, etc) mark the connection.  Otherwise, accept
 * the identity of the router on the other side of the connection.
 */
static void
command_process_authenticate_cell(var_cell_t *cell, or_connection_t *conn)
{
  uint8_t expected[V3_AUTH_FIXED_PART_LEN];
  const uint8_t *auth;
  int authlen;

#define ERR(s)                                                  \
  do {                                                          \
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,                      \
           "Received a bad AUTHENTICATE cell from %s:%d: %s",   \
           safe_str(conn->_base.address), conn->_base.port, (s));       \
    connection_mark_for_close(TO_CONN(conn));                   \
    return;                                                     \
  } while (0)

  if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3)
    ERR("We're not doing a v3 handshake");
  if (conn->link_proto < 3)
    ERR("We're not using link protocol >= 3");
  if (conn->handshake_state->started_here)
    ERR("We originated this connection");
  if (conn->handshake_state->received_authenticate)
    ERR("We already got one!");
  if (conn->handshake_state->authenticated) {
    /* Should be impossible given other checks */
    ERR("The peer is already authenticated");
  }
  if (! conn->handshake_state->received_certs_cell)
    ERR("We never got a certs cell");
  if (conn->handshake_state->auth_cert == NULL)
    ERR("We never got an authentication certificate");
  if (conn->handshake_state->id_cert == NULL)
    ERR("We never got an identity certificate");
  if (cell->payload_len < 4)
    ERR("Cell was way too short");

  auth = cell->payload;
  {
    uint16_t type = ntohs(get_uint16(auth));
    uint16_t len = ntohs(get_uint16(auth+2));
    if (4 + len > cell->payload_len)
      ERR("Authenticator was truncated");

    if (type != AUTHTYPE_RSA_SHA256_TLSSECRET)
      ERR("Authenticator type was not recognized");

    auth += 4;
    authlen = len;
  }

  if (authlen < V3_AUTH_BODY_LEN + 1)
    ERR("Authenticator was too short");

  if (connection_or_compute_authenticate_cell_body(
                        conn, expected, sizeof(expected), NULL, 1) < 0)
    ERR("Couldn't compute expected AUTHENTICATE cell body");

  if (tor_memneq(expected, auth, sizeof(expected)))
    ERR("Some field in the AUTHENTICATE cell body was not as expected");

  {
    crypto_pk_t *pk = tor_tls_cert_get_key(
                                   conn->handshake_state->auth_cert);
    char d[DIGEST256_LEN];
    char *signed_data;
    size_t keysize;
    int signed_len;

    if (!pk)
      ERR("Internal error: couldn't get RSA key from AUTH cert.");
    crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256);

    keysize = crypto_pk_keysize(pk);
    signed_data = tor_malloc(keysize);
    signed_len = crypto_pk_public_checksig(pk, signed_data, keysize,
                                           (char*)auth + V3_AUTH_BODY_LEN,
                                           authlen - V3_AUTH_BODY_LEN);
    crypto_pk_free(pk);
    if (signed_len < 0) {
      tor_free(signed_data);
      ERR("Signature wasn't valid");
    }
    if (signed_len < DIGEST256_LEN) {
      tor_free(signed_data);
      ERR("Not enough data was signed");
    }
    /* Note that we deliberately allow *more* than DIGEST256_LEN bytes here,
     * in case they're later used to hold a SHA3 digest or something. */
    if (tor_memneq(signed_data, d, DIGEST256_LEN)) {
      tor_free(signed_data);
      ERR("Signature did not match data to be signed.");
    }
    tor_free(signed_data);
  }

  /* Okay, we are authenticated. */
  conn->handshake_state->received_authenticate = 1;
  conn->handshake_state->authenticated = 1;
  conn->handshake_state->digest_received_data = 0;
  {
    crypto_pk_t *identity_rcvd =
      tor_tls_cert_get_key(conn->handshake_state->id_cert);
    const digests_t *id_digests =
      tor_cert_get_id_digests(conn->handshake_state->id_cert);

    /* This must exist; we checked key type when reading the cert. */
    tor_assert(id_digests);

    memcpy(conn->handshake_state->authenticated_peer_id,
           id_digests->d[DIGEST_SHA1], DIGEST_LEN);

    connection_or_set_circid_type(conn, identity_rcvd);
    crypto_pk_free(identity_rcvd);

    connection_or_init_conn_from_address(conn,
                  &conn->_base.addr,
                  conn->_base.port,
                  (const char*)conn->handshake_state->authenticated_peer_id,
                  0);

    log_info(LD_OR, "Got an AUTHENTICATE cell from %s:%d: Looks good.",
             safe_str(conn->_base.address), conn->_base.port);
  }

#undef ERR
}
Пример #28
0
Файл: test.c Проект: ageis/tor
static void
test_bad_onion_handshake(void *arg)
{
  char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
  char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN];
  /* client-side */
  crypto_dh_t *c_dh = NULL;
  char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
  char c_keys[40];
  /* server-side */
  char s_buf[TAP_ONIONSKIN_REPLY_LEN];
  char s_keys[40];
  /* shared */
  crypto_pk_t *pk = NULL, *pk2 = NULL;

  (void)arg;

  pk = pk_generate(0);
  pk2 = pk_generate(1);

  /* Server: Case 1: the encrypted data is degenerate. */
  memset(junk_buf, 0, sizeof(junk_buf));
  crypto_pk_obsolete_public_hybrid_encrypt(pk,
                               junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN,
                               junk_buf, DH_KEY_LEN, PK_PKCS1_OAEP_PADDING, 1);
  tt_int_op(-1, OP_EQ,
            onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
                                            s_buf, s_keys, 40));

  /* Server: Case 2: the encrypted data is not long enough. */
  memset(junk_buf, 0, sizeof(junk_buf));
  memset(junk_buf2, 0, sizeof(junk_buf2));
  crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2),
                               junk_buf, 48, PK_PKCS1_OAEP_PADDING);
  tt_int_op(-1, OP_EQ,
            onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
                                            s_buf, s_keys, 40));

  /* client handshake 1: do it straight. */
  memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
  tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));

  /* Server: Case 3: we just don't have the right key. */
  tt_int_op(-1, OP_EQ,
            onion_skin_TAP_server_handshake(c_buf, pk2, NULL,
                                            s_buf, s_keys, 40));

  /* Server: Case 4: The RSA-encrypted portion is corrupt. */
  c_buf[64] ^= 33;
  tt_int_op(-1, OP_EQ,
            onion_skin_TAP_server_handshake(c_buf, pk, NULL,
                                            s_buf, s_keys, 40));
  c_buf[64] ^= 33;

  /* (Let the server procede) */
  tt_int_op(0, OP_EQ,
            onion_skin_TAP_server_handshake(c_buf, pk, NULL,
                                            s_buf, s_keys, 40));

  /* Client: Case 1: The server sent back junk. */
  const char *msg = NULL;
  s_buf[64] ^= 33;
  tt_int_op(-1, OP_EQ,
            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
  s_buf[64] ^= 33;
  tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. "
            "Bug or attack.");

  /* Let the client finish; make sure it can. */
  msg = NULL;
  tt_int_op(0, OP_EQ,
            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
  tt_mem_op(s_keys,OP_EQ, c_keys, 40);
  tt_ptr_op(msg, OP_EQ, NULL);

  /* Client: Case 2: The server sent back a degenerate DH. */
  memset(s_buf, 0, sizeof(s_buf));
  tt_int_op(-1, OP_EQ,
            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
  tt_str_op(msg, OP_EQ, "DH computation failed.");

 done:
  crypto_dh_free(c_dh);
  crypto_pk_free(pk);
  crypto_pk_free(pk2);
}
Пример #29
0
/** Process a CERTS cell from an OR connection.
 *
 * If the other side should not have sent us a CERTS cell, or the cell is
 * malformed, or it is supposed to authenticate the TLS key but it doesn't,
 * then mark the connection.
 *
 * If the cell has a good cert chain and we're doing a v3 handshake, then
 * store the certificates in or_handshake_state.  If this is the client side
 * of the connection, we then authenticate the server or mark the connection.
 * If it's the server side, wait for an AUTHENTICATE cell.
 */
static void
command_process_certs_cell(var_cell_t *cell, or_connection_t *conn)
{
#define ERR(s)                                                  \
  do {                                                          \
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,                      \
           "Received a bad CERTS cell from %s:%d: %s",          \
           safe_str(conn->_base.address), conn->_base.port, (s)); \
    connection_mark_for_close(TO_CONN(conn));                   \
    goto err;                                                   \
  } while (0)

  tor_cert_t *link_cert = NULL;
  tor_cert_t *id_cert = NULL;
  tor_cert_t *auth_cert = NULL;

  uint8_t *ptr;
  int n_certs, i;

  if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3)
    ERR("We're not doing a v3 handshake!");
  if (conn->link_proto < 3)
    ERR("We're not using link protocol >= 3");
  if (conn->handshake_state->received_certs_cell)
    ERR("We already got one");
  if (conn->handshake_state->authenticated) {
    /* Should be unreachable, but let's make sure. */
    ERR("We're already authenticated!");
  }
  if (cell->payload_len < 1)
    ERR("It had no body");
  if (cell->circ_id)
    ERR("It had a nonzero circuit ID");

  n_certs = cell->payload[0];
  ptr = cell->payload + 1;
  for (i = 0; i < n_certs; ++i) {
    uint8_t cert_type;
    uint16_t cert_len;
    if (ptr + 3 > cell->payload + cell->payload_len) {
      goto truncated;
    }
    cert_type = *ptr;
    cert_len = ntohs(get_uint16(ptr+1));
    if (ptr + 3 + cert_len > cell->payload + cell->payload_len) {
      goto truncated;
    }
    if (cert_type == OR_CERT_TYPE_TLS_LINK ||
        cert_type == OR_CERT_TYPE_ID_1024 ||
        cert_type == OR_CERT_TYPE_AUTH_1024) {
      tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len);
      if (!cert) {
        log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
               "Received undecodable certificate in CERTS cell from %s:%d",
               safe_str(conn->_base.address), conn->_base.port);
      } else {
        if (cert_type == OR_CERT_TYPE_TLS_LINK) {
          if (link_cert) {
            tor_cert_free(cert);
            ERR("Too many TLS_LINK certificates");
          }
          link_cert = cert;
        } else if (cert_type == OR_CERT_TYPE_ID_1024) {
          if (id_cert) {
            tor_cert_free(cert);
            ERR("Too many ID_1024 certificates");
          }
          id_cert = cert;
        } else if (cert_type == OR_CERT_TYPE_AUTH_1024) {
          if (auth_cert) {
            tor_cert_free(cert);
            ERR("Too many AUTH_1024 certificates");
          }
          auth_cert = cert;
        } else {
          tor_cert_free(cert);
        }
      }
    }
    ptr += 3 + cert_len;
    continue;

  truncated:
    ERR("It ends in the middle of a certificate");
  }

  if (conn->handshake_state->started_here) {
    int severity;
    if (! (id_cert && link_cert))
      ERR("The certs we wanted were missing");
    /* Okay. We should be able to check the certificates now. */
    if (! tor_tls_cert_matches_key(conn->tls, link_cert)) {
      ERR("The link certificate didn't match the TLS public key");
    }
    /* Note that this warns more loudly about time and validity if we were
    * _trying_ to connect to an authority, not necessarily if we _did_ connect
    * to one. */
    if (router_digest_is_trusted_dir(conn->identity_digest))
      severity = LOG_WARN;
    else
      severity = LOG_PROTOCOL_WARN;

    if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0))
      ERR("The link certificate was not valid");
    if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1))
      ERR("The ID certificate was not valid");

    conn->handshake_state->authenticated = 1;
    {
      const digests_t *id_digests = tor_cert_get_id_digests(id_cert);
      crypto_pk_t *identity_rcvd;
      if (!id_digests)
        ERR("Couldn't compute digests for key in ID cert");

      identity_rcvd = tor_tls_cert_get_key(id_cert);
      if (!identity_rcvd)
        ERR("Internal error: Couldn't get RSA key from ID cert.");
      memcpy(conn->handshake_state->authenticated_peer_id,
             id_digests->d[DIGEST_SHA1], DIGEST_LEN);
      connection_or_set_circid_type(conn, identity_rcvd);
      crypto_pk_free(identity_rcvd);
    }

    if (connection_or_client_learned_peer_id(conn,
                      conn->handshake_state->authenticated_peer_id) < 0)
      ERR("Problem setting or checking peer id");

    log_info(LD_OR, "Got some good certificates from %s:%d: Authenticated it.",
             safe_str(conn->_base.address), conn->_base.port);

    conn->handshake_state->id_cert = id_cert;
    id_cert = NULL;
  } else {
    if (! (id_cert && auth_cert))
      ERR("The certs we wanted were missing");

    /* Remember these certificates so we can check an AUTHENTICATE cell */
    if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1))
      ERR("The authentication certificate was not valid");
    if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1))
      ERR("The ID certificate was not valid");

    log_info(LD_OR, "Got some good certificates from %s:%d: "
             "Waiting for AUTHENTICATE.",
             safe_str(conn->_base.address), conn->_base.port);
    /* XXXX check more stuff? */

    conn->handshake_state->id_cert = id_cert;
    conn->handshake_state->auth_cert = auth_cert;
    id_cert = auth_cert = NULL;
  }

  conn->handshake_state->received_certs_cell = 1;
 err:
  tor_cert_free(id_cert);
  tor_cert_free(link_cert);
  tor_cert_free(auth_cert);
#undef ERR
}
Пример #30
0
/** Successfully register a v2 intro point and a v3 intro point. Ensure that HS
 *  circuitmap is maintained properly. */
static void
test_intro_point_registration(void *arg)
{
  int retval;
  hs_circuitmap_ht *the_hs_circuitmap = NULL;

  or_circuit_t *intro_circ = NULL;
  trn_cell_establish_intro_t *establish_intro_cell = NULL;
  ed25519_public_key_t auth_key;

  crypto_pk_t *legacy_auth_key = NULL;
  or_circuit_t *legacy_intro_circ = NULL;

  or_circuit_t *returned_intro_circ = NULL;

  (void) arg;

  MOCK(hs_intro_send_intro_established_cell, mock_send_intro_established_cell);

  hs_circuitmap_init();

  /* Check that the circuitmap is currently empty */
  {
    the_hs_circuitmap = get_hs_circuitmap();
    tt_assert(the_hs_circuitmap);
    tt_int_op(0, OP_EQ, HT_SIZE(the_hs_circuitmap));
    /* Do a circuitmap query in any case */
    returned_intro_circ =hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
    tt_ptr_op(returned_intro_circ, OP_EQ, NULL);
  }

  /* Create a v3 intro point */
  {
    intro_circ = or_circuit_new(0, NULL);
    tt_assert(intro_circ);
    establish_intro_cell = helper_establish_intro_v3(intro_circ);

    /* Check that the intro point was registered on the HS circuitmap */
    the_hs_circuitmap = get_hs_circuitmap();
    tt_assert(the_hs_circuitmap);
    tt_int_op(1, OP_EQ, HT_SIZE(the_hs_circuitmap));
    get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO,
                           establish_intro_cell);
    returned_intro_circ =
      hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
    tt_ptr_op(intro_circ, OP_EQ, returned_intro_circ);
  }

  /* Create a v2 intro point */
  {
    char key_digest[DIGEST_LEN];

    legacy_intro_circ = or_circuit_new(1, NULL);
    tt_assert(legacy_intro_circ);
    legacy_auth_key = helper_establish_intro_v2(legacy_intro_circ);
    tt_assert(legacy_auth_key);

    /* Check that the circuitmap now has two elements */
    the_hs_circuitmap = get_hs_circuitmap();
    tt_assert(the_hs_circuitmap);
    tt_int_op(2, OP_EQ, HT_SIZE(the_hs_circuitmap));

    /* Check that the new element is our legacy intro circuit. */
    retval = crypto_pk_get_digest(legacy_auth_key, key_digest);
    tt_int_op(retval, OP_EQ, 0);
    returned_intro_circ =
      hs_circuitmap_get_intro_circ_v2_relay_side((uint8_t*)key_digest);
    tt_ptr_op(legacy_intro_circ, OP_EQ, returned_intro_circ);
  }

  /* XXX Continue test and try to register a second v3 intro point with the
   * same auth key. Make sure that old intro circuit gets closed. */

 done:
  crypto_pk_free(legacy_auth_key);
  circuit_free_(TO_CIRCUIT(intro_circ));
  circuit_free_(TO_CIRCUIT(legacy_intro_circ));
  trn_cell_establish_intro_free(establish_intro_cell);
  test_circuitmap_free_all();

  UNMOCK(hs_intro_send_intro_established_cell);
}