Example #1
0
ssize_t
trn_cell_introduce1_encode(uint8_t *output, const size_t avail, const trn_cell_introduce1_t *obj)
{
  ssize_t result = 0;
  size_t written = 0;
  uint8_t *ptr = output;
  const char *msg;
#ifdef TRUNNEL_CHECK_ENCODED_LEN
  const ssize_t encoded_len = trn_cell_introduce1_encoded_len(obj);
#endif

  if (NULL != (msg = trn_cell_introduce1_check(obj)))
    goto check_failed;

#ifdef TRUNNEL_CHECK_ENCODED_LEN
  trunnel_assert(encoded_len >= 0);
#endif

  /* Encode u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
  trunnel_assert(written <= avail);
  if (avail - written < TRUNNEL_SHA1_LEN)
    goto truncated;
  memcpy(ptr, obj->legacy_key_id, TRUNNEL_SHA1_LEN);
  written += TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;

  /* Encode u8 auth_key_type IN [0, 1, 2] */
  trunnel_assert(written <= avail);
  if (avail - written < 1)
    goto truncated;
  trunnel_set_uint8(ptr, (obj->auth_key_type));
  written += 1; ptr += 1;

  /* Encode u16 auth_key_len */
  trunnel_assert(written <= avail);
  if (avail - written < 2)
    goto truncated;
  trunnel_set_uint16(ptr, trunnel_htons(obj->auth_key_len));
  written += 2; ptr += 2;

  /* Encode u8 auth_key[auth_key_len] */
  {
    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
    trunnel_assert(obj->auth_key_len == elt_len);
    trunnel_assert(written <= avail);
    if (avail - written < elt_len)
      goto truncated;
    if (elt_len)
      memcpy(ptr, obj->auth_key.elts_, elt_len);
    written += elt_len; ptr += elt_len;
  }

  /* Encode struct trn_cell_extension extensions */
  trunnel_assert(written <= avail);
  result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
  if (result < 0)
    goto fail; /* XXXXXXX !*/
  written += result; ptr += result;

  /* Encode u8 encrypted[] */
  {
    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
    trunnel_assert(written <= avail);
    if (avail - written < elt_len)
      goto truncated;
    if (elt_len)
      memcpy(ptr, obj->encrypted.elts_, elt_len);
    written += elt_len; ptr += elt_len;
  }


  trunnel_assert(ptr == output + written);
#ifdef TRUNNEL_CHECK_ENCODED_LEN
  {
    trunnel_assert(encoded_len >= 0);
    trunnel_assert((size_t)encoded_len == written);
  }

#endif

  return written;

 truncated:
  result = -2;
  goto fail;
 check_failed:
  (void)msg;
  result = -1;
  goto fail;
 fail:
  trunnel_assert(result < 0);
  return result;
}
Example #2
0
static void
test_received_introduce1_handling(void *arg)
{
  int ret;
  uint8_t *request = NULL, buf[128];
  trn_cell_introduce1_t *cell = NULL;
  or_circuit_t *circ = NULL;

  (void) arg;

  MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);

  hs_circuitmap_init();

  /* Too small request length. An INTRODUCE1 expect at the very least a
   * DIGEST_LEN size. */
  {
    memset(buf, 0, sizeof(buf));
    circ = helper_create_intro_circuit();
    ret = hs_intro_received_introduce1(circ, buf, DIGEST_LEN - 1);
    tt_int_op(ret, OP_EQ, -1);
    circuit_free_(TO_CIRCUIT(circ));
  }

  /* We have a unit test only for the suitability of a circuit to receive an
   * INTRODUCE1 cell so from now on we'll only test the handling of a cell. */

  /* Bad request. */
  {
    circ = helper_create_intro_circuit();
    uint8_t test[2]; /* Too small request. */
    memset(test, 0, sizeof(test));
    ret = handle_introduce1(circ, test, sizeof(test));
    tor_free(circ->p_chan);
    circuit_free_(TO_CIRCUIT(circ));
    tt_int_op(ret, OP_EQ, -1);
  }

  /* Valid case. */
  {
    cell = helper_create_introduce1_cell();
    ssize_t request_len = trn_cell_introduce1_encoded_len(cell);
    tt_int_op((int)request_len, OP_GT, 0);
    request = tor_malloc_zero(request_len);
    ssize_t encoded_len =
      trn_cell_introduce1_encode(request, request_len, cell);
    tt_int_op((int)encoded_len, OP_GT, 0);

    circ = helper_create_intro_circuit();
    or_circuit_t *service_circ = helper_create_intro_circuit();
    circuit_change_purpose(TO_CIRCUIT(service_circ),
                           CIRCUIT_PURPOSE_INTRO_POINT);
    /* Register the circuit in the map for the auth key of the cell. */
    ed25519_public_key_t auth_key;
    const uint8_t *cell_auth_key =
      trn_cell_introduce1_getconstarray_auth_key(cell);
    memcpy(auth_key.pubkey, cell_auth_key, ED25519_PUBKEY_LEN);
    hs_circuitmap_register_intro_circ_v3_relay_side(service_circ, &auth_key);
    ret = hs_intro_received_introduce1(circ, request, request_len);
    circuit_free_(TO_CIRCUIT(circ));
    circuit_free_(TO_CIRCUIT(service_circ));
    tt_int_op(ret, OP_EQ, 0);
  }

  /* Valid legacy cell. */
  {
    tor_free(request);
    trn_cell_introduce1_free(cell);
    cell = helper_create_introduce1_cell();
    uint8_t *legacy_key_id = trn_cell_introduce1_getarray_legacy_key_id(cell);
    memset(legacy_key_id, 'a', DIGEST_LEN);
    /* Add an arbitrary amount of data for the payload of a v2 cell. */
    size_t request_len = trn_cell_introduce1_encoded_len(cell) + 256;
    tt_size_op(request_len, OP_GT, 0);
    request = tor_malloc_zero(request_len + 256);
    ssize_t encoded_len =
      trn_cell_introduce1_encode(request, request_len, cell);
    tt_int_op((int)encoded_len, OP_GT, 0);

    circ = helper_create_intro_circuit();
    or_circuit_t *service_circ = helper_create_intro_circuit();
    circuit_change_purpose(TO_CIRCUIT(service_circ),
                           CIRCUIT_PURPOSE_INTRO_POINT);
    /* Register the circuit in the map for the auth key of the cell. */
    uint8_t token[REND_TOKEN_LEN];
    memcpy(token, legacy_key_id, sizeof(token));
    hs_circuitmap_register_intro_circ_v2_relay_side(service_circ, token);
    ret = hs_intro_received_introduce1(circ, request, request_len);
    circuit_free_(TO_CIRCUIT(circ));
    circuit_free_(TO_CIRCUIT(service_circ));
    tt_int_op(ret, OP_EQ, 0);
  }

 done:
  trn_cell_introduce1_free(cell);
  tor_free(request);
  hs_circuitmap_free_all();
  UNMOCK(relay_send_command_from_edge_);
}