Пример #1
0
/** 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);
}
Пример #2
0
static size_t
new_establish_intro_cell(const char *circ_nonce,
                         trn_cell_establish_intro_t **cell_out)
{
  ssize_t cell_len = 0;
  uint8_t buf[RELAY_PAYLOAD_SIZE] = {0};
  trn_cell_establish_intro_t *cell = NULL;
  hs_service_intro_point_t *ip = NULL;

  /* Ensure that *cell_out is NULL such that we can use to check if we need to
   * free `cell` in case of an error. */
  *cell_out = NULL;

  /* Auth key pair is generated in the constructor so we are all set for
   * using this IP object. */
  ip = service_intro_point_new(NULL);
  tt_assert(ip);
  cell_len = hs_cell_build_establish_intro(circ_nonce, ip, buf);
  tt_i64_op(cell_len, OP_GT, 0);

  cell_len = trn_cell_establish_intro_parse(&cell, buf, sizeof(buf));
  tt_i64_op(cell_len, OP_GT, 0);
  tt_assert(cell);
  *cell_out = cell;

 done:
  if (*cell_out == NULL)
    trn_cell_establish_intro_free(cell);

  service_intro_point_free(ip);
  return cell_len;
}
Пример #3
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);
}
Пример #4
0
static ssize_t
new_establish_intro_encoded_cell(const char *circ_nonce, uint8_t *cell_out)
{
  ssize_t cell_len = 0;
  hs_service_intro_point_t *ip = NULL;

  /* Auth key pair is generated in the constructor so we are all set for
   * using this IP object. */
  ip = service_intro_point_new(NULL);
  tt_assert(ip);
  cell_len = hs_cell_build_establish_intro(circ_nonce, ip, cell_out);
  tt_i64_op(cell_len, OP_GT, 0);

 done:
  service_intro_point_free(ip);
  return cell_len;
}
Пример #5
0
/* For a given introduction point and an introduction circuit, send the
 * ESTABLISH_INTRO cell. The service object is used for logging. This can fail
 * and if so, the circuit is closed and the intro point object is flagged
 * that the circuit is not established anymore which is important for the
 * retry mechanism. */
static void
send_establish_intro(const hs_service_t *service,
                     hs_service_intro_point_t *ip, origin_circuit_t *circ)
{
  ssize_t cell_len;
  uint8_t payload[RELAY_PAYLOAD_SIZE];

  tor_assert(service);
  tor_assert(ip);
  tor_assert(circ);

  /* Encode establish intro cell. */
  cell_len = hs_cell_build_establish_intro(circ->cpath->prev->rend_circ_nonce,
                                           ip, payload);
  if (cell_len < 0) {
    log_warn(LD_REND, "Unable to encode ESTABLISH_INTRO cell for service %s "
                      "on circuit %u. Closing circuit.",
             safe_str_client(service->onion_address),
             TO_CIRCUIT(circ)->n_circ_id);
    goto err;
  }

  /* Send the cell on the circuit. */
  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
                                   RELAY_COMMAND_ESTABLISH_INTRO,
                                   (char *) payload, cell_len,
                                   circ->cpath->prev) < 0) {
    log_info(LD_REND, "Unable to send ESTABLISH_INTRO cell for service %s "
                      "on circuit %u.",
             safe_str_client(service->onion_address),
             TO_CIRCUIT(circ)->n_circ_id);
    /* On error, the circuit has been closed. */
    goto done;
  }

  /* Record the attempt to use this circuit. */
  pathbias_count_use_attempt(circ);
  goto done;

 err:
  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
 done:
  memwipe(payload, 0, sizeof(payload));
}