diff --git a/changes/bug3122_memcmp b/changes/bug3122_memcmp
new file mode 100644
index 0000000000..a049476743
--- /dev/null
+++ b/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.)
diff --git a/configure.in b/configure.in
index 26c933b156..e5db37060f 100644
--- a/configure.in
+++ b/configure.in
@@ -905,6 +905,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,
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 20e3f5ae16..3a80eb80d4 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -15,6 +15,7 @@ libor_a_SOURCES = \
address.c \
compat.c \
container.c \
+ di_ops.c \
log.c \
memarea.c \
mempool.c \
@@ -38,6 +39,7 @@ noinst_HEADERS = \
compat_libevent.h \
container.h \
crypto.h \
+ di_ops.h \
ht.h \
memarea.h \
mempool.h \
diff --git a/src/common/address.c b/src/common/address.c
index b612149157..65f429a4d2 100644
--- a/src/common/address.c
+++ b/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);
diff --git a/src/common/compat.c b/src/common/compat.c
index 7a77f94dcf..436d882f30 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -442,6 +442,8 @@ tor_vasprintf(char **strp, const char *fmt, va_list args)
* needle, return a pointer to the first occurrence of the needle
* within the haystack, or NULL if there is no such occurrence.
*
+ * This function is not timing-safe.
+ *
* Requires that nlen be greater than zero.
*/
const void *
@@ -466,7 +468,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;
}
diff --git a/src/common/container.c b/src/common/container.c
index bc61226cb5..eba5a2f704 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -216,7 +216,7 @@ smartlist_string_num_isin(const smartlist_t *sl, int num)
}
/** Return true iff sl has some element E such that
- * !memcmp(E,element,DIGEST_LEN)
+ * tor_memeq(E,element,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;
}
@@ -801,7 +801,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. */
@@ -823,7 +823,7 @@ smartlist_uniq_digests(smartlist_t *sl)
static int
_compare_digests256(const void **_a, const void **_b)
{
- return memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN);
+ return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN);
}
/** Sort the list of DIGEST256_LEN-byte digests into ascending order. */
@@ -885,7 +885,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. */
diff --git a/src/common/container.h b/src/common/container.h
index 8a3a405273..b39d4ca07e 100644
--- a/src/common/container.h
+++ b/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) {
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 424fd09b6c..3de6fdded2 100644
--- a/src/common/crypto.c
+++ b/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;
diff --git a/src/common/di_ops.c b/src/common/di_ops.c
new file mode 100644
index 0000000000..c1e292fe2f
--- /dev/null
+++ b/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 sz bytes
+ * at a with the sz bytes at , and returns less than 0 if the
+ * bytes at a lexically precede those at b, 0 if the byte ranges
+ * are equal, and greater than zero if the bytes at a lexically follow
+ * those at .
+ *
+ * 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 a and 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 sz bytes at
+ * a are the same as the sz bytes at , 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 a and 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);
+}
+
diff --git a/src/common/di_ops.h b/src/common/di_ops.h
new file mode 100644
index 0000000000..4a212b0ca2
--- /dev/null
+++ b/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
+ * not 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
diff --git a/src/common/torgzip.c b/src/common/torgzip.c
index e9079e0ba5..2937c67de2 100644
--- a/src/common/torgzip.c
+++ b/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) {
diff --git a/src/common/util.c b/src/common/util.c
index e676530b29..d2140c3f32 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -516,7 +516,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
@@ -558,17 +558,17 @@ strcasecmpend(const char *s1, const char *s2)
/** Compare the value of the string prefix with the start of the
* memlen-byte memory chunk at mem. 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
@@ -724,14 +724,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;
}
@@ -740,7 +742,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. */
diff --git a/src/common/util.h b/src/common/util.h
index 759f068b03..974b7d6fdc 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -14,6 +14,7 @@
#include "orconfig.h"
#include "torint.h"
#include "compat.h"
+#include "di_ops.h"
#include
#include
@@ -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,
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index d02ea1678e..17e7c14990 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1818,7 +1818,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;
}
@@ -2226,7 +2226,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.");
@@ -3527,7 +3527,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;
@@ -3860,7 +3860,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;
@@ -4524,7 +4524,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);
@@ -4605,7 +4605,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;
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 0aadcbfa0b..7c5fd25700 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -254,7 +254,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;
}
@@ -717,7 +717,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 &&
@@ -911,7 +911,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);
}
@@ -929,7 +929,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;
@@ -1006,7 +1006,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
const node_t *ri1 = node_get_by_id(info->identity_digest);
do {
const node_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 &&
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 135aa803ac..fe75df9775 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -109,7 +109,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)) {
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 4e45cbeff6..186137b1df 100644
--- a/src/or/connection_edge.c
+++ b/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 */
@@ -3072,7 +3072,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit)
if (conn->chosen_exit_name) {
const node_t *chosen_exit =
node_get_by_nickname(conn->chosen_exit_name, 1);
- if (!chosen_exit || memcmp(chosen_exit->identity,
+ if (!chosen_exit || tor_memneq(chosen_exit->identity,
exit->identity, DIGEST_LEN)) {
/* doesn't match */
// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 1f2575ae14..73aad7e485 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -124,7 +124,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. */
@@ -143,7 +143,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
@@ -585,7 +585,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. */
@@ -788,7 +788,7 @@ connection_or_set_bad_connections(const char *digest, int force)
return;
DIGESTMAP_FOREACH(orconn_identity_map, identity, or_connection_t *, conn) {
- if (!digest || !memcmp(digest, conn->identity_digest, DIGEST_LEN))
+ if (!digest || tor_memeq(digest, conn->identity_digest, DIGEST_LEN))
connection_or_group_set_badness(conn, force);
} DIGESTMAP_FOREACH_END;
}
@@ -1221,7 +1221,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];
diff --git a/src/or/control.c b/src/or/control.c
index 0aada57307..75f025f937 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -341,7 +341,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';
}
@@ -507,7 +507,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';
@@ -588,7 +588,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';
@@ -1078,7 +1078,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.";
@@ -1128,7 +1128,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));
@@ -2921,13 +2921,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;
diff --git a/src/or/directory.c b/src/or/directory.c
index 313c6c5a40..56c4457700 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -2541,7 +2541,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;
};
@@ -3744,17 +3744,17 @@ dir_microdesc_download_failed(smartlist_t *failed,
} SMARTLIST_FOREACH_END(d);
}
-/** 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 res of the form FP1-FP2+FP3-FP4...[.z], where each
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 0ac2d804c7..d22ef3bac3 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -2116,7 +2116,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
/* This assert can fire for the control port, because
* it can request NS documents before all descriptors
* have been fetched. */
- if (memcmp(desc->cache_info.signed_descriptor_digest,
+ if (tor_memneq(desc->cache_info.signed_descriptor_digest,
rs->descriptor_digest,
DIGEST_LEN)) {
char rl_d[HEX_DIGEST_LEN+1];
@@ -2132,7 +2132,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
"(router %s)\n",
rl_d, rs_d, id);
- tor_assert(!memcmp(desc->cache_info.signed_descriptor_digest,
+ tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest,
rs->descriptor_digest,
DIGEST_LEN));
};
@@ -2234,9 +2234,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 routers, return a new digestmap_t
@@ -3185,7 +3185,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;
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index fa0398c287..6fe29f2f4f 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -337,7 +337,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);
}
@@ -354,7 +354,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 in, add every member to out
@@ -391,10 +391,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)))
@@ -1641,7 +1641,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 {
@@ -1665,7 +1665,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 {
@@ -1698,7 +1698,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;
}
});
@@ -1717,7 +1717,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".
@@ -1762,7 +1762,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);
@@ -1786,7 +1786,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;
@@ -1884,11 +1884,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);
@@ -2204,7 +2204,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target,
}
for (alg = DIGEST_SHA1; alg < N_DIGEST_ALGORITHMS; ++alg) {
if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) {
- if (!memcmp(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) {
+ if (fast_memeq(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) {
++n_matches;
} else {
*msg_out = "Mismatched digest.";
@@ -2968,11 +2968,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);
@@ -3473,23 +3473,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);
}
}
@@ -3608,7 +3608,7 @@ vote_routerstatus_find_microdesc_hash(char *digest256_out,
* the first part. */
while (1) {
num_len = strspn(cp, "1234567890");
- if (num_len == mlen && !memcmp(mstr, cp, mlen)) {
+ if (num_len == mlen && fast_memeq(mstr, cp, mlen)) {
/* This is the line. */
char buf[BASE64_DIGEST256_LEN+1];
/* XXXX ignores extraneous stuff if the digest is too long. This
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index e9770c8c72..fb05e48d33 100644
--- a/src/or/eventdns.c
+++ b/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;
@@ -2253,7 +2253,7 @@ sockaddr_is_loopback(const struct sockaddr *addr)
return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000;
} else if (addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
- return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16);
+ return fast_memeq(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16);
}
return 0;
}
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 717488bded..f7f42a4dec 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -55,7 +55,7 @@ _microdesc_hash(microdesc_t *md)
static INLINE int
_microdesc_eq(microdesc_t *a, microdesc_t *b)
{
- return !memcmp(a->digest, b->digest, DIGEST256_LEN);
+ return tor_memeq(a->digest, b->digest, DIGEST256_LEN);
}
HT_PROTOTYPE(microdesc_map, microdesc_t, node,
@@ -477,7 +477,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
" with \"onion-key\". Instead I got %s.",
(int)md->off, escaped(bad_str));
tor_free(bad_str);
- tor_assert(!memcmp(md->body, "onion-key", 9));
+ tor_assert(fast_memeq(md->body, "onion-key", 9));
}
} SMARTLIST_FOREACH_END(md);
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 7fd3d365f4..837c8c2bf2 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -424,7 +424,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;
}
@@ -445,9 +445,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);
@@ -457,7 +457,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 {
@@ -509,7 +509,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
authority_cert_t *cert =
authority_cert_get_by_digests(sig->identity_digest,
sig->signing_key_digest);
- tor_assert(!memcmp(sig->identity_digest, voter->identity_digest,
+ tor_assert(tor_memeq(sig->identity_digest, voter->identity_digest,
DIGEST_LEN));
if (!is_v3_auth) {
@@ -812,8 +812,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);
@@ -939,7 +939,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);
}
/** As networkstatus_v2_find_entry, but do not return a const pointer */
@@ -1404,7 +1404,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;
@@ -1467,10 +1467,10 @@ networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
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 ||
@@ -1522,7 +1522,7 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
SMARTLIST_FOREACH_JOIN(
old_c->routerstatus_list, const routerstatus_t *, rs_old,
new_c->routerstatus_list, const routerstatus_t *, rs_new,
- memcmp(rs_old->identity_digest,
+ tor_memcmp(rs_old->identity_digest,
rs_new->identity_digest, DIGEST_LEN),
smartlist_add(changed, (void*) rs_new)) {
if (routerstatus_has_changed(rs_old, rs_new))
@@ -1546,13 +1546,13 @@ 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->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));
@@ -1668,7 +1668,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;
@@ -2003,7 +2003,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),
{
#if 0
@@ -2020,7 +2020,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
ds = router_get_trusteddirserver_by_digest(digest);
/* 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;
@@ -2049,10 +2049,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, const 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;
diff --git a/src/or/onion.c b/src/or/onion.c
index e1d10a60bb..211d14c1e1 100644
--- a/src/or/onion.c
+++ b/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.");
diff --git a/src/or/relay.c b/src/or/relay.c
index e5bc310fed..cf531169e7 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -134,7 +134,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 */
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 838b8f7423..3a2aaf1c41 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -158,7 +158,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;
@@ -629,7 +629,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);
@@ -728,7 +728,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;
}
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 3ee7419d7b..45044324a3 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -884,15 +884,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)
@@ -1066,7 +1066,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);
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index 5e2dd986ba..04edd8e3e2 100644
--- a/src/or/rendmid.c
+++ b/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;
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 767712c329..3d5c80c234 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -466,7 +466,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;
@@ -761,7 +761,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;
}
@@ -801,7 +801,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;
@@ -915,7 +915,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).",
@@ -1270,7 +1270,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),
@@ -1556,7 +1556,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;
@@ -1566,7 +1566,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;
@@ -1823,7 +1823,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. "
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 7aa91b8f56..1ab4171a5f 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -118,7 +118,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);
@@ -146,7 +146,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) {
diff --git a/src/or/router.c b/src/or/router.c
index 6de069f03f..42b07cb9ad 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -725,7 +725,7 @@ init_keys(void)
ds->type = type;
}
if (v3_digest_set && (ds->type & V3_DIRINFO) &&
- 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);
@@ -1267,7 +1267,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 digest is equal to
@@ -1279,7 +1279,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);
}
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 04f421481d..8d25eaa862 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -170,7 +170,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;
@@ -384,16 +384,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;
@@ -412,7 +412,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;
@@ -1008,7 +1008,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;
});
@@ -1027,7 +1027,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_DIRINFO))
return ds;
});
@@ -2280,7 +2280,7 @@ hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
return 0;
}
- return !memcmp(digest, identity_digest, DIGEST_LEN);
+ return tor_memeq(digest, identity_digest, DIGEST_LEN);
}
/* Return true iff router is listed as named in the current
@@ -2292,7 +2292,7 @@ router_is_named(const routerinfo_t *router)
networkstatus_get_router_digest_by_nickname(router->nickname);
return (digest &&
- !memcmp(digest, router->cache_info.identity_digest, DIGEST_LEN));
+ tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN));
}
/** Return true iff the digest of router's identity key,
@@ -2382,7 +2382,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;
@@ -2459,7 +2459,7 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_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;
@@ -2608,7 +2608,7 @@ signed_descriptor_get_body_impl(const 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.",
@@ -3086,7 +3086,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);
@@ -3103,7 +3103,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
&ri_new->cache_info);
}
- same_descriptors = ! memcmp(ri_old->cache_info.signed_descriptor_digest,
+ same_descriptors = tor_memeq(ri_old->cache_info.signed_descriptor_digest,
ri_new->cache_info.signed_descriptor_digest,
DIGEST_LEN);
@@ -3125,7 +3125,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
sdmap_remove(rl->desc_digest_map,
ri_old->cache_info.signed_descriptor_digest);
- if (memcmp(ri_old->cache_info.extra_info_digest,
+ if (tor_memneq(ri_old->cache_info.extra_info_digest,
ri_new->cache_info.extra_info_digest, DIGEST_LEN)) {
ei_tmp = eimap_remove(rl->extra_info_map,
ri_old->cache_info.extra_info_digest);
@@ -3224,7 +3224,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);
node = node_get_mutable_by_id(digest);
@@ -3348,7 +3348,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
{
routerstatus_t *rs =
networkstatus_v2_find_mutable_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;
@@ -3356,7 +3356,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (consensus) {
routerstatus_t *rs = networkstatus_vote_find_mutable_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;
@@ -3478,7 +3478,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);
}
@@ -3526,7 +3526,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. */
@@ -3738,7 +3738,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;
@@ -3976,7 +3976,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;
}
@@ -3985,7 +3985,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;
});
@@ -4630,7 +4630,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
const routerinfo_t *ri;
++n_have;
if (!(ri = router_get_by_id_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,
@@ -5159,12 +5159,12 @@ routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
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 */
@@ -5175,7 +5175,7 @@ routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
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);
@@ -5271,25 +5271,25 @@ routerlist_assert_ok(const 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;
@@ -5335,7 +5335,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);
}
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 0410e5e37e..3f5aad8dfa 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1093,7 +1093,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;
@@ -1480,7 +1480,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;
@@ -1795,7 +1795,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;
@@ -1843,7 +1843,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;
@@ -2203,7 +2203,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. */
@@ -2296,7 +2296,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;
@@ -3000,7 +3000,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;
@@ -3106,7 +3106,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;
@@ -3225,7 +3226,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.");
@@ -3507,8 +3508,8 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
is_duplicate = 0;
SMARTLIST_FOREACH(siglist, document_signature_t *, s, {
if (s->alg == alg &&
- !memcmp(id_digest, s->identity_digest, DIGEST_LEN) &&
- !memcmp(sk_digest, s->signing_key_digest, DIGEST_LEN)) {
+ tor_memeq(id_digest, s->identity_digest, DIGEST_LEN) &&
+ tor_memeq(sk_digest, s->signing_key_digest, DIGEST_LEN)) {
is_duplicate = 1;
}
});
@@ -4546,7 +4547,7 @@ tor_version_compare(tor_version_t *a, tor_version_t *b)
else if ((i = a->git_tag_len - b->git_tag_len))
return i;
else if (a->git_tag_len)
- return memcmp(a->git_tag, b->git_tag, a->git_tag_len);
+ return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len);
else
return 0;
}
@@ -4765,7 +4766,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;
@@ -4830,7 +4831,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);
@@ -4854,7 +4855,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);
@@ -4923,7 +4924,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,
diff --git a/src/test/test_util.c b/src/test/test_util.c
index efbc47b460..f4b17c9a5d 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1418,6 +1418,60 @@ test_util_spawn_background_fail(void *ptr)
}
#endif
+
+static void
+test_util_di_ops(void)
+{
+#define LT -1
+#define GT 1
+#define EQ 0
+ const struct {
+ const char *a; int want_sign; const char *b;
+ } examples[] = {
+ { "Foo", EQ, "Foo" },
+ { "foo", GT, "bar", },
+ { "foobar", EQ ,"foobar" },
+ { "foobar", LT, "foobaw" },
+ { "foobar", GT, "f00bar" },
+ { "foobar", GT, "boobar" },
+ { "", EQ, "" },
+ { NULL, 0, NULL },
+ };
+
+ int i;
+
+ for (i = 0; examples[i].a; ++i) {
+ size_t len = strlen(examples[i].a);
+ int eq1, eq2, neq1, neq2, cmp1, cmp2;
+ test_eq(len, strlen(examples[i].b));
+ /* We do all of the operations, with operands in both orders. */
+ eq1 = tor_memeq(examples[i].a, examples[i].b, len);
+ eq2 = tor_memeq(examples[i].b, examples[i].a, len);
+ neq1 = tor_memneq(examples[i].a, examples[i].b, len);
+ neq2 = tor_memneq(examples[i].b, examples[i].a, len);
+ cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
+ cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
+
+ /* Check for correctness of cmp1 */
+ if (cmp1 < 0 && examples[i].want_sign != LT)
+ test_fail();
+ else if (cmp1 > 0 && examples[i].want_sign != GT)
+ test_fail();
+ else if (cmp1 == 0 && examples[i].want_sign != EQ)
+ test_fail();
+
+ /* Check for consistency of everything else with cmp1 */
+ test_eq(eq1, eq2);
+ test_eq(neq1, neq2);
+ test_eq(cmp1, -cmp2);
+ test_eq(eq1, cmp1 == 0);
+ test_eq(neq1, !eq1);
+ }
+
+ done:
+ ;
+}
+
#define UTIL_LEGACY(name) \
{ #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
@@ -1438,6 +1492,7 @@ struct testcase_t util_tests[] = {
UTIL_LEGACY(threads),
UTIL_LEGACY(sscanf),
UTIL_LEGACY(strtok),
+ UTIL_LEGACY(di_ops),
UTIL_TEST(find_str_at_start_of_line, 0),
UTIL_TEST(asprintf, 0),
UTIL_TEST(listdir, 0),