Browse Source

ntor: Don't fail fast server-side on an unrecognized KEYID(B)

Nick Mathewson 11 years ago
parent
commit
839016ac79
6 changed files with 21 additions and 7 deletions
  1. 4 0
      src/or/onion.c
  2. 1 0
      src/or/onion.h
  3. 12 5
      src/or/onion_ntor.c
  4. 1 0
      src/or/onion_ntor.h
  5. 1 1
      src/test/bench.c
  6. 2 1
      src/test/test.c

+ 4 - 0
src/or/onion.c

@@ -192,6 +192,8 @@ setup_server_onion_keys(server_onion_keys_t *keys)
   dup_onion_keys(&keys->onion_key, &keys->last_onion_key);
 #ifdef CURVE25519_ENABLED
   keys->curve25519_key_map = construct_ntor_key_map();
+  keys->junk_keypair = tor_malloc_zero(sizeof(curve25519_keypair_t));
+  curve25519_keypair_generate(keys->junk_keypair, 0);
 #endif
 }
 
@@ -207,6 +209,7 @@ release_server_onion_keys(server_onion_keys_t *keys)
   crypto_pk_free(keys->last_onion_key);
 #ifdef CURVE25519_ENABLED
   ntor_key_map_free(keys->curve25519_key_map);
+  tor_free(keys->junk_keypair);
 #endif
   memset(keys, 0, sizeof(server_onion_keys_t));
 }
@@ -345,6 +348,7 @@ onion_skin_server_handshake(int type,
 
       if (onion_skin_ntor_server_handshake(
                                    onion_skin, keys->curve25519_key_map,
+                                   keys->junk_keypair,
                                    keys->my_identity,
                                    reply_out, keys_tmp, keys_tmp_len)<0) {
         tor_free(keys_tmp);

+ 1 - 0
src/or/onion.h

@@ -24,6 +24,7 @@ typedef struct server_onion_keys_t {
   crypto_pk_t *last_onion_key;
 #ifdef CURVE25519_ENABLED
   di_digest256_map_t *curve25519_key_map;
+  curve25519_keypair_t *junk_keypair;
 #endif
 } server_onion_keys_t;
 

+ 12 - 5
src/or/onion_ntor.c

@@ -121,14 +121,16 @@ onion_skin_ntor_create(const uint8_t *router_id,
  * NTOR_ONIONSKIN_LEN-byte message in <b>onion_skin</b>, our own identity
  * fingerprint as <b>my_node_id</b>, and an associative array mapping public
  * onion keys to curve25519_keypair_t in <b>private_keys</b>, attempt to
- * perform the handshake.  Write an NTOR_REPLY_LEN-byte message to send back
- * to the client into <b>handshake_reply_out</b>, and generate
- * <b>key_out_len</b> bytes of key material in <b>key_out</b>. Return 0 on
- * success, -1 on failure.
+ * perform the handshake.  Use <b>junk_keys</b> if present if the handshake
+ * indicates an unrecognized public key.  Write an NTOR_REPLY_LEN-byte
+ * message to send back to the client into <b>handshake_reply_out</b>, and
+ * generate <b>key_out_len</b> bytes of key material in <b>key_out</b>. Return
+ * 0 on success, -1 on failure.
  */
 int
 onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
                                  const di_digest256_map_t *private_keys,
+                                 const curve25519_keypair_t *junk_keys,
                                  const uint8_t *my_node_id,
                                  uint8_t *handshake_reply_out,
                                  uint8_t *key_out,
@@ -153,9 +155,14 @@ onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
   /* XXXX Does this possible early-return business threaten our security? */
   if (tor_memneq(onion_skin, my_node_id, DIGEST_LEN))
     return -1;
-  keypair_bB = dimap_search(private_keys, onion_skin + DIGEST_LEN, NULL);
+  /* Note that on key-not-found, we go through with this operation anyway,
+   * using "junk_keys". This will result in failed authentication, but won't
+   * leak whether we recognized the key. */
+  keypair_bB = dimap_search(private_keys, onion_skin + DIGEST_LEN,
+                            (void*)junk_keys);
   if (!keypair_bB)
     return -1;
+
   memcpy(s.pubkey_X.public_key, onion_skin+DIGEST_LEN+DIGEST256_LEN,
          CURVE25519_PUBKEY_LEN);
 

+ 1 - 0
src/or/onion_ntor.h

@@ -27,6 +27,7 @@ int onion_skin_ntor_create(const uint8_t *router_id,
 
 int onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
                                  const di_digest256_map_t *private_keys,
+                                 const curve25519_keypair_t *junk_keypair,
                                  const uint8_t *my_node_id,
                                  uint8_t *handshake_reply_out,
                                  uint8_t *key_out,

+ 1 - 1
src/test/bench.c

@@ -199,7 +199,7 @@ bench_onion_ntor(void)
   start = perftime();
   for (i = 0; i < iters; ++i) {
     uint8_t key_out[CPATH_KEY_MATERIAL_LEN];
-    onion_skin_ntor_server_handshake(os, keymap, nodeid, or,
+    onion_skin_ntor_server_handshake(os, keymap, NULL, nodeid, or,
                                 key_out, sizeof(key_out));
   }
   end = perftime();

+ 2 - 1
src/test/test.c

@@ -895,7 +895,8 @@ test_ntor_handshake(void *arg)
   /* server handshake */
   memset(s_buf, 0, NTOR_REPLY_LEN);
   memset(s_keys, 0, 40);
-  tt_int_op(0, ==, onion_skin_ntor_server_handshake(c_buf, s_keymap, node_id,
+  tt_int_op(0, ==, onion_skin_ntor_server_handshake(c_buf, s_keymap, NULL,
+                                                    node_id,
                                                     s_buf, s_keys, 400));
 
   /* client handshake 2 */