tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

conflux_cell.c (10582B)


      1 /* Copyright (c) 2023, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file conflux_cell.c
      6 * \brief XXX: Write a brief introduction to this module.
      7 **/
      8 
      9 #define CONFLUX_CELL_PRIVATE
     10 
     11 #include "app/config/config.h"
     12 
     13 #include "core/or/conflux.h"
     14 #include "core/or/conflux_cell.h"
     15 #include "core/or/relay.h"
     16 #include "core/or/circuitlist.h"
     17 
     18 #include "lib/crypt_ops/crypto_rand.h"
     19 
     20 #include "trunnel/conflux.h"
     21 
     22 #include "core/or/crypt_path_st.h"
     23 #include "core/or/or_circuit_st.h"
     24 #include "core/or/origin_circuit_st.h"
     25 
     26 STATIC ssize_t
     27 build_link_cell(const conflux_cell_link_t *link, uint8_t *cell_out)
     28 {
     29  ssize_t cell_len = -1;
     30  trn_cell_conflux_link_t *cell = NULL;
     31  trn_cell_conflux_link_payload_v1_t *payload = NULL;
     32 
     33  tor_assert(cell_out);
     34 
     35  cell = trn_cell_conflux_link_new();
     36  trn_cell_conflux_link_set_version(cell, 0x01);
     37 
     38  payload = trn_cell_conflux_link_payload_v1_new();
     39 
     40  /* Set the nonce. */
     41  size_t nonce_len = trn_cell_conflux_link_payload_v1_getlen_nonce(payload);
     42  tor_assert(nonce_len == sizeof(link->nonce));
     43  memcpy(trn_cell_conflux_link_payload_v1_getarray_nonce(payload),
     44         link->nonce, nonce_len);
     45 
     46  /* Set the sequence number. */
     47  trn_cell_conflux_link_payload_v1_set_last_seqno_recv(payload,
     48                                                       link->last_seqno_recv);
     49  trn_cell_conflux_link_payload_v1_set_last_seqno_sent(payload,
     50                                                       link->last_seqno_sent);
     51 
     52  /* Set the algorithm */
     53  trn_cell_conflux_link_payload_v1_set_desired_ux(payload, link->desired_ux);
     54 
     55  /* Encode payload. */
     56  ssize_t pay_len = trn_cell_conflux_link_payload_v1_encoded_len(payload);
     57  tor_assert(pay_len >= 0);
     58 
     59  trn_cell_conflux_link_setlen_payload(cell, pay_len);
     60 
     61  trn_cell_conflux_link_payload_v1_encode(
     62      trn_cell_conflux_link_getarray_payload(cell),
     63      trn_cell_conflux_link_getlen_payload(cell), payload);
     64 
     65  /* Encode cell. */
     66  cell_len = trn_cell_conflux_link_encode(cell_out,
     67                                          RELAY_PAYLOAD_SIZE_MAX, cell);
     68 
     69  trn_cell_conflux_link_payload_v1_free(payload);
     70  trn_cell_conflux_link_free(cell);
     71  return cell_len;
     72 }
     73 
     74 static ssize_t
     75 build_linked_cell(const conflux_cell_link_t *link, uint8_t *cell_out)
     76 {
     77  /* Same payload. This might not be true in the future but for now, we don't
     78   * need to duplicate the code as it is really the same. */
     79  return build_link_cell(link, cell_out);
     80 }
     81 
     82 static ssize_t
     83 build_linked_ack_cell(uint8_t *cell_out)
     84 {
     85  ssize_t cell_len = -1;
     86  trn_cell_conflux_linked_ack_t *cell = NULL;
     87 
     88  tor_assert(cell_out);
     89 
     90  cell = trn_cell_conflux_linked_ack_new();
     91  cell_len = trn_cell_conflux_linked_ack_encode(cell_out,
     92                                                RELAY_PAYLOAD_SIZE_MAX,
     93                                                cell);
     94 
     95  trn_cell_conflux_linked_ack_free(cell);
     96  return cell_len;
     97 }
     98 
     99 bool
    100 conflux_cell_send_link(const conflux_cell_link_t *link, origin_circuit_t *circ)
    101 {
    102  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
    103  ssize_t cell_len;
    104 
    105  tor_assert(link);
    106  tor_assert(circ);
    107 
    108  log_info(LD_CIRC, "Sending CONFLUX_LINK cell onto origin circuit");
    109 
    110  /* Build the CONFLUX_LINK cell. */
    111  cell_len = build_link_cell(link, payload);
    112  if (BUG(cell_len < 0)) {
    113    log_info(LD_CIRC, "Unable to build CONFLUX_LINK cell.");
    114    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
    115    goto err;
    116  }
    117 
    118  /* Send the cell to the endpoint of the circuit. */
    119  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
    120                                   RELAY_COMMAND_CONFLUX_LINK,
    121                                   (char *) payload, cell_len,
    122                                   circ->cpath->prev) < 0) {
    123    log_info(LD_CIRC, "Unable to send CONFLUX_LINK cell.");
    124    goto err;
    125  }
    126 
    127  return true;
    128 
    129 err:
    130  return false;
    131 }
    132 
    133 bool
    134 conflux_cell_send_linked(const conflux_cell_link_t *link, or_circuit_t *circ)
    135 {
    136  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
    137  ssize_t cell_len;
    138 
    139  tor_assert(link);
    140  tor_assert(circ);
    141 
    142  log_info(LD_CIRC, "Sending CONFLUX_LINKED cell onto OR circuit");
    143 
    144  /* Build the CONFLUX_LINK cell. */
    145  cell_len = build_linked_cell(link, payload);
    146  if (BUG(cell_len < 0)) {
    147    log_info(LD_CIRC, "Unable to build CONFLUX_LINKED cell.");
    148    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
    149    goto err;
    150  }
    151 
    152  /* Send back the LINKED cell. */
    153  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
    154                                   RELAY_COMMAND_CONFLUX_LINKED,
    155                                   (char *) payload, cell_len, NULL) < 0) {
    156    log_info(LD_CIRC, "Unable to send CONFLUX_LINKED cell.");
    157    goto err;
    158  }
    159 
    160  return true;
    161 
    162 err:
    163  return false;
    164 }
    165 
    166 bool
    167 conflux_cell_send_linked_ack(origin_circuit_t *circ)
    168 {
    169  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
    170  ssize_t cell_len;
    171 
    172  tor_assert(circ);
    173 
    174  log_info(LD_CIRC, "Sending CONFLUX_LINKED_ACK cell onto origin circuit");
    175 
    176  /* Build the CONFLUX_LINKED_ACK cell. */
    177  cell_len = build_linked_ack_cell(payload);
    178  if (BUG(cell_len < 0)) {
    179    log_info(LD_CIRC, "Unable to build CONFLUX_LINKED_ACK cell.");
    180    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
    181    goto err;
    182  }
    183 
    184  /* Send the cell to the endpoint of the circuit. */
    185  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
    186                                   RELAY_COMMAND_CONFLUX_LINKED_ACK,
    187                                   (char *) payload, cell_len,
    188                                   circ->cpath->prev) < 0) {
    189    log_info(LD_CIRC, "Unable to send CONFLUX_LINKED_ACK cell.");
    190    goto err;
    191  }
    192 
    193  return true;
    194 
    195 err:
    196  return false;
    197 }
    198 
    199 static conflux_cell_link_t *
    200 conflux_cell_parse_link_v1(const trn_cell_conflux_link_t *trn_link)
    201 {
    202  conflux_cell_link_t *link = NULL;
    203  trn_cell_conflux_link_payload_v1_t *payload = NULL;
    204 
    205  if (trn_cell_conflux_link_payload_v1_parse(&payload,
    206               trn_cell_conflux_link_getconstarray_payload(trn_link),
    207               trn_cell_conflux_link_getlen_payload(trn_link)) < 0) {
    208    log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
    209           "Unable to parse CONFLUX_LINK v1 payload.");
    210    goto end;
    211  }
    212 
    213  link = tor_malloc_zero(sizeof(*link));
    214  link->version = trn_cell_conflux_link_get_version(trn_link);
    215  link->desired_ux =
    216    trn_cell_conflux_link_payload_v1_get_desired_ux(payload);
    217  link->last_seqno_recv =
    218    trn_cell_conflux_link_payload_v1_get_last_seqno_recv(payload);
    219  link->last_seqno_sent =
    220    trn_cell_conflux_link_payload_v1_get_last_seqno_sent(payload);
    221  memcpy(link->nonce,
    222         trn_cell_conflux_link_payload_v1_getconstarray_nonce(payload),
    223         trn_cell_conflux_link_payload_v1_getlen_nonce(payload));
    224 
    225 end:
    226  trn_cell_conflux_link_payload_v1_free(payload);
    227  return link;
    228 }
    229 
    230 conflux_cell_link_t *
    231 conflux_cell_parse_link(const relay_msg_t *msg)
    232 {
    233  conflux_cell_link_t *link = NULL;
    234  trn_cell_conflux_link_t *trn_cell = NULL;
    235 
    236  tor_assert(msg);
    237 
    238  if (trn_cell_conflux_link_parse(&trn_cell, msg->body, msg->length) < 0) {
    239    log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
    240           "Unable to parse CONFLUX_LINK cell.");
    241    goto end;
    242  }
    243 
    244  uint8_t version = trn_cell_conflux_link_get_version(trn_cell);
    245  switch (version) {
    246  case 0x01:
    247    link = conflux_cell_parse_link_v1(trn_cell);
    248    break;
    249  default:
    250    log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
    251           "Unsupported version %d in CONFLUX_LINK cell", version);
    252    goto end;
    253  }
    254 
    255 end:
    256  trn_cell_conflux_link_free(trn_cell);
    257  return link;
    258 }
    259 
    260 conflux_cell_link_t *
    261 conflux_cell_parse_linked(const relay_msg_t *msg)
    262 {
    263  /* At the moment, same exact payload so avoid code duplication. */
    264  return conflux_cell_parse_link(msg);
    265 }
    266 
    267 conflux_cell_link_t *
    268 conflux_cell_new_link(const uint8_t *nonce, uint64_t last_seqno_sent,
    269                      uint64_t last_seqno_recv, uint8_t ux)
    270 {
    271  conflux_cell_link_t *link = tor_malloc_zero(sizeof(*link));
    272 
    273  link->version = 0x01;
    274  link->desired_ux = ux;
    275 
    276  link->last_seqno_sent = last_seqno_sent;
    277  link->last_seqno_recv = last_seqno_recv;
    278  memcpy(link->nonce, nonce, sizeof(link->nonce));
    279 
    280  return link;
    281 }
    282 
    283 /**
    284 * Extracts the sequence number from a switch cell.
    285 */
    286 uint32_t
    287 conflux_cell_parse_switch(const relay_msg_t *msg)
    288 {
    289  uint32_t seq = 0;
    290  trn_cell_conflux_switch_t *switch_cell = NULL;
    291 
    292  tor_assert(msg);
    293 
    294  if (trn_cell_conflux_switch_parse(&switch_cell,
    295                                    msg->body, msg->length) < 0) {
    296    log_warn(LD_BUG, "Failed to parse switch cell");
    297    // Zero counts as a failure to the validation, since legs should
    298    // not switch after 0 cells.
    299    return 0;
    300  }
    301 
    302  seq = trn_cell_conflux_switch_get_seqnum(switch_cell);
    303 
    304  trn_cell_conflux_switch_free(switch_cell);
    305 
    306  return seq;
    307 }
    308 
    309 /** Send a RELAY_COMMAND_CONFLUX_SWITCH cell on the circuit. */
    310 bool
    311 conflux_send_switch_command(circuit_t *send_circ, uint64_t relative_seq)
    312 {
    313  trn_cell_conflux_switch_t *switch_cell = trn_cell_conflux_switch_new();
    314  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
    315  bool ret = true;
    316 
    317  tor_assert(send_circ);
    318 
    319  /* This is possible unfortunately because the sequence numbers are 64 bit
    320   * while in the SWITCH it is 32 bit. It would require more than 2.2 TB of
    321   * data to be transfered on a circuit to reach this. Worth avoiding. */
    322  if (relative_seq >= UINT32_MAX) {
    323    /* Avoid spamming logs with this, every hours should be fine. */
    324    static ratelim_t rlimit = RATELIM_INIT(60 * 60);
    325    log_fn_ratelim(&rlimit, LOG_WARN, LD_CIRC,
    326           "Relative sequence number is too high. Closing circuit.");
    327    ret = false;
    328    goto end;
    329  }
    330 
    331  trn_cell_conflux_switch_set_seqnum(switch_cell, (uint32_t)relative_seq);
    332 
    333  ssize_t len = trn_cell_conflux_switch_encode(
    334                                payload, RELAY_PAYLOAD_SIZE_MAX,
    335                                switch_cell);
    336  if (len < 0) {
    337    log_warn(LD_BUG, "Failed to encode conflux switch cell");
    338    ret = false;
    339    goto end;
    340  }
    341 
    342  /* Send the switch command to the new hop */
    343  if (CIRCUIT_IS_ORIGIN(send_circ)) {
    344    relay_send_command_from_edge(0, send_circ,
    345                               RELAY_COMMAND_CONFLUX_SWITCH,
    346                               (const char*)payload, len,
    347                               TO_ORIGIN_CIRCUIT(send_circ)->cpath->prev);
    348  } else {
    349    relay_send_command_from_edge(0, send_circ,
    350                               RELAY_COMMAND_CONFLUX_SWITCH,
    351                               (const char*)payload, len,
    352                               NULL);
    353  }
    354 
    355 end:
    356  trn_cell_conflux_switch_free(switch_cell);
    357  return ret;
    358 }