[tor-commits] [tor/master] Check for replays in PK-encrypted part of intro cell, not just in the g^x value

nickm at torproject.org nickm at torproject.org
Fri Sep 9 16:56:11 UTC 2011


commit cb9226bcdb811c6b30fb4bb2b6b06b378ebf0559
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue May 10 21:40:10 2011 -0400

    Check for replays in PK-encrypted part of intro cell, not just in the g^x value
---
 changes/replay-firstpart |   13 +++++++++++++
 src/or/rendservice.c     |   26 +++++++++++++++++++++++---
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/changes/replay-firstpart b/changes/replay-firstpart
new file mode 100644
index 0000000..f4a7767
--- /dev/null
+++ b/changes/replay-firstpart
@@ -0,0 +1,13 @@
+  o Minor features (security):
+
+    - Check for replays of the public-key encrypted portion of an
+      INTRODUCE1 cell, in addition to the current check for replays of
+      the g^x value.  This prevents a possible class of active attacks
+      by an attacker who controls both an introduction point and a
+      rendezvous point, and who uses the malleability of AES-CTR to
+      alter the encrypted g^x portion of the INTRODUCE1 cell.  We
+      think that these attacks is infeasible (requiring the attacker
+      to send on the order of zettabytes of altered cells in a short
+      interval), but we'd rather block them off in case there are any
+      classes of this attack that we missed.  Reported by dvorak.
+
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index d1cc7f4..af6737b 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -976,6 +976,29 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
              "PK-encrypted portion of INTRODUCE2 cell was truncated.");
     return -1;
   }
+
+  if (!service->accepted_intros)
+    service->accepted_intros = digestmap_new();
+
+  {
+    char pkpart_digest[DIGEST_LEN];
+    /* Check for replay of PK-encrypted portion.  It is slightly naughty to
+       use the same digestmap to check for this and for g^x replays, but
+       collisions are tremendously unlikely.
+    */
+    crypto_digest(pkpart_digest, (char*)request+DIGEST_LEN, keylen);
+    access_time = digestmap_get(service->accepted_intros, pkpart_digest);
+    if (access_time != NULL) {
+      log_warn(LD_REND, "Possible replay detected! We received an "
+               "INTRODUCE2 cell with same PK-encrypted part %d seconds ago. "
+               "Dropping cell.", (int)(now-*access_time));
+      return -1;
+    }
+    access_time = tor_malloc(sizeof(time_t));
+    *access_time = now;
+    digestmap_set(service->accepted_intros, pkpart_digest, access_time);
+  }
+
   /* Next N bytes is encrypted with service key */
   note_crypto_pk_op(REND_SERVER);
   r = crypto_pk_private_hybrid_decrypt(
@@ -1109,9 +1132,6 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
 
   /* Check whether there is a past request with the same Diffie-Hellman,
    * part 1. */
-  if (!service->accepted_intros)
-    service->accepted_intros = digestmap_new();
-
   access_time = digestmap_get(service->accepted_intros, diffie_hellman_hash);
   if (access_time != NULL) {
     log_warn(LD_REND, "Possible replay detected! We received an "





More information about the tor-commits mailing list