diff options
Diffstat (limited to 'src/or/relay.c')
-rw-r--r-- | src/or/relay.c | 179 |
1 files changed, 6 insertions, 173 deletions
diff --git a/src/or/relay.c b/src/or/relay.c index 5651579c3e..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; |