Exemplo n.º 1
0
/** We received an ESTABLISH_INTRO <b>cell</b>. Verify its signature and MAC,
 *  given <b>circuit_key_material</b>. Return 0 on success else -1 on error. */
STATIC int
verify_establish_intro_cell(const trn_cell_establish_intro_t *cell,
                            const uint8_t *circuit_key_material,
                            size_t circuit_key_material_len)
{
  /* We only reach this function if the first byte of the cell is 0x02 which
   * means that auth_key_type is of ed25519 type, hence this check should
   * always pass. See hs_intro_received_establish_intro().  */
  if (BUG(cell->auth_key_type != HS_INTRO_AUTH_KEY_TYPE_ED25519)) {
    return -1;
  }

  /* Make sure the auth key length is of the right size for this type. For
   * EXTRA safety, we check both the size of the array and the length which
   * must be the same. Safety first!*/
  if (trn_cell_establish_intro_getlen_auth_key(cell) != ED25519_PUBKEY_LEN ||
      trn_cell_establish_intro_get_auth_key_len(cell) != ED25519_PUBKEY_LEN) {
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "ESTABLISH_INTRO auth key length is invalid");
    return -1;
  }

  const uint8_t *msg = cell->start_cell;

  /* Verify the sig */
  {
    ed25519_signature_t sig_struct;
    const uint8_t *sig_array =
      trn_cell_establish_intro_getconstarray_sig(cell);

    /* Make sure the signature length is of the right size. For EXTRA safety,
     * we check both the size of the array and the length which must be the
     * same. Safety first!*/
    if (trn_cell_establish_intro_getlen_sig(cell) != sizeof(sig_struct.sig) ||
        trn_cell_establish_intro_get_sig_len(cell) != sizeof(sig_struct.sig)) {
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "ESTABLISH_INTRO sig len is invalid");
      return -1;
    }
    /* We are now sure that sig_len is of the right size. */
    memcpy(sig_struct.sig, sig_array, cell->sig_len);

    ed25519_public_key_t auth_key;
    get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO, cell);

    const size_t sig_msg_len = cell->end_sig_fields - msg;
    int sig_mismatch = ed25519_checksig_prefixed(&sig_struct,
                                                 msg, sig_msg_len,
                                                 ESTABLISH_INTRO_SIG_PREFIX,
                                                 &auth_key);
    if (sig_mismatch) {
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "ESTABLISH_INTRO signature not as expected");
      return -1;
    }
  }

  /* Verify the MAC */
  {
    const size_t auth_msg_len = cell->end_mac_fields - msg;
    uint8_t mac[DIGEST256_LEN];
    crypto_mac_sha3_256(mac, sizeof(mac),
                        circuit_key_material, circuit_key_material_len,
                        msg, auth_msg_len);
    if (tor_memneq(mac, cell->handshake_mac, sizeof(mac))) {
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "ESTABLISH_INTRO handshake_auth not as expected");
      return -1;
    }
  }

  return 0;
}
Exemplo n.º 2
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);
}