tor

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

commit 90f0c977f8625fe929003cedbf7ef4372aff00f8
parent ed67ef78ab16cfaaee2e16dab94c28a940aa6b6d
Author: Nick Mathewson <nickm@torproject.org>
Date:   Wed, 28 May 2025 08:52:57 -0400

Refactor tor1 relay crypto functions into per-layer calls.

We'll need this for mixed circuits.

Also, the APIs here are a bit closer to the CGO APIs.

Diffstat:
Msrc/core/crypto/relay_crypto.c | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/core/crypto/relay_crypto.h | 20++++++++++++++------
Msrc/core/or/crypt_path.c | 29-----------------------------
Msrc/core/or/crypt_path.h | 9---------
Msrc/core/or/or.h | 2++
Msrc/core/or/sendme.c | 27+--------------------------
Msrc/core/or/sendme.h | 1-
7 files changed, 112 insertions(+), 111 deletions(-)

diff --git a/src/core/crypto/relay_crypto.c b/src/core/crypto/relay_crypto.c @@ -25,9 +25,14 @@ #include "core/or/or_circuit_st.h" #include "core/or/origin_circuit_st.h" +#include "core/or/congestion_control_common.h" // XXXX refactor. + /* TODO CGO: This file will be largely incorrect when we have * CGO crypto. */ +// XXXX: Remove this definition once I'm done refactoring. +#define pvt_crypto crypto_crypt_path_private_field + /* Offset of digest within relay cell body for v0 cells. */ #define V0_DIGEST_OFFSET 5 #define V0_DIGEST_LEN 4 @@ -109,6 +114,73 @@ tor1_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in) crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE); } +/* XXXX DOCDOC */ +void +tor1_crypt_client_originate(relay_crypto_t *tor1, + cell_t *cell, + bool record_sendme_digest) +{ + tor1_set_digest_v0(tor1->f_digest, cell); + if (record_sendme_digest) { + tor1_save_sendme_digest(tor1, true); + } + tor1_crypt_one_payload(tor1->f_crypto, cell->payload); +} + +/* XXXX DOCDOC */ +void +tor1_crypt_relay_originate(relay_crypto_t *tor1, + cell_t *cell, + bool save_sendme_digest) +{ + tor1_set_digest_v0(tor1->b_digest, cell); + if (save_sendme_digest) { + tor1_save_sendme_digest(tor1, false); + } + tor1_crypt_one_payload(tor1->b_crypto, cell->payload); +} + +/* XXXX DOCDOC */ +void +tor1_crypt_client_forward(relay_crypto_t *tor1, cell_t *cell) +{ + tor1_crypt_one_payload(tor1->f_crypto, cell->payload); +} + +/* XXXX DOCDOC */ +void +tor1_crypt_relay_backward(relay_crypto_t *tor1, cell_t *cell) +{ + tor1_crypt_one_payload(tor1->b_crypto, cell->payload); +} + +/* XXXX DOCDOC */ +bool +tor1_crypt_relay_forward(relay_crypto_t *tor1, cell_t *cell) +{ + tor1_crypt_one_payload(tor1->f_crypto, cell->payload); + if (relay_cell_is_recognized_v0(cell)) { + if (tor1_relay_digest_matches_v0(tor1->f_digest, cell)) { + return true; + } + } + return false; +} + +/* XXXX DOCDOC */ +bool +tor1_crypt_client_backward(relay_crypto_t *tor1, cell_t *cell) +{ + tor1_crypt_one_payload(tor1->b_crypto, cell->payload); + + if (relay_cell_is_recognized_v0(cell)) { + if (tor1_relay_digest_matches_v0(tor1->b_digest, cell)) { + return true; + } + } + return false; +} + /** Return the sendme_digest within the <b>crypto</b> object. * * Before calling this function, you must call relay_crypto_save_sendme_digest. @@ -184,41 +256,31 @@ relay_decrypt_cell(circuit_t *circ, cell_t *cell, do { /* Remember: cpath is in forward order, that is, first hop first. */ tor_assert(thishop); - /* decrypt one layer */ - cpath_crypt_cell(thishop, cell->payload, true); - - if (relay_cell_is_recognized_v0(cell)) { - /* it's possibly recognized. have to check digest to be sure. */ - if (tor1_relay_digest_matches_v0(cpath_get_incoming_digest(thishop), - cell)) { - *recognized = 1; - *layer_hint = thishop; - return 0; - } - } + bool rec = tor1_crypt_client_backward(&thishop->pvt_crypto, cell); + if (rec) { + *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. */ - tor1_crypt_one_payload(crypto->b_crypto, cell->payload); + relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto; + tor1_crypt_relay_backward(crypto, cell); } } else /* cell_direction == CELL_DIRECTION_OUT */ { /* We're in the middle. Decrypt one layer. */ relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto; - tor1_crypt_one_payload(crypto->f_crypto, cell->payload); - - if (relay_cell_is_recognized_v0(cell)) { - /* it's possibly recognized. have to check digest to be sure. */ - if (tor1_relay_digest_matches_v0(crypto->f_digest, cell)) { - *recognized = 1; - return 0; - } + bool rec = tor1_crypt_relay_forward(crypto, cell); + if (rec) { + *recognized = 1; + return 0; } } return 0; @@ -236,21 +298,18 @@ relay_encrypt_cell_outbound(cell_t *cell, origin_circuit_t *circ, crypt_path_t *layer_hint) { - crypt_path_t *thishop; /* counter for repeated crypts */ - cpath_set_cell_forward_digest(layer_hint, cell); + crypt_path_t *thishop = layer_hint; - /* Record cell digest as the SENDME digest if need be. */ - sendme_save_sending_cell_digest(TO_CIRCUIT(circ), layer_hint); + bool save_sendme = + circuit_sent_cell_for_sendme(TO_CIRCUIT(circ), thishop); - thishop = layer_hint; - /* moving from farthest to nearest hop */ - do { - tor_assert(thishop); - log_debug(LD_OR,"encrypting a layer of the relay cell."); - cpath_crypt_cell(thishop, cell->payload, false); + tor1_crypt_client_originate(&thishop->pvt_crypto, cell, save_sendme); + thishop = thishop->prev; + while (thishop != circ->cpath->prev) { + tor1_crypt_client_forward(&thishop->pvt_crypto, cell); thishop = thishop->prev; - } while (thishop != circ->cpath->prev); + } } /** @@ -264,13 +323,9 @@ void relay_encrypt_cell_inbound(cell_t *cell, or_circuit_t *or_circ) { - tor1_set_digest_v0(or_circ->crypto.b_digest, cell); - - /* Record cell digest as the SENDME digest if need be. */ - sendme_save_sending_cell_digest(TO_CIRCUIT(or_circ), NULL); - - /* encrypt one layer */ - tor1_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload); + bool save_sendme = + circuit_sent_cell_for_sendme(TO_CIRCUIT(or_circ), NULL); + tor1_crypt_relay_originate(&or_circ->crypto, cell, save_sendme); } /** diff --git a/src/core/crypto/relay_crypto.h b/src/core/crypto/relay_crypto.h @@ -29,13 +29,21 @@ void relay_crypto_assert_ok(const relay_crypto_t *crypto); uint8_t *relay_crypto_get_sendme_digest(relay_crypto_t *crypto); -void tor1_save_sendme_digest(relay_crypto_t *crypto, +void tor1_save_sendme_digest(tor1_crypt_t *crypto, bool is_foward_digest); -void -tor1_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in); - -void -tor1_set_digest_v0(crypto_digest_t *digest, cell_t *cell); +void tor1_crypt_client_originate(tor1_crypt_t *tor1, + cell_t *cell, + bool record_sendme_digest); +void tor1_crypt_relay_originate(tor1_crypt_t *tor1, + cell_t *cell, + bool record_sendme_digest); +void tor1_crypt_relay_backward(tor1_crypt_t *tor1, cell_t *cell); +bool tor1_crypt_relay_forward(tor1_crypt_t *tor1, cell_t *cell); +bool tor1_crypt_client_backward(tor1_crypt_t *tor1, cell_t *cell); +void tor1_crypt_client_forward(tor1_crypt_t *tor1, cell_t *cell); + +void tor1_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in); +void tor1_set_digest_v0(crypto_digest_t *digest, cell_t *cell); #endif /* !defined(TOR_RELAY_CRYPTO_H) */ diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c @@ -175,35 +175,6 @@ cpath_free(crypt_path_t *victim) tor_free(victim); } -/********************** cpath crypto API *******************************/ - -/** Encrypt or decrypt <b>payload</b> using the crypto of <b>cpath</b>. Actual - * operation decided by <b>is_decrypt</b>. */ -void -cpath_crypt_cell(const crypt_path_t *cpath, uint8_t *payload, bool is_decrypt) -{ - if (is_decrypt) { - tor1_crypt_one_payload(cpath->pvt_crypto.b_crypto, payload); - } else { - tor1_crypt_one_payload(cpath->pvt_crypto.f_crypto, payload); - } -} - -/** Getter for the incoming digest of <b>cpath</b>. */ -struct crypto_digest_t * -cpath_get_incoming_digest(const crypt_path_t *cpath) -{ - return cpath->pvt_crypto.b_digest; -} - -/** Set the right integrity digest on the outgoing <b>cell</b> based on the - * cell payload and update the forward digest of <b>cpath</b>. */ -void -cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell) -{ - tor1_set_digest_v0(cpath->pvt_crypto.f_digest, cell); -} - /************ cpath sendme API ***************************/ /** Return the sendme_digest of this <b>cpath</b>. */ diff --git a/src/core/or/crypt_path.h b/src/core/or/crypt_path.h @@ -21,18 +21,9 @@ cpath_free(crypt_path_t *victim); void cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop); -void -cpath_crypt_cell(const crypt_path_t *cpath, uint8_t *payload, bool is_decrypt); - -struct crypto_digest_t * -cpath_get_incoming_digest(const crypt_path_t *cpath); - void cpath_sendme_save_cell_digest(crypt_path_t *cpath, bool is_foward_digest); -void -cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell); - crypt_path_t *cpath_get_next_non_open_hop(crypt_path_t *cpath); void cpath_sendme_circuit_record_inbound_cell(crypt_path_t *cpath); diff --git a/src/core/or/or.h b/src/core/or/or.h @@ -894,6 +894,8 @@ typedef enum { typedef struct onion_handshake_state_t onion_handshake_state_t; typedef struct relay_crypto_t relay_crypto_t; +// XXXX Temporary alias. +typedef struct relay_crypto_t tor1_crypt_t; typedef struct crypt_path_t crypt_path_t; typedef struct crypt_path_reference_t crypt_path_reference_t; diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c @@ -727,6 +727,7 @@ sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath) void sendme_save_received_cell_digest(circuit_t *circ, crypt_path_t *cpath) { + // XXXX: all sendme_save functions probably belong inside tor1_* tor_assert(circ); /* Only record if the next cell is expected to be a SENDME. */ @@ -744,29 +745,3 @@ sendme_save_received_cell_digest(circuit_t *circ, crypt_path_t *cpath) tor1_save_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, true); } } - -/* Called once we encrypted a cell. Save the cell digest as the next sendme - * as the next sendme digest in the cpath's relay_crypto_t - * only if the we expect to receive a SENDME matching this cell's digest. - */ -void -sendme_save_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath) -{ - tor_assert(circ); - - /* Only record if the next cell is expected to be a SENDME. */ - if (!circuit_sent_cell_for_sendme(circ, cpath)) { - goto end; - } - - if (cpath) { - /* Record the forward digest. */ - cpath_sendme_save_cell_digest(cpath, true); - } else { - /* Record the incoming digest. */ - tor1_save_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, false); - } - - end: - return; -} diff --git a/src/core/or/sendme.h b/src/core/or/sendme.h @@ -39,7 +39,6 @@ int sendme_note_stream_data_packaged(edge_connection_t *conn, size_t len); void sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath); /* Record cell digest as the SENDME digest. */ void sendme_save_received_cell_digest(circuit_t *circ, crypt_path_t *cpath); -void sendme_save_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath); /* Private section starts. */ #ifdef SENDME_PRIVATE