Pārlūkot izejas kodu

Merge remote-tracking branch 'public/3122_memcmp_squashed' into bug3122_memcmp_022

Conflicts throughout.  All resolved in favor of taking HEAD and
adding tor_mem* or fast_mem* ops as appropriate.

	src/common/Makefile.am
	src/or/circuitbuild.c
	src/or/directory.c
	src/or/dirserv.c
	src/or/dirvote.c
	src/or/networkstatus.c
	src/or/rendclient.c
	src/or/rendservice.c
	src/or/router.c
	src/or/routerlist.c
	src/or/routerparse.c
	src/or/test.c
Nick Mathewson 13 gadi atpakaļ
vecāks
revīzija
44ad734573

+ 7 - 0
changes/bug3122_memcmp

@@ -0,0 +1,7 @@
+  o Security fixes
+    - Replace all potentially sensitive memory comparison operations
+      with versions whose runtime does not depend on the data being
+      compared. This will help resist a class of attacks where an
+      adversary can use variations in timing information to learn
+      sensitive data.  Fix for one case of bug 3122.  (Safe memcmp
+      implementation by Robert Ransom based partially on code by DJB.)

+ 18 - 0
configure.in

@@ -695,6 +695,24 @@ if test "$tor_cv_twos_complement" != no ; then
             [Define to 1 iff we represent negative integers with two's complement])
 fi
 
+# What does shifting a negative value do?
+AC_CACHE_CHECK([whether right-shift on negative values does sign-extension], tor_cv_sign_extend,
+[AC_RUN_IFELSE([AC_LANG_SOURCE(
+[[int main () { int okay = (-60 >> 8) == -1; return okay ? 0 : 1; }]])],
+       [tor_cv_sign_extend=yes],
+       [tor_cv_sign_extend=no],
+       [tor_cv_sign_extend=cross])])
+
+if test "$tor_cv_sign_extend" = cross ; then
+  # Cross-compiling; let's hope that the target isn't raving mad.
+  AC_MSG_NOTICE([Cross-compiling: we'll assume that right-shifting negative integers causes sign-extension])
+fi
+
+if test "$tor_cv_sign_extend" != no ; then
+  AC_DEFINE([RSHIFT_DOES_SIGN_EXTEND], 1,
+            [Define to 1 iff right-shifting a negative value performs sign-extension])
+fi
+
 # Whether we should use the dmalloc memory allocation debugging library.
 AC_MSG_CHECKING(whether to use dmalloc (debug memory allocation library))
 AC_ARG_WITH(dmalloc,

+ 2 - 2
src/common/Makefile.am

@@ -12,11 +12,11 @@ libor_extra_source=
 endif
 
 libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
-	memarea.c util_codedigest.c $(libor_extra_source)
+	memarea.c di_ops.c util_codedigest.c $(libor_extra_source)
 libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
 libor_event_a_SOURCES = compat_libevent.c
 
-noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h
+noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h
 
 common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
 	if test "@SHA1SUM@" != none; then \

+ 1 - 1
src/common/address.c

@@ -837,7 +837,7 @@ tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
         const uint8_t *a2 = tor_addr_to_in6_addr8(addr2);
         const int bytes = mbits >> 3;
         const int leftover_bits = mbits & 7;
-        if (bytes && (r = memcmp(a1, a2, bytes))) {
+        if (bytes && (r = tor_memcmp(a1, a2, bytes))) {
           return r;
         } else if (leftover_bits) {
           uint8_t b1 = a1[bytes] >> (8-leftover_bits);

+ 3 - 1
src/common/compat.c

@@ -413,6 +413,8 @@ tor_vasprintf(char **strp, const char *fmt, va_list args)
  * <b>needle</b>, return a pointer to the first occurrence of the needle
  * within the haystack, or NULL if there is no such occurrence.
  *
+ * This function is <em>not</em> timing-safe.
+ *
  * Requires that nlen be greater than zero.
  */
 const void *
@@ -437,7 +439,7 @@ tor_memmem(const void *_haystack, size_t hlen,
   while ((p = memchr(p, first, end-p))) {
     if (p+nlen > end)
       return NULL;
-    if (!memcmp(p, needle, nlen))
+    if (fast_memeq(p, needle, nlen))
       return p;
     ++p;
   }

+ 4 - 4
src/common/container.c

@@ -216,7 +216,7 @@ smartlist_string_num_isin(const smartlist_t *sl, int num)
 }
 
 /** Return true iff <b>sl</b> has some element E such that
- * !memcmp(E,<b>element</b>,DIGEST_LEN)
+ * tor_memeq(E,<b>element</b>,DIGEST_LEN)
  */
 int
 smartlist_digest_isin(const smartlist_t *sl, const char *element)
@@ -224,7 +224,7 @@ smartlist_digest_isin(const smartlist_t *sl, const char *element)
   int i;
   if (!sl) return 0;
   for (i=0; i < sl->num_used; i++)
-    if (memcmp((const char*)sl->list[i],element,DIGEST_LEN)==0)
+    if (tor_memeq((const char*)sl->list[i],element,DIGEST_LEN))
       return 1;
   return 0;
 }
@@ -802,7 +802,7 @@ smartlist_pqueue_assert_ok(smartlist_t *sl,
 static int
 _compare_digests(const void **_a, const void **_b)
 {
-  return memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
+  return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
 }
 
 /** Sort the list of DIGEST_LEN-byte digests into ascending order. */
@@ -886,7 +886,7 @@ strmap_entry_hash(const strmap_entry_t *a)
 static INLINE int
 digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
 {
-  return !memcmp(a->key, b->key, DIGEST_LEN);
+  return tor_memeq(a->key, b->key, DIGEST_LEN);
 }
 
 /** Helper: return a hash value for a digest_map_t. */

+ 2 - 2
src/common/container.h

@@ -259,7 +259,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
  * Example use:
  *  SMARTLIST_FOREACH_JOIN(routerstatus_list, routerstatus_t *, rs,
  *                     routerinfo_list, routerinfo_t *, ri,
- *                     memcmp(rs->identity_digest, ri->identity_digest, 20),
+ *                     tor_memcmp(rs->identity_digest, ri->identity_digest, 20),
  *                     log_info(LD_GENERAL,"No match for %s", ri->nickname)) {
  *    log_info(LD_GENERAL, "%s matches routerstatus %p", ri->nickname, rs);
  * } SMARTLIST_FOREACH_JOIN_END(rs, ri);
@@ -274,7 +274,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
  *    ri = smartlist_get(routerinfo_list, ri_sl_idx);
  *    while (rs_sl_idx < rs_sl_len) {
  *      rs = smartlist_get(routerstatus_list, rs_sl_idx);
- *      rs_ri_cmp = memcmp(rs->identity_digest, ri->identity_digest, 20);
+ *      rs_ri_cmp = tor_memcmp(rs->identity_digest, ri->identity_digest, 20);
  *      if (rs_ri_cmp > 0) {
  *        break;
  *      } else if (rs_ri_cmp == 0) {

+ 1 - 1
src/common/crypto.c

@@ -933,7 +933,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data,
     tor_free(buf);
     return -1;
   }
-  if (memcmp(buf, digest, DIGEST_LEN)) {
+  if (tor_memneq(buf, digest, DIGEST_LEN)) {
     log_warn(LD_CRYPTO, "Signature mismatched with digest.");
     tor_free(buf);
     return -1;

+ 133 - 0
src/common/di_ops.c

@@ -0,0 +1,133 @@
+/* Copyright (c) 2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file di_ops.c
+ * \brief Functions for data-independent operations
+ **/
+
+#include "orconfig.h"
+#include "di_ops.h"
+
+/**
+ * Timing-safe version of memcmp.  As memcmp, compare the <b>sz</b> bytes
+ * at <b>a</b> with the <b>sz</b> bytes at <b>, and returns less than 0 if the
+ * bytes at <b>a</b> lexically precede those at <b>b</b>, 0 if the byte ranges
+ * are equal, and greater than zero if the bytes at <b>a</b> lexically follow
+ * those at <b>.
+ *
+ * This implementation differs from memcmp in that its timing behavior is not
+ * data-dependent: it should return in the same amount of time regardless of
+ * the contents of <b>a</b> and <b>b</b>.
+ */
+int
+tor_memcmp(const void *a, const void *b, size_t len)
+{
+  const uint8_t *x = a;
+  const uint8_t *y = b;
+  size_t i = len;
+  int retval = 0;
+
+  /* This loop goes from the end of the arrays to the start.  At the
+   * start of every iteration, before we decrement i, we have set
+   * "retval" equal to the result of memcmp(a+i,b+i,len-i).  During the
+   * loop, we update retval by leaving it unchanged if x[i]==y[i] and
+   * setting it to x[i]-y[i] if x[i]!= y[i].
+   *
+   * The following assumes we are on a system with two's-complement
+   * arithmetic.  We check for this at configure-time with the check
+   * that sets USING_TWOS_COMPLEMENT.  If we aren't two's complement, then
+   * torint.h will stop compilation with an error.
+   */
+  while (i--) {
+    int v1 = x[i];
+    int v2 = y[i];
+    int equal_p = v1 ^ v2;
+
+    /* The following sets bits 8 and above of equal_p to 'equal_p ==
+     * 0', and thus to v1 == v2.  (To see this, note that if v1 ==
+     * v2, then v1^v2 == equal_p == 0, so equal_p-1 == -1, which is the
+     * same as ~0 on a two's-complement machine.  Then note that if
+     * v1 != v2, then 0 < v1 ^ v2 < 256, so 0 <= equal_p - 1 < 255.)
+     */
+    --equal_p;
+
+    equal_p >>= 8;
+    /* Thanks to (sign-preserving) arithmetic shift, equal_p is now
+     * equal to -(v1 == v2), which is exactly what we need below.
+     * (Since we're assuming two's-complement arithmetic, -1 is the
+     * same as ~0 (all bits set).)
+     *
+     * (The result of an arithmetic shift on a negative value is
+     * actually implementation-defined in standard C.  So how do we
+     * get away with assuming it?  Easy.  We check.) */
+#if ((-60 >> 8) != -1)
+#error "According to cpp, right-shift doesn't perform sign-extension."
+#endif
+#ifndef RSHIFT_DOES_SIGN_EXTEND
+#error "According to configure, right-shift doesn't perform sign-extension."
+#endif
+
+    /* If v1 == v2, equal_p is ~0, so this will leave retval
+     * unchanged; otherwise, equal_p is 0, so this will zero it. */
+    retval &= equal_p;
+
+    /* If v1 == v2, then this adds 0, and leaves retval unchanged.
+     * Otherwise, we just zeroed retval, so this sets it to v1 - v2. */
+    retval += (v1 - v2);
+
+    /* There.  Now retval is equal to its previous value if v1 == v2, and
+     * equal to v1 - v2 if v1 != v2. */
+  }
+
+  return retval;
+}
+
+/**
+ * Timing-safe memory comparison.  Return true if the <b>sz</b> bytes at
+ * <b>a</b> are the same as the <b>sz</b> bytes at <b>, and 0 otherwise.
+ *
+ * This implementation differs from !memcmp(a,b,sz) in that its timing
+ * behavior is not data-dependent: it should return in the same amount of time
+ * regardless of the contents of <b>a</b> and <b>b</b>.  It differs from
+ * !tor_memcmp(a,b,sz) by being faster.
+ */
+int
+tor_memeq(const void *a, const void *b, size_t sz)
+{
+  /* Treat a and b as byte ranges. */
+  const uint8_t *ba = a, *bb = b;
+  uint32_t any_difference = 0;
+  while (sz--) {
+    /* Set byte_diff to all of those bits that are different in *ba and *bb,
+     * and advance both ba and bb. */
+    const uint8_t byte_diff = *ba++ ^ *bb++;
+
+    /* Set bits in any_difference if they are set in byte_diff. */
+    any_difference |= byte_diff;
+  }
+
+  /* Now any_difference is 0 if there are no bits different between
+   * a and b, and is nonzero if there are bits different between a
+   * and b.  Now for paranoia's sake, let's convert it to 0 or 1.
+   *
+   * (If we say "!any_difference", the compiler might get smart enough
+   * to optimize-out our data-independence stuff above.)
+   *
+   * To unpack:
+   *
+   * If any_difference == 0:
+   *            any_difference - 1 == ~0
+   *     (any_difference - 1) >> 8 == 0x00ffffff
+   *     1 & ((any_difference - 1) >> 8) == 1
+   *
+   * If any_difference != 0:
+   *            0 < any_difference < 256, so
+   *            0 < any_difference - 1 < 255
+   *            (any_difference - 1) >> 8 == 0
+   *            1 & ((any_difference - 1) >> 8) == 0
+   */
+
+  return 1 & ((any_difference - 1) >> 8);
+}
+

+ 30 - 0
src/common/di_ops.h

@@ -0,0 +1,30 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file di_ops.h
+ * \brief Headers for di_ops.c
+ **/
+
+#ifndef TOR_DI_OPS_H
+#define TOR_DI_OPS_H
+
+#include "orconfig.h"
+#include "torint.h"
+
+int tor_memcmp(const void *a, const void *b, size_t sz);
+int tor_memeq(const void *a, const void *b, size_t sz);
+#define tor_memneq(a,b,sz) (!tor_memeq((a),(b),(sz)))
+
+/** Alias for the platform's memcmp() function.  This function is
+ * <em>not</em> data-independent: we define this alias so that we can
+ * mark cases where we are deliberately using a data-dependent memcmp()
+ * implementation.
+ */
+#define fast_memcmp(a,b,c) (memcmp((a),(b),(c)))
+#define fast_memeq(a,b,c)  (0==memcmp((a),(b),(c)))
+#define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c)))
+
+#endif

+ 1 - 1
src/common/torgzip.c

@@ -378,7 +378,7 @@ tor_gzip_uncompress(char **out, size_t *out_len,
 compress_method_t
 detect_compression_method(const char *in, size_t in_len)
 {
-  if (in_len > 2 && !memcmp(in, "\x1f\x8b", 2)) {
+  if (in_len > 2 && fast_memeq(in, "\x1f\x8b", 2)) {
     return GZIP_METHOD;
   } else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
              (ntohs(get_uint16(in)) % 31) == 0) {

+ 13 - 8
src/common/util.c

@@ -515,7 +515,7 @@ strcmp_len(const char *s1, const char *s2, size_t s1_len)
     return -1;
   if (s1_len > s2_len)
     return 1;
-  return memcmp(s1, s2, s2_len);
+  return fast_memcmp(s1, s2, s2_len);
 }
 
 /** Compares the first strlen(s2) characters of s1 with s2.  Returns as for
@@ -557,17 +557,17 @@ strcasecmpend(const char *s1, const char *s2)
 /** Compare the value of the string <b>prefix</b> with the start of the
  * <b>memlen</b>-byte memory chunk at <b>mem</b>.  Return as for strcmp.
  *
- * [As memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is less
- * than strlen(prefix).]
+ * [As fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is
+ * less than strlen(prefix).]
  */
 int
-memcmpstart(const void *mem, size_t memlen,
+fast_memcmpstart(const void *mem, size_t memlen,
                 const char *prefix)
 {
   size_t plen = strlen(prefix);
   if (memlen < plen)
     return -1;
-  return memcmp(mem, prefix, plen);
+  return fast_memcmp(mem, prefix, plen);
 }
 
 /** Return a pointer to the first char of s that is not whitespace and
@@ -723,14 +723,16 @@ tor_mem_is_zero(const char *mem, size_t len)
     0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
   };
   while (len >= sizeof(ZERO)) {
-    if (memcmp(mem, ZERO, sizeof(ZERO)))
+    /* It's safe to use fast_memcmp here, since the very worst thing an
+     * attacker could learn is how many initial bytes of a secret were zero */
+    if (fast_memcmp(mem, ZERO, sizeof(ZERO)))
       return 0;
     len -= sizeof(ZERO);
     mem += sizeof(ZERO);
   }
   /* Deal with leftover bytes. */
   if (len)
-    return ! memcmp(mem, ZERO, len);
+    return fast_memeq(mem, ZERO, len);
 
   return 1;
 }
@@ -739,7 +741,10 @@ tor_mem_is_zero(const char *mem, size_t len)
 int
 tor_digest_is_zero(const char *digest)
 {
-  return tor_mem_is_zero(digest, DIGEST_LEN);
+  static const uint8_t ZERO_DIGEST[] = {
+    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
+  };
+  return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
 }
 
 /** Return true iff the DIGEST256_LEN bytes in digest are all zero. */

+ 3 - 2
src/common/util.h

@@ -14,6 +14,7 @@
 #include "orconfig.h"
 #include "torint.h"
 #include "compat.h"
+#include "di_ops.h"
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -181,8 +182,8 @@ int strcasecmpstart(const char *s1, const char *s2)
 int strcmpend(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2));
 int strcasecmpend(const char *s1, const char *s2)
   ATTR_PURE ATTR_NONNULL((1,2));
-int memcmpstart(const void *mem, size_t memlen,
-                const char *prefix) ATTR_PURE;
+int fast_memcmpstart(const void *mem, size_t memlen,
+                     const char *prefix) ATTR_PURE;
 
 void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2));
 long tor_parse_long(const char *s, int base, long min,

+ 6 - 6
src/or/circuitbuild.c

@@ -1823,7 +1823,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
           continue;
       } else {
         /* We expected a key. See if it's the right one. */
-        if (memcmp(or_conn->identity_digest,
+        if (tor_memneq(or_conn->identity_digest,
                    circ->n_hop->identity_digest, DIGEST_LEN))
           continue;
       }
@@ -2231,7 +2231,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
   /* Next, check if we're being asked to connect to the hop that the
    * extend cell came from. There isn't any reason for that, and it can
    * assist circular-path attacks. */
-  if (!memcmp(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest,
+  if (tor_memeq(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest,
               DIGEST_LEN)) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Client asked me to extend back to the previous hop.");
@@ -3512,7 +3512,7 @@ static INLINE entry_guard_t *
 is_an_entry_guard(const char *digest)
 {
   SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
-                    if (!memcmp(digest, entry->identity, DIGEST_LEN))
+                    if (tor_memeq(digest, entry->identity, DIGEST_LEN))
                       return entry;
                    );
   return NULL;
@@ -3844,7 +3844,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
 
   SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
     {
-      if (!memcmp(e->identity, digest, DIGEST_LEN)) {
+      if (tor_memeq(e->identity, digest, DIGEST_LEN)) {
         entry = e;
         idx = e_sl_idx;
         break;
@@ -4507,7 +4507,7 @@ get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
           !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
           bridge->port == port)
         return bridge;
-      if (!memcmp(bridge->identity, digest, DIGEST_LEN))
+      if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
         return bridge;
     }
   SMARTLIST_FOREACH_END(bridge);
@@ -4588,7 +4588,7 @@ find_bridge_by_digest(const char *digest)
 {
   SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
     {
-      if (!memcmp(bridge->identity, digest, DIGEST_LEN))
+      if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
         return bridge;
     });
   return NULL;

+ 5 - 5
src/or/circuitlist.c

@@ -256,7 +256,7 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn)
         continue;
     } else {
       /* We expected a key. See if it's the right one. */
-      if (memcmp(or_conn->identity_digest,
+      if (tor_memneq(or_conn->identity_digest,
                  circ->n_hop->identity_digest, DIGEST_LEN))
         continue;
     }
@@ -719,7 +719,7 @@ circuit_dump_by_conn(connection_t *conn, int severity)
         tor_addr_eq(&circ->n_hop->addr, &conn->addr) &&
         circ->n_hop->port == conn->port &&
         conn->type == CONN_TYPE_OR &&
-        !memcmp(TO_OR_CONN(conn)->identity_digest,
+        tor_memeq(TO_OR_CONN(conn)->identity_digest,
                 circ->n_hop->identity_digest, DIGEST_LEN)) {
       circuit_dump_details(severity, circ, conn->conn_array_index,
                            (circ->state == CIRCUIT_STATE_OPEN &&
@@ -913,7 +913,7 @@ circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
     if (!digest)
       return TO_ORIGIN_CIRCUIT(circ);
     else if (TO_ORIGIN_CIRCUIT(circ)->rend_data &&
-             !memcmp(TO_ORIGIN_CIRCUIT(circ)->rend_data->rend_pk_digest,
+             tor_memeq(TO_ORIGIN_CIRCUIT(circ)->rend_data->rend_pk_digest,
                      digest, DIGEST_LEN))
       return TO_ORIGIN_CIRCUIT(circ);
   }
@@ -931,7 +931,7 @@ circuit_get_by_rend_token_and_purpose(uint8_t purpose, const char *token,
   for (circ = global_circuitlist; circ; circ = circ->next) {
     if (! circ->marked_for_close &&
         circ->purpose == purpose &&
-        ! memcmp(TO_OR_CIRCUIT(circ)->rend_token, token, len))
+        tor_memeq(TO_OR_CIRCUIT(circ)->rend_token, token, len))
       return TO_OR_CIRCUIT(circ);
   }
   return NULL;
@@ -1008,7 +1008,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
           routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
           do {
             routerinfo_t *ri2;
-            if (!memcmp(hop->extend_info->identity_digest,
+            if (tor_memeq(hop->extend_info->identity_digest,
                         info->identity_digest, DIGEST_LEN))
               goto next;
             if (ri1 &&

+ 1 - 1
src/or/circuituse.c

@@ -108,7 +108,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
         char digest[DIGEST_LEN];
         if (hexdigest_to_digest(conn->chosen_exit_name, digest) < 0)
           return 0; /* broken digest, we don't want it */
-        if (memcmp(digest, build_state->chosen_exit->identity_digest,
+        if (tor_memneq(digest, build_state->chosen_exit->identity_digest,
                           DIGEST_LEN))
           return 0; /* this is a circuit to somewhere else */
         if (tor_digest_is_zero(digest)) {

+ 2 - 2
src/or/connection_edge.c

@@ -577,7 +577,7 @@ connection_ap_fail_onehop(const char *failed_digest,
     if (!edge_conn->want_onehop)
       continue;
     if (hexdigest_to_digest(edge_conn->chosen_exit_name, digest) < 0 ||
-        memcmp(digest, failed_digest, DIGEST_LEN))
+        tor_memneq(digest, failed_digest, DIGEST_LEN))
       continue;
     if (tor_digest_is_zero(digest)) {
       /* we don't know the digest; have to compare addr:port */
@@ -3061,7 +3061,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
   if (conn->chosen_exit_name) {
     routerinfo_t *chosen_exit =
       router_get_by_nickname(conn->chosen_exit_name, 1);
-    if (!chosen_exit || memcmp(chosen_exit->cache_info.identity_digest,
+    if (!chosen_exit || tor_memneq(chosen_exit->cache_info.identity_digest,
                                exit->cache_info.identity_digest, DIGEST_LEN)) {
       /* doesn't match */
 //      log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",

+ 4 - 4
src/or/connection_or.c

@@ -111,7 +111,7 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
 
   if (!orconn_identity_map)
     orconn_identity_map = digestmap_new();
-  if (!memcmp(conn->identity_digest, digest, DIGEST_LEN))
+  if (tor_memeq(conn->identity_digest, digest, DIGEST_LEN))
     return;
 
   /* If the identity was set previously, remove the old mapping. */
@@ -130,7 +130,7 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
 #if 1
   /* Testing code to check for bugs in representation. */
   for (; tmp; tmp = tmp->next_with_same_id) {
-    tor_assert(!memcmp(tmp->identity_digest, digest, DIGEST_LEN));
+    tor_assert(tor_memeq(tmp->identity_digest, digest, DIGEST_LEN));
     tor_assert(tmp != conn);
   }
 #endif
@@ -545,7 +545,7 @@ connection_or_get_for_extend(const char *digest,
   for (; conn; conn = conn->next_with_same_id) {
     tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC);
     tor_assert(conn->_base.type == CONN_TYPE_OR);
-    tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN));
+    tor_assert(tor_memeq(conn->identity_digest, digest, DIGEST_LEN));
     if (conn->_base.marked_for_close)
       continue;
     /* Never return a non-open connection. */
@@ -1082,7 +1082,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
     int as_advertised = 1;
     tor_assert(has_cert);
     tor_assert(has_identity);
-    if (memcmp(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) {
+    if (tor_memneq(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) {
       /* I was aiming for a particular digest. I didn't get it! */
       char seen[HEX_DIGEST_LEN+1];
       char expected[HEX_DIGEST_LEN+1];

+ 7 - 7
src/or/control.c

@@ -334,7 +334,7 @@ write_escaped_data(const char *data, size_t len, char **out)
     }
     *outp++ = *data++;
   }
-  if (outp < *out+2 || memcmp(outp-2, "\r\n", 2)) {
+  if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) {
     *outp++ = '\r';
     *outp++ = '\n';
   }
@@ -500,7 +500,7 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
     return;
   }
   len = strlen(buf);
-  if (memcmp("\r\n\0", buf+len-2, 3)) {
+  if (fast_memcmp("\r\n\0", buf+len-2, 3)) {
     buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-1] = '\0';
     buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n';
     buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r';
@@ -581,7 +581,7 @@ send_control_event_impl(uint16_t event, event_format_t which,
   }
 
   len = strlen(buf);
-  if (memcmp("\r\n\0", buf+len-2, 3)) {
+  if (fast_memcmp("\r\n\0", buf+len-2, 3)) {
     /* if it is not properly terminated, do it now */
     buf[SEND_CONTROL1_EVENT_BUFFERSIZE-1] = '\0';
     buf[SEND_CONTROL1_EVENT_BUFFERSIZE-2] = '\n';
@@ -1069,7 +1069,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
         goto err;
       }
       bad_cookie = 1;
-    } else if (memcmp(authentication_cookie, password, password_len)) {
+    } else if (tor_memneq(authentication_cookie, password, password_len)) {
       if (!also_password) {
         log_warn(LD_CONTROL, "Got mismatched authentication cookie");
         errstr = "Authentication cookie did not match expected value.";
@@ -1119,7 +1119,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
       SMARTLIST_FOREACH(sl, char *, expected,
       {
         secret_to_key(received,DIGEST_LEN,password,password_len,expected);
-        if (!memcmp(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN))
+        if (tor_memeq(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN))
           goto ok;
       });
       SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
@@ -2834,13 +2834,13 @@ connection_control_process_inbuf(control_connection_t *conn)
       break;
     /* XXXX this code duplication is kind of dumb. */
     if (last_idx+3 == conn->incoming_cmd_cur_len &&
-        !memcmp(conn->incoming_cmd + last_idx, ".\r\n", 3)) {
+        tor_memeq(conn->incoming_cmd + last_idx, ".\r\n", 3)) {
       /* Just appended ".\r\n"; we're done. Remove it. */
       conn->incoming_cmd[last_idx] = '\0';
       conn->incoming_cmd_cur_len -= 3;
       break;
     } else if (last_idx+2 == conn->incoming_cmd_cur_len &&
-               !memcmp(conn->incoming_cmd + last_idx, ".\n", 2)) {
+               tor_memeq(conn->incoming_cmd + last_idx, ".\n", 2)) {
       /* Just appended ".\n"; we're done. Remove it. */
       conn->incoming_cmd[last_idx] = '\0';
       conn->incoming_cmd_cur_len -= 2;

+ 5 - 5
src/or/directory.c

@@ -2436,7 +2436,7 @@ client_likes_consensus(networkstatus_t *v, const char *want_url)
 
     SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
       if (smartlist_len(vi->sigs) &&
-          !memcmp(vi->identity_digest, want_digest, want_len)) {
+          tor_memeq(vi->identity_digest, want_digest, want_len)) {
         have++;
         break;
       };
@@ -3609,17 +3609,17 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
    * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
 }
 
-/** Helper.  Compare two fp_pair_t objects, and return -1, 0, or 1 as
- * appropriate. */
+/** Helper.  Compare two fp_pair_t objects, and return negative, 0, or
+ * positive as appropriate. */
 static int
 _compare_pairs(const void **a, const void **b)
 {
   const fp_pair_t *fp1 = *a, *fp2 = *b;
   int r;
-  if ((r = memcmp(fp1->first, fp2->first, DIGEST_LEN)))
+  if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
     return r;
   else
-    return memcmp(fp1->second, fp2->second, DIGEST_LEN);
+    return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
 }
 
 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each

+ 4 - 4
src/or/dirserv.c

@@ -2198,9 +2198,9 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
 
   /* They're equal! Compare by identity digest, so there's a
    * deterministic order and we avoid flapping. */
-  return memcmp(first->cache_info.identity_digest,
-                second->cache_info.identity_digest,
-                DIGEST_LEN);
+  return fast_memcmp(first->cache_info.identity_digest,
+                     second->cache_info.identity_digest,
+                     DIGEST_LEN);
 }
 
 /** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t
@@ -3158,7 +3158,7 @@ dirserv_orconn_tls_done(const char *address,
   SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
     if (!strcasecmp(address, ri->address) && or_port == ri->or_port &&
         as_advertised &&
-        !memcmp(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) {
+        fast_memeq(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) {
       /* correct digest. mark this router reachable! */
       if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) {
         tor_addr_t addr, *addrp=NULL;

+ 18 - 18
src/or/dirvote.c

@@ -340,7 +340,7 @@ static int
 _compare_votes_by_authority_id(const void **_a, const void **_b)
 {
   const networkstatus_t *a = *_a, *b = *_b;
-  return memcmp(get_voter(a)->identity_digest,
+  return fast_memcmp(get_voter(a)->identity_digest,
                 get_voter(b)->identity_digest, DIGEST_LEN);
 }
 
@@ -357,7 +357,7 @@ _compare_dir_src_ents_by_authority_id(const void **_a, const void **_b)
   a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest;
   b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest;
 
-  return memcmp(a_id, b_id, DIGEST_LEN);
+  return fast_memcmp(a_id, b_id, DIGEST_LEN);
 }
 
 /** Given a sorted list of strings <b>in</b>, add every member to <b>out</b>
@@ -394,10 +394,10 @@ static int
 compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
 {
   int r;
-  if ((r = memcmp(a->status.identity_digest, b->status.identity_digest,
+  if ((r = fast_memcmp(a->status.identity_digest, b->status.identity_digest,
                   DIGEST_LEN)))
     return r;
-  if ((r = memcmp(a->status.descriptor_digest, b->status.descriptor_digest,
+  if ((r = fast_memcmp(a->status.descriptor_digest, b->status.descriptor_digest,
                   DIGEST_LEN)))
     return r;
   if ((r = (int)(b->status.published_on - a->status.published_on)))
@@ -1648,7 +1648,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
               strmap_set_lc(name_to_id_map, rs->status.nickname,
                             rs->status.identity_digest);
             } else if (d != conflict &&
-                memcmp(d, rs->status.identity_digest, DIGEST_LEN)) {
+                fast_memcmp(d, rs->status.identity_digest, DIGEST_LEN)) {
               /* Authorities disagree about this nickname. */
               strmap_set_lc(name_to_id_map, rs->status.nickname, conflict);
             } else {
@@ -1672,7 +1672,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
             } else if (!d) {
               /* We have no name officially mapped to this digest. */
               strmap_set_lc(name_to_id_map, rs->status.nickname, unknown);
-            } else if (!memcmp(d, rs->status.identity_digest, DIGEST_LEN)) {
+            } else if (fast_memeq(d, rs->status.identity_digest, DIGEST_LEN)) {
               /* Authorities disagree about this nickname. */
               strmap_set_lc(name_to_id_map, rs->status.nickname, conflict);
             } else {
@@ -1705,7 +1705,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
         if (index[v_sl_idx] < size[v_sl_idx]) {
           rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
           if (!lowest_id ||
-              memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0)
+              fast_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0)
             lowest_id = rs->status.identity_digest;
         }
       });
@@ -1724,7 +1724,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
         if (index[v_sl_idx] >= size[v_sl_idx])
           continue; /* out of entries. */
         rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
-        if (memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN))
+        if (fast_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN))
           continue; /* doesn't include this router. */
         /* At this point, we know that we're looking at a routerstatus with
          * identity "lowest".
@@ -1769,7 +1769,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
       rs = compute_routerstatus_consensus(matching_descs, consensus_method,
                                           microdesc_digest);
       /* Copy bits of that into rs_out. */
-      tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN));
+      tor_assert(fast_memeq(lowest_id, rs->status.identity_digest, DIGEST_LEN));
       memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
       memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
              DIGEST_LEN);
@@ -1793,7 +1793,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
         const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname);
         if (!d) {
           is_named = is_unnamed = 0;
-        } else if (!memcmp(d, lowest_id, DIGEST_LEN)) {
+        } else if (fast_memeq(d, lowest_id, DIGEST_LEN)) {
           is_named = 1; is_unnamed = 0;
         } else {
           is_named = 0; is_unnamed = 1;
@@ -1891,11 +1891,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
         SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
           /* Check if the vote where this status comes from had the
            * proper descriptor */
-          tor_assert(!memcmp(rs_out.identity_digest,
+          tor_assert(fast_memeq(rs_out.identity_digest,
                              vsr->status.identity_digest,
                              DIGEST_LEN));
           if (vsr->status.has_exitsummary &&
-               !memcmp(rs_out.descriptor_digest,
+               fast_memeq(rs_out.descriptor_digest,
                        vsr->status.descriptor_digest,
                        DIGEST_LEN)) {
             tor_assert(vsr->status.exitsummary);
@@ -2975,11 +2975,11 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
 
   /* Now see whether we already have a vote from this authority. */
   SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
-      if (! memcmp(v->vote->cert->cache_info.identity_digest,
+      if (fast_memeq(v->vote->cert->cache_info.identity_digest,
                    vote->cert->cache_info.identity_digest,
                    DIGEST_LEN)) {
         networkstatus_voter_info_t *vi_old = get_voter(v->vote);
-        if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
+        if (fast_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
           /* Ah, it's the same vote. Not a problem. */
           log_info(LD_DIR, "Discarding a vote we already have (from %s).",
                    vi->address);
@@ -3480,23 +3480,23 @@ dirvote_get_vote(const char *fp, int flags)
   if (by_id) {
     if (pending_vote_list && include_pending) {
       SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
-        if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
+        if (fast_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
           return pv->vote_body);
     }
     if (previous_vote_list && include_previous) {
       SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
-        if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
+        if (fast_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
           return pv->vote_body);
     }
   } else {
     if (pending_vote_list && include_pending) {
       SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
-        if (!memcmp(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
+        if (fast_memeq(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
           return pv->vote_body);
     }
     if (previous_vote_list && include_previous) {
       SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
-        if (!memcmp(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
+        if (fast_memeq(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
           return pv->vote_body);
     }
   }

+ 1 - 1
src/or/eventdns.c

@@ -461,7 +461,7 @@ sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2,
 		const struct sockaddr_in6 *sin1, *sin2;
 		sin1 = (const struct sockaddr_in6 *)sa1;
 		sin2 = (const struct sockaddr_in6 *)sa2;
-		if (memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))
+		if (tor_memneq(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))
 			return 0;
 		else if (include_port && sin1->sin6_port != sin2->sin6_port)
 			return 0;

+ 19 - 19
src/or/networkstatus.c

@@ -409,7 +409,7 @@ networkstatus_get_voter_by_id(networkstatus_t *vote,
   if (!vote || !vote->voters)
     return NULL;
   SMARTLIST_FOREACH(vote->voters, networkstatus_voter_info_t *, voter,
-    if (!memcmp(voter->identity_digest, identity, DIGEST_LEN))
+    if (fast_memeq(voter->identity_digest, identity, DIGEST_LEN))
       return voter);
   return NULL;
 }
@@ -430,9 +430,9 @@ networkstatus_check_document_signature(const networkstatus_t *consensus,
 
   if (crypto_pk_get_digest(cert->signing_key, key_digest)<0)
     return -1;
-  if (memcmp(sig->signing_key_digest, key_digest, DIGEST_LEN) ||
-      memcmp(sig->identity_digest, cert->cache_info.identity_digest,
-             DIGEST_LEN))
+  if (tor_memneq(sig->signing_key_digest, key_digest, DIGEST_LEN) ||
+      tor_memneq(sig->identity_digest, cert->cache_info.identity_digest,
+                 DIGEST_LEN))
     return -1;
 
   signed_digest_len = crypto_pk_keysize(cert->signing_key);
@@ -442,7 +442,7 @@ networkstatus_check_document_signature(const networkstatus_t *consensus,
                                 signed_digest_len,
                                 sig->signature,
                                 sig->signature_len) < dlen ||
-      memcmp(signed_digest, consensus->digests.d[sig->alg], dlen)) {
+      tor_memneq(signed_digest, consensus->digests.d[sig->alg], dlen)) {
     log_warn(LD_DIR, "Got a bad signature on a networkstatus vote");
     sig->bad_signature = 1;
   } else {
@@ -797,8 +797,8 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at,
   for (i=0; i < smartlist_len(networkstatus_v2_list); ++i) {
     networkstatus_v2_t *old_ns = smartlist_get(networkstatus_v2_list, i);
 
-    if (!memcmp(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) {
-      if (!memcmp(old_ns->networkstatus_digest,
+    if (tor_memeq(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) {
+      if (tor_memeq(old_ns->networkstatus_digest,
                   ns->networkstatus_digest, DIGEST_LEN)) {
         /* Same one we had before. */
         networkstatus_v2_free(ns);
@@ -924,7 +924,7 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member)
 {
   const char *key = _key;
   const routerstatus_t *rs = *_member;
-  return memcmp(key, rs->identity_digest, DIGEST_LEN);
+  return tor_memcmp(key, rs->identity_digest, DIGEST_LEN);
 }
 
 /** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
@@ -1392,7 +1392,7 @@ networkstatus_v2_get_by_digest(const char *digest)
 {
   SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
     {
-      if (!memcmp(ns->identity_digest, digest, DIGEST_LEN))
+      if (tor_memeq(ns->identity_digest, digest, DIGEST_LEN))
         return ns;
     });
   return NULL;
@@ -1441,10 +1441,10 @@ networkstatus_get_reasonably_live_consensus(time_t now)
 static int
 routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
 {
-  tor_assert(!memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN));
+  tor_assert(tor_memeq(a->identity_digest, b->identity_digest, DIGEST_LEN));
 
   return strcmp(a->nickname, b->nickname) ||
-         memcmp(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) ||
+         fast_memneq(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) ||
          a->addr != b->addr ||
          a->or_port != b->or_port ||
          a->dir_port != b->dir_port ||
@@ -1495,7 +1495,7 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
 
   SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
                          new_c->routerstatus_list, routerstatus_t *, rs_new,
-                         memcmp(rs_old->identity_digest,
+                         tor_memcmp(rs_old->identity_digest,
                                 rs_new->identity_digest, DIGEST_LEN),
                          smartlist_add(changed, rs_new)) {
     if (routerstatus_has_changed(rs_old, rs_new))
@@ -1519,14 +1519,14 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
 
   SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
                          new_c->routerstatus_list, routerstatus_t *, rs_new,
-                         memcmp(rs_old->identity_digest,
+                         tor_memcmp(rs_old->identity_digest,
                                 rs_new->identity_digest, DIGEST_LEN),
                          STMT_NIL) {
     /* Okay, so we're looking at the same identity. */
     rs_new->name_lookup_warned = rs_old->name_lookup_warned;
     rs_new->last_dir_503_at = rs_old->last_dir_503_at;
 
-    if (!memcmp(rs_old->descriptor_digest, rs_new->descriptor_digest,
+    if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
                 DIGEST_LEN)) {
       /* And the same descriptor too! */
       memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t));
@@ -1635,7 +1635,7 @@ networkstatus_set_current_consensus(const char *consensus,
   }
 
   if (current_digests &&
-      !memcmp(&c->digests, current_digests, sizeof(c->digests))) {
+      tor_memeq(&c->digests, current_digests, sizeof(c->digests))) {
     /* We already have this one. That's a failure. */
     log_info(LD_DIR, "Got a %s consensus we already have", flavor);
     goto done;
@@ -1957,7 +1957,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
 
   SMARTLIST_FOREACH_JOIN(ns->routerstatus_list, routerstatus_t *, rs,
                          routers, routerinfo_t *, router,
-                         memcmp(rs->identity_digest,
+                         tor_memcmp(rs->identity_digest,
                                router->cache_info.identity_digest, DIGEST_LEN),
   {
     /* We have no routerstatus for this router. Clear flags and skip it. */
@@ -1980,7 +1980,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
         router->is_named = 0;
     }
     /* Is it the same descriptor, or only the same identity? */
-    if (!memcmp(router->cache_info.signed_descriptor_digest,
+    if (tor_memeq(router->cache_info.signed_descriptor_digest,
                 rs->descriptor_digest, DIGEST_LEN)) {
       if (ns->valid_until > router->cache_info.last_listed_as_valid_until)
         router->cache_info.last_listed_as_valid_until = ns->valid_until;
@@ -2021,10 +2021,10 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
     time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
     SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
                          routers, routerinfo_t *, ri,
-                         memcmp(rs->identity_digest,
+                         tor_memcmp(rs->identity_digest,
                                 ri->cache_info.identity_digest, DIGEST_LEN),
                          STMT_NIL) {
-      if (!memcmp(ri->cache_info.signed_descriptor_digest,
+      if (tor_memeq(ri->cache_info.signed_descriptor_digest,
                   rs->descriptor_digest, DIGEST_LEN)) {
         if (live_until > ri->cache_info.last_listed_as_valid_until)
           ri->cache_info.last_listed_as_valid_until = live_until;

+ 2 - 2
src/or/onion.c

@@ -328,7 +328,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
   if (len < 0)
     goto err;
 
-  if (memcmp(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
+  if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
     /* H(K) does *not* match. Something fishy. */
     log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. "
              "Bug or attack.");
@@ -415,7 +415,7 @@ fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/
   if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
     goto done;
   }
-  if (memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) {
+  if (tor_memneq(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) {
     /* H(K) does *not* match. Something fishy. */
     log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. "
              "Bug or attack.");

+ 1 - 1
src/or/relay.c

@@ -133,7 +133,7 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell)
   crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE);
   crypto_digest_get_digest(digest, calculated_integrity, 4);
 
-  if (memcmp(received_integrity, calculated_integrity, 4)) {
+  if (tor_memneq(received_integrity, calculated_integrity, 4)) {
 //    log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing.");
 // (%d vs %d).", received_integrity, calculated_integrity);
     /* restore digest to its old form */

+ 3 - 3
src/or/rendclient.c

@@ -157,7 +157,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
   intro_key = NULL;
   SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
                     intro, {
-    if (!memcmp(introcirc->build_state->chosen_exit->identity_digest,
+    if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest,
                 intro->extend_info->identity_digest, DIGEST_LEN)) {
       intro_key = intro->intro_key;
       break;
@@ -626,7 +626,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
 
   for (i = 0; i < smartlist_len(ent->parsed->intro_nodes); i++) {
     rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i);
-    if (!memcmp(failed_intro->identity_digest,
+    if (tor_memeq(failed_intro->identity_digest,
                 intro->extend_info->identity_digest, DIGEST_LEN)) {
       rend_intro_point_free(intro);
       smartlist_del(ent->parsed->intro_nodes, i);
@@ -725,7 +725,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
     goto err;
 
   /* Check whether the digest is right... */
-  if (memcmp(keys, request+DH_KEY_LEN, DIGEST_LEN)) {
+  if (tor_memneq(keys, request+DH_KEY_LEN, DIGEST_LEN)) {
     log_warn(LD_PROTOCOL, "Incorrect digest of key material.");
     goto err;
   }

+ 4 - 4
src/or/rendcommon.c

@@ -885,15 +885,15 @@ rend_id_is_in_interval(const char *a, const char *b, const char *c)
   tor_assert(c);
 
   /* There are five cases in which a is outside the interval ]b,c]: */
-  a_b = memcmp(a,b,DIGEST_LEN);
+  a_b = tor_memcmp(a,b,DIGEST_LEN);
   if (a_b == 0)
     return 0; /* 1. a == b (b is excluded) */
-  b_c = memcmp(b,c,DIGEST_LEN);
+  b_c = tor_memcmp(b,c,DIGEST_LEN);
   if (b_c == 0)
     return 0; /* 2. b == c (interval is empty) */
   else if (a_b <= 0 && b_c < 0)
     return 0; /* 3. a b c */
-  c_a = memcmp(c,a,DIGEST_LEN);
+  c_a = tor_memcmp(c,a,DIGEST_LEN);
   if (c_a < 0 && a_b <= 0)
     return 0; /* 4. c a b */
   else if (b_c < 0 && c_a < 0)
@@ -1067,7 +1067,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published)
     rend_service_descriptor_free(parsed);
     return 0;
   }
-  if (e && e->len == desc_len && !memcmp(desc,e->desc,desc_len)) {
+  if (e && e->len == desc_len && tor_memeq(desc,e->desc,desc_len)) {
     log_info(LD_REND,"We already have this service descriptor %s.",
              safe_str_client(query));
     e->received = time(NULL);

+ 1 - 1
src/or/rendmid.c

@@ -62,7 +62,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,
     log_warn(LD_BUG, "Internal error computing digest.");
     goto err;
   }
-  if (memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) {
+  if (tor_memneq(expected_digest, request+2+asn1len, DIGEST_LEN)) {
     log_warn(LD_PROTOCOL, "Hash of session info was not as expected.");
     reason = END_CIRC_REASON_TORPROTOCOL;
     goto err;

+ 8 - 8
src/or/rendservice.c

@@ -465,7 +465,7 @@ rend_config_services(or_options_t *options, int validate_only)
         int keep_it = 0;
         tor_assert(oc->rend_data);
         SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
-          if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest,
+          if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest,
                       DIGEST_LEN)) {
             keep_it = 1;
             break;
@@ -760,7 +760,7 @@ static rend_service_t *
 rend_service_get_by_pk_digest(const char* digest)
 {
   SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
-                    if (!memcmp(s->pk_digest,digest,DIGEST_LEN))
+                    if (tor_memeq(s->pk_digest,digest,DIGEST_LEN))
                         return s);
   return NULL;
 }
@@ -800,7 +800,7 @@ rend_check_authorization(rend_service_t *service,
 
   /* Look up client authorization by descriptor cookie. */
   SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, client, {
-    if (!memcmp(client->descriptor_cookie, descriptor_cookie,
+    if (tor_memeq(client->descriptor_cookie, descriptor_cookie,
                 REND_DESC_COOKIE_LEN)) {
       auth_client = client;
       break;
@@ -914,7 +914,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
 
   /* first DIGEST_LEN bytes of request is intro or service pk digest */
   crypto_pk_get_digest(intro_key, intro_key_digest);
-  if (memcmp(intro_key_digest, request, DIGEST_LEN)) {
+  if (tor_memneq(intro_key_digest, request, DIGEST_LEN)) {
     base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
                   (char*)request, REND_SERVICE_ID_LEN);
     log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
@@ -1269,7 +1269,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
     return -1;
   }
 
-  if (memcmp(intro->extend_info->identity_digest,
+  if (tor_memneq(intro->extend_info->identity_digest,
       launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) {
     char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1];
     base16_encode(cann, sizeof(cann),
@@ -1555,7 +1555,7 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
   tor_assert(intro);
   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
                                                   CIRCUIT_PURPOSE_S_INTRO))) {
-    if (!memcmp(circ->build_state->chosen_exit->identity_digest,
+    if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
                 intro->extend_info->identity_digest, DIGEST_LEN) &&
         circ->rend_data) {
       return circ;
@@ -1565,7 +1565,7 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
   circ = NULL;
   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
                                         CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
-    if (!memcmp(circ->build_state->chosen_exit->identity_digest,
+    if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
                 intro->extend_info->identity_digest, DIGEST_LEN) &&
         circ->rend_data) {
       return circ;
@@ -1822,7 +1822,7 @@ rend_services_introduce(void)
         if (service->desc) {
           SMARTLIST_FOREACH(service->desc->intro_nodes, rend_intro_point_t *,
                             dintro, {
-            if (!memcmp(dintro->extend_info->identity_digest,
+            if (tor_memeq(dintro->extend_info->identity_digest,
                 intro->extend_info->identity_digest, DIGEST_LEN)) {
               log_info(LD_REND, "The intro point we are giving up on was "
                                 "included in the last published descriptor. "

+ 2 - 2
src/or/rephist.c

@@ -117,7 +117,7 @@ get_or_history(const char* id)
 {
   or_history_t *hist;
 
-  if (tor_mem_is_zero(id, DIGEST_LEN))
+  if (tor_digest_is_zero(id))
     return NULL;
 
   hist = digestmap_get(history_map, id);
@@ -145,7 +145,7 @@ get_link_history(const char *from_id, const char *to_id)
   orhist = get_or_history(from_id);
   if (!orhist)
     return NULL;
-  if (tor_mem_is_zero(to_id, DIGEST_LEN))
+  if (tor_digest_is_zero(to_id))
     return NULL;
   lhist = (link_history_t*) digestmap_get(orhist->link_history_map, to_id);
   if (!lhist) {

+ 3 - 3
src/or/router.c

@@ -722,7 +722,7 @@ init_keys(void)
     ds->type = type;
   }
   if (v3_digest_set && (ds->type & V3_AUTHORITY) &&
-      memcmp(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
+      tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
     log_warn(LD_DIR, "V3 identity key does not match identity declared in "
              "DirServer line.  Adjusting.");
     memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN);
@@ -1261,7 +1261,7 @@ int
 router_digest_is_me(const char *digest)
 {
   return (server_identitykey &&
-          !memcmp(server_identitykey_digest, digest, DIGEST_LEN));
+          tor_memeq(server_identitykey_digest, digest, DIGEST_LEN));
 }
 
 /** Return true iff I'm a server and <b>digest</b> is equal to
@@ -1273,7 +1273,7 @@ router_extrainfo_digest_is_me(const char *digest)
   if (!ei)
     return 0;
 
-  return !memcmp(digest,
+  return tor_memeq(digest,
                  ei->cache_info.signed_descriptor_digest,
                  DIGEST_LEN);
 }

+ 30 - 30
src/or/routerlist.c

@@ -165,7 +165,7 @@ already_have_cert(authority_cert_t *cert)
 
   SMARTLIST_FOREACH(cl->certs, authority_cert_t *, c,
   {
-    if (!memcmp(c->cache_info.signed_descriptor_digest,
+    if (tor_memeq(c->cache_info.signed_descriptor_digest,
                 cert->cache_info.signed_descriptor_digest,
                 DIGEST_LEN))
       return 1;
@@ -378,16 +378,16 @@ authority_cert_get_by_sk_digest(const char *sk_digest)
     return NULL;
 
   if ((c = get_my_v3_authority_cert()) &&
-      !memcmp(c->signing_key_digest, sk_digest, DIGEST_LEN))
+      tor_memeq(c->signing_key_digest, sk_digest, DIGEST_LEN))
     return c;
   if ((c = get_my_v3_legacy_cert()) &&
-      !memcmp(c->signing_key_digest, sk_digest, DIGEST_LEN))
+      tor_memeq(c->signing_key_digest, sk_digest, DIGEST_LEN))
     return c;
 
   DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
     SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
     {
-      if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
+      if (tor_memeq(cert->signing_key_digest, sk_digest, DIGEST_LEN))
         return cert;
     });
   } DIGESTMAP_FOREACH_END;
@@ -406,7 +406,7 @@ authority_cert_get_by_digests(const char *id_digest,
       !(cl = digestmap_get(trusted_dir_certs, id_digest)))
     return NULL;
   SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
-    if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
+    if (tor_memeq(cert->signing_key_digest, sk_digest, DIGEST_LEN))
       return cert; );
 
   return NULL;
@@ -1002,7 +1002,7 @@ router_get_trusteddirserver_by_digest(const char *digest)
 
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
      {
-       if (!memcmp(ds->digest, digest, DIGEST_LEN))
+       if (tor_memeq(ds->digest, digest, DIGEST_LEN))
          return ds;
      });
 
@@ -1021,7 +1021,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
 
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
      {
-       if (!memcmp(ds->v3_identity_digest, digest, DIGEST_LEN) &&
+       if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) &&
            (ds->type & V3_AUTHORITY))
          return ds;
      });
@@ -2267,7 +2267,7 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest,
 
   if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
     return 0;
-  return (!memcmp(digest, identity_digest, DIGEST_LEN));
+  return (tor_memeq(digest, identity_digest, DIGEST_LEN));
 }
 
 /** Return true iff the digest of <b>router</b>'s identity key,
@@ -2332,7 +2332,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
       if (n_matches <= 1 || router->is_running)
         best_match = router;
     } else if (maybedigest &&
-               !memcmp(digest, router->cache_info.identity_digest, DIGEST_LEN)
+               tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN)
                ) {
       if (router_hex_digest_matches(router, nickname))
         return router;
@@ -2422,7 +2422,7 @@ router_digest_is_trusted_dir_type(const char *digest, authority_type_t type)
   if (authdir_mode(get_options()) && router_digest_is_me(digest))
     return 1;
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent,
-    if (!memcmp(digest, ent->digest, DIGEST_LEN)) {
+    if (tor_memeq(digest, ent->digest, DIGEST_LEN)) {
       return (!type) || ((type & ent->type) != 0);
     });
   return 0;
@@ -2587,7 +2587,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc,
 
   tor_assert(r);
   if (!with_annotations) {
-    if (memcmp("router ", r, 7) && memcmp("extra-info ", r, 11)) {
+    if (fast_memcmp("router ", r, 7) && fast_memcmp("extra-info ", r, 11)) {
       char *cp = tor_strndup(r, 64);
       log_err(LD_DIR, "descriptor at %p begins with unexpected string %s.  "
               "Is another process running in our data directory?  Exiting.",
@@ -3066,7 +3066,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
     routerlist_insert(rl, ri_new);
     return;
   }
-  if (memcmp(ri_old->cache_info.identity_digest,
+  if (tor_memneq(ri_old->cache_info.identity_digest,
              ri_new->cache_info.identity_digest, DIGEST_LEN)) {
     /* digests don't match; digestmap_set won't replace */
     rimap_remove(rl->identity_map, ri_old->cache_info.identity_digest);
@@ -3205,7 +3205,7 @@ router_set_status(const char *digest, int up)
   tor_assert(digest);
 
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
-                    if (!memcmp(d->digest, digest, DIGEST_LEN))
+                    if (tor_memeq(d->digest, digest, DIGEST_LEN))
                       d->is_running = up);
 
   router = router_get_by_digest(digest);
@@ -3329,14 +3329,14 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
   {
     routerstatus_t *rs =
       networkstatus_v2_find_entry(ns, id_digest);
-    if (rs && !memcmp(rs->descriptor_digest,
+    if (rs && tor_memeq(rs->descriptor_digest,
                       router->cache_info.signed_descriptor_digest,
                       DIGEST_LEN))
       rs->need_to_mirror = 0;
   });
   if (consensus) {
     routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest);
-    if (rs && !memcmp(rs->descriptor_digest,
+    if (rs && tor_memeq(rs->descriptor_digest,
                       router->cache_info.signed_descriptor_digest,
                       DIGEST_LEN)) {
       in_consensus = 1;
@@ -3458,7 +3458,7 @@ _compare_old_routers_by_identity(const void **_a, const void **_b)
 {
   int i;
   const signed_descriptor_t *r1 = *_a, *r2 = *_b;
-  if ((i = memcmp(r1->identity_digest, r2->identity_digest, DIGEST_LEN)))
+  if ((i = fast_memcmp(r1->identity_digest, r2->identity_digest, DIGEST_LEN)))
     return i;
   return (int)(r1->published_on - r2->published_on);
 }
@@ -3506,7 +3506,7 @@ routerlist_remove_old_cached_routers_with_id(time_t now,
   ident = ((signed_descriptor_t*)smartlist_get(lst, lo))->identity_digest;
   for (i = lo+1; i <= hi; ++i) {
     signed_descriptor_t *r = smartlist_get(lst, i);
-    tor_assert(!memcmp(ident, r->identity_digest, DIGEST_LEN));
+    tor_assert(tor_memeq(ident, r->identity_digest, DIGEST_LEN));
   }
 #endif
   /* Check whether we need to do anything at all. */
@@ -3718,7 +3718,7 @@ routerlist_remove_old_routers(void)
       cur_id = r->identity_digest;
       hi = i;
     }
-    if (memcmp(cur_id, r->identity_digest, DIGEST_LEN)) {
+    if (tor_memneq(cur_id, r->identity_digest, DIGEST_LEN)) {
       routerlist_remove_old_cached_routers_with_id(now,
                                                    cutoff, i+1, hi, retain);
       cur_id = r->identity_digest;
@@ -3956,7 +3956,7 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
 
   if (consensus) {
     rs = networkstatus_vote_find_entry(consensus, desc->identity_digest);
-    if (rs && !memcmp(rs->descriptor_digest,
+    if (rs && tor_memeq(rs->descriptor_digest,
                       desc->signed_descriptor_digest, DIGEST_LEN))
       return 1;
   }
@@ -3965,7 +3965,7 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
     {
       if (!(rs = networkstatus_v2_find_entry(ns, desc->identity_digest)))
         continue;
-      if (!memcmp(rs->descriptor_digest,
+      if (tor_memeq(rs->descriptor_digest,
                   desc->signed_descriptor_digest, DIGEST_LEN))
         return 1;
     });
@@ -4548,7 +4548,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
         routerinfo_t *ri;
         ++n_have;
         if (!(ri = router_get_by_digest(rs->identity_digest)) ||
-            memcmp(ri->cache_info.signed_descriptor_digest,
+            tor_memneq(ri->cache_info.signed_descriptor_digest,
                    sd->signed_descriptor_digest, DIGEST_LEN)) {
           /* We have a descriptor with this digest, but either there is no
            * entry in routerlist with the same ID (!ri), or there is one,
@@ -5058,12 +5058,12 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
     return 1;
   }
 
-  digest_matches = !memcmp(ei->cache_info.signed_descriptor_digest,
+  digest_matches = tor_memeq(ei->cache_info.signed_descriptor_digest,
                            sd->extra_info_digest, DIGEST_LEN);
 
   /* The identity must match exactly to have been generated at the same time
    * by the same router. */
-  if (memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest,
+  if (tor_memneq(ri->cache_info.identity_digest, ei->cache_info.identity_digest,
              DIGEST_LEN)) {
     if (msg) *msg = "Extrainfo nickname or identity did not match routerinfo";
     goto err; /* different servers */
@@ -5074,7 +5074,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
     if (crypto_pk_public_checksig(ri->identity_pkey,
                        signed_digest, sizeof(signed_digest),
                        ei->pending_sig, ei->pending_sig_len) != DIGEST_LEN ||
-        memcmp(signed_digest, ei->cache_info.signed_descriptor_digest,
+        tor_memneq(signed_digest, ei->cache_info.signed_descriptor_digest,
                DIGEST_LEN)) {
       ei->bad_sig = 1;
       tor_free(ei->pending_sig);
@@ -5170,25 +5170,25 @@ routerlist_assert_ok(routerlist_t *rl)
   });
 
   RIMAP_FOREACH(rl->identity_map, d, r) {
-    tor_assert(!memcmp(r->cache_info.identity_digest, d, DIGEST_LEN));
+    tor_assert(tor_memeq(r->cache_info.identity_digest, d, DIGEST_LEN));
   } DIGESTMAP_FOREACH_END;
   SDMAP_FOREACH(rl->desc_digest_map, d, sd) {
-    tor_assert(!memcmp(sd->signed_descriptor_digest, d, DIGEST_LEN));
+    tor_assert(tor_memeq(sd->signed_descriptor_digest, d, DIGEST_LEN));
   } DIGESTMAP_FOREACH_END;
   SDMAP_FOREACH(rl->desc_by_eid_map, d, sd) {
     tor_assert(!tor_digest_is_zero(d));
     tor_assert(sd);
-    tor_assert(!memcmp(sd->extra_info_digest, d, DIGEST_LEN));
+    tor_assert(tor_memeq(sd->extra_info_digest, d, DIGEST_LEN));
   } DIGESTMAP_FOREACH_END;
   EIMAP_FOREACH(rl->extra_info_map, d, ei) {
     signed_descriptor_t *sd;
-    tor_assert(!memcmp(ei->cache_info.signed_descriptor_digest,
+    tor_assert(tor_memeq(ei->cache_info.signed_descriptor_digest,
                        d, DIGEST_LEN));
     sd = sdmap_get(rl->desc_by_eid_map,
                    ei->cache_info.signed_descriptor_digest);
     // tor_assert(sd); // XXXX see above
     if (sd) {
-      tor_assert(!memcmp(ei->cache_info.signed_descriptor_digest,
+      tor_assert(tor_memeq(ei->cache_info.signed_descriptor_digest,
                          sd->extra_info_digest, DIGEST_LEN));
     }
   } DIGESTMAP_FOREACH_END;
@@ -5234,7 +5234,7 @@ static int
 _compare_routerinfo_by_id_digest(const void **a, const void **b)
 {
   routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
-  return memcmp(first->cache_info.identity_digest,
+  return fast_memcmp(first->cache_info.identity_digest,
                 second->cache_info.identity_digest,
                 DIGEST_LEN);
 }

+ 14 - 13
src/or/routerparse.c

@@ -1095,7 +1095,7 @@ check_signature_token(const char *digest,
   }
 //  log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
 //            hex_str(signed_digest,4));
-  if (memcmp(digest, signed_digest, digest_len)) {
+  if (tor_memneq(digest, signed_digest, digest_len)) {
     log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
     tor_free(signed_digest);
     return -1;
@@ -1483,7 +1483,7 @@ router_parse_entry_from_string(const char *s, const char *end,
                escaped(tok->args[0]));
       goto err;
     }
-    if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
+    if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) {
       log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
                tok->args[0]);
       goto err;
@@ -1807,7 +1807,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
                            cert->cache_info.identity_digest))
     goto err;
 
-  if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
+  if (tor_memneq(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
     log_warn(LD_DIR, "Digest of certificate key didn't match declared "
              "fingerprint");
     goto err;
@@ -1855,7 +1855,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
      * buy us much. */
     if (old_cert->cache_info.signed_descriptor_len == len &&
         old_cert->cache_info.signed_descriptor_body &&
-        !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
+        tor_memeq(s, old_cert->cache_info.signed_descriptor_body, len)) {
       log_debug(LD_DIR, "We already checked the signature on this "
                 "certificate; no need to do so again.");
       found = 1;
@@ -2194,7 +2194,7 @@ int
 compare_routerstatus_entries(const void **_a, const void **_b)
 {
   const routerstatus_t *a = *_a, *b = *_b;
-  return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
+  return fast_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
 }
 
 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
@@ -2287,7 +2287,7 @@ networkstatus_v2_parse_from_string(const char *s)
     log_warn(LD_DIR, "Couldn't compute signing key digest");
     goto err;
   }
-  if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
+  if (tor_memneq(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
     log_warn(LD_DIR,
              "network-status fingerprint did not match dir-signing-key");
     goto err;
@@ -2991,7 +2991,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
         goto err;
       }
       if (ns->type != NS_TYPE_CONSENSUS &&
-          memcmp(ns->cert->cache_info.identity_digest,
+          tor_memneq(ns->cert->cache_info.identity_digest,
                  voter->identity_digest, DIGEST_LEN)) {
         log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
         goto err;
@@ -3097,7 +3097,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
       rs1 = smartlist_get(ns->routerstatus_list, i-1);
       rs2 = smartlist_get(ns->routerstatus_list, i);
     }
-    if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
+    if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN)
+        >= 0) {
       log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
                "digest");
       goto err;
@@ -3216,7 +3217,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
     }
 
     if (ns->type != NS_TYPE_CONSENSUS) {
-      if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
+      if (tor_memneq(declared_identity, ns->cert->cache_info.identity_digest,
                  DIGEST_LEN)) {
         log_warn(LD_DIR, "Digest mismatch between declared and actual on "
                  "network-status vote.");
@@ -4756,7 +4757,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
   crypto_pk_get_digest(result->pk, public_key_hash);
   rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
                                secret_id_part);
-  if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
+  if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
     log_warn(LD_REND, "Parsed descriptor ID does not match "
              "computed descriptor ID.");
     goto err;
@@ -4821,7 +4822,7 @@ rend_decrypt_introduction_points(char **ipos_decrypted,
     crypto_free_digest_env(digest);
     for (pos = 2; pos < 2 + client_entries_len;
          pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
-      if (!memcmp(ipos_encrypted + pos, client_id,
+      if (tor_memeq(ipos_encrypted + pos, client_id,
                   REND_BASIC_AUTH_CLIENT_ID_LEN)) {
         /* Attempt to decrypt introduction points. */
         cipher = crypto_create_init_cipher(descriptor_cookie, 0);
@@ -4845,7 +4846,7 @@ rend_decrypt_introduction_points(char **ipos_decrypted,
           tor_free(dec);
           return -1;
         }
-        if (memcmpstart(dec, declen, "introduction-point ")) {
+        if (fast_memcmpstart(dec, declen, "introduction-point ")) {
           log_warn(LD_REND, "Decrypted introduction points don't "
                             "look like we could parse them.");
           tor_free(dec);
@@ -4914,7 +4915,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
   parsed->intro_nodes = smartlist_create();
   area = memarea_new();
 
-  while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
+  while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo,
                       "introduction-point ")) {
     /* Determine end of string. */
     const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,