Commit 3835a3ac authored by David Goulet's avatar David Goulet 🐼 Committed by Nick Mathewson
Browse files

sendme: Properly record SENDMEs on both edges



Turns out that we were only recording the "b_digest" but to have
bidirectionnal authenticated SENDMEs, we need to use the "f_digest" in the
forward cell situation.

Because of the cpath refactoring, this commit plays with the crypt_path_ and
relay_crypto_t API a little bit in order to respect the abstractions.

Previously, we would record the cell digest as the SENDME digest in the
decrypt cell function but to avoid code duplication (both directions needs to
record), we now do that right after iff the cell is recognized (at the edge).
It is now done in circuit_receive_relay_cell() instead.

We now also record the cell digest as the SENDME digest in both relay cell
encryption functions since they are split depending on the direction.
relay_encrypt_cell_outbound() and relay_encrypt_cell_inbound() need to
consider recording the cell digest depending on their direction (f vs b
digest).

Fixes #30428

Signed-off-by: David Goulet's avatarDavid Goulet <dgoulet@torproject.org>
parent 44265dd6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ problem file-size /src/core/or/policies.c 3249
problem function-size /src/core/or/policies.c:policy_summarize() 107
problem function-size /src/core/or/protover.c:protover_all_supported() 117
problem file-size /src/core/or/relay.c 3173
problem function-size /src/core/or/relay.c:circuit_receive_relay_cell() 123
problem function-size /src/core/or/relay.c:circuit_receive_relay_cell() 127
problem function-size /src/core/or/relay.c:relay_send_command_from_edge_() 116
problem function-size /src/core/or/relay.c:connection_ap_process_end_not_open() 194
problem function-size /src/core/or/relay.c:connection_edge_process_relay_cell_not_open() 139
+18 −13
Original line number Diff line number Diff line
@@ -100,12 +100,22 @@ relay_crypto_get_sendme_digest(relay_crypto_t *crypto)
  return crypto->sendme_digest;
}

/** Record the b_digest from <b>crypto</b> and put it in the sendme_digest. */
/** Record the cell digest, indicated by is_foward_digest or not, as the
 * SENDME cell digest. */
void
relay_crypto_record_sendme_digest(relay_crypto_t *crypto)
relay_crypto_record_sendme_digest(relay_crypto_t *crypto,
                                  bool is_foward_digest)
{
  struct crypto_digest_t *digest;

  tor_assert(crypto);
  crypto_digest_get_digest(crypto->b_digest, (char *) crypto->sendme_digest,

  digest = crypto->b_digest;
  if (is_foward_digest) {
    digest = crypto->f_digest;
  }

  crypto_digest_get_digest(digest, (char *) crypto->sendme_digest,
                           sizeof(crypto->sendme_digest));
}

@@ -161,11 +171,6 @@ relay_decrypt_cell(circuit_t *circ, cell_t *cell,
          if (relay_digest_matches(cpath_get_incoming_digest(thishop), cell)) {
            *recognized = 1;
            *layer_hint = thishop;
            /* This cell is for us. Keep a record of this cell because we will
             * use it in the next SENDME cell. */
            if (sendme_circuit_cell_is_next(thishop->deliver_window)) {
              cpath_sendme_circuit_record_inbound_cell(thishop);
            }
            return 0;
          }
        }
@@ -213,6 +218,9 @@ relay_encrypt_cell_outbound(cell_t *cell,
  crypt_path_t *thishop; /* counter for repeated crypts */
  cpath_set_cell_forward_digest(layer_hint, cell);

  /* Record cell digest as the SENDME digest if need be. */
  sendme_record_sending_cell_digest(TO_CIRCUIT(circ), layer_hint);

  thishop = layer_hint;
  /* moving from farthest to nearest hop */
  do {
@@ -237,11 +245,8 @@ relay_encrypt_cell_inbound(cell_t *cell,
{
  relay_set_digest(or_circ->crypto.b_digest, cell);

  /* We are about to send this cell outbound on the circuit. Keep a record of
   * this cell if we are expecting that the next cell is a SENDME. */
  if (sendme_circuit_cell_is_next(TO_CIRCUIT(or_circ)->package_window)) {
    sendme_circuit_record_outbound_cell(or_circ);
  }
  /* 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);
+4 −1
Original line number Diff line number Diff line
@@ -28,7 +28,10 @@ void relay_crypto_clear(relay_crypto_t *crypto);
void relay_crypto_assert_ok(const relay_crypto_t *crypto);

uint8_t *relay_crypto_get_sendme_digest(relay_crypto_t *crypto);
void relay_crypto_record_sendme_digest(relay_crypto_t *crypto);

void relay_crypto_record_sendme_digest(relay_crypto_t *crypto,
                                       bool is_foward_digest);

void
relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in);

+9 −9
Original line number Diff line number Diff line
@@ -204,15 +204,6 @@ cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell)

/************ cpath sendme API ***************************/

/** Keep the current inbound cell digest for the next SENDME digest. This part
 * is only done by the client as the circuit came back from the Exit. */
void
cpath_sendme_circuit_record_inbound_cell(crypt_path_t *cpath)
{
  tor_assert(cpath);
  relay_crypto_record_sendme_digest(&cpath->pvt_crypto);
}

/** Return the sendme_digest of this <b>cpath</b>. */
uint8_t *
cpath_get_sendme_digest(crypt_path_t *cpath)
@@ -220,6 +211,15 @@ cpath_get_sendme_digest(crypt_path_t *cpath)
  return relay_crypto_get_sendme_digest(&cpath->pvt_crypto);
}

/** Record the cell digest, indicated by is_foward_digest or not, as the
 * SENDME cell digest. */
void
cpath_sendme_record_cell_digest(crypt_path_t *cpath, bool is_foward_digest)
{
  tor_assert(cpath);
  relay_crypto_record_sendme_digest(&cpath->pvt_crypto, is_foward_digest);
}

/************ other cpath functions ***************************/

/** Return the first non-open hop in cpath, or return NULL if all
+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ 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_record_cell_digest(crypt_path_t *cpath,
                                     bool is_foward_digest);

void
cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell);

Loading