/** * Encrypt a cell <b>cell</b> that we are creating, and sending on * <b>circuit</b> to the origin. * * The integrity field and recognized field of <b>cell</b>'s relay headers * must be set to zero. */ void relay_encrypt_cell_inbound(cell_t *cell, or_circuit_t *or_circ) { relay_set_digest(or_circ->crypto.b_digest, cell); /* encrypt one layer */ relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload); }
/** * Encrypt a cell <b>cell</b> that we are creating, and sending on * <b>circuit</b> to the origin. * * The integrity field and recognized field of <b>cell</b>'s relay headers * must be set to zero. */ void relay_encrypt_cell_inbound(cell_t *cell, or_circuit_t *or_circ) { relay_set_digest(or_circ->crypto.b_digest, cell); /* Record cell digest as the SENDME digest if need be. */ sendme_record_sending_cell_digest(TO_CIRCUIT(or_circ), NULL); /* encrypt one layer */ relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload); }
/** * Encrypt a cell <b>cell</b> that we are creating, and sending outbound on * <b>circ</b> until the hop corresponding to <b>layer_hint</b>. * * The integrity field and recognized field of <b>cell</b>'s relay headers * must be set to zero. */ void relay_encrypt_cell_outbound(cell_t *cell, origin_circuit_t *circ, crypt_path_t *layer_hint) { crypt_path_t *thishop; /* counter for repeated crypts */ relay_set_digest(layer_hint->crypto.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->crypto.f_crypto, cell->payload); thishop = thishop->prev; } while (thishop != circ->cpath->prev); }
/** 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_decrypt_cell(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->crypto.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->crypto.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 { relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto; /* We're in the middle. Encrypt one layer. */ relay_crypt_one_payload(crypto->b_crypto, cell->payload); } } else /* cell_direction == CELL_DIRECTION_OUT */ { /* We're in the middle. Decrypt one layer. */ relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto; relay_crypt_one_payload(crypto->f_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(crypto->f_digest, cell)) { *recognized = 1; return 0; } } } return 0; }