commit e165c9c304800718daa589469349282110e00909 Author: Nick Mathewson nickm@torproject.org Date: Wed Jun 27 15:36:42 2018 -0400
Move various mem* functions to lib/string --- src/common/compat.c | 46 ------------------ src/common/compat.h | 10 ---- src/common/util.c | 55 ---------------------- src/common/util.h | 4 -- src/lib/string/.may_include | 1 + src/lib/string/util_string.c | 108 +++++++++++++++++++++++++++++++++++++++++++ src/lib/string/util_string.h | 8 ++++ 7 files changed, 117 insertions(+), 115 deletions(-)
diff --git a/src/common/compat.c b/src/common/compat.c index 367ea26c2..cdc53175d 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -131,52 +131,6 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt) #include "lib/net/address.h" #include "lib/sandbox/sandbox.h"
-/** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at - * <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 <b>nlen</b> be greater than zero. - */ -const void * -tor_memmem(const void *_haystack, size_t hlen, - const void *_needle, size_t nlen) -{ -#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) - tor_assert(nlen); - return memmem(_haystack, hlen, _needle, nlen); -#else - /* This isn't as fast as the GLIBC implementation, but it doesn't need to - * be. */ - const char *p, *last_possible_start; - const char *haystack = (const char*)_haystack; - const char *needle = (const char*)_needle; - char first; - tor_assert(nlen); - - if (nlen > hlen) - return NULL; - - p = haystack; - /* Last position at which the needle could start. */ - last_possible_start = haystack + hlen - nlen; - first = *(const char*)needle; - while ((p = memchr(p, first, last_possible_start + 1 - p))) { - if (fast_memeq(p, needle, nlen)) - return p; - if (++p > last_possible_start) { - /* This comparison shouldn't be necessary, since if p was previously - * equal to last_possible_start, the next memchr call would be - * "memchr(p, first, 0)", which will return NULL. But it clarifies the - * logic. */ - return NULL; - } - } - return NULL; -#endif /* defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) */ -} - /** Represents a lockfile on which we hold the lock. */ struct tor_lockfile_t { /** Name of the file */ diff --git a/src/common/compat.h b/src/common/compat.h index 766f62557..399badb6a 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -63,16 +63,6 @@ #include <stdio.h> #include <errno.h>
-const void *tor_memmem(const void *haystack, size_t hlen, const void *needle, - size_t nlen) ATTR_NONNULL((1,3)); -static const void *tor_memstr(const void *haystack, size_t hlen, - const char *needle) ATTR_NONNULL((1,3)); -static inline const void * -tor_memstr(const void *haystack, size_t hlen, const char *needle) -{ - return tor_memmem(haystack, hlen, needle, strlen(needle)); -} - /* ===== Time compatibility */
struct tm *tor_localtime_r(const time_t *timep, struct tm *result); diff --git a/src/common/util.c b/src/common/util.c index 09d3b2679..64efbc81e 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -240,54 +240,6 @@ hex_str(const char *from, size_t fromlen) return buf; }
-/** 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 fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is - * less than strlen(prefix).] - */ -int -fast_memcmpstart(const void *mem, size_t memlen, - const char *prefix) -{ - size_t plen = strlen(prefix); - if (memlen < plen) - return -1; - return fast_memcmp(mem, prefix, plen); -} - -/** Return true iff the 'len' bytes at 'mem' are all zero. */ -int -tor_mem_is_zero(const char *mem, size_t len) -{ - static const char ZERO[] = { - 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)) { - /* 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 fast_memeq(mem, ZERO, len); - - return 1; -} - -/** Return true iff the DIGEST_LEN bytes in digest are all zero. */ -int -tor_digest_is_zero(const char *digest) -{ - 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 if <b>string</b> is a valid 'key=[value]' string. * "value" is optional, to indicate the empty string. Log at logging * <b>severity</b> if something ugly happens. */ @@ -436,13 +388,6 @@ string_is_valid_nonrfc_hostname(const char *string) return result; }
-/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */ -int -tor_digest256_is_zero(const char *digest) -{ - return tor_mem_is_zero(digest, DIGEST256_LEN); -} - /** Return a newly allocated string equal to <b>string</b>, except that every * character in <b>chars_to_escape</b> is preceded by a backslash. */ char * diff --git a/src/common/util.h b/src/common/util.h index 2b16fc457..f16a1fa98 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -78,10 +78,6 @@ int string_is_valid_nonrfc_hostname(const char *string); int string_is_valid_ipv4_address(const char *string); int string_is_valid_ipv6_address(const char *string);
-int tor_mem_is_zero(const char *mem, size_t len); -int tor_digest_is_zero(const char *digest); -int tor_digest256_is_zero(const char *digest); - char *tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape);
diff --git a/src/lib/string/.may_include b/src/lib/string/.may_include index c5d771861..ec5c76983 100644 --- a/src/lib/string/.may_include +++ b/src/lib/string/.may_include @@ -1,5 +1,6 @@ orconfig.h lib/cc/*.h +lib/defs/*.h lib/err/*.h lib/malloc/*.h lib/ctime/*.h diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c index aba37fcc0..e8ed3d4f5 100644 --- a/src/lib/string/util_string.c +++ b/src/lib/string/util_string.c @@ -7,10 +7,102 @@ #include "lib/string/compat_ctype.h" #include "lib/err/torerr.h" #include "lib/ctime/di_ops.h" +#include "lib/defs/digest_sizes.h"
#include <string.h> #include <stdlib.h>
+/** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at + * <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 <b>nlen</b> be greater than zero. + */ +const void * +tor_memmem(const void *_haystack, size_t hlen, + const void *_needle, size_t nlen) +{ +#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) + raw_assert(nlen); + return memmem(_haystack, hlen, _needle, nlen); +#else + /* This isn't as fast as the GLIBC implementation, but it doesn't need to + * be. */ + const char *p, *last_possible_start; + const char *haystack = (const char*)_haystack; + const char *needle = (const char*)_needle; + char first; + raw_assert(nlen); + + if (nlen > hlen) + return NULL; + + p = haystack; + /* Last position at which the needle could start. */ + last_possible_start = haystack + hlen - nlen; + first = *(const char*)needle; + while ((p = memchr(p, first, last_possible_start + 1 - p))) { + if (fast_memeq(p, needle, nlen)) + return p; + if (++p > last_possible_start) { + /* This comparison shouldn't be necessary, since if p was previously + * equal to last_possible_start, the next memchr call would be + * "memchr(p, first, 0)", which will return NULL. But it clarifies the + * logic. */ + return NULL; + } + } + return NULL; +#endif /* defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) */ +} + +const void * +tor_memstr(const void *haystack, size_t hlen, const char *needle) +{ + return tor_memmem(haystack, hlen, needle, strlen(needle)); +} + +/** Return true iff the 'len' bytes at 'mem' are all zero. */ +int +tor_mem_is_zero(const char *mem, size_t len) +{ + static const char ZERO[] = { + 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)) { + /* 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 fast_memeq(mem, ZERO, len); + + return 1; +} + +/** Return true iff the DIGEST_LEN bytes in digest are all zero. */ +int +tor_digest_is_zero(const char *digest) +{ + 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. */ +int +tor_digest256_is_zero(const char *digest) +{ + return tor_mem_is_zero(digest, DIGEST256_LEN); +} + /** Remove from the string <b>s</b> every character which appears in * <b>strip</b>. */ void @@ -140,6 +232,22 @@ strcasecmpstart(const char *s1, const char *s2) return strncasecmp(s1, s2, n); }
+/** 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 fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is + * less than strlen(prefix).] + */ +int +fast_memcmpstart(const void *mem, size_t memlen, + const char *prefix) +{ + size_t plen = strlen(prefix); + if (memlen < plen) + return -1; + return fast_memcmp(mem, prefix, plen); +} + /** Compares the last strlen(s2) characters of s1 with s2. Returns as for * strcmp. */ diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h index f194c3637..bdc2e77ce 100644 --- a/src/lib/string/util_string.h +++ b/src/lib/string/util_string.h @@ -11,6 +11,14 @@
#include <stddef.h>
+const void *tor_memmem(const void *haystack, size_t hlen, const void *needle, + size_t nlen) ATTR_NONNULL((1,3)); +const void *tor_memstr(const void *haystack, size_t hlen, + const char *needle) ATTR_NONNULL((1,3)); +int tor_mem_is_zero(const char *mem, size_t len); +int tor_digest_is_zero(const char *digest); +int tor_digest256_is_zero(const char *digest); + /** Allowable characters in a hexadecimal string. */ #define HEX_CHARACTERS "0123456789ABCDEFabcdef" void tor_strlower(char *s) ATTR_NONNULL((1));
tor-commits@lists.torproject.org