diff options
Diffstat (limited to 'src/or/relay.c')
-rw-r--r-- | src/or/relay.c | 206 |
1 files changed, 7 insertions, 199 deletions
diff --git a/src/or/relay.c b/src/or/relay.c index 7c21839a86..c6f030945b 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -70,6 +70,7 @@ #include "policies.h" #include "reasons.h" #include "relay.h" +#include "relay_crypto.h" #include "rendcache.h" #include "rendcommon.h" #include "router.h" @@ -122,79 +123,6 @@ uint64_t stats_n_relay_cells_delivered = 0; /** Used to tell which stream to read from first on a circuit. */ static tor_weak_rng_t stream_choice_rng = TOR_WEAK_RNG_INIT; -/** Update digest from the payload of cell. Assign integrity part to - * cell. - */ -static void -relay_set_digest(crypto_digest_t *digest, cell_t *cell) -{ - char integrity[4]; - relay_header_t rh; - - crypto_digest_add_bytes(digest, (char*)cell->payload, CELL_PAYLOAD_SIZE); - crypto_digest_get_digest(digest, integrity, 4); -// log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.", -// integrity[0], integrity[1], integrity[2], integrity[3]); - relay_header_unpack(&rh, cell->payload); - memcpy(rh.integrity, integrity, 4); - relay_header_pack(cell->payload, &rh); -} - -/** Does the digest for this circuit indicate that this cell is for us? - * - * Update digest from the payload of cell (with the integrity part set - * to 0). If the integrity part is valid, return 1, else restore digest - * and cell to their original state and return 0. - */ -static int -relay_digest_matches(crypto_digest_t *digest, cell_t *cell) -{ - uint32_t received_integrity, calculated_integrity; - relay_header_t rh; - crypto_digest_checkpoint_t backup_digest; - - crypto_digest_checkpoint(&backup_digest, digest); - - relay_header_unpack(&rh, cell->payload); - memcpy(&received_integrity, rh.integrity, 4); - memset(rh.integrity, 0, 4); - relay_header_pack(cell->payload, &rh); - -// log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.", -// received_integrity[0], received_integrity[1], -// received_integrity[2], received_integrity[3]); - - crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE); - crypto_digest_get_digest(digest, (char*) &calculated_integrity, 4); - - int rv = 1; - - if (calculated_integrity != received_integrity) { -// log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing."); -// (%d vs %d).", received_integrity, calculated_integrity); - /* restore digest to its old form */ - crypto_digest_restore(digest, &backup_digest); - /* restore the relay header */ - memcpy(rh.integrity, &received_integrity, 4); - relay_header_pack(cell->payload, &rh); - rv = 0; - } - - memwipe(&backup_digest, 0, sizeof(backup_digest)); - return rv; -} - -/** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b> - * (in place). - * - * Note that we use the same operation for encrypting and for decrypting. - */ -static void -relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in) -{ - crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE); -} - /** * Update channel usage state based on the type of relay cell and * circuit properties. @@ -299,7 +227,8 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, if (circ->marked_for_close) return 0; - if (relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) { + if (relay_decrypt_cell(circ, cell, cell_direction, &layer_hint, &recognized) + < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "relay crypt failed. Dropping connection."); return -END_CIRC_REASON_INTERNAL; @@ -404,87 +333,6 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, return 0; } -/** Do the appropriate en/decryptions for <b>cell</b> arriving on - * <b>circ</b> in direction <b>cell_direction</b>. - * - * If cell_direction == CELL_DIRECTION_IN: - * - If we're at the origin (we're the OP), for hops 1..N, - * decrypt cell. If recognized, stop. - * - Else (we're not the OP), encrypt one hop. Cell is not recognized. - * - * If cell_direction == CELL_DIRECTION_OUT: - * - decrypt one hop. Check if recognized. - * - * If cell is recognized, set *recognized to 1, and set - * *layer_hint to the hop that recognized it. - * - * Return -1 to indicate that we should mark the circuit for close, - * else return 0. - */ -int -relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, - crypt_path_t **layer_hint, char *recognized) -{ - relay_header_t rh; - - tor_assert(circ); - tor_assert(cell); - tor_assert(recognized); - tor_assert(cell_direction == CELL_DIRECTION_IN || - cell_direction == CELL_DIRECTION_OUT); - - if (cell_direction == CELL_DIRECTION_IN) { - if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit. - * We'll want to do layered decrypts. */ - crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath; - thishop = cpath; - if (thishop->state != CPATH_STATE_OPEN) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Relay cell before first created cell? Closing."); - return -1; - } - do { /* Remember: cpath is in forward order, that is, first hop first. */ - tor_assert(thishop); - - /* decrypt one layer */ - relay_crypt_one_payload(thishop->b_crypto, cell->payload); - - relay_header_unpack(&rh, cell->payload); - if (rh.recognized == 0) { - /* it's possibly recognized. have to check digest to be sure. */ - if (relay_digest_matches(thishop->b_digest, cell)) { - *recognized = 1; - *layer_hint = thishop; - return 0; - } - } - - thishop = thishop->next; - } while (thishop != cpath && thishop->state == CPATH_STATE_OPEN); - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Incoming cell at client not recognized. Closing."); - return -1; - } else { - /* We're in the middle. Encrypt one layer. */ - relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto, cell->payload); - } - } else /* cell_direction == CELL_DIRECTION_OUT */ { - /* We're in the middle. Decrypt one layer. */ - - relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto, cell->payload); - - relay_header_unpack(&rh, cell->payload); - if (rh.recognized == 0) { - /* it's possibly recognized. have to check digest to be sure. */ - if (relay_digest_matches(TO_OR_CIRCUIT(circ)->n_digest, cell)) { - *recognized = 1; - return 0; - } - } - } - return 0; -} - /** Package a relay cell from an edge: * - Encrypt it to the right layer * - Append it to the appropriate cell_queue on <b>circ</b>. @@ -503,7 +351,6 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, } if (cell_direction == CELL_DIRECTION_OUT) { - crypt_path_t *thishop; /* counter for repeated crypts */ chan = circ->n_chan; if (!chan) { log_warn(LD_BUG,"outgoing relay cell sent from %s:%d has n_chan==NULL." @@ -526,20 +373,8 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, return 0; /* just drop it */ } - relay_set_digest(layer_hint->f_digest, cell); - - thishop = layer_hint; - /* moving from farthest to nearest hop */ - do { - tor_assert(thishop); - log_debug(LD_OR,"encrypting a layer of the relay cell."); - relay_crypt_one_payload(thishop->f_crypto, cell->payload); - - thishop = thishop->prev; - } while (thishop != TO_ORIGIN_CIRCUIT(circ)->cpath->prev); - + relay_encrypt_cell_outbound(cell, TO_ORIGIN_CIRCUIT(circ), layer_hint); } else { /* incoming cell */ - or_circuit_t *or_circ; if (CIRCUIT_IS_ORIGIN(circ)) { /* We should never package an _incoming_ cell from the circuit * origin; that means we messed up somewhere. */ @@ -547,11 +382,9 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, assert_circuit_ok(circ); return 0; /* just drop it */ } - or_circ = TO_OR_CIRCUIT(circ); + or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); + relay_encrypt_cell_inbound(cell, or_circ); chan = or_circ->p_chan; - relay_set_digest(or_circ->p_digest, cell); - /* encrypt one layer */ - relay_crypt_one_payload(or_circ->p_crypto, cell->payload); } ++stats_n_relay_cells_relayed; @@ -2399,13 +2232,6 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint) } } -#ifdef ACTIVE_CIRCUITS_PARANOIA -#define assert_cmux_ok_paranoid(chan) \ - assert_circuit_mux_okay(chan) -#else -#define assert_cmux_ok_paranoid(chan) -#endif /* defined(ACTIVE_CIRCUITS_PARANOIA) */ - /** The total number of cells we have allocated. */ static size_t total_cells_allocated = 0; @@ -2693,16 +2519,12 @@ update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction, } tor_assert(circuitmux_attached_circuit_direction(cmux, circ) == direction); - assert_cmux_ok_paranoid(chan); - /* Update the number of cells we have for the circuit mux */ if (direction == CELL_DIRECTION_OUT) { circuitmux_set_num_cells(cmux, circ, circ->n_chan_cells.n); } else { circuitmux_set_num_cells(cmux, circ, or_circ->p_chan_cells.n); } - - assert_cmux_ok_paranoid(chan); } /** Remove all circuits from the cmux on <b>chan</b>. @@ -2847,7 +2669,6 @@ channel_flush_from_first_active_circuit, (channel_t *chan, int max)) } /* If it returns NULL, no cells left to send */ if (!circ) break; - assert_cmux_ok_paranoid(chan); if (circ->n_chan == chan) { queue = &circ->n_chan_cells; @@ -2951,15 +2772,13 @@ channel_flush_from_first_active_circuit, (channel_t *chan, int max)) } /* Okay, we're done sending now */ - assert_cmux_ok_paranoid(chan); - return n_flushed; } /** Add <b>cell</b> to the queue of <b>circ</b> writing to <b>chan</b> * transmitting in <b>direction</b>. * - * The given <b>cell</b> is copied over the circuit queue so the caller must + * The given <b>cell</b> is copied onto the circuit queue so the caller must * cleanup the memory. * * This function is part of the fast path. */ @@ -3103,17 +2922,6 @@ circuit_clear_cell_queue(circuit_t *circ, channel_t *chan) update_circuit_on_cmux(circ, direction); } -/** Fail with an assert if the circuit mux on chan is corrupt - */ -void -assert_circuit_mux_okay(channel_t *chan) -{ - tor_assert(chan); - tor_assert(chan->cmux); - - circuitmux_assert_okay(chan->cmux); -} - /** Return 1 if we shouldn't restart reading on this circuit, even if * we get a SENDME. Else return 0. */ |