]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
prop289: Remember the last cell digest for v1 SENDMEs
authorDavid Goulet <dgoulet@torproject.org>
Wed, 23 Jan 2019 19:39:04 +0000 (14:39 -0500)
committerDavid Goulet <dgoulet@torproject.org>
Mon, 29 Apr 2019 16:17:57 +0000 (12:17 -0400)
In order to do so, depending on where the cell is going, we'll keep the last
cell digest that is either received inbound or sent outbound.

Then it can be used for validation.

Part of #26288

Signed-off-by: David Goulet <dgoulet@torproject.org>
src/core/crypto/relay_crypto.c
src/core/or/relay.c
src/core/or/relay_crypto_st.h
src/core/or/sendme.c
src/core/or/sendme.h

index 0b83b2d0a5f17596be0763487e244dcfde8044d2..d4116d47ab2a30739e40a6f59b29d167c46fedc2 100644 (file)
@@ -142,6 +142,13 @@ relay_decrypt_cell(circuit_t *circ, cell_t *cell,
           if (relay_digest_matches(thishop->crypto.b_digest, cell)) {
             *recognized = 1;
             *layer_hint = thishop;
+            /* Keep current digest of this cell for the possible SENDME. */
+            if (thishop->crypto.sendme_digest) {
+              crypto_digest_free(thishop->crypto.sendme_digest);
+            }
+            thishop->crypto.sendme_digest =
+              crypto_digest_dup(thishop->crypto.b_digest);
+
             return 0;
           }
         }
@@ -212,6 +219,11 @@ relay_encrypt_cell_inbound(cell_t *cell,
                            or_circuit_t *or_circ)
 {
   relay_set_digest(or_circ->crypto.b_digest, cell);
+  /* Keep a record of this cell, we might use it for validating the SENDME. */
+  if (or_circ->crypto.sendme_digest) {
+    crypto_digest_free(or_circ->crypto.sendme_digest);
+  }
+  or_circ->crypto.sendme_digest = crypto_digest_dup(or_circ->crypto.b_digest);
   /* encrypt one layer */
   relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload);
 }
@@ -229,6 +241,7 @@ relay_crypto_clear(relay_crypto_t *crypto)
   crypto_cipher_free(crypto->b_crypto);
   crypto_digest_free(crypto->f_digest);
   crypto_digest_free(crypto->b_digest);
+  crypto_digest_free(crypto->sendme_digest);
 }
 
 /** Initialize <b>crypto</b> from the key material in key_data.
index b26360b24501cc0137819a4aa3469c1f5ed40f79..47275a811ee2fc3b7248719379928dc117ecfa1b 100644 (file)
@@ -1568,7 +1568,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
       }
 
       /* Consider sending a circuit-level SENDME cell. */
-      sendme_circuit_consider_sending(circ, layer_hint, NULL);
+      sendme_circuit_consider_sending(circ, layer_hint);
 
       if (rh.stream_id == 0) {
         log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero "
index dafce257c70d666a38465a7f9715e7a7a9bfd2ee..dbdf1599dc9d8137fa123b68fdeae4b183c15815 100644 (file)
@@ -25,6 +25,8 @@ struct relay_crypto_t {
   /** Digest state for cells heading away from the OR at this step. */
   struct crypto_digest_t *b_digest;
 
+  /** Digest used for the next SENDME cell if any. */
+  struct crypto_digest_t *sendme_digest;
 };
 #undef crypto_cipher_t
 
index afade43f7493fe5b1ddcbea086d359ac11758e62..76f551a92938d860e268ff1c72ae41fcfbdf3b87 100644 (file)
@@ -14,6 +14,7 @@
 #include "core/or/cell_st.h"
 #include "core/or/circuitlist.h"
 #include "core/or/circuituse.h"
+#include "core/or/or_circuit_st.h"
 #include "core/or/relay.h"
 #include "core/or/sendme.h"
 #include "feature/nodelist/networkstatus.h"
@@ -342,18 +343,20 @@ sendme_connection_edge_consider_sending(edge_connection_t *conn)
  * more.
  */
 void
-sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint,
-                                crypto_digest_t *digest)
+sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
 {
-  tor_assert(digest);
+  crypto_digest_t *digest;
 
   while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
           CIRCWINDOW_START - CIRCWINDOW_INCREMENT) {
     log_debug(LD_CIRC,"Queuing circuit sendme.");
-    if (layer_hint)
+    if (layer_hint) {
       layer_hint->deliver_window += CIRCWINDOW_INCREMENT;
-    else
+      digest = layer_hint->crypto.sendme_digest;
+    } else {
       circ->deliver_window += CIRCWINDOW_INCREMENT;
+      digest = TO_OR_CIRCUIT(circ)->crypto.sendme_digest;
+    }
     if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) {
       return; /* The circuit's closed, don't continue */
     }
@@ -557,9 +560,16 @@ sendme_note_cell_digest(circuit_t *circ)
     return;
   }
 
-  digest = tor_malloc_zero(4);
-  if (circ->sendme_last_digests == NULL) {
-    circ->sendme_last_digests = smartlist_new();
+  /* Only note the digest if we actually have the digest of the previous cell
+   * recorded. It should never happen in theory as we always record the last
+   * digest for the v1 SENDME. */
+  if (TO_OR_CIRCUIT(circ)->crypto.sendme_digest) {
+    digest = tor_malloc_zero(4);
+    crypto_digest_get_digest(TO_OR_CIRCUIT(circ)->crypto.sendme_digest,
+                             (char *) digest, 4);
+    if (circ->sendme_last_digests == NULL) {
+      circ->sendme_last_digests = smartlist_new();
+    }
+    smartlist_add(circ->sendme_last_digests, digest);
   }
-  smartlist_add(circ->sendme_last_digests, digest);
 }
index 300fb25d9623aca0ad069e7789438fafa85e43d2..e7cf718bb16f056594de9d4e6b13c33243b144bb 100644 (file)
@@ -16,8 +16,7 @@
 /* Sending SENDME cell. */
 void sendme_connection_edge_consider_sending(edge_connection_t *edge_conn);
 void sendme_circuit_consider_sending(circuit_t *circ,
-                                     crypt_path_t *layer_hint,
-                                     crypto_digest_t *digest);
+                                     crypt_path_t *layer_hint);
 
 /* Processing SENDME cell. */
 int sendme_process_circuit_level(crypt_path_t *layer_hint,