[tor-commits] [tor/maint-0.4.4] Validate ed25519 keys and canonicity from circuit_n_conn_done()

nickm at torproject.org nickm at torproject.org
Mon Nov 9 21:18:11 UTC 2020


commit afb6ff17390cb13780c6e813ad0535048dbd9d3c
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Aug 6 11:47:01 2020 -0400

    Validate ed25519 keys and canonicity from circuit_n_conn_done()
    
    Fixes bug 40080. Bugfix on 0.2.7.2-alpha.
---
 changes/bug40080           |  6 ++++++
 src/core/or/channel.c      |  2 +-
 src/core/or/channel.h      |  3 +++
 src/core/or/circuitbuild.c | 24 ++++++++++++++++++++----
 4 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/changes/bug40080 b/changes/bug40080
new file mode 100644
index 0000000000..8162466354
--- /dev/null
+++ b/changes/bug40080
@@ -0,0 +1,6 @@
+  o Minor bugfixes (security):
+    - When completing a channel, relays now check more thoroughly to make
+      sure that it matches any pending circuits before attaching those
+      circuits. Previously, address correctness and Ed25519 identities were not
+      checked in this case, but only when extending circuits on an existing
+      channel. Fixes bug 40080; bugfix on 0.2.7.2-alpha.
diff --git a/src/core/or/channel.c b/src/core/or/channel.c
index 3886906875..3bef6218ef 100644
--- a/src/core/or/channel.c
+++ b/src/core/or/channel.c
@@ -663,7 +663,7 @@ channel_find_by_global_id(uint64_t global_identifier)
 
 /** Return true iff <b>chan</b> matches <b>rsa_id_digest</b> and <b>ed_id</b>.
  * as its identity keys.  If either is NULL, do not check for a match. */
-static int
+int
 channel_remote_identity_matches(const channel_t *chan,
                                 const char *rsa_id_digest,
                                 const ed25519_public_key_t *ed_id)
diff --git a/src/core/or/channel.h b/src/core/or/channel.h
index 97aa000337..4c0c9aeb4c 100644
--- a/src/core/or/channel.h
+++ b/src/core/or/channel.h
@@ -741,6 +741,9 @@ int channel_is_outgoing(channel_t *chan);
 void channel_mark_client(channel_t *chan);
 void channel_clear_client(channel_t *chan);
 int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info);
+int channel_remote_identity_matches(const channel_t *chan,
+                                    const char *rsa_id_digest,
+                                    const ed25519_public_key_t *ed_id);
 int channel_matches_target_addr_for_extend(channel_t *chan,
                                            const tor_addr_t *target);
 unsigned int channel_num_circuits(channel_t *chan);
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index f3a5791d6c..67b47b38f1 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -623,21 +623,37 @@ circuit_n_chan_done(channel_t *chan, int status, int close_origin_circuits)
           circ->state != CIRCUIT_STATE_CHAN_WAIT)
         continue;
 
-      if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
+      const char *rsa_ident = NULL;
+      const ed25519_public_key_t *ed_ident = NULL;
+      if (! tor_digest_is_zero(circ->n_hop->identity_digest)) {
+        rsa_ident = circ->n_hop->identity_digest;
+      }
+      if (! ed25519_public_key_is_zero(&circ->n_hop->ed_identity)) {
+        ed_ident = &circ->n_hop->ed_identity;
+      }
+
+      if (rsa_ident == NULL && ed_ident == NULL) {
         /* Look at addr/port. This is an unkeyed connection. */
         if (!channel_matches_extend_info(chan, circ->n_hop))
           continue;
       } else {
-        /* We expected a key. See if it's the right one. */
-        if (tor_memneq(chan->identity_digest,
-                   circ->n_hop->identity_digest, DIGEST_LEN))
+        /* We expected a key or keys. See if they matched. */
+        if (!channel_remote_identity_matches(chan, rsa_ident, ed_ident))
           continue;
+
+        /* If the channel is canonical, great.  If not, it needs to match
+         * the requested address exactly. */
+        if (! chan->is_canonical &&
+            ! channel_matches_extend_info(chan, circ->n_hop)) {
+          continue;
+        }
       }
       if (!status) { /* chan failed; close circ */
         log_info(LD_CIRC,"Channel failed; closing circ.");
         circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED);
         continue;
       }
+
       if (close_origin_circuits && CIRCUIT_IS_ORIGIN(circ)) {
         log_info(LD_CIRC,"Channel deprecated for origin circs; closing circ.");
         circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED);





More information about the tor-commits mailing list