diff options
Diffstat (limited to 'src')
219 files changed, 18335 insertions, 4602 deletions
diff --git a/src/common/address.c b/src/common/address.c index 8591f387e6..07b76597da 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -323,17 +323,23 @@ tor_addr_is_internal_(const tor_addr_t *addr, int for_listening, { uint32_t iph4 = 0; uint32_t iph6[4]; - sa_family_t v_family; tor_assert(addr); - v_family = tor_addr_family(addr); + sa_family_t v_family = tor_addr_family(addr); if (v_family == AF_INET) { iph4 = tor_addr_to_ipv4h(addr); } else if (v_family == AF_INET6) { if (tor_addr_is_v4(addr)) { /* v4-mapped */ + uint32_t *addr32 = NULL; v_family = AF_INET; - iph4 = ntohl(tor_addr_to_in6_addr32(addr)[3]); + // Work around an incorrect NULL pointer dereference warning in + // "clang --analyze" due to limited analysis depth + addr32 = tor_addr_to_in6_addr32(addr); + // To improve performance, wrap this assertion in: + // #if !defined(__clang_analyzer__) || PARANOIA + tor_assert(addr32); + iph4 = ntohl(addr32[3]); } } @@ -465,7 +471,6 @@ tor_addr_parse_PTR_name(tor_addr_t *result, const char *address, if (!strcasecmpend(address, ".ip6.arpa")) { const char *cp; - int i; int n0, n1; struct in6_addr in6; @@ -473,7 +478,7 @@ tor_addr_parse_PTR_name(tor_addr_t *result, const char *address, return -1; cp = address; - for (i = 0; i < 16; ++i) { + for (int i = 0; i < 16; ++i) { n0 = hex_decode_digit(*cp++); /* The low-order nybble appears first. */ if (*cp++ != '.') return -1; /* Then a dot. */ n1 = hex_decode_digit(*cp++); /* The high-order nybble appears first. */ @@ -598,7 +603,7 @@ tor_addr_parse_mask_ports(const char *s, int any_flag=0, v4map=0; sa_family_t family; struct in6_addr in6_tmp; - struct in_addr in_tmp; + struct in_addr in_tmp = { .s_addr = 0 }; tor_assert(s); tor_assert(addr_out); @@ -659,7 +664,7 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_from_ipv4h(addr_out, 0); any_flag = 1; } else if (!strcmp(address, "*6") && (flags & TAPMP_EXTENDED_STAR)) { - static char nil_bytes[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; + static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; family = AF_INET6; tor_addr_from_ipv6_bytes(addr_out, nil_bytes); any_flag = 1; diff --git a/src/common/address.h b/src/common/address.h index 8dc63b71c1..42844e8ad1 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -103,7 +103,18 @@ tor_addr_to_ipv4h(const tor_addr_t *a) static INLINE uint32_t tor_addr_to_mapped_ipv4h(const tor_addr_t *a) { - return a->family == AF_INET6 ? ntohl(tor_addr_to_in6_addr32(a)[3]) : 0; + if (a->family == AF_INET6) { + uint32_t *addr32 = NULL; + // Work around an incorrect NULL pointer dereference warning in + // "clang --analyze" due to limited analysis depth + addr32 = tor_addr_to_in6_addr32(a); + // To improve performance, wrap this assertion in: + // #if !defined(__clang_analyzer__) || PARANOIA + tor_assert(addr32); + return ntohl(addr32[3]); + } else { + return 0; + } } /** Return the address family of <b>a</b>. Possible values are: * AF_INET6, AF_INET, AF_UNSPEC. */ diff --git a/src/common/compat.c b/src/common/compat.c index e25ecc462d..4dd04455a2 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -981,14 +981,23 @@ tor_fd_getpos(int fd) #endif } -/** Move <b>fd</b> to the end of the file. Return -1 on error, 0 on success. */ +/** Move <b>fd</b> to the end of the file. Return -1 on error, 0 on success. + * If the file is a pipe, do nothing and succeed. + **/ int tor_fd_seekend(int fd) { #ifdef _WIN32 return _lseek(fd, 0, SEEK_END) < 0 ? -1 : 0; #else - return lseek(fd, 0, SEEK_END) < 0 ? -1 : 0; + off_t rc = lseek(fd, 0, SEEK_END) < 0 ? -1 : 0; +#ifdef ESPIPE + /* If we get an error and ESPIPE, then it's a pipe or a socket of a fifo: + * no need to worry. */ + if (rc < 0 && errno == ESPIPE) + rc = 0; +#endif + return (rc < 0) ? -1 : 0; #endif } @@ -1004,6 +1013,23 @@ tor_fd_setpos(int fd, off_t pos) #endif } +/** Replacement for ftruncate(fd, 0): move to the front of the file and remove + * all the rest of the file. Return -1 on error, 0 on success. */ +int +tor_ftruncate(int fd) +{ + /* Rumor has it that some versions of ftruncate do not move the file pointer. + */ + if (tor_fd_setpos(fd, 0) < 0) + return -1; + +#ifdef _WIN32 + return _chsize(fd, 0); +#else + return ftruncate(fd, 0); +#endif +} + #undef DEBUG_SOCKET_COUNTING #ifdef DEBUG_SOCKET_COUNTING /** A bitarray of all fds that should be passed to tor_socket_close(). Only @@ -1409,6 +1435,9 @@ tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) socklen_t size; int saved_errno = -1; + memset(&connect_addr, 0, sizeof(connect_addr)); + memset(&listen_addr, 0, sizeof(listen_addr)); + if (protocol #ifdef AF_UNIX || family != AF_UNIX @@ -1670,12 +1699,12 @@ log_credential_status(void) /* log supplementary groups */ sup_gids_size = 64; - sup_gids = tor_malloc(sizeof(gid_t) * 64); + sup_gids = tor_calloc(sizeof(gid_t), 64); while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 && errno == EINVAL && sup_gids_size < NGROUPS_MAX) { sup_gids_size *= 2; - sup_gids = tor_realloc(sup_gids, sizeof(gid_t) * sup_gids_size); + sup_gids = tor_reallocarray(sup_gids, sizeof(gid_t), sup_gids_size); } if (ngids < 0) { @@ -2485,14 +2514,12 @@ get_uname(void) "Unrecognized version of Windows [major=%d,minor=%d]", (int)info.dwMajorVersion,(int)info.dwMinorVersion); } -#if !defined (WINCE) #ifdef VER_NT_SERVER if (info.wProductType == VER_NT_SERVER || info.wProductType == VER_NT_DOMAIN_CONTROLLER) { strlcat(uname_result, " [server]", sizeof(uname_result)); } #endif -#endif #else strlcpy(uname_result, "Unknown platform", sizeof(uname_result)); #endif @@ -2697,15 +2724,8 @@ tor_gettimeofday(struct timeval *timeval) uint64_t ft_64; FILETIME ft_ft; } ft; -#if defined (WINCE) - /* wince do not have GetSystemTimeAsFileTime */ - SYSTEMTIME stime; - GetSystemTime(&stime); - SystemTimeToFileTime(&stime,&ft.ft_ft); -#else /* number of 100-nsec units since Jan 1, 1601 */ GetSystemTimeAsFileTime(&ft.ft_ft); -#endif if (ft.ft_64 < EPOCH_BIAS) { log_err(LD_GENERAL,"System time is before 1970; failing."); exit(1); @@ -2731,7 +2751,7 @@ tor_gettimeofday(struct timeval *timeval) return; } -#if defined(TOR_IS_MULTITHREADED) && !defined(_WIN32) +#if !defined(_WIN32) /** Defined iff we need to add locks when defining fake versions of reentrant * versions of time-related functions. */ #define TIME_FNS_NEED_LOCKS @@ -2991,7 +3011,6 @@ tor_get_thread_id(void) } #endif -#ifdef TOR_IS_MULTITHREADED /** Return a newly allocated, ready-for-use mutex. */ tor_mutex_t * tor_mutex_new(void) @@ -3009,7 +3028,6 @@ tor_mutex_free(tor_mutex_t *m) tor_mutex_uninit(m); tor_free(m); } -#endif /* Conditions. */ #ifdef USE_PTHREADS @@ -3548,12 +3566,12 @@ get_total_system_memory(size_t *mem_out) return 0; } -#if SIZE_T_MAX != UINT64_MAX - if (m > SIZE_T_MAX) { +#if SIZE_MAX != UINT64_MAX + if (m > SIZE_MAX) { /* I think this could happen if we're a 32-bit Tor running on a 64-bit * system: we could have more system memory than would fit in a * size_t. */ - m = SIZE_T_MAX; + m = SIZE_MAX; } #endif diff --git a/src/common/compat.h b/src/common/compat.h index ec7d2415ed..852a432187 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -56,21 +56,6 @@ #include <stdio.h> #include <errno.h> -#if defined (WINCE) -#include <fcntl.h> -#include <io.h> -#include <math.h> -#include <projects.h> -/* this is not exported as W .... */ -#define SHGetPathFromIDListW SHGetPathFromIDList -/* wcecompat has vasprintf */ -#define HAVE_VASPRINTF -/* no service here */ -#ifdef NT_SERVICE -#undef NT_SERVICE -#endif -#endif // WINCE - #ifndef NULL_REP_IS_ZERO_BYTES #error "It seems your platform does not represent NULL as zero. We can't cope." #endif @@ -423,6 +408,7 @@ void tor_lockfile_unlock(tor_lockfile_t *lockfile); off_t tor_fd_getpos(int fd); int tor_fd_setpos(int fd, off_t pos); int tor_fd_seekend(int fd); +int tor_ftruncate(int fd); #ifdef _WIN32 #define PATH_SEPARATOR "\\" @@ -648,15 +634,12 @@ int get_total_system_memory(size_t *mem_out); int spawn_func(void (*func)(void *), void *data); void spawn_exit(void) ATTR_NORETURN; -#if defined(ENABLE_THREADS) && defined(_WIN32) +#if defined(_WIN32) #define USE_WIN32_THREADS -#define TOR_IS_MULTITHREADED 1 -#elif (defined(ENABLE_THREADS) && defined(HAVE_PTHREAD_H) && \ - defined(HAVE_PTHREAD_CREATE)) +#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE) #define USE_PTHREADS -#define TOR_IS_MULTITHREADED 1 #else -#undef TOR_IS_MULTITHREADED +#error "No threading system was found" #endif int compute_num_cpus(void); @@ -682,7 +665,6 @@ typedef struct tor_mutex_t { int tor_mlockall(void); -#ifdef TOR_IS_MULTITHREADED tor_mutex_t *tor_mutex_new(void); void tor_mutex_init(tor_mutex_t *m); void tor_mutex_acquire(tor_mutex_t *m); @@ -691,21 +673,10 @@ void tor_mutex_free(tor_mutex_t *m); void tor_mutex_uninit(tor_mutex_t *m); unsigned long tor_get_thread_id(void); void tor_threads_init(void); -#else -#define tor_mutex_new() ((tor_mutex_t*)tor_malloc(sizeof(int))) -#define tor_mutex_init(m) STMT_NIL -#define tor_mutex_acquire(m) STMT_VOID(m) -#define tor_mutex_release(m) STMT_NIL -#define tor_mutex_free(m) STMT_BEGIN tor_free(m); STMT_END -#define tor_mutex_uninit(m) STMT_NIL -#define tor_get_thread_id() (1UL) -#define tor_threads_init() STMT_NIL -#endif void set_main_thread(void); int in_main_thread(void); -#ifdef TOR_IS_MULTITHREADED #if 0 typedef struct tor_cond_t tor_cond_t; tor_cond_t *tor_cond_new(void); @@ -714,7 +685,6 @@ int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex); void tor_cond_signal_one(tor_cond_t *cond); void tor_cond_signal_all(tor_cond_t *cond); #endif -#endif /** Macros for MIN/MAX. Never use these when the arguments could have * side-effects. diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 74b54bb855..7e6f304c6b 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -210,6 +210,9 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) } else { using_iocp_bufferevents = 0; } +#elif defined(__COVERITY__) + /* Avoid a 'dead code' warning below. */ + using_threads = ! torcfg->disable_iocp; #endif if (!using_threads) { diff --git a/src/common/container.c b/src/common/container.c index b937d544fc..f7dfc69c2f 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -28,21 +28,21 @@ /** Allocate and return an empty smartlist. */ -smartlist_t * -smartlist_new(void) +MOCK_IMPL(smartlist_t *, +smartlist_new,(void)) { smartlist_t *sl = tor_malloc(sizeof(smartlist_t)); sl->num_used = 0; sl->capacity = SMARTLIST_DEFAULT_CAPACITY; - sl->list = tor_malloc(sizeof(void *) * sl->capacity); + sl->list = tor_calloc(sizeof(void *), sl->capacity); return sl; } /** Deallocate a smartlist. Does not release storage associated with the * list's elements. */ -void -smartlist_free(smartlist_t *sl) +MOCK_IMPL(void, +smartlist_free,(smartlist_t *sl)) { if (!sl) return; @@ -66,19 +66,28 @@ smartlist_ensure_capacity(smartlist_t *sl, int size) #define MAX_CAPACITY (INT_MAX) #else #define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*)))) +#define ASSERT_CAPACITY #endif if (size > sl->capacity) { int higher = sl->capacity; if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) { +#ifdef ASSERT_CAPACITY + /* We don't include this assertion when MAX_CAPACITY == INT_MAX, + * since int size; (size <= INT_MAX) makes analysis tools think we're + * doing something stupid. */ tor_assert(size <= MAX_CAPACITY); +#endif higher = MAX_CAPACITY; } else { while (size > higher) higher *= 2; } sl->capacity = higher; - sl->list = tor_realloc(sl->list, sizeof(void*)*((size_t)sl->capacity)); + sl->list = tor_reallocarray(sl->list, sizeof(void *), + ((size_t)sl->capacity)); } +#undef ASSERT_CAPACITY +#undef MAX_CAPACITY } /** Append element to the end of the list. */ @@ -1043,18 +1052,18 @@ digestmap_entry_hash(const digestmap_entry_t *a) HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash, strmap_entries_eq) -HT_GENERATE(strmap_impl, strmap_entry_t, node, strmap_entry_hash, - strmap_entries_eq, 0.6, malloc, realloc, free) +HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash, + strmap_entries_eq, 0.6, tor_reallocarray_, tor_free_) HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash, digestmap_entries_eq) -HT_GENERATE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash, - digestmap_entries_eq, 0.6, malloc, realloc, free) +HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash, + digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_) /** Constructor to create a new empty map from strings to void*'s. */ -strmap_t * -strmap_new(void) +MOCK_IMPL(strmap_t *, +strmap_new,(void)) { strmap_t *result; result = tor_malloc(sizeof(strmap_t)); @@ -1064,8 +1073,8 @@ strmap_new(void) /** Constructor to create a new empty map from digests to void*'s. */ -digestmap_t * -digestmap_new(void) +MOCK_IMPL(digestmap_t *, +digestmap_new,(void)) { digestmap_t *result; result = tor_malloc(sizeof(digestmap_t)); @@ -1418,8 +1427,8 @@ digestmap_iter_done(digestmap_iter_t *iter) * entries. If free_val is provided, it is invoked on every value in * <b>map</b>. */ -void -strmap_free(strmap_t *map, void (*free_val)(void*)) +MOCK_IMPL(void, +strmap_free,(strmap_t *map, void (*free_val)(void*))) { strmap_entry_t **ent, **next, *this; if (!map) @@ -1442,8 +1451,8 @@ strmap_free(strmap_t *map, void (*free_val)(void*)) * entries. If free_val is provided, it is invoked on every value in * <b>map</b>. */ -void -digestmap_free(digestmap_t *map, void (*free_val)(void*)) +MOCK_IMPL(void, +digestmap_free, (digestmap_t *map, void (*free_val)(void*))) { digestmap_entry_t **ent, **next, *this; if (!map) diff --git a/src/common/container.h b/src/common/container.h index 0d31f2093b..c3756c83a6 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -27,8 +27,8 @@ typedef struct smartlist_t { /** @} */ } smartlist_t; -smartlist_t *smartlist_new(void); -void smartlist_free(smartlist_t *sl); +MOCK_DECL(smartlist_t *, smartlist_new, (void)); +MOCK_DECL(void, smartlist_free, (smartlist_t *sl)); void smartlist_clear(smartlist_t *sl); void smartlist_add(smartlist_t *sl, void *element); void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2); @@ -328,11 +328,11 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join, #define DECLARE_MAP_FNS(maptype, keytype, prefix) \ typedef struct maptype maptype; \ typedef struct prefix##entry_t *prefix##iter_t; \ - maptype* prefix##new(void); \ + MOCK_DECL(maptype*, prefix##new, (void)); \ void* prefix##set(maptype *map, keytype key, void *val); \ void* prefix##get(const maptype *map, keytype key); \ void* prefix##remove(maptype *map, keytype key); \ - void prefix##free(maptype *map, void (*free_val)(void*)); \ + MOCK_DECL(void, prefix##free, (maptype *map, void (*free_val)(void*))); \ int prefix##isempty(const maptype *map); \ int prefix##size(const maptype *map); \ prefix##iter_t *prefix##iter_init(maptype *map); \ @@ -473,7 +473,7 @@ void* strmap_remove_lc(strmap_t *map, const char *key); #define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \ typedef struct maptype maptype; \ - typedef struct prefix##iter_t prefix##iter_t; \ + typedef struct prefix##iter_t *prefix##iter_t; \ ATTR_UNUSED static INLINE maptype* \ prefix##new(void) \ { \ @@ -563,7 +563,7 @@ bitarray_init_zero(unsigned int n_bits) { /* round up to the next int. */ size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT; - return tor_malloc_zero(sz*sizeof(unsigned int)); + return tor_calloc(sz, sizeof(unsigned int)); } /** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>, * clearing all new bits. Returns a possibly changed pointer to the @@ -577,7 +577,7 @@ bitarray_expand(bitarray_t *ba, char *ptr; if (sz_new <= sz_old) return ba; - ptr = tor_realloc(ba, sz_new*sizeof(unsigned int)); + ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int)); /* This memset does nothing to the older excess bytes. But they were * already set to 0 by bitarry_init_zero. */ memset(ptr+sz_old*sizeof(unsigned int), 0, @@ -689,5 +689,11 @@ median_int32(int32_t *array, int n_elements) return find_nth_int32(array, n_elements, (n_elements-1)/2); } +static INLINE uint32_t +third_quartile_uint32(uint32_t *array, int n_elements) +{ + return find_nth_uint32(array, n_elements, (n_elements*3)/4); +} + #endif diff --git a/src/common/crypto.c b/src/common/crypto.c index a247a87d48..fa91f6dd82 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -75,12 +75,10 @@ /** Macro: is k a valid RSA private key? */ #define PRIVATE_KEY_OK(k) ((k) && (k)->key && (k)->key->p) -#ifdef TOR_IS_MULTITHREADED /** A number of preallocated mutexes for use by OpenSSL. */ static tor_mutex_t **openssl_mutexes_ = NULL; /** How many mutexes have we allocated for use by OpenSSL? */ static int n_openssl_mutexes_ = 0; -#endif /** A public key, or a public/private key-pair. */ struct crypto_pk_t @@ -1840,7 +1838,7 @@ crypto_store_dynamic_dh_modulus(const char *fname) goto done; } - base64_encoded_dh = tor_malloc_zero(len * 2); /* should be enough */ + base64_encoded_dh = tor_calloc(len, 2); /* should be enough */ new_len = base64_encode(base64_encoded_dh, len * 2, (char *)dh_string_repr, len); if (new_len < 0) { @@ -3003,50 +3001,6 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen) return 0; } -/** Implement RFC2440-style iterated-salted S2K conversion: convert the - * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte - * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier - * are a salt; the 9th byte describes how much iteration to do. - * Does not support <b>key_out_len</b> > DIGEST_LEN. - */ -void -secret_to_key(char *key_out, size_t key_out_len, const char *secret, - size_t secret_len, const char *s2k_specifier) -{ - crypto_digest_t *d; - uint8_t c; - size_t count, tmplen; - char *tmp; - tor_assert(key_out_len < SIZE_T_CEILING); - -#define EXPBIAS 6 - c = s2k_specifier[8]; - count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS); -#undef EXPBIAS - - tor_assert(key_out_len <= DIGEST_LEN); - - d = crypto_digest_new(); - tmplen = 8+secret_len; - tmp = tor_malloc(tmplen); - memcpy(tmp,s2k_specifier,8); - memcpy(tmp+8,secret,secret_len); - secret_len += 8; - while (count) { - if (count >= secret_len) { - crypto_digest_add_bytes(d, tmp, secret_len); - count -= secret_len; - } else { - crypto_digest_add_bytes(d, tmp, count); - count = 0; - } - } - crypto_digest_get_digest(d, key_out, key_out_len); - memwipe(tmp, 0, tmplen); - tor_free(tmp); - crypto_digest_free(d); -} - /** * Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to * the value <b>byte</b>. @@ -3090,8 +3044,6 @@ memwipe(void *mem, uint8_t byte, size_t sz) memset(mem, byte, sz); } -#ifdef TOR_IS_MULTITHREADED - #ifndef OPENSSL_THREADS #error OpenSSL has been built without thread support. Tor requires an \ OpenSSL library with thread support enabled. @@ -3168,7 +3120,7 @@ setup_openssl_threading(void) int i; int n = CRYPTO_num_locks(); n_openssl_mutexes_ = n; - openssl_mutexes_ = tor_malloc(n*sizeof(tor_mutex_t *)); + openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *)); for (i=0; i < n; ++i) openssl_mutexes_[i] = tor_mutex_new(); CRYPTO_set_locking_callback(openssl_locking_cb_); @@ -3178,13 +3130,6 @@ setup_openssl_threading(void) CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy_cb_); return 0; } -#else -static int -setup_openssl_threading(void) -{ - return 0; -} -#endif /** Uninitialize the crypto library. Return 0 on success, -1 on failure. */ @@ -3208,7 +3153,7 @@ crypto_global_cleanup(void) CONF_modules_unload(1); CRYPTO_cleanup_all_ex_data(); -#ifdef TOR_IS_MULTITHREADED + if (n_openssl_mutexes_) { int n = n_openssl_mutexes_; tor_mutex_t **ms = openssl_mutexes_; @@ -3220,7 +3165,7 @@ crypto_global_cleanup(void) } tor_free(ms); } -#endif + tor_free(crypto_openssl_version_str); tor_free(crypto_openssl_header_version_str); return 0; diff --git a/src/common/crypto.h b/src/common/crypto.h index aa4271aa33..39bbdb5717 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -280,12 +280,6 @@ int digest_from_base64(char *digest, const char *d64); int digest256_to_base64(char *d64, const char *digest); int digest256_from_base64(char *digest, const char *d64); -/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the - * 9th describes how much iteration to do. */ -#define S2K_SPECIFIER_LEN 9 -void secret_to_key(char *key_out, size_t key_out_len, const char *secret, - size_t secret_len, const char *s2k_specifier); - /** OpenSSL-based utility functions. */ void memwipe(void *mem, uint8_t byte, size_t sz); diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c index 9e83440e16..8b8e560c89 100644 --- a/src/common/crypto_curve25519.c +++ b/src/common/crypto_curve25519.c @@ -8,6 +8,7 @@ #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif +#include "container.h" #include "crypto.h" #include "crypto_curve25519.h" #include "util.h" @@ -63,26 +64,44 @@ curve25519_public_key_is_ok(const curve25519_public_key_t *key) return !safe_mem_is_zero(key->public_key, CURVE25519_PUBKEY_LEN); } -/** Generate a new keypair and return the secret key. If <b>extra_strong</b> - * is true, this key is possibly going to get used more than once, so - * use a better-than-usual RNG. Return 0 on success, -1 on failure. */ +/** + * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If + * <b>extra_strong</b> is true, this key is possibly going to get used more + * than once, so use a better-than-usual RNG. Return 0 on success, -1 on + * failure. + * + * This function does not adjust the output of the RNG at all; the will caller + * will need to clear or set the appropriate bits to make curve25519 work. + */ int -curve25519_secret_key_generate(curve25519_secret_key_t *key_out, - int extra_strong) +curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong) { uint8_t k_tmp[CURVE25519_SECKEY_LEN]; - if (crypto_rand((char*)key_out->secret_key, CURVE25519_SECKEY_LEN) < 0) + if (crypto_rand((char*)out, CURVE25519_SECKEY_LEN) < 0) return -1; if (extra_strong && !crypto_strongest_rand(k_tmp, CURVE25519_SECKEY_LEN)) { /* If they asked for extra-strong entropy and we have some, use it as an * HMAC key to improve not-so-good entropy rather than using it directly, * just in case the extra-strong entropy is less amazing than we hoped. */ - crypto_hmac_sha256((char *)key_out->secret_key, - (const char *)k_tmp, sizeof(k_tmp), - (const char *)key_out->secret_key, CURVE25519_SECKEY_LEN); + crypto_hmac_sha256((char*) out, + (const char *)k_tmp, sizeof(k_tmp), + (const char *)out, CURVE25519_SECKEY_LEN); } memwipe(k_tmp, 0, sizeof(k_tmp)); + return 0; +} + +/** Generate a new keypair and return the secret key. If <b>extra_strong</b> + * is true, this key is possibly going to get used more than once, so + * use a better-than-usual RNG. Return 0 on success, -1 on failure. */ +int +curve25519_secret_key_generate(curve25519_secret_key_t *key_out, + int extra_strong) +{ + if (curve25519_rand_seckey_bytes(key_out->secret_key, extra_strong) < 0) + return -1; + key_out->secret_key[0] &= 248; key_out->secret_key[31] &= 127; key_out->secret_key[31] |= 64; @@ -109,69 +128,144 @@ curve25519_keypair_generate(curve25519_keypair_t *keypair_out, return 0; } +/** Write the <b>datalen</b> bytes from <b>data</b> to the file named + * <b>fname</b> in the tagged-data format. This format contains a + * 32-byte header, followed by the data itself. The header is the + * NUL-padded string "== <b>typestring</b>: <b>tag</b> ==". The length + * of <b>typestring</b> and <b>tag</b> must therefore be no more than + * 24. + **/ int -curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair, - const char *fname, - const char *tag) +crypto_write_tagged_contents_to_file(const char *fname, + const char *typestring, + const char *tag, + const uint8_t *data, + size_t datalen) { - char contents[32 + CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN]; - int r; + char header[32]; + smartlist_t *chunks = smartlist_new(); + sized_chunk_t ch0, ch1; + int r = -1; - memset(contents, 0, sizeof(contents)); - tor_snprintf(contents, sizeof(contents), "== c25519v1: %s ==", tag); - tor_assert(strlen(contents) <= 32); - memcpy(contents+32, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN); - memcpy(contents+32+CURVE25519_SECKEY_LEN, - keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN); + memset(header, 0, sizeof(header)); + if (tor_snprintf(header, sizeof(header), + "== %s: %s ==", typestring, tag) < 0) + goto end; + ch0.bytes = header; + ch0.len = 32; + ch1.bytes = (const char*) data; + ch1.len = datalen; + smartlist_add(chunks, &ch0); + smartlist_add(chunks, &ch1); - r = write_bytes_to_file(fname, contents, sizeof(contents), 1); + r = write_chunks_to_file(fname, chunks, 1, 0); - memwipe(contents, 0, sizeof(contents)); + end: + smartlist_free(chunks); return r; } -int -curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, - char **tag_out, - const char *fname) +/** Read a tagged-data file from <b>fname</b> into the + * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the + * typestring matches <b>typestring</b>; store the tag into a newly allocated + * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of + * data on success. */ +ssize_t +crypto_read_tagged_contents_from_file(const char *fname, + const char *typestring, + char **tag_out, + uint8_t *data_out, + ssize_t data_out_len) { char prefix[33]; - char *content; + char *content = NULL; struct stat st; - int r = -1; + ssize_t r = -1; + size_t st_size = 0; *tag_out = NULL; - st.st_size = 0; content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st); if (! content) goto end; - if (st.st_size != 32 + CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN) + if (st.st_size < 32 || st.st_size > 32 + data_out_len) goto end; + st_size = (size_t)st.st_size; memcpy(prefix, content, 32); - prefix[32] = '\0'; - if (strcmpstart(prefix, "== c25519v1: ") || - strcmpend(prefix, " ==")) + prefix[32] = 0; + /* Check type, extract tag. */ + if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") || + ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) + goto end; + + if (strcmpstart(prefix+3, typestring) || + 3+strlen(typestring) >= 32 || + strcmpstart(prefix+3+strlen(typestring), ": ")) goto end; - *tag_out = tor_strndup(prefix+strlen("== c25519v1: "), - strlen(prefix) - strlen("== c25519v1: ==")); + *tag_out = tor_strndup(prefix+5+strlen(typestring), + strlen(prefix)-8-strlen(typestring)); + + memcpy(data_out, content+32, st_size-32); + r = st_size - 32; + + end: + if (content) + memwipe(content, 0, st_size); + tor_free(content); + return r; +} + +/** DOCDOC */ +int +curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair, + const char *fname, + const char *tag) +{ + uint8_t contents[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN]; + int r; + + memcpy(contents, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN); + memcpy(contents+CURVE25519_SECKEY_LEN, + keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN); + + r = crypto_write_tagged_contents_to_file(fname, + "c25519v1", + tag, + contents, + sizeof(contents)); + + memwipe(contents, 0, sizeof(contents)); + return r; +} + +/** DOCDOC */ +int +curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, + char **tag_out, + const char *fname) +{ + uint8_t content[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN]; + ssize_t len; + int r = -1; + + len = crypto_read_tagged_contents_from_file(fname, "c25519v1", tag_out, + content, sizeof(content)); + if (len != sizeof(content)) + goto end; - memcpy(keypair_out->seckey.secret_key, content+32, CURVE25519_SECKEY_LEN); + memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN); curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey); if (tor_memneq(keypair_out->pubkey.public_key, - content + 32 + CURVE25519_SECKEY_LEN, + content + CURVE25519_SECKEY_LEN, CURVE25519_PUBKEY_LEN)) goto end; r = 0; end: - if (content) { - memwipe(content, 0, (size_t) st.st_size); - tor_free(content); - } + memwipe(content, 0, sizeof(content)); if (r != 0) { memset(keypair_out, 0, sizeof(*keypair_out)); tor_free(*tag_out); diff --git a/src/common/crypto_curve25519.h b/src/common/crypto_curve25519.h index 57018ac2f5..404f99c18e 100644 --- a/src/common/crypto_curve25519.h +++ b/src/common/crypto_curve25519.h @@ -57,6 +57,8 @@ int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, char **tag_out, const char *fname); +int curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong); + #ifdef CRYPTO_CURVE25519_PRIVATE STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret, const uint8_t *basepoint); @@ -70,5 +72,17 @@ int curve25519_public_from_base64(curve25519_public_key_t *pkey, int curve25519_public_to_base64(char *output, const curve25519_public_key_t *pkey); +int crypto_write_tagged_contents_to_file(const char *fname, + const char *typestring, + const char *tag, + const uint8_t *data, + size_t datalen); + +ssize_t crypto_read_tagged_contents_from_file(const char *fname, + const char *typestring, + char **tag_out, + uint8_t *data_out, + ssize_t data_out_len); + #endif diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c new file mode 100644 index 0000000000..408c12b4fd --- /dev/null +++ b/src/common/crypto_ed25519.c @@ -0,0 +1,353 @@ +/* Copyright (c) 2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Wrapper code for an ed25519 implementation. */ + +#include "orconfig.h" +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#include "crypto.h" + +#include "crypto_curve25519.h" +#include "crypto_ed25519.h" +#include "torlog.h" +#include "util.h" + +#include "ed25519/ref10/ed25519_ref10.h" + +#include <openssl/sha.h> + +/** + * Initialize a new ed25519 secret key in <b>seckey_out</b>. If + * <b>extra_strong</b>, take the RNG inputs directly from the operating + * system. Return 0 on success, -1 on failure. + */ +int +ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out, + int extra_strong) +{ + int r; + uint8_t seed[32]; + if (! extra_strong || crypto_strongest_rand(seed, sizeof(seed)) < 0) + crypto_rand((char*)seed, sizeof(seed)); + + r = ed25519_ref10_seckey_expand(seckey_out->seckey, seed); + memwipe(seed, 0, sizeof(seed)); + + return r < 0 ? -1 : 0; +} + +/** + * Given a 32-byte random seed in <b>seed</b>, expand it into an ed25519 + * secret key in <b>seckey_out</b>. Return 0 on success, -1 on failure. + */ +int +ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out, + const uint8_t *seed) +{ + if (ed25519_ref10_seckey_expand(seckey_out->seckey, seed) < 0) + return -1; + return 0; +} + +/** + * Given a secret key in <b>seckey</b>, expand it into an + * ed25519 public key. Return 0 on success, -1 on failure. + */ +int +ed25519_public_key_generate(ed25519_public_key_t *pubkey_out, + const ed25519_secret_key_t *seckey) +{ + if (ed25519_ref10_pubkey(pubkey_out->pubkey, seckey->seckey) < 0) + return -1; + return 0; +} + +/** Generate a new ed25519 keypair in <b>keypair_out</b>. If + * <b>extra_strong</b> is set, try to mix some system entropy into the key + * generation process. Return 0 on success, -1 on failure. */ +int +ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong) +{ + if (ed25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0) + return -1; + if (ed25519_public_key_generate(&keypair_out->pubkey, + &keypair_out->seckey)<0) + return -1; + return 0; +} + +/** + * Set <b>signature_out</b> to a signature of the <b>len</b>-byte message + * <b>msg</b>, using the secret and public key in <b>keypair</b>. + */ +int +ed25519_sign(ed25519_signature_t *signature_out, + const uint8_t *msg, size_t len, + const ed25519_keypair_t *keypair) +{ + + if (ed25519_ref10_sign(signature_out->sig, msg, len, + keypair->seckey.seckey, + keypair->pubkey.pubkey) < 0) { + return -1; + } + + return 0; +} + +/** + * Check whether if <b>signature</b> is a valid signature for the + * <b>len</b>-byte message in <b>msg</b> made with the key <b>pubkey</b>. + * + * Return 0 if the signature is valid; -1 if it isn't. + */ +int +ed25519_checksig(const ed25519_signature_t *signature, + const uint8_t *msg, size_t len, + const ed25519_public_key_t *pubkey) +{ + return + ed25519_ref10_open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0; +} + +/** Validate every signature among those in <b>checkable</b>, which contains + * exactly <b>n_checkable</b> elements. If <b>okay_out</b> is non-NULL, set + * the i'th element of <b>okay_out</b> to 1 if the i'th element of + * <b>checkable</b> is valid, and to 0 otherwise. Return 0 if every signature + * was valid. Otherwise return -N, where N is the number of invalid + * signatures. + */ +int +ed25519_checksig_batch(int *okay_out, + const ed25519_checkable_t *checkable, + int n_checkable) +{ + int res, i; + + res = 0; + for (i = 0; i < n_checkable; ++i) { + const ed25519_checkable_t *ch = &checkable[i]; + int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey); + if (r < 0) + --res; + if (okay_out) + okay_out[i] = (r == 0); + } + +#if 0 + /* This is how we'd do it if we were using ed25519_donna. I'll keep this + * code around here in case we ever do that. */ + const uint8_t **ms; + size_t *lens; + const uint8_t **pks; + const uint8_t **sigs; + int *oks; + + ms = tor_malloc(sizeof(uint8_t*)*n_checkable); + lens = tor_malloc(sizeof(size_t)*n_checkable); + pks = tor_malloc(sizeof(uint8_t*)*n_checkable); + sigs = tor_malloc(sizeof(uint8_t*)*n_checkable); + oks = okay_out ? okay_out : tor_malloc(sizeof(int)*n_checkable); + + for (i = 0; i < n_checkable; ++i) { + ms[i] = checkable[i].msg; + lens[i] = checkable[i].len; + pks[i] = checkable[i].pubkey->pubkey; + sigs[i] = checkable[i].signature.sig; + oks[i] = 0; + } + + ed25519_sign_open_batch_donna_fb(ms, lens, pks, sigs, n_checkable, oks); + + res = 0; + for (i = 0; i < n_checkable; ++i) { + if (!oks[i]) + --res; + } + + tor_free(ms); + tor_free(lens); + tor_free(pks); + if (! okay_out) + tor_free(oks); +#endif + + return res; +} + +/** + * Given a curve25519 keypair in <b>inp</b>, generate a corresponding + * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the + * sign bit of the X coordinate of the ed25519 key. + * + * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING + * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228. In particular, it's probably + * not a great idea to use it to sign attacker-supplied anything. + */ +int +ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out, + int *signbit_out, + const curve25519_keypair_t *inp) +{ + const char string[] = "Derive high part of ed25519 key from curve25519 key"; + ed25519_public_key_t pubkey_check; + SHA512_CTX ctx; + uint8_t sha512_output[64]; + + memcpy(out->seckey.seckey, inp->seckey.secret_key, 32); + SHA512_Init(&ctx); + SHA512_Update(&ctx, out->seckey.seckey, 32); + SHA512_Update(&ctx, string, sizeof(string)); + SHA512_Final(sha512_output, &ctx); + memcpy(out->seckey.seckey + 32, sha512_output, 32); + + ed25519_public_key_generate(&out->pubkey, &out->seckey); + + *signbit_out = out->pubkey.pubkey[31] >> 7; + + ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey, + *signbit_out); + + tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32)); + + memwipe(&pubkey_check, 0, sizeof(pubkey_check)); + memwipe(&ctx, 0, sizeof(ctx)); + memwipe(sha512_output, 0, sizeof(sha512_output)); + + return 0; +} + +/** + * Given a curve25519 public key and sign bit of X coordinate of the ed25519 + * public key, generate the corresponding ed25519 public key. + */ +int +ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey, + const curve25519_public_key_t *pubkey_in, + int signbit) +{ + return ed25519_ref10_pubkey_from_curve25519_pubkey(pubkey->pubkey, + pubkey_in->public_key, + signbit); +} + +/** + * Given an ed25519 keypair in <b>inp</b>, generate a corresponding + * ed25519 keypair in <b>out</b>, blinded by the corresponding 32-byte input + * in 'param'. + * + * Tor uses key blinding for the "next-generation" hidden services design: + * service descriptors are encrypted with a key derived from the service's + * long-term public key, and then signed with (and stored at a position + * indexed by) a short-term key derived by blinding the long-term keys. + */ +int +ed25519_keypair_blind(ed25519_keypair_t *out, + const ed25519_keypair_t *inp, + const uint8_t *param) +{ + ed25519_public_key_t pubkey_check; + + ed25519_ref10_blind_secret_key(out->seckey.seckey, + inp->seckey.seckey, param); + + ed25519_public_blind(&pubkey_check, &inp->pubkey, param); + ed25519_public_key_generate(&out->pubkey, &out->seckey); + + tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32)); + + memwipe(&pubkey_check, 0, sizeof(pubkey_check)); + + return 0; +} + +/** + * Given an ed25519 public key in <b>inp</b>, generate a corresponding blinded + * public key in <b>out</b>, blinded with the 32-byte parameter in + * <b>param</b>. Return 0 on sucess, -1 on railure. + */ +int +ed25519_public_blind(ed25519_public_key_t *out, + const ed25519_public_key_t *inp, + const uint8_t *param) +{ + ed25519_ref10_blind_public_key(out->pubkey, inp->pubkey, param); + return 0; +} + +/** + * Store seckey unencrypted to <b>filename</b>, marking it with <b>tag</b>. + * Return 0 on success, -1 on failure. + */ +int +ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey, + const char *filename, + const char *tag) +{ + return crypto_write_tagged_contents_to_file(filename, + "ed25519v1-secret", + tag, + seckey->seckey, + sizeof(seckey->seckey)); +} + +/** + * Read seckey unencrypted from <b>filename</b>, storing it into + * <b>seckey_out</b>. Set *<b>tag_out</> to the tag it was marked with. + * Return 0 on success, -1 on failure. + */ +int +ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out, + char **tag_out, + const char *filename) +{ + ssize_t len; + + len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-secret", + tag_out, seckey_out->seckey, + sizeof(seckey_out->seckey)); + if (len != sizeof(seckey_out->seckey)) + return -1; + + return 0; +} + +/** + * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>. + * Return 0 on success, -1 on failure. + */ +int +ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey, + const char *filename, + const char *tag) +{ + return crypto_write_tagged_contents_to_file(filename, + "ed25519v1-public", + tag, + pubkey->pubkey, + sizeof(pubkey->pubkey)); +} + +/** + * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>. + * Return 0 on success, -1 on failure. + */ +int +ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out, + char **tag_out, + const char *filename) +{ + ssize_t len; + + len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-public", + tag_out, pubkey_out->pubkey, + sizeof(pubkey_out->pubkey)); + if (len != sizeof(pubkey_out->pubkey)) + return -1; + + return 0; +} + diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h new file mode 100644 index 0000000000..13b05c7c1e --- /dev/null +++ b/src/common/crypto_ed25519.h @@ -0,0 +1,116 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_CRYPTO_ED25519_H +#define TOR_CRYPTO_ED25519_H + +#include "testsupport.h" +#include "torint.h" + +#define ED25519_PUBKEY_LEN 32 +#define ED25519_SECKEY_LEN 64 +#define ED25519_SECKEY_SEED_LEN 32 +#define ED25519_SIG_LEN 64 + +/** An Ed25519 signature. */ +typedef struct { + uint8_t sig[ED25519_SIG_LEN]; +} ed25519_signature_t; + +/** An Ed25519 public key */ +typedef struct { + uint8_t pubkey[ED25519_PUBKEY_LEN]; +} ed25519_public_key_t; + +/** An Ed25519 secret key */ +typedef struct { + /** Note that we store secret keys in an expanded format that doesn't match + * the format from standard ed25519. Ed25519 stores a 32-byte value k and + * expands it into a 64-byte H(k), using the first 32 bytes for a multiplier + * of the base point, and second 32 bytes as an input to a hash function + * for deriving r. But because we implement key blinding, we need to store + * keys in the 64-byte expanded form. */ + uint8_t seckey[ED25519_SECKEY_LEN]; +} ed25519_secret_key_t; + +/** An Ed25519 keypair. */ +typedef struct { + ed25519_public_key_t pubkey; + ed25519_secret_key_t seckey; +} ed25519_keypair_t; + +#ifdef CURVE25519_ENABLED +int ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out, + int extra_strong); +int ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out, + const uint8_t *seed); + +int ed25519_public_key_generate(ed25519_public_key_t *pubkey_out, + const ed25519_secret_key_t *seckey); +int ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong); +int ed25519_sign(ed25519_signature_t *signature_out, + const uint8_t *msg, size_t len, + const ed25519_keypair_t *key); +int ed25519_checksig(const ed25519_signature_t *signature, + const uint8_t *msg, size_t len, + const ed25519_public_key_t *pubkey); + +/** + * A collection of information necessary to check an Ed25519 signature. Used + * for batch verification. + */ +typedef struct { + /** The public key that supposedly generated the signature. */ + ed25519_public_key_t *pubkey; + /** The signature to check. */ + ed25519_signature_t signature; + /** The message that the signature is supposed to have been applied to. */ + const uint8_t *msg; + /** The length of the message. */ + size_t len; +} ed25519_checkable_t; + +int ed25519_checksig_batch(int *okay_out, + const ed25519_checkable_t *checkable, + int n_checkable); + +int ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out, + int *signbit_out, + const curve25519_keypair_t *inp); + +int ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey, + const curve25519_public_key_t *pubkey_in, + int signbit); +int ed25519_keypair_blind(ed25519_keypair_t *out, + const ed25519_keypair_t *inp, + const uint8_t *param); +int ed25519_public_blind(ed25519_public_key_t *out, + const ed25519_public_key_t *inp, + const uint8_t *param); + +#endif + +#define ED25519_BASE64_LEN 43 + +int ed25519_public_from_base64(ed25519_public_key_t *pkey, + const char *input); +int ed25519_public_to_base64(char *output, + const ed25519_public_key_t *pkey); + +/* XXXX read encrypted, write encrypted. */ + +int ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey, + const char *filename, + const char *tag); +int ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out, + char **tag_out, + const char *filename); +int ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey, + const char *filename, + const char *tag); +int ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out, + char **tag_out, + const char *filename); + +#endif + diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c index be669c8d2b..a9f104cab2 100644 --- a/src/common/crypto_format.c +++ b/src/common/crypto_format.c @@ -9,6 +9,7 @@ #endif #include "crypto.h" #include "crypto_curve25519.h" +#include "crypto_ed25519.h" #include "util.h" #include "torlog.h" @@ -43,3 +44,24 @@ curve25519_public_from_base64(curve25519_public_key_t *pkey, } } +/** Try to decode the string <b>input</b> into an ed25519 public key. On + * success, store the value in <b>pkey</b> and return 0. Otherwise return + * -1. */ +int +ed25519_public_from_base64(ed25519_public_key_t *pkey, + const char *input) +{ + return digest256_from_base64((char*)pkey->pubkey, input); +} + +/** Encode the public key <b>pkey</b> into the buffer at <b>output</b>, + * which must have space for ED25519_BASE64_LEN bytes of encoded key, + * plus one byte for a terminating NUL. Return 0 on success, -1 on failure. + */ +int +ed25519_public_to_base64(char *output, + const ed25519_public_key_t *pkey) +{ + return digest256_to_base64(output, (const char *)pkey->pubkey); +} + diff --git a/src/common/crypto_pwbox.c b/src/common/crypto_pwbox.c new file mode 100644 index 0000000000..91659db2bc --- /dev/null +++ b/src/common/crypto_pwbox.c @@ -0,0 +1,187 @@ + +#include "crypto.h" +#include "crypto_s2k.h" +#include "crypto_pwbox.h" +#include "di_ops.h" +#include "util.h" +#include "pwbox.h" + +/* 8 bytes "TORBOX00" + 1 byte: header len (H) + H bytes: header, denoting secret key algorithm. + 16 bytes: IV + Round up to multiple of 128 bytes, then encrypt: + 4 bytes: data len + data + zeros + 32 bytes: HMAC-SHA256 of all previous bytes. +*/ + +#define MAX_OVERHEAD (S2K_MAXLEN + 8 + 1 + 32 + CIPHER_IV_LEN) + +/** + * Make an authenticated passphrase-encrypted blob to encode the + * <b>input_len</b> bytes in <b>input</b> using the passphrase + * <b>secret</b> of <b>secret_len</b> bytes. Allocate a new chunk of memory + * to hold the encrypted data, and store a pointer to that memory in + * *<b>out</b>, and its size in <b>outlen_out</b>. Use <b>s2k_flags</b> as an + * argument to the passphrase-hashing function. + */ +int +crypto_pwbox(uint8_t **out, size_t *outlen_out, + const uint8_t *input, size_t input_len, + const char *secret, size_t secret_len, + unsigned s2k_flags) +{ + uint8_t *result = NULL, *encrypted_portion; + size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128); + ssize_t result_len; + int spec_len; + uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN]; + pwbox_encoded_t *enc = NULL; + ssize_t enc_len; + + crypto_cipher_t *cipher; + int rv; + + enc = pwbox_encoded_new(); + + pwbox_encoded_setlen_skey_header(enc, S2K_MAXLEN); + + spec_len = secret_to_key_make_specifier( + pwbox_encoded_getarray_skey_header(enc), + S2K_MAXLEN, + s2k_flags); + if (spec_len < 0 || spec_len > S2K_MAXLEN) + goto err; + pwbox_encoded_setlen_skey_header(enc, spec_len); + enc->header_len = spec_len; + + crypto_rand((char*)enc->iv, sizeof(enc->iv)); + + pwbox_encoded_setlen_data(enc, encrypted_len); + encrypted_portion = pwbox_encoded_getarray_data(enc); + + set_uint32(encrypted_portion, htonl(input_len)); + memcpy(encrypted_portion+4, input, input_len); + + /* Now that all the data is in position, derive some keys, encrypt, and + * digest */ + if (secret_to_key_derivekey(keys, sizeof(keys), + pwbox_encoded_getarray_skey_header(enc), + spec_len, + secret, secret_len) < 0) + goto err; + + cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv); + crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len); + crypto_cipher_free(cipher); + + result_len = pwbox_encoded_encoded_len(enc); + if (result_len < 0) + goto err; + result = tor_malloc(result_len); + enc_len = pwbox_encoded_encode(result, result_len, enc); + if (enc_len < 0) + goto err; + tor_assert(enc_len == result_len); + + crypto_hmac_sha256((char*) result + result_len - 32, + (const char*)keys + CIPHER_KEY_LEN, + DIGEST256_LEN, + (const char*)result, + result_len - 32); + + *out = result; + *outlen_out = result_len; + rv = 0; + goto out; + + err: + tor_free(result); + rv = -1; + + out: + pwbox_encoded_free(enc); + memwipe(keys, 0, sizeof(keys)); + return rv; +} + +/** + * Try to decrypt the passphrase-encrypted blob of <b>input_len</b> bytes in + * <b>input</b> using the passphrase <b>secret</b> of <b>secret_len</b> bytes. + * On success, return 0 and allocate a new chunk of memory to hold the + * decrypted data, and store a pointer to that memory in *<b>out</b>, and its + * size in <b>outlen_out</b>. On failure, return UNPWBOX_BAD_SECRET if + * the passphrase might have been wrong, and UNPWBOX_CORRUPT if the object is + * definitely corrupt. + */ +int +crypto_unpwbox(uint8_t **out, size_t *outlen_out, + const uint8_t *inp, size_t input_len, + const char *secret, size_t secret_len) +{ + uint8_t *result = NULL; + const uint8_t *encrypted; + uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN]; + uint8_t hmac[DIGEST256_LEN]; + uint32_t result_len; + size_t encrypted_len; + crypto_cipher_t *cipher = NULL; + int rv = UNPWBOX_CORRUPTED; + ssize_t got_len; + + pwbox_encoded_t *enc = NULL; + + got_len = pwbox_encoded_parse(&enc, inp, input_len); + if (got_len < 0 || (size_t)got_len != input_len) + goto err; + + /* Now derive the keys and check the hmac. */ + if (secret_to_key_derivekey(keys, sizeof(keys), + pwbox_encoded_getarray_skey_header(enc), + pwbox_encoded_getlen_skey_header(enc), + secret, secret_len) < 0) + goto err; + + crypto_hmac_sha256((char *)hmac, + (const char*)keys + CIPHER_KEY_LEN, DIGEST256_LEN, + (const char*)inp, input_len - DIGEST256_LEN); + + if (tor_memneq(hmac, enc->hmac, DIGEST256_LEN)) { + rv = UNPWBOX_BAD_SECRET; + goto err; + } + + /* How long is the plaintext? */ + encrypted = pwbox_encoded_getarray_data(enc); + encrypted_len = pwbox_encoded_getlen_data(enc); + if (encrypted_len < 4) + goto err; + + cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv); + crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4); + result_len = ntohl(result_len); + if (encrypted_len < result_len + 4) + goto err; + + /* Allocate a buffer and decrypt */ + result = tor_malloc_zero(result_len); + crypto_cipher_decrypt(cipher, (char*)result, (char*)encrypted+4, result_len); + + *out = result; + *outlen_out = result_len; + + rv = UNPWBOX_OKAY; + goto out; + + err: + tor_free(result); + + out: + crypto_cipher_free(cipher); + pwbox_encoded_free(enc); + memwipe(keys, 0, sizeof(keys)); + return rv; +} + diff --git a/src/common/crypto_pwbox.h b/src/common/crypto_pwbox.h new file mode 100644 index 0000000000..aadd477078 --- /dev/null +++ b/src/common/crypto_pwbox.h @@ -0,0 +1,20 @@ +#ifndef CRYPTO_PWBOX_H_INCLUDED_ +#define CRYPTO_PWBOX_H_INCLUDED_ + +#include "torint.h" + +#define UNPWBOX_OKAY 0 +#define UNPWBOX_BAD_SECRET -1 +#define UNPWBOX_CORRUPTED -2 + +int crypto_pwbox(uint8_t **out, size_t *outlen_out, + const uint8_t *inp, size_t input_len, + const char *secret, size_t secret_len, + unsigned s2k_flags); + +int crypto_unpwbox(uint8_t **out, size_t *outlen_out, + const uint8_t *inp, size_t input_len, + const char *secret, size_t secret_len); + +#endif + diff --git a/src/common/crypto_s2k.c b/src/common/crypto_s2k.c new file mode 100644 index 0000000000..aef8436ad9 --- /dev/null +++ b/src/common/crypto_s2k.c @@ -0,0 +1,460 @@ +/* Copyright (c) 2001, Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define CRYPTO_S2K_PRIVATE + +#include "crypto.h" +#include "util.h" +#include "compat.h" +#include "crypto_s2k.h" + +#include <openssl/evp.h> + +#ifdef HAVE_LIBSCRYPT_H +#define HAVE_SCRYPT +#include <libscrypt.h> +#endif + +/* Encoded secrets take the form: + + u8 type; + u8 salt_and_parameters[depends on type]; + u8 key[depends on type]; + + As a special case, if the encoded secret is exactly 29 bytes long, + type 0 is understood. + + Recognized types are: + 00 -- RFC2440. salt_and_parameters is 9 bytes. key is 20 bytes. + salt_and_parameters is 8 bytes random salt, + 1 byte iteration info. + 01 -- PKBDF2_SHA1. salt_and_parameters is 17 bytes. key is 20 bytes. + salt_and_parameters is 16 bytes random salt, + 1 byte iteration info. + 02 -- SCRYPT_SALSA208_SHA256. salt_and_parameters is 18 bytes. key is + 32 bytes. + salt_and_parameters is 18 bytes random salt, 2 bytes iteration + info. +*/ + +#define S2K_TYPE_RFC2440 0 +#define S2K_TYPE_PBKDF2 1 +#define S2K_TYPE_SCRYPT 2 + +#define PBKDF2_SPEC_LEN 17 +#define PBKDF2_KEY_LEN 20 + +#define SCRYPT_SPEC_LEN 18 +#define SCRYPT_KEY_LEN 32 + +/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the + * specifier part of it, without the prefix type byte. */ +static int +secret_to_key_spec_len(uint8_t type) +{ + switch (type) { + case S2K_TYPE_RFC2440: + return S2K_RFC2440_SPECIFIER_LEN; + case S2K_TYPE_PBKDF2: + return PBKDF2_SPEC_LEN; + case S2K_TYPE_SCRYPT: + return SCRYPT_SPEC_LEN; + default: + return -1; + } +} + +/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the + * its preferred output. */ +static int +secret_to_key_key_len(uint8_t type) +{ + switch (type) { + case S2K_TYPE_RFC2440: + return DIGEST_LEN; + case S2K_TYPE_PBKDF2: + return DIGEST_LEN; + case S2K_TYPE_SCRYPT: + return DIGEST256_LEN; + default: + return -1; + } +} + +/** Given a specifier in <b>spec_and_key</b> of length + * <b>spec_and_key_len</b>, along with its prefix algorithm ID byte, and along + * with a key if <b>key_included</b> is true, check whether the whole + * specifier-and-key is of valid length, and return the algorithm type if it + * is. Set *<b>legacy_out</b> to 1 iff this is a legacy password hash or + * legacy specifier. Return an error code on failure. + */ +static int +secret_to_key_get_type(const uint8_t *spec_and_key, size_t spec_and_key_len, + int key_included, int *legacy_out) +{ + size_t legacy_len = S2K_RFC2440_SPECIFIER_LEN; + uint8_t type; + int total_len; + + if (key_included) + legacy_len += DIGEST_LEN; + + if (spec_and_key_len == legacy_len) { + *legacy_out = 1; + return S2K_TYPE_RFC2440; + } + + *legacy_out = 0; + if (spec_and_key_len == 0) + return S2K_BAD_LEN; + + type = spec_and_key[0]; + total_len = secret_to_key_spec_len(type); + if (total_len < 0) + return S2K_BAD_ALGORITHM; + if (key_included) { + int keylen = secret_to_key_key_len(type); + if (keylen < 0) + return S2K_BAD_ALGORITHM; + total_len += keylen; + } + + if ((size_t)total_len + 1 == spec_and_key_len) + return type; + else + return S2K_BAD_LEN; +} + +/** + * Write a new random s2k specifier of type <b>type</b>, without prefixing + * type byte, to <b>spec_out</b>, which must have enough room. May adjust + * parameter choice based on <b>flags</b>. + */ +static int +make_specifier(uint8_t *spec_out, uint8_t type, unsigned flags) +{ + int speclen = secret_to_key_spec_len(type); + if (speclen < 0) + return S2K_BAD_ALGORITHM; + + crypto_rand((char*)spec_out, speclen); + switch (type) { + case S2K_TYPE_RFC2440: + /* Hash 64 k of data. */ + spec_out[S2K_RFC2440_SPECIFIER_LEN-1] = 96; + break; + case S2K_TYPE_PBKDF2: + /* 131 K iterations */ + spec_out[PBKDF2_SPEC_LEN-1] = 17; + break; + case S2K_TYPE_SCRYPT: + if (flags & S2K_FLAG_LOW_MEM) { + /* N = 1<<12 */ + spec_out[SCRYPT_SPEC_LEN-2] = 12; + } else { + /* N = 1<<15 */ + spec_out[SCRYPT_SPEC_LEN-2] = 15; + } + /* r = 8; p = 2. */ + spec_out[SCRYPT_SPEC_LEN-1] = (3u << 4) | (1u << 0); + break; + default: + tor_fragile_assert(); + return S2K_BAD_ALGORITHM; + } + + return speclen; +} + +/** Implement RFC2440-style iterated-salted S2K conversion: convert the + * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte + * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier + * are a salt; the 9th byte describes how much iteration to do. + * If <b>key_out_len</b> > DIGEST_LEN, use HDKF to expand the result. + */ +void +secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret, + size_t secret_len, const char *s2k_specifier) +{ + crypto_digest_t *d; + uint8_t c; + size_t count, tmplen; + char *tmp; + uint8_t buf[DIGEST_LEN]; + tor_assert(key_out_len < SIZE_T_CEILING); + +#define EXPBIAS 6 + c = s2k_specifier[8]; + count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS); +#undef EXPBIAS + + d = crypto_digest_new(); + tmplen = 8+secret_len; + tmp = tor_malloc(tmplen); + memcpy(tmp,s2k_specifier,8); + memcpy(tmp+8,secret,secret_len); + secret_len += 8; + while (count) { + if (count >= secret_len) { + crypto_digest_add_bytes(d, tmp, secret_len); + count -= secret_len; + } else { + crypto_digest_add_bytes(d, tmp, count); + count = 0; + } + } + crypto_digest_get_digest(d, (char*)buf, sizeof(buf)); + + if (key_out_len <= sizeof(buf)) { + memcpy(key_out, buf, key_out_len); + } else { + crypto_expand_key_material_rfc5869_sha256(buf, DIGEST_LEN, + (const uint8_t*)s2k_specifier, 8, + (const uint8_t*)"EXPAND", 6, + (uint8_t*)key_out, key_out_len); + } + memwipe(tmp, 0, tmplen); + memwipe(buf, 0, sizeof(buf)); + tor_free(tmp); + crypto_digest_free(d); +} + +/** + * Helper: given a valid specifier without prefix type byte in <b>spec</b>, + * whose length must be correct, and given a secret passphrase <b>secret</b> + * of length <b>secret_len</b>, compute the key and store it into + * <b>key_out</b>, which must have enough room for secret_to_key_key_len(type) + * bytes. Return the number of bytes written on success and an error code + * on failure. + */ +STATIC int +secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len, + const uint8_t *spec, size_t spec_len, + const char *secret, size_t secret_len, + int type) +{ + int rv; + if (key_out_len > INT_MAX) + return S2K_BAD_LEN; + + switch (type) { + case S2K_TYPE_RFC2440: + secret_to_key_rfc2440((char*)key_out, key_out_len, secret, secret_len, + (const char*)spec); + return (int)key_out_len; + + case S2K_TYPE_PBKDF2: { + uint8_t log_iters; + if (spec_len < 1 || secret_len > INT_MAX || spec_len > INT_MAX) + return S2K_BAD_LEN; + log_iters = spec[spec_len-1]; + if (log_iters > 31) + return S2K_BAD_PARAMS; + rv = PKCS5_PBKDF2_HMAC_SHA1(secret, (int)secret_len, + spec, (int)spec_len-1, + (1<<log_iters), + (int)key_out_len, key_out); + if (rv < 0) + return S2K_FAILED; + return (int)key_out_len; + } + + case S2K_TYPE_SCRYPT: { +#ifdef HAVE_SCRYPT + uint8_t log_N, log_r, log_p; + uint64_t N; + uint32_t r, p; + if (spec_len < 2) + return S2K_BAD_LEN; + log_N = spec[spec_len-2]; + log_r = (spec[spec_len-1]) >> 4; + log_p = (spec[spec_len-1]) & 15; + if (log_N > 63) + return S2K_BAD_PARAMS; + N = ((uint64_t)1) << log_N; + r = 1u << log_r; + p = 1u << log_p; + rv = libscrypt_scrypt((const uint8_t*)secret, secret_len, + spec, spec_len-2, N, r, p, key_out, key_out_len); + if (rv != 0) + return S2K_FAILED; + return (int)key_out_len; +#else + return S2K_NO_SCRYPT_SUPPORT; +#endif + } + default: + return S2K_BAD_ALGORITHM; + } +} + +/** + * Given a specifier previously constructed with secret_to_key_make_specifier + * in <b>spec</b> of length <b>spec_len</b>, and a secret password in + * <b>secret</b> of length <b>secret_len</b>, generate <b>key_out_len</b> + * bytes of cryptographic material in <b>key_out</b>. The native output of + * the secret-to-key function will be truncated if key_out_len is short, and + * expanded with HKDF if key_out_len is long. Returns S2K_OKAY on success, + * and an error code on failure. + */ +int +secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len, + const uint8_t *spec, size_t spec_len, + const char *secret, size_t secret_len) +{ + int legacy_format = 0; + int type = secret_to_key_get_type(spec, spec_len, 0, &legacy_format); + int r; + + if (type < 0) + return type; +#ifndef HAVE_SCRYPT + if (type == S2K_TYPE_SCRYPT) + return S2K_NO_SCRYPT_SUPPORT; + #endif + + if (! legacy_format) { + ++spec; + --spec_len; + } + + r = secret_to_key_compute_key(key_out, key_out_len, spec, spec_len, + secret, secret_len, type); + if (r < 0) + return r; + else + return S2K_OKAY; +} + +/** + * Construct a new s2k algorithm specifier and salt in <b>buf</b>, according + * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>. Up to + * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Return the + * number of bytes used on success and an error code on failure. + */ +int +secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags) +{ + int rv; + int spec_len; +#ifdef HAVE_SCRYPT + uint8_t type = S2K_TYPE_SCRYPT; +#else + uint8_t type = S2K_TYPE_RFC2440; +#endif + + if (flags & S2K_FLAG_NO_SCRYPT) + type = S2K_TYPE_RFC2440; + if (flags & S2K_FLAG_USE_PBKDF2) + type = S2K_TYPE_PBKDF2; + + spec_len = secret_to_key_spec_len(type); + + if ((int)buf_len < spec_len + 1) + return S2K_TRUNCATED; + + buf[0] = type; + rv = make_specifier(buf+1, type, flags); + if (rv < 0) + return rv; + else + return rv + 1; +} + +/** + * Hash a passphrase from <b>secret</b> of length <b>secret_len</b>, according + * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>, and store the + * hash along with salt and hashing parameters into <b>buf</b>. Up to + * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Set + * *<b>len_out</b> to the number of bytes used and return S2K_OKAY on success; + * and return an error code on failure. + */ +int +secret_to_key_new(uint8_t *buf, + size_t buf_len, + size_t *len_out, + const char *secret, size_t secret_len, + unsigned flags) +{ + int key_len; + int spec_len; + int type; + int rv; + + spec_len = secret_to_key_make_specifier(buf, buf_len, flags); + + if (spec_len < 0) + return spec_len; + + type = buf[0]; + key_len = secret_to_key_key_len(type); + + if (key_len < 0) + return key_len; + + if ((int)buf_len < key_len + spec_len) + return S2K_TRUNCATED; + + rv = secret_to_key_compute_key(buf + spec_len, key_len, + buf + 1, spec_len-1, + secret, secret_len, type); + if (rv < 0) + return rv; + + *len_out = spec_len + key_len; + + return S2K_OKAY; +} + +/** + * Given a hashed passphrase in <b>spec_and_key</b> of length + * <b>spec_and_key_len</b> as generated by secret_to_key_new(), verify whether + * it is a hash of the passphrase <b>secret</b> of length <b>secret_len</b>. + * Return S2K_OKAY on a match, S2K_BAD_SECRET on a well-formed hash that + * doesn't match this secret, and another error code on other errors. + */ +int +secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len, + const char *secret, size_t secret_len) +{ + int is_legacy = 0; + int type = secret_to_key_get_type(spec_and_key, spec_and_key_len, + 1, &is_legacy); + uint8_t buf[32]; + int spec_len; + int key_len; + int rv; + + if (type < 0) + return type; + + if (! is_legacy) { + spec_and_key++; + spec_and_key_len--; + } + + spec_len = secret_to_key_spec_len(type); + key_len = secret_to_key_key_len(type); + tor_assert(spec_len > 0); + tor_assert(key_len > 0); + tor_assert(key_len <= (int) sizeof(buf)); + tor_assert((int)spec_and_key_len == spec_len + key_len); + rv = secret_to_key_compute_key(buf, key_len, + spec_and_key, spec_len, + secret, secret_len, type); + if (rv < 0) + goto done; + + if (tor_memeq(buf, spec_and_key + spec_len, key_len)) + rv = S2K_OKAY; + else + rv = S2K_BAD_SECRET; + + done: + memwipe(buf, 0, sizeof(buf)); + return rv; +} + diff --git a/src/common/crypto_s2k.h b/src/common/crypto_s2k.h new file mode 100644 index 0000000000..3693a430e7 --- /dev/null +++ b/src/common/crypto_s2k.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2001, Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_CRYPTO_S2K_H_INCLUDED +#define TOR_CRYPTO_S2K_H_INCLUDED + +#include <stdio.h> +#include "torint.h" + +/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the + * 9th describes how much iteration to do. */ +#define S2K_RFC2440_SPECIFIER_LEN 9 +void secret_to_key_rfc2440( + char *key_out, size_t key_out_len, const char *secret, + size_t secret_len, const char *s2k_specifier); + +/** Flag for secret-to-key function: do not use scrypt. */ +#define S2K_FLAG_NO_SCRYPT (1u<<0) +/** Flag for secret-to-key functions: if using a memory-tuned s2k function, + * assume that we have limited memory. */ +#define S2K_FLAG_LOW_MEM (1u<<1) +/** Flag for secret-to-key functions: force use of pbkdf2. Without this, we + * default to scrypt, then RFC2440. */ +#define S2K_FLAG_USE_PBKDF2 (1u<<2) + +/** Maximum possible output length from secret_to_key_new. */ +#define S2K_MAXLEN 64 + +/** Error code from secret-to-key functions: all is well */ +#define S2K_OKAY 0 +/** Error code from secret-to-key functions: generic failure */ +#define S2K_FAILED -1 +/** Error code from secret-to-key functions: provided secret didn't match */ +#define S2K_BAD_SECRET -2 +/** Error code from secret-to-key functions: didn't recognize the algorithm */ +#define S2K_BAD_ALGORITHM -3 +/** Error code from secret-to-key functions: specifier wasn't valid */ +#define S2K_BAD_PARAMS -4 +/** Error code from secret-to-key functions: compiled without scrypt */ +#define S2K_NO_SCRYPT_SUPPORT -5 +/** Error code from secret-to-key functions: not enough space to write output. + */ +#define S2K_TRUNCATED -6 +/** Error code from secret-to-key functions: Wrong length for specifier. */ +#define S2K_BAD_LEN -7 + +int secret_to_key_new(uint8_t *buf, + size_t buf_len, + size_t *len_out, + const char *secret, size_t secret_len, + unsigned flags); + +int secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags); + +int secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len, + const char *secret, size_t secret_len); + +int secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len, + const uint8_t *spec, size_t spec_len, + const char *secret, size_t secret_len); + +#ifdef CRYPTO_S2K_PRIVATE +STATIC int secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len, + const uint8_t *spec, size_t spec_len, + const char *secret, size_t secret_len, + int type); +#endif + +#endif + diff --git a/src/common/di_ops.c b/src/common/di_ops.c index 14a1443400..a8bfd02532 100644 --- a/src/common/di_ops.c +++ b/src/common/di_ops.c @@ -130,6 +130,7 @@ tor_memeq(const void *a, const void *b, size_t sz) * 1 & ((any_difference - 1) >> 8) == 0 */ + /*coverity[overflow]*/ return 1 & ((any_difference - 1) >> 8); } @@ -217,6 +218,7 @@ safe_mem_is_zero(const void *mem, size_t sz) total |= *ptr++; } + /*coverity[overflow]*/ return 1 & ((total - 1) >> 8); } diff --git a/src/common/include.am b/src/common/include.am index 68e0110c26..5c000e86f3 100644 --- a/src/common/include.am +++ b/src/common/include.am @@ -16,7 +16,7 @@ EXTRA_DIST+= \ src/common/Makefile.nmake #CFLAGS = -Wall -Wpointer-arith -O2 -AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common +AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel if USE_OPENBSD_MALLOC libor_extra_source=src/ext/OpenBSD_malloc_Linux.c @@ -52,8 +52,12 @@ LIBDONNA= endif endif +LIBDONNA += $(LIBED25519_REF10) + if CURVE25519_ENABLED -libcrypto_extra_source=src/common/crypto_curve25519.c +libcrypto_extra_source = \ + src/common/crypto_curve25519.c \ + src/common/crypto_ed25519.c endif LIBOR_A_SOURCES = \ @@ -69,15 +73,19 @@ LIBOR_A_SOURCES = \ src/common/util_process.c \ src/common/sandbox.c \ src/ext/csiphash.c \ + src/ext/trunnel/trunnel.c \ $(libor_extra_source) \ $(libor_mempool_source) LIBOR_CRYPTO_A_SOURCES = \ src/common/aes.c \ src/common/crypto.c \ + src/common/crypto_pwbox.c \ + src/common/crypto_s2k.c \ src/common/crypto_format.c \ src/common/torgzip.c \ src/common/tortls.c \ + src/trunnel/pwbox.c \ $(libcrypto_extra_source) LIBOR_EVENT_A_SOURCES = \ @@ -110,6 +118,9 @@ COMMONHEADERS = \ src/common/container.h \ src/common/crypto.h \ src/common/crypto_curve25519.h \ + src/common/crypto_ed25519.h \ + src/common/crypto_pwbox.h \ + src/common/crypto_s2k.h \ src/common/di_ops.h \ src/common/memarea.h \ src/common/linux_syscalls.inc \ diff --git a/src/common/log.c b/src/common/log.c index 517fa4faaa..2e51e5c578 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -1010,12 +1010,16 @@ mark_logs_temp(void) * logfile fails, -1 is returned and errno is set appropriately (by open(2)). */ int -add_file_log(const log_severity_list_t *severity, const char *filename) +add_file_log(const log_severity_list_t *severity, const char *filename, + const int truncate) { int fd; logfile_t *lf; - fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644); + int open_flags = O_WRONLY|O_CREAT; + open_flags |= truncate ? O_TRUNC : O_APPEND; + + fd = tor_open_cloexec(filename, open_flags, 0644); if (fd<0) return -1; if (tor_fd_seekend(fd)<0) { @@ -1297,3 +1301,15 @@ switch_logs_debug(void) UNLOCK_LOGS(); } +/** Truncate all the log files. */ +void +truncate_logs(void) +{ + logfile_t *lf; + for (lf = logfiles; lf; lf = lf->next) { + if (lf->fd >= 0) { + tor_ftruncate(lf->fd); + } + } +} + diff --git a/src/common/sandbox.c b/src/common/sandbox.c index dbbaa59d7c..36022c921c 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -98,6 +98,8 @@ static sandbox_cfg_t *filter_dynamic = NULL; #undef SCMP_CMP #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0}) +#define SCMP_CMP_STR(a,b,c) \ + ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0}) #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)}) /* We use a wrapper here because these masked comparisons seem to be pretty * verbose. Also, it's important to cast to scmp_datum_t before negating the @@ -252,7 +254,7 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(execve)) { rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), - SCMP_CMP(0, SCMP_CMP_EQ, param->value)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received " "libseccomp error %d", rc); @@ -389,7 +391,7 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(open)) { rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), - SCMP_CMP(0, SCMP_CMP_EQ, param->value)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); @@ -444,8 +446,8 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) param->syscall == SCMP_SYS(rename)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename), - SCMP_CMP(0, SCMP_CMP_EQ, param->value), - SCMP_CMP(1, SCMP_CMP_EQ, param->value2)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received " "libseccomp error %d", rc); @@ -475,7 +477,7 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) == SCMP_SYS(openat)) { rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD), - SCMP_CMP(1, SCMP_CMP_EQ, param->value), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| O_CLOEXEC)); if (rc != 0) { @@ -884,7 +886,7 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open) || param->syscall == SCMP_SYS(stat64))) { rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64), - SCMP_CMP(0, SCMP_CMP_EQ, param->value)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); @@ -967,7 +969,7 @@ static int prot_strings_helper(strmap_t *locations, char **pr_mem_next_p, size_t *pr_mem_left_p, - intptr_t *value_p) + char **value_p) { char *param_val; size_t param_size; @@ -983,7 +985,7 @@ prot_strings_helper(strmap_t *locations, if (location) { // We already interned this string. tor_free(param_val); - *value_p = (intptr_t) location; + *value_p = location; return 0; } else if (*pr_mem_left_p >= param_size) { // copy to protected @@ -992,7 +994,7 @@ prot_strings_helper(strmap_t *locations, // re-point el parameter to protected tor_free(param_val); - *value_p = (intptr_t) location; + *value_p = location; strmap_set(locations, location, location); /* good real estate advice */ @@ -1074,7 +1076,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base)); if (ret) { log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!"); - return ret; + goto out; } // no munmap of the protected base address @@ -1082,7 +1084,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base)); if (ret) { log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!"); - return ret; + goto out; } /* @@ -1101,7 +1103,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); if (ret) { log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!"); - return ret; + goto out; } ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), @@ -1111,7 +1113,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); if (ret) { log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!"); - return ret; + goto out; } out: @@ -1126,7 +1128,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) * point. */ static sandbox_cfg_t* -new_element2(int syscall, intptr_t value, intptr_t value2) +new_element2(int syscall, char *value, char *value2) { smp_param_t *param = NULL; @@ -1142,9 +1144,9 @@ new_element2(int syscall, intptr_t value, intptr_t value2) } static sandbox_cfg_t* -new_element(int syscall, intptr_t value) +new_element(int syscall, char *value) { - return new_element2(syscall, value, 0); + return new_element2(syscall, value, NULL); } #ifdef __NR_stat64 @@ -1158,7 +1160,7 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_stat, (intptr_t)(void*) file); + elem = new_element(SCMP_stat, file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1171,33 +1173,11 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) } int -sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) -{ - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); - - while ((fn = va_arg(ap, char*)) != NULL) { - rc = sandbox_cfg_allow_stat_filename(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat_filename_array fail"); - goto end; - } - } - - end: - va_end(ap); - return 0; -} - -int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(open), (intptr_t)(void *) file); + elem = new_element(SCMP_SYS(open), file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1214,9 +1194,7 @@ sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) { sandbox_cfg_t *elem = NULL; - elem = new_element2(SCMP_SYS(rename), - (intptr_t)(void *) file1, - (intptr_t)(void *) file2); + elem = new_element2(SCMP_SYS(rename), file1, file2); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); @@ -1230,33 +1208,11 @@ sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) } int -sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...) -{ - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); - - while ((fn = va_arg(ap, char*)) != NULL) { - rc = sandbox_cfg_allow_open_filename(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_open_filename_array fail"); - goto end; - } - } - - end: - va_end(ap); - return 0; -} - -int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(openat), (intptr_t)(void *) file); + elem = new_element(SCMP_SYS(openat), file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1268,35 +1224,13 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) return 0; } -int -sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) -{ - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); - - while ((fn = va_arg(ap, char*)) != NULL) { - rc = sandbox_cfg_allow_openat_filename(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_openat_filename_array fail"); - goto end; - } - } - - end: - va_end(ap); - return 0; -} - #if 0 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(execve), (intptr_t)(void *) com); + elem = new_element(SCMP_SYS(execve), com); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1308,28 +1242,6 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) return 0; } -int -sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) -{ - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); - - while ((fn = va_arg(ap, char*)) != NULL) { - - rc = sandbox_cfg_allow_execve(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_execve_array failed"); - goto end; - } - } - - end: - va_end(ap); - return 0; -} #endif /** Cache entry for getaddrinfo results; used when sandboxing is implemented @@ -1380,10 +1292,10 @@ static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t) HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node, cached_getaddrinfo_item_hash, cached_getaddrinfo_items_eq); -HT_GENERATE(getaddrinfo_cache, cached_getaddrinfo_item_t, node, - cached_getaddrinfo_item_hash, - cached_getaddrinfo_items_eq, - 0.6, tor_malloc_, tor_realloc_, tor_free_); +HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node, + cached_getaddrinfo_item_hash, + cached_getaddrinfo_items_eq, + 0.6, tor_reallocarray_, tor_free_) /** If true, don't try to cache getaddrinfo results. */ static int sandbox_getaddrinfo_cache_disabled = 0; @@ -1788,26 +1700,12 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) } int -sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...) -{ - (void)cfg; - return 0; -} - -int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) { (void)cfg; (void)file; return 0; } -int -sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) -{ - (void)cfg; - return 0; -} - #if 0 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) @@ -1815,13 +1713,6 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) (void)cfg; (void)com; return 0; } - -int -sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) -{ - (void)cfg; - return 0; -} #endif int @@ -1832,13 +1723,6 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) } int -sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) -{ - (void)cfg; - return 0; -} - -int sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) { (void)cfg; (void)file1; (void)file2; diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 35d87772fd..ddb2be5695 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -66,9 +66,9 @@ typedef struct smp_param { int syscall; /** parameter value. */ - intptr_t value; + char *value; /** parameter value, second argument. */ - intptr_t value2; + char *value2; /** parameter flag (0 = not protected, 1 = protected). */ int prot; @@ -149,14 +149,6 @@ int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); /**DOCDOC*/ int sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2); -/** Function used to add a series of open allowed filenames to a supplied - * configuration. - * @param cfg sandbox configuration. - * @param ... a list of stealable pointers to permitted files. The last - * one must be NULL. -*/ -int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...); - /** * Function used to add a openat allowed filename to a supplied configuration. * The (char*) specifies the path to the allowed file; we steal the pointer to @@ -164,28 +156,12 @@ int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...); */ int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file); -/** Function used to add a series of openat allowed filenames to a supplied - * configuration. - * @param cfg sandbox configuration. - * @param ... a list of stealable pointers to permitted files. The last - * one must be NULL. - */ -int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...); - #if 0 /** * Function used to add a execve allowed filename to a supplied configuration. * The (char*) specifies the path to the allowed file; that pointer is stolen. */ int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com); - -/** Function used to add a series of execve allowed filenames to a supplied - * configuration. - * @param cfg sandbox configuration. - * @param ... an array of stealable pointers to permitted files. The last - * one must be NULL. - */ -int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...); #endif /** @@ -194,14 +170,6 @@ int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...); */ int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file); -/** Function used to add a series of stat64 allowed filenames to a supplied - * configuration. - * @param cfg sandbox configuration. - * @param ... an array of stealable pointers to permitted files. The last - * one must be NULL. - */ -int sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...); - /** Function used to initialise a sandbox configuration.*/ int sandbox_init(sandbox_cfg_t* cfg); diff --git a/src/common/torgzip.c b/src/common/torgzip.c index 15451ee30d..b4688bf9d8 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -46,6 +46,12 @@ #include <zlib.h> +static size_t tor_zlib_state_size_precalc(int inflate, + int windowbits, int memlevel); + +/** Total number of bytes allocated for zlib state */ +static size_t total_zlib_allocation = 0; + /** Set to 1 if zlib is a version that supports gzip; set to 0 if it doesn't; * set to -1 if we haven't checked yet. */ static int gzip_is_supported = -1; @@ -411,6 +417,9 @@ struct tor_zlib_state_t { size_t input_so_far; /** Number of bytes written so far. Used to detect zlib bombs. */ size_t output_so_far; + + /** Approximate number of bytes allocated for this object. */ + size_t allocation; }; /** Construct and return a tor_zlib_state_t object using <b>method</b>. If @@ -420,6 +429,7 @@ tor_zlib_state_t * tor_zlib_new(int compress, compress_method_t method) { tor_zlib_state_t *out; + int bits; if (method == GZIP_METHOD && !is_gzip_supported()) { /* Old zlib version don't support gzip in inflateInit2 */ @@ -432,14 +442,19 @@ tor_zlib_new(int compress, compress_method_t method) out->stream.zfree = Z_NULL; out->stream.opaque = NULL; out->compress = compress; + bits = method_bits(method); if (compress) { if (deflateInit2(&out->stream, Z_BEST_COMPRESSION, Z_DEFLATED, - method_bits(method), 8, Z_DEFAULT_STRATEGY) != Z_OK) + bits, 8, Z_DEFAULT_STRATEGY) != Z_OK) goto err; } else { - if (inflateInit2(&out->stream, method_bits(method)) != Z_OK) + if (inflateInit2(&out->stream, bits) != Z_OK) goto err; } + out->allocation = tor_zlib_state_size_precalc(!compress, bits, 8); + + total_zlib_allocation += out->allocation; + return out; err: @@ -472,7 +487,7 @@ tor_zlib_process(tor_zlib_state_t *state, state->stream.avail_out = (unsigned int)*out_len; if (state->compress) { - err = deflate(&state->stream, finish ? Z_FINISH : Z_SYNC_FLUSH); + err = deflate(&state->stream, finish ? Z_FINISH : Z_NO_FLUSH); } else { err = inflate(&state->stream, finish ? Z_FINISH : Z_SYNC_FLUSH); } @@ -517,6 +532,8 @@ tor_zlib_free(tor_zlib_state_t *state) if (!state) return; + total_zlib_allocation -= state->allocation; + if (state->compress) deflateEnd(&state->stream); else @@ -525,3 +542,48 @@ tor_zlib_free(tor_zlib_state_t *state) tor_free(state); } +/** Return an approximate number of bytes used in RAM to hold a state with + * window bits <b>windowBits</b> and compression level 'memlevel' */ +static size_t +tor_zlib_state_size_precalc(int inflate, int windowbits, int memlevel) +{ + windowbits &= 15; + +#define A_FEW_KILOBYTES 2048 + + if (inflate) { + /* From zconf.h: + + "The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects." + */ + return sizeof(tor_zlib_state_t) + sizeof(struct z_stream_s) + + (1 << 15) + A_FEW_KILOBYTES; + } else { + /* Also from zconf.h: + + "The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + ... plus a few kilobytes for small objects." + */ + return sizeof(tor_zlib_state_t) + sizeof(struct z_stream_s) + + (1 << (windowbits + 2)) + (1 << (memlevel + 9)) + A_FEW_KILOBYTES; + } +#undef A_FEW_KILOBYTES +} + +/** Return the approximate number of bytes allocated for <b>state</b>. */ +size_t +tor_zlib_state_size(const tor_zlib_state_t *state) +{ + return state->allocation; +} + +/** Return the approximate number of bytes allocated for all zlib states. */ +size_t +tor_zlib_get_total_allocation(void) +{ + return total_zlib_allocation; +} + diff --git a/src/common/torgzip.h b/src/common/torgzip.h index 5db03fe6e0..d407bf48c6 100644 --- a/src/common/torgzip.h +++ b/src/common/torgzip.h @@ -55,5 +55,8 @@ tor_zlib_output_t tor_zlib_process(tor_zlib_state_t *state, int finish); void tor_zlib_free(tor_zlib_state_t *state); +size_t tor_zlib_state_size(const tor_zlib_state_t *state); +size_t tor_zlib_get_total_allocation(void); + #endif diff --git a/src/common/torint.h b/src/common/torint.h index a993d7649a..b46f306668 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -332,30 +332,30 @@ typedef uint32_t uintptr_t; #endif /* time_t_is_signed */ #endif /* ifndef(TIME_MAX) */ -#ifndef SIZE_T_MAX +#ifndef SIZE_MAX #if (SIZEOF_SIZE_T == 4) -#define SIZE_T_MAX UINT32_MAX +#define SIZE_MAX UINT32_MAX #elif (SIZEOF_SIZE_T == 8) -#define SIZE_T_MAX UINT64_MAX +#define SIZE_MAX UINT64_MAX #else -#error "Can't define SIZE_T_MAX" +#error "Can't define SIZE_MAX" #endif #endif -#ifndef SSIZE_T_MAX +#ifndef SSIZE_MAX #if (SIZEOF_SIZE_T == 4) -#define SSIZE_T_MAX INT32_MAX +#define SSIZE_MAX INT32_MAX #elif (SIZEOF_SIZE_T == 8) -#define SSIZE_T_MAX INT64_MAX +#define SSIZE_MAX INT64_MAX #else -#error "Can't define SSIZE_T_MAX" +#error "Can't define SSIZE_MAX" #endif #endif /** Any ssize_t larger than this amount is likely to be an underflow. */ -#define SSIZE_T_CEILING ((ssize_t)(SSIZE_T_MAX-16)) +#define SSIZE_T_CEILING ((ssize_t)(SSIZE_MAX-16)) /** Any size_t larger than this amount is likely to be an underflow. */ -#define SIZE_T_CEILING ((size_t)(SSIZE_T_MAX-16)) +#define SIZE_T_CEILING ((size_t)(SSIZE_MAX-16)) #endif /* __TORINT_H */ diff --git a/src/common/torlog.h b/src/common/torlog.h index 34f70f3c00..34e39b4b94 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -130,7 +130,8 @@ void set_log_severity_config(int minSeverity, int maxSeverity, log_severity_list_t *severity_out); void add_stream_log(const log_severity_list_t *severity, const char *name, int fd); -int add_file_log(const log_severity_list_t *severity, const char *filename); +int add_file_log(const log_severity_list_t *severity, const char *filename, + const int truncate); #ifdef HAVE_SYSLOG_H int add_syslog_log(const log_severity_list_t *severity); #endif @@ -148,6 +149,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax, void flush_pending_log_callbacks(void); void log_set_application_name(const char *name); void set_log_time_granularity(int granularity_msec); +void truncate_logs(void); void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) CHECK_PRINTF(3,4); diff --git a/src/common/tortls.c b/src/common/tortls.c index 4fd9bba380..eda10bbe2e 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -16,10 +16,6 @@ #include "orconfig.h" -#if defined (WINCE) -#include <WinSock2.h> -#endif - #include <assert.h> #ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/ #ifndef _WIN32_WINNT @@ -786,8 +782,7 @@ static const cipher_info_t CLIENT_CIPHER_INFO_LIST[] = { }; /** The length of CLIENT_CIPHER_INFO_LIST and CLIENT_CIPHER_DUMMIES. */ -static const int N_CLIENT_CIPHERS = - sizeof(CLIENT_CIPHER_INFO_LIST)/sizeof(CLIENT_CIPHER_INFO_LIST[0]); +static const int N_CLIENT_CIPHERS = ARRAY_LENGTH(CLIENT_CIPHER_INFO_LIST); #endif #ifndef V2_HANDSHAKE_CLIENT @@ -2615,16 +2610,20 @@ check_no_tls_errors_(const char *fname, int line) int tor_tls_used_v1_handshake(tor_tls_t *tls) { +#if defined(V2_HANDSHAKE_SERVER) && defined(V2_HANDSHAKE_CLIENT) + return ! tls->wasV2Handshake; +#else if (tls->isServer) { -#ifdef V2_HANDSHAKE_SERVER +# ifdef V2_HANDSHAKE_SERVER return ! tls->wasV2Handshake; -#endif +# endif } else { -#ifdef V2_HANDSHAKE_CLIENT +# ifdef V2_HANDSHAKE_CLIENT return ! tls->wasV2Handshake; -#endif +# endif } return 1; +#endif } /** Return true iff <b>name</b> is a DN of a kind that could only diff --git a/src/common/util.c b/src/common/util.c index 2d7893b38a..f4d293c838 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -96,6 +96,10 @@ #include <sys/wait.h> #endif +#ifdef __clang_analyzer__ +#undef MALLOC_ZERO_WORKS +#endif + /* ===== * Assertion helper. * ===== */ @@ -231,6 +235,13 @@ tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS) tor_assert(size < SIZE_T_CEILING); +#ifndef MALLOC_ZERO_WORKS + /* Some libc mallocs don't work when size==0. Override them. */ + if (size==0) { + size=1; + } +#endif + #ifdef USE_DMALLOC result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0); #else @@ -244,6 +255,20 @@ tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS) return result; } +/** + * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for + * overflow. Unlike other allocation functions, return NULL on overflow. + */ +void * +tor_reallocarray_(void *ptr, size_t sz1, size_t sz2 DMALLOC_PARAMS) +{ + /* XXXX we can make this return 0, but we would need to check all the + * reallocarray users. */ + tor_assert(sz2 == 0 || sz1 < SIZE_T_CEILING / sz2); + + return tor_realloc(ptr, (sz1 * sz2) DMALLOC_FN_ARGS); +} + /** Return a newly allocated copy of the NUL-terminated string s. On * error, log and terminate. (Like strdup(s), but never returns * NULL.) @@ -1183,9 +1208,14 @@ esc_for_log(const char *s) } } + tor_assert(len <= SSIZE_MAX); + result = outp = tor_malloc(len); *outp++ = '\"'; for (cp = s; *cp; ++cp) { + /* This assertion should always succeed, since we will write at least + * one char here, and two chars for closing quote and nul later */ + tor_assert((outp-result) < (ssize_t)len-2); switch (*cp) { case '\\': case '\"': @@ -1209,6 +1239,7 @@ esc_for_log(const char *s) if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) { *outp++ = *cp; } else { + tor_assert((outp-result) < (ssize_t)len-4); tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp); outp += 4; } @@ -1216,6 +1247,7 @@ esc_for_log(const char *s) } } + tor_assert((outp-result) <= (ssize_t)len-2); *outp++ = '\"'; *outp++ = 0; @@ -1754,7 +1786,7 @@ write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket) { size_t written = 0; ssize_t result; - tor_assert(count < SSIZE_T_MAX); + tor_assert(count < SSIZE_MAX); while (written != count) { if (isSocket) @@ -1779,7 +1811,7 @@ read_all(tor_socket_t fd, char *buf, size_t count, int isSocket) size_t numread = 0; ssize_t result; - if (count > SIZE_T_CEILING || count > SSIZE_T_MAX) + if (count > SIZE_T_CEILING || count > SSIZE_MAX) return -1; while (numread != count) { @@ -1893,7 +1925,7 @@ check_private_dir(const char *dirname, cpd_check_t check, } if (check & CPD_CREATE) { log_info(LD_GENERAL, "Creating directory %s", dirname); -#if defined (_WIN32) && !defined (WINCE) +#if defined (_WIN32) r = mkdir(dirname); #else r = mkdir(dirname, 0700); @@ -2332,6 +2364,7 @@ read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) pos += r; } while (r > 0 && pos < max_bytes_to_read); + tor_assert(pos < string_max); *sz_out = pos; string[pos] = '\0'; return string; @@ -2804,10 +2837,14 @@ scan_unsigned(const char **bufp, unsigned long *out, int width, int base) while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp)) && scanned_so_far < width) { int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++); - unsigned long new_result = result * base + digit; - if (new_result < result) - return -1; /* over/underflow. */ - result = new_result; + // Check for overflow beforehand, without actually causing any overflow + // This preserves functionality on compilers that don't wrap overflow + // (i.e. that trap or optimise away overflow) + // result * base + digit > ULONG_MAX + // result * base > ULONG_MAX - digit + if (result > (ULONG_MAX - digit)/base) + return -1; /* Processing this digit would overflow */ + result = result * base + digit; ++scanned_so_far; } @@ -2842,10 +2879,17 @@ scan_signed(const char **bufp, long *out, int width) if (scan_unsigned(bufp, &result, width, 10) < 0) return -1; - if (neg) { + if (neg && result > 0) { if (result > ((unsigned long)LONG_MAX) + 1) return -1; /* Underflow */ - *out = -(long)result; + // Avoid overflow on the cast to signed long when result is LONG_MIN + // by subtracting 1 from the unsigned long positive value, + // then, after it has been cast to signed and negated, + // subtracting the original 1 (the double-subtraction is intentional). + // Otherwise, the cast to signed could cause a temporary long + // to equal LONG_MAX + 1, which is undefined. + // We avoid underflow on the subtraction by treating -0 as positive. + *out = (-(long)(result - 1)) - 1; } else { if (result > LONG_MAX) return -1; /* Overflow */ @@ -3378,8 +3422,8 @@ format_win_cmdline_argument(const char *arg) smartlist_add(arg_chars, (void*)&backslash); /* Allocate space for argument, quotes (if needed), and terminator */ - formatted_arg = tor_malloc(sizeof(char) * - (smartlist_len(arg_chars) + (need_quotes?2:0) + 1)); + formatted_arg = tor_calloc(sizeof(char), + (smartlist_len(arg_chars) + (need_quotes ? 2 : 0) + 1)); /* Add leading quote */ i=0; @@ -3544,7 +3588,13 @@ format_helper_exit_status(unsigned char child_state, int saved_errno, /* Convert errno to be unsigned for hex conversion */ if (saved_errno < 0) { - unsigned_errno = (unsigned int) -saved_errno; + // Avoid overflow on the cast to unsigned int when result is INT_MIN + // by adding 1 to the signed int negative value, + // then, after it has been negated and cast to unsigned, + // adding the original 1 back (the double-addition is intentional). + // Otherwise, the cast to signed could cause a temporary int + // to equal INT_MAX + 1, which is undefined. + unsigned_errno = ((unsigned int) -(saved_errno + 1)) + 1; } else { unsigned_errno = (unsigned int) saved_errno; } @@ -4038,8 +4088,11 @@ tor_spawn_background(const char *const filename, const char **argv, status = process_handle->status = PROCESS_STATUS_RUNNING; /* Set stdout/stderr pipes to be non-blocking */ - fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK); - fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK); + if (fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK) < 0 || + fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK) < 0) { + log_warn(LD_GENERAL, "Failed to set stderror/stdout pipes nonblocking " + "in parent process: %s", strerror(errno)); + } /* Open the buffered IO streams */ process_handle->stdout_handle = fdopen(process_handle->stdout_pipe, "r"); process_handle->stderr_handle = fdopen(process_handle->stderr_pipe, "r"); @@ -4373,7 +4426,7 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, DWORD byte_count; BOOL process_exited = FALSE; - if (count > SIZE_T_CEILING || count > SSIZE_T_MAX) + if (count > SIZE_T_CEILING || count > SSIZE_MAX) return -1; while (numread != count) { @@ -4439,7 +4492,7 @@ tor_read_all_handle(FILE *h, char *buf, size_t count, if (eof) *eof = 0; - if (count > SIZE_T_CEILING || count > SSIZE_T_MAX) + if (count > SIZE_T_CEILING || count > SSIZE_MAX) return -1; while (numread != count) { @@ -5008,7 +5061,7 @@ tor_check_port_forwarding(const char *filename, for each smartlist element (one for "-p" and one for the ports), and one for the final NULL. */ args_n = 1 + 2*smartlist_len(ports_to_forward) + 1; - argv = tor_malloc_zero(sizeof(char*)*args_n); + argv = tor_calloc(sizeof(char *), args_n); argv[argv_index++] = filename; SMARTLIST_FOREACH_BEGIN(ports_to_forward, const char *, port) { diff --git a/src/common/util.h b/src/common/util.h index 97367a9a7b..61bb05f016 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -79,6 +79,7 @@ void *tor_malloc_(size_t size DMALLOC_PARAMS) ATTR_MALLOC; void *tor_malloc_zero_(size_t size DMALLOC_PARAMS) ATTR_MALLOC; void *tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC; void *tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS); +void *tor_reallocarray_(void *ptr, size_t size1, size_t size2 DMALLOC_PARAMS); char *tor_strdup_(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); char *tor_strndup_(const char *s, size_t n DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); @@ -116,6 +117,8 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, #define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS) #define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS) #define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS) +#define tor_reallocarray(ptr, sz1, sz2) \ + tor_reallocarray_((ptr), (sz1), (sz2) DMALLOC_ARGS) #define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS) #define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS) #define tor_memdup(s, n) tor_memdup_(s, n DMALLOC_ARGS) diff --git a/src/common/util_process.c b/src/common/util_process.c index d6ef590162..a6a2a9dcd9 100644 --- a/src/common/util_process.c +++ b/src/common/util_process.c @@ -62,8 +62,8 @@ static HT_HEAD(process_map, waitpid_callback_t) process_map = HT_INITIALIZER(); HT_PROTOTYPE(process_map, waitpid_callback_t, node, process_map_entry_hash_, process_map_entries_eq_); -HT_GENERATE(process_map, waitpid_callback_t, node, process_map_entry_hash_, - process_map_entries_eq_, 0.6, malloc, realloc, free); +HT_GENERATE2(process_map, waitpid_callback_t, node, process_map_entry_hash_, + process_map_entries_eq_, 0.6, tor_reallocarray_, tor_free_); /** * Begin monitoring the child pid <b>pid</b> to see if we get a SIGCHLD for diff --git a/src/config/include.am b/src/config/include.am index 35961b829a..c283628513 100644 --- a/src/config/include.am +++ b/src/config/include.am @@ -2,7 +2,7 @@ confdir = $(sysconfdir)/tor tordatadir = $(datadir)/tor -EXTRA_DIST+= src/config/geoip src/config/geoip6 +EXTRA_DIST+= src/config/geoip src/config/geoip6 src/config/torrc.minimal.in # fallback-consensus conf_DATA = src/config/torrc.sample diff --git a/src/config/torrc.minimal.in b/src/config/torrc.minimal.in new file mode 100644 index 0000000000..d842fbcaf5 --- /dev/null +++ b/src/config/torrc.minimal.in @@ -0,0 +1,192 @@ +## Configuration file for a typical Tor user +## Last updated 9 October 2013 for Tor 0.2.5.2-alpha. +## (may or may not work for much older or much newer versions of Tor.) +## +## Lines that begin with "## " try to explain what's going on. Lines +## that begin with just "#" are disabled commands: you can enable them +## by removing the "#" symbol. +## +## See 'man tor', or https://www.torproject.org/docs/tor-manual.html, +## for more options you can use in this file. +## +## Tor will look for this file in various places based on your platform: +## https://www.torproject.org/docs/faq#torrc + +## Tor opens a socks proxy on port 9050 by default -- even if you don't +## configure one below. Set "SocksPort 0" if you plan to run Tor only +## as a relay, and not make any local application connections yourself. +#SocksPort 9050 # Default: Bind to localhost:9050 for local connections. +#SocksPort 192.168.0.1:9100 # Bind to this address:port too. + +## Entry policies to allow/deny SOCKS requests based on IP address. +## First entry that matches wins. If no SocksPolicy is set, we accept +## all (and only) requests that reach a SocksPort. Untrusted users who +## can access your SocksPort may be able to learn about the connections +## you make. +#SocksPolicy accept 192.168.0.0/16 +#SocksPolicy reject * + +## Logs go to stdout at level "notice" unless redirected by something +## else, like one of the below lines. You can have as many Log lines as +## you want. +## +## We advise using "notice" in most cases, since anything more verbose +## may provide sensitive information to an attacker who obtains the logs. +## +## Send all messages of level 'notice' or higher to @LOCALSTATEDIR@/log/tor/notices.log +#Log notice file @LOCALSTATEDIR@/log/tor/notices.log +## Send every possible message to @LOCALSTATEDIR@/log/tor/debug.log +#Log debug file @LOCALSTATEDIR@/log/tor/debug.log +## Use the system log instead of Tor's logfiles +#Log notice syslog +## To send all messages to stderr: +#Log debug stderr + +## Uncomment this to start the process in the background... or use +## --runasdaemon 1 on the command line. This is ignored on Windows; +## see the FAQ entry if you want Tor to run as an NT service. +#RunAsDaemon 1 + +## The directory for keeping all the keys/etc. By default, we store +## things in $HOME/.tor on Unix, and in Application Data\tor on Windows. +#DataDirectory @LOCALSTATEDIR@/lib/tor + +## The port on which Tor will listen for local connections from Tor +## controller applications, as documented in control-spec.txt. +#ControlPort 9051 +## If you enable the controlport, be sure to enable one of these +## authentication methods, to prevent attackers from accessing it. +#HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C +#CookieAuthentication 1 + +############### This section is just for location-hidden services ### + +## Once you have configured a hidden service, you can look at the +## contents of the file ".../hidden_service/hostname" for the address +## to tell people. +## +## HiddenServicePort x y:z says to redirect requests on port x to the +## address y:z. + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 +#HiddenServicePort 22 127.0.0.1:22 + +################ This section is just for relays ##################### +# +## See https://www.torproject.org/docs/tor-doc-relay for details. + +## Required: what port to advertise for incoming Tor connections. +#ORPort 9001 +## If you want to listen on a port other than the one advertised in +## ORPort (e.g. to advertise 443 but bind to 9090), you can do it as +## follows. You'll need to do ipchains or other port forwarding +## yourself to make this work. +#ORPort 443 NoListen +#ORPort 127.0.0.1:9090 NoAdvertise + +## The IP address or full DNS name for incoming connections to your +## relay. Leave commented out and Tor will guess. +#Address noname.example.com + +## If you have multiple network interfaces, you can specify one for +## outgoing traffic to use. +# OutboundBindAddress 10.0.0.5 + +## A handle for your relay, so people don't have to refer to it by key. +#Nickname ididnteditheconfig + +## Define these to limit how much relayed traffic you will allow. Your +## own traffic is still unthrottled. Note that RelayBandwidthRate must +## be at least 20 KB. +## Note that units for these config options are bytes per second, not bits +## per second, and that prefixes are binary prefixes, i.e. 2^10, 2^20, etc. +#RelayBandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps) +#RelayBandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps) + +## Use these to restrict the maximum traffic per day, week, or month. +## Note that this threshold applies separately to sent and received bytes, +## not to their sum: setting "4 GB" may allow up to 8 GB total before +## hibernating. +## +## Set a maximum of 4 gigabytes each way per period. +#AccountingMax 4 GB +## Each period starts daily at midnight (AccountingMax is per day) +#AccountingStart day 00:00 +## Each period starts on the 3rd of the month at 15:00 (AccountingMax +## is per month) +#AccountingStart month 3 15:00 + +## Administrative contact information for this relay or bridge. This line +## can be used to contact you if your relay or bridge is misconfigured or +## something else goes wrong. Note that we archive and publish all +## descriptors containing these lines and that Google indexes them, so +## spammers might also collect them. You may want to obscure the fact that +## it's an email address and/or generate a new address for this purpose. +#ContactInfo Random Person <nobody AT example dot com> +## You might also include your PGP or GPG fingerprint if you have one: +#ContactInfo 0xFFFFFFFF Random Person <nobody AT example dot com> + +## Uncomment this to mirror directory information for others. Please do +## if you have enough bandwidth. +#DirPort 9030 # what port to advertise for directory connections +## If you want to listen on a port other than the one advertised in +## DirPort (e.g. to advertise 80 but bind to 9091), you can do it as +## follows. below too. You'll need to do ipchains or other port +## forwarding yourself to make this work. +#DirPort 80 NoListen +#DirPort 127.0.0.1:9091 NoAdvertise +## Uncomment to return an arbitrary blob of html on your DirPort. Now you +## can explain what Tor is if anybody wonders why your IP address is +## contacting them. See contrib/tor-exit-notice.html in Tor's source +## distribution for a sample. +#DirPortFrontPage @CONFDIR@/tor-exit-notice.html + +## Uncomment this if you run more than one Tor relay, and add the identity +## key fingerprint of each Tor relay you control, even if they're on +## different networks. You declare it here so Tor clients can avoid +## using more than one of your relays in a single circuit. See +## https://www.torproject.org/docs/faq#MultipleRelays +## However, you should never include a bridge's fingerprint here, as it would +## break its concealability and potentionally reveal its IP/TCP address. +#MyFamily $keyid,$keyid,... + +## A comma-separated list of exit policies. They're considered first +## to last, and the first match wins. If you want to _replace_ +## the default exit policy, end this with either a reject *:* or an +## accept *:*. Otherwise, you're _augmenting_ (prepending to) the +## default exit policy. Leave commented to just use the default, which is +## described in the man page or at +## https://www.torproject.org/documentation.html +## +## Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses +## for issues you might encounter if you use the default exit policy. +## +## If certain IPs and ports are blocked externally, e.g. by your firewall, +## you should update your exit policy to reflect this -- otherwise Tor +## users will be told that those destinations are down. +## +## For security, by default Tor rejects connections to private (local) +## networks, including to your public IP address. See the man page entry +## for ExitPolicyRejectPrivate if you want to allow "exit enclaving". +## +#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more +#ExitPolicy accept *:119 # accept nntp as well as default exit policy +#ExitPolicy reject *:* # no exits allowed + +## Bridge relays (or "bridges") are Tor relays that aren't listed in the +## main directory. Since there is no complete public list of them, even an +## ISP that filters connections to all the known Tor relays probably +## won't be able to block all the bridges. Also, websites won't treat you +## differently because they won't know you're running Tor. If you can +## be a real relay, please do; but if not, be a bridge! +#BridgeRelay 1 +## By default, Tor will advertise your bridge to users through various +## mechanisms like https://bridges.torproject.org/. If you want to run +## a private bridge, for example because you'll give out your bridge +## address manually to your friends, uncomment this line: +#PublishServerDescriptor 0 + diff --git a/src/config/torrc.minimal.in-staging b/src/config/torrc.minimal.in-staging new file mode 100644 index 0000000000..bde800fd23 --- /dev/null +++ b/src/config/torrc.minimal.in-staging @@ -0,0 +1,193 @@ +## Configuration file for a typical Tor user +## Last updated 2 September 2014 for Tor 0.2.6.1-alpha. +## (may or may not work for much older or much newer versions of Tor.) +## +## Lines that begin with "## " try to explain what's going on. Lines +## that begin with just "#" are disabled commands: you can enable them +## by removing the "#" symbol. +## +## See 'man tor', or https://www.torproject.org/docs/tor-manual.html, +## for more options you can use in this file. +## +## Tor will look for this file in various places based on your platform: +## https://www.torproject.org/docs/faq#torrc + +## Tor opens a socks proxy on port 9050 by default -- even if you don't +## configure one below. Set "SocksPort 0" if you plan to run Tor only +## as a relay, and not make any local application connections yourself. +#SocksPort 9050 # Default: Bind to localhost:9050 for local connections. +#SocksPort 192.168.0.1:9100 # Bind to this address:port too. + +## Entry policies to allow/deny SOCKS requests based on IP address. +## First entry that matches wins. If no SocksPolicy is set, we accept +## all (and only) requests that reach a SocksPort. Untrusted users who +## can access your SocksPort may be able to learn about the connections +## you make. +#SocksPolicy accept 192.168.0.0/16 +#SocksPolicy reject * + +## Logs go to stdout at level "notice" unless redirected by something +## else, like one of the below lines. You can have as many Log lines as +## you want. +## +## We advise using "notice" in most cases, since anything more verbose +## may provide sensitive information to an attacker who obtains the logs. +## +## Send all messages of level 'notice' or higher to @LOCALSTATEDIR@/log/tor/notices.log +#Log notice file @LOCALSTATEDIR@/log/tor/notices.log +## Send every possible message to @LOCALSTATEDIR@/log/tor/debug.log +#Log debug file @LOCALSTATEDIR@/log/tor/debug.log +## Use the system log instead of Tor's logfiles +#Log notice syslog +## To send all messages to stderr: +#Log debug stderr + +## Uncomment this to start the process in the background... or use +## --runasdaemon 1 on the command line. This is ignored on Windows; +## see the FAQ entry if you want Tor to run as an NT service. +#RunAsDaemon 1 + +## The directory for keeping all the keys/etc. By default, we store +## things in $HOME/.tor on Unix, and in Application Data\tor on Windows. +#DataDirectory @LOCALSTATEDIR@/lib/tor + +## The port on which Tor will listen for local connections from Tor +## controller applications, as documented in control-spec.txt. +#ControlPort 9051 +## If you enable the controlport, be sure to enable one of these +## authentication methods, to prevent attackers from accessing it. +#HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C +#CookieAuthentication 1 + +############### This section is just for location-hidden services ### + +## Once you have configured a hidden service, you can look at the +## contents of the file ".../hidden_service/hostname" for the address +## to tell people. +## +## HiddenServicePort x y:z says to redirect requests on port x to the +## address y:z. + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 +#HiddenServicePort 22 127.0.0.1:22 + +################ This section is just for relays ##################### +# +## See https://www.torproject.org/docs/tor-doc-relay for details. + +## Required: what port to advertise for incoming Tor connections. +#ORPort 9001 +## If you want to listen on a port other than the one advertised in +## ORPort (e.g. to advertise 443 but bind to 9090), you can do it as +## follows. You'll need to do ipchains or other port forwarding +## yourself to make this work. +#ORPort 443 NoListen +#ORPort 127.0.0.1:9090 NoAdvertise + +## The IP address or full DNS name for incoming connections to your +## relay. Leave commented out and Tor will guess. +#Address noname.example.com + +## If you have multiple network interfaces, you can specify one for +## outgoing traffic to use. +# OutboundBindAddress 10.0.0.5 + +## A handle for your relay, so people don't have to refer to it by key. +#Nickname ididnteditheconfig + +## Define these to limit how much relayed traffic you will allow. Your +## own traffic is still unthrottled. Note that RelayBandwidthRate must +## be at least 20 kilobytes per second. +## Note that units for these config options are bytes (per second), not +## bits (per second), and that prefixes are binary prefixes, i.e. 2^10, +## 2^20, etc. +#RelayBandwidthRate 100 KBytes # Throttle traffic to 100KB/s (800Kbps) +#RelayBandwidthBurst 200 KBytes # But allow bursts up to 200KB (1600Kb) + +## Use these to restrict the maximum traffic per day, week, or month. +## Note that this threshold applies separately to sent and received bytes, +## not to their sum: setting "4 GB" may allow up to 8 GB total before +## hibernating. +## +## Set a maximum of 4 gigabytes each way per period. +#AccountingMax 4 GBytes +## Each period starts daily at midnight (AccountingMax is per day) +#AccountingStart day 00:00 +## Each period starts on the 3rd of the month at 15:00 (AccountingMax +## is per month) +#AccountingStart month 3 15:00 + +## Administrative contact information for this relay or bridge. This line +## can be used to contact you if your relay or bridge is misconfigured or +## something else goes wrong. Note that we archive and publish all +## descriptors containing these lines and that Google indexes them, so +## spammers might also collect them. You may want to obscure the fact that +## it's an email address and/or generate a new address for this purpose. +#ContactInfo Random Person <nobody AT example dot com> +## You might also include your PGP or GPG fingerprint if you have one: +#ContactInfo 0xFFFFFFFF Random Person <nobody AT example dot com> + +## Uncomment this to mirror directory information for others. Please do +## if you have enough bandwidth. +#DirPort 9030 # what port to advertise for directory connections +## If you want to listen on a port other than the one advertised in +## DirPort (e.g. to advertise 80 but bind to 9091), you can do it as +## follows. below too. You'll need to do ipchains or other port +## forwarding yourself to make this work. +#DirPort 80 NoListen +#DirPort 127.0.0.1:9091 NoAdvertise +## Uncomment to return an arbitrary blob of html on your DirPort. Now you +## can explain what Tor is if anybody wonders why your IP address is +## contacting them. See contrib/tor-exit-notice.html in Tor's source +## distribution for a sample. +#DirPortFrontPage @CONFDIR@/tor-exit-notice.html + +## Uncomment this if you run more than one Tor relay, and add the identity +## key fingerprint of each Tor relay you control, even if they're on +## different networks. You declare it here so Tor clients can avoid +## using more than one of your relays in a single circuit. See +## https://www.torproject.org/docs/faq#MultipleRelays +## However, you should never include a bridge's fingerprint here, as it would +## break its concealability and potentially reveal its IP/TCP address. +#MyFamily $keyid,$keyid,... + +## A comma-separated list of exit policies. They're considered first +## to last, and the first match wins. If you want to _replace_ +## the default exit policy, end this with either a reject *:* or an +## accept *:*. Otherwise, you're _augmenting_ (prepending to) the +## default exit policy. Leave commented to just use the default, which is +## described in the man page or at +## https://www.torproject.org/documentation.html +## +## Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses +## for issues you might encounter if you use the default exit policy. +## +## If certain IPs and ports are blocked externally, e.g. by your firewall, +## you should update your exit policy to reflect this -- otherwise Tor +## users will be told that those destinations are down. +## +## For security, by default Tor rejects connections to private (local) +## networks, including to your public IP address. See the man page entry +## for ExitPolicyRejectPrivate if you want to allow "exit enclaving". +## +#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more +#ExitPolicy accept *:119 # accept nntp as well as default exit policy +#ExitPolicy reject *:* # no exits allowed + +## Bridge relays (or "bridges") are Tor relays that aren't listed in the +## main directory. Since there is no complete public list of them, even an +## ISP that filters connections to all the known Tor relays probably +## won't be able to block all the bridges. Also, websites won't treat you +## differently because they won't know you're running Tor. If you can +## be a real relay, please do; but if not, be a bridge! +#BridgeRelay 1 +## By default, Tor will advertise your bridge to users through various +## mechanisms like https://bridges.torproject.org/. If you want to run +## a private bridge, for example because you'll give out your bridge +## address manually to your friends, uncomment this line: +#PublishServerDescriptor 0 + diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in index d842fbcaf5..bde800fd23 100644 --- a/src/config/torrc.sample.in +++ b/src/config/torrc.sample.in @@ -1,5 +1,5 @@ ## Configuration file for a typical Tor user -## Last updated 9 October 2013 for Tor 0.2.5.2-alpha. +## Last updated 2 September 2014 for Tor 0.2.6.1-alpha. ## (may or may not work for much older or much newer versions of Tor.) ## ## Lines that begin with "## " try to explain what's going on. Lines @@ -101,11 +101,12 @@ ## Define these to limit how much relayed traffic you will allow. Your ## own traffic is still unthrottled. Note that RelayBandwidthRate must -## be at least 20 KB. -## Note that units for these config options are bytes per second, not bits -## per second, and that prefixes are binary prefixes, i.e. 2^10, 2^20, etc. -#RelayBandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps) -#RelayBandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps) +## be at least 20 kilobytes per second. +## Note that units for these config options are bytes (per second), not +## bits (per second), and that prefixes are binary prefixes, i.e. 2^10, +## 2^20, etc. +#RelayBandwidthRate 100 KBytes # Throttle traffic to 100KB/s (800Kbps) +#RelayBandwidthBurst 200 KBytes # But allow bursts up to 200KB (1600Kb) ## Use these to restrict the maximum traffic per day, week, or month. ## Note that this threshold applies separately to sent and received bytes, @@ -113,7 +114,7 @@ ## hibernating. ## ## Set a maximum of 4 gigabytes each way per period. -#AccountingMax 4 GB +#AccountingMax 4 GBytes ## Each period starts daily at midnight (AccountingMax is per day) #AccountingStart day 00:00 ## Each period starts on the 3rd of the month at 15:00 (AccountingMax @@ -151,7 +152,7 @@ ## using more than one of your relays in a single circuit. See ## https://www.torproject.org/docs/faq#MultipleRelays ## However, you should never include a bridge's fingerprint here, as it would -## break its concealability and potentionally reveal its IP/TCP address. +## break its concealability and potentially reveal its IP/TCP address. #MyFamily $keyid,$keyid,... ## A comma-separated list of exit policies. They're considered first diff --git a/src/ext/OpenBSD_malloc_Linux.c b/src/ext/OpenBSD_malloc_Linux.c index da82729811..855c912310 100644 --- a/src/ext/OpenBSD_malloc_Linux.c +++ b/src/ext/OpenBSD_malloc_Linux.c @@ -58,7 +58,7 @@ #include <limits.h> #include <errno.h> #include <err.h> -/* For SIZE_T_MAX */ +/* For SIZE_MAX */ #include "torint.h" //#include "thread_private.h" @@ -1961,16 +1961,6 @@ realloc(void *ptr, size_t size) return (r); } -#ifndef SIZE_MAX -//#if defined(__i386__)||defined(__arm__)||defined(__powerpc__) -//#define SIZE_MAX 0xffffffff -//#endif -//#if defined(__x86_64__) -//#define SIZE_MAX 0xffffffffffffffff -//#endif -#define SIZE_MAX SIZE_T_MAX -#endif - void * calloc(size_t num, size_t size) { diff --git a/src/ext/README b/src/ext/README index 5d5a6e1518..616716e099 100644 --- a/src/ext/README +++ b/src/ext/README @@ -49,3 +49,15 @@ siphash.h Marek Majkowski's implementation of siphash 2-4, a secure keyed hash algorithm to avoid collision-based DoS attacks against hash tables. + +trunnel/*.[ch] + + Headers and runtime code for Trunnel, a system for generating + code to encode and decode binary formats. + +ed25519/ref10/* + + Daniel Bernsten's portable ref10 implementation of ed25519. + Public domain. + + diff --git a/src/ext/ed25519/ref10/Makefile b/src/ext/ed25519/ref10/Makefile new file mode 100644 index 0000000000..9b0ba7ad45 --- /dev/null +++ b/src/ext/ed25519/ref10/Makefile @@ -0,0 +1,41 @@ +all: d.h d2.h sqrtm1.h base.h base2.h \ +ge_add.h ge_sub.h \ +ge_madd.h ge_msub.h \ +ge_p2_dbl.h \ +pow225521.h pow22523.h + +d.h: d.py + python d.py > d.h + +d2.h: d2.py + python d2.py > d2.h + +sqrtm1.h: sqrtm1.py + python sqrtm1.py > sqrtm1.h + +base.h: base.py + python base.py > base.h + +base2.h: base2.py + python base2.py > base2.h + +ge_add.h: ge_add.q q2h.sh + ./q2h.sh < ge_add.q > ge_add.h + +ge_sub.h: ge_sub.q q2h.sh + ./q2h.sh < ge_sub.q > ge_sub.h + +ge_madd.h: ge_madd.q q2h.sh + ./q2h.sh < ge_madd.q > ge_madd.h + +ge_msub.h: ge_msub.q q2h.sh + ./q2h.sh < ge_msub.q > ge_msub.h + +ge_p2_dbl.h: ge_p2_dbl.q q2h.sh + ./q2h.sh < ge_p2_dbl.q > ge_p2_dbl.h + +pow22523.h: pow22523.q q2h.sh + ./q2h.sh < pow22523.q > pow22523.h + +pow225521.h: pow225521.q q2h.sh + ./q2h.sh < pow225521.q > pow225521.h diff --git a/src/ext/ed25519/ref10/README.tor b/src/ext/ed25519/ref10/README.tor new file mode 100644 index 0000000000..38ed97ba05 --- /dev/null +++ b/src/ext/ed25519/ref10/README.tor @@ -0,0 +1,23 @@ + +We've made the following changes to the stock ed25519_ref10 from +supercop-20140622: + + * We added the necessary glue to provide integers of fixed bit + sizes, SHA512, and to compile without warnings everywhere we need + to build. + + * Secret keys are stored in expanded format. There are functions + to expand them from the 32-byte seed. + + * Signatures are made and processed detached from the messages that + they sign. (In other words, we support "make signature" and + "check signature", not "create signed message" and "check and + unpack signed message".) + + * There's an implementation of 'convert a curve25519 key to an + ed25519 key' so we can do cross-certification with curve25519 keys. + (keyconv.c) + + * There's an implementation of multiplicative key blinding so we + can use it for next-gen hidden srevice descriptors. (blinding.c) + diff --git a/src/ext/ed25519/ref10/api.h b/src/ext/ed25519/ref10/api.h new file mode 100644 index 0000000000..d88dae0c32 --- /dev/null +++ b/src/ext/ed25519/ref10/api.h @@ -0,0 +1,4 @@ +#define CRYPTO_SECRETKEYBYTES 64 +#define CRYPTO_PUBLICKEYBYTES 32 +#define CRYPTO_BYTES 64 +#define CRYPTO_DETERMINISTIC 1 diff --git a/src/ext/ed25519/ref10/base.h b/src/ext/ed25519/ref10/base.h new file mode 100644 index 0000000000..573bd8a05c --- /dev/null +++ b/src/ext/ed25519/ref10/base.h @@ -0,0 +1,1344 @@ +{ + { + { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, + { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, + { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, + }, + { + { -12815894,-12976347,-21581243,11784320,-25355658,-2750717,-11717903,-3814571,-358445,-10211303 }, + { -21703237,6903825,27185491,6451973,-29577724,-9554005,-15616551,11189268,-26829678,-5319081 }, + { 26966642,11152617,32442495,15396054,14353839,-12752335,-3128826,-9541118,-15472047,-4166697 }, + }, + { + { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, + { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, + { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, + }, + { + { -17036878,13921892,10945806,-6033431,27105052,-16084379,-28926210,15006023,3284568,-6276540 }, + { 23599295,-8306047,-11193664,-7687416,13236774,10506355,7464579,9656445,13059162,10374397 }, + { 7798556,16710257,3033922,2874086,28997861,2835604,32406664,-3839045,-641708,-101325 }, + }, + { + { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, + { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, + { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, + }, + { + { -15371964,-12862754,32573250,4720197,-26436522,5875511,-19188627,-15224819,-9818940,-12085777 }, + { -8549212,109983,15149363,2178705,22900618,4543417,3044240,-15689887,1762328,14866737 }, + { -18199695,-15951423,-10473290,1707278,-17185920,3916101,-28236412,3959421,27914454,4383652 }, + }, + { + { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, + { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, + { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, + }, + { + { 14499471,-2729599,-33191113,-4254652,28494862,14271267,30290735,10876454,-33154098,2381726 }, + { -7195431,-2655363,-14730155,462251,-27724326,3941372,-6236617,3696005,-32300832,15351955 }, + { 27431194,8222322,16448760,-3907995,-18707002,11938355,-32961401,-2970515,29551813,10109425 }, + }, +}, +{ + { + { -13657040,-13155431,-31283750,11777098,21447386,6519384,-2378284,-1627556,10092783,-4764171 }, + { 27939166,14210322,4677035,16277044,-22964462,-12398139,-32508754,12005538,-17810127,12803510 }, + { 17228999,-15661624,-1233527,300140,-1224870,-11714777,30364213,-9038194,18016357,4397660 }, + }, + { + { -10958843,-7690207,4776341,-14954238,27850028,-15602212,-26619106,14544525,-17477504,982639 }, + { 29253598,15796703,-2863982,-9908884,10057023,3163536,7332899,-4120128,-21047696,9934963 }, + { 5793303,16271923,-24131614,-10116404,29188560,1206517,-14747930,4559895,-30123922,-10897950 }, + }, + { + { -27643952,-11493006,16282657,-11036493,28414021,-15012264,24191034,4541697,-13338309,5500568 }, + { 12650548,-1497113,9052871,11355358,-17680037,-8400164,-17430592,12264343,10874051,13524335 }, + { 25556948,-3045990,714651,2510400,23394682,-10415330,33119038,5080568,-22528059,5376628 }, + }, + { + { -26088264,-4011052,-17013699,-3537628,-6726793,1920897,-22321305,-9447443,4535768,1569007 }, + { -2255422,14606630,-21692440,-8039818,28430649,8775819,-30494562,3044290,31848280,12543772 }, + { -22028579,2943893,-31857513,6777306,13784462,-4292203,-27377195,-2062731,7718482,14474653 }, + }, + { + { 2385315,2454213,-22631320,46603,-4437935,-15680415,656965,-7236665,24316168,-5253567 }, + { 13741529,10911568,-33233417,-8603737,-20177830,-1033297,33040651,-13424532,-20729456,8321686 }, + { 21060490,-2212744,15712757,-4336099,1639040,10656336,23845965,-11874838,-9984458,608372 }, + }, + { + { -13672732,-15087586,-10889693,-7557059,-6036909,11305547,1123968,-6780577,27229399,23887 }, + { -23244140,-294205,-11744728,14712571,-29465699,-2029617,12797024,-6440308,-1633405,16678954 }, + { -29500620,4770662,-16054387,14001338,7830047,9564805,-1508144,-4795045,-17169265,4904953 }, + }, + { + { 24059557,14617003,19037157,-15039908,19766093,-14906429,5169211,16191880,2128236,-4326833 }, + { -16981152,4124966,-8540610,-10653797,30336522,-14105247,-29806336,916033,-6882542,-2986532 }, + { -22630907,12419372,-7134229,-7473371,-16478904,16739175,285431,2763829,15736322,4143876 }, + }, + { + { 2379352,11839345,-4110402,-5988665,11274298,794957,212801,-14594663,23527084,-16458268 }, + { 33431127,-11130478,-17838966,-15626900,8909499,8376530,-32625340,4087881,-15188911,-14416214 }, + { 1767683,7197987,-13205226,-2022635,-13091350,448826,5799055,4357868,-4774191,-16323038 }, + }, +}, +{ + { + { 6721966,13833823,-23523388,-1551314,26354293,-11863321,23365147,-3949732,7390890,2759800 }, + { 4409041,2052381,23373853,10530217,7676779,-12885954,21302353,-4264057,1244380,-12919645 }, + { -4421239,7169619,4982368,-2957590,30256825,-2777540,14086413,9208236,15886429,16489664 }, + }, + { + { 1996075,10375649,14346367,13311202,-6874135,-16438411,-13693198,398369,-30606455,-712933 }, + { -25307465,9795880,-2777414,14878809,-33531835,14780363,13348553,12076947,-30836462,5113182 }, + { -17770784,11797796,31950843,13929123,-25888302,12288344,-30341101,-7336386,13847711,5387222 }, + }, + { + { -18582163,-3416217,17824843,-2340966,22744343,-10442611,8763061,3617786,-19600662,10370991 }, + { 20246567,-14369378,22358229,-543712,18507283,-10413996,14554437,-8746092,32232924,16763880 }, + { 9648505,10094563,26416693,14745928,-30374318,-6472621,11094161,15689506,3140038,-16510092 }, + }, + { + { -16160072,5472695,31895588,4744994,8823515,10365685,-27224800,9448613,-28774454,366295 }, + { 19153450,11523972,-11096490,-6503142,-24647631,5420647,28344573,8041113,719605,11671788 }, + { 8678025,2694440,-6808014,2517372,4964326,11152271,-15432916,-15266516,27000813,-10195553 }, + }, + { + { -15157904,7134312,8639287,-2814877,-7235688,10421742,564065,5336097,6750977,-14521026 }, + { 11836410,-3979488,26297894,16080799,23455045,15735944,1695823,-8819122,8169720,16220347 }, + { -18115838,8653647,17578566,-6092619,-8025777,-16012763,-11144307,-2627664,-5990708,-14166033 }, + }, + { + { -23308498,-10968312,15213228,-10081214,-30853605,-11050004,27884329,2847284,2655861,1738395 }, + { -27537433,-14253021,-25336301,-8002780,-9370762,8129821,21651608,-3239336,-19087449,-11005278 }, + { 1533110,3437855,23735889,459276,29970501,11335377,26030092,5821408,10478196,8544890 }, + }, + { + { 32173121,-16129311,24896207,3921497,22579056,-3410854,19270449,12217473,17789017,-3395995 }, + { -30552961,-2228401,-15578829,-10147201,13243889,517024,15479401,-3853233,30460520,1052596 }, + { -11614875,13323618,32618793,8175907,-15230173,12596687,27491595,-4612359,3179268,-9478891 }, + }, + { + { 31947069,-14366651,-4640583,-15339921,-15125977,-6039709,-14756777,-16411740,19072640,-9511060 }, + { 11685058,11822410,3158003,-13952594,33402194,-4165066,5977896,-5215017,473099,5040608 }, + { -20290863,8198642,-27410132,11602123,1290375,-2799760,28326862,1721092,-19558642,-3131606 }, + }, +}, +{ + { + { 7881532,10687937,7578723,7738378,-18951012,-2553952,21820786,8076149,-27868496,11538389 }, + { -19935666,3899861,18283497,-6801568,-15728660,-11249211,8754525,7446702,-5676054,5797016 }, + { -11295600,-3793569,-15782110,-7964573,12708869,-8456199,2014099,-9050574,-2369172,-5877341 }, + }, + { + { -22472376,-11568741,-27682020,1146375,18956691,16640559,1192730,-3714199,15123619,10811505 }, + { 14352098,-3419715,-18942044,10822655,32750596,4699007,-70363,15776356,-28886779,-11974553 }, + { -28241164,-8072475,-4978962,-5315317,29416931,1847569,-20654173,-16484855,4714547,-9600655 }, + }, + { + { 15200332,8368572,19679101,15970074,-31872674,1959451,24611599,-4543832,-11745876,12340220 }, + { 12876937,-10480056,33134381,6590940,-6307776,14872440,9613953,8241152,15370987,9608631 }, + { -4143277,-12014408,8446281,-391603,4407738,13629032,-7724868,15866074,-28210621,-8814099 }, + }, + { + { 26660628,-15677655,8393734,358047,-7401291,992988,-23904233,858697,20571223,8420556 }, + { 14620715,13067227,-15447274,8264467,14106269,15080814,33531827,12516406,-21574435,-12476749 }, + { 236881,10476226,57258,-14677024,6472998,2466984,17258519,7256740,8791136,15069930 }, + }, + { + { 1276410,-9371918,22949635,-16322807,-23493039,-5702186,14711875,4874229,-30663140,-2331391 }, + { 5855666,4990204,-13711848,7294284,-7804282,1924647,-1423175,-7912378,-33069337,9234253 }, + { 20590503,-9018988,31529744,-7352666,-2706834,10650548,31559055,-11609587,18979186,13396066 }, + }, + { + { 24474287,4968103,22267082,4407354,24063882,-8325180,-18816887,13594782,33514650,7021958 }, + { -11566906,-6565505,-21365085,15928892,-26158305,4315421,-25948728,-3916677,-21480480,12868082 }, + { -28635013,13504661,19988037,-2132761,21078225,6443208,-21446107,2244500,-12455797,-8089383 }, + }, + { + { -30595528,13793479,-5852820,319136,-25723172,-6263899,33086546,8957937,-15233648,5540521 }, + { -11630176,-11503902,-8119500,-7643073,2620056,1022908,-23710744,-1568984,-16128528,-14962807 }, + { 23152971,775386,27395463,14006635,-9701118,4649512,1689819,892185,-11513277,-15205948 }, + }, + { + { 9770129,9586738,26496094,4324120,1556511,-3550024,27453819,4763127,-19179614,5867134 }, + { -32765025,1927590,31726409,-4753295,23962434,-16019500,27846559,5931263,-29749703,-16108455 }, + { 27461885,-2977536,22380810,1815854,-23033753,-3031938,7283490,-15148073,-19526700,7734629 }, + }, +}, +{ + { + { -8010264,-9590817,-11120403,6196038,29344158,-13430885,7585295,-3176626,18549497,15302069 }, + { -32658337,-6171222,-7672793,-11051681,6258878,13504381,10458790,-6418461,-8872242,8424746 }, + { 24687205,8613276,-30667046,-3233545,1863892,-1830544,19206234,7134917,-11284482,-828919 }, + }, + { + { 11334899,-9218022,8025293,12707519,17523892,-10476071,10243738,-14685461,-5066034,16498837 }, + { 8911542,6887158,-9584260,-6958590,11145641,-9543680,17303925,-14124238,6536641,10543906 }, + { -28946384,15479763,-17466835,568876,-1497683,11223454,-2669190,-16625574,-27235709,8876771 }, + }, + { + { -25742899,-12566864,-15649966,-846607,-33026686,-796288,-33481822,15824474,-604426,-9039817 }, + { 10330056,70051,7957388,-9002667,9764902,15609756,27698697,-4890037,1657394,3084098 }, + { 10477963,-7470260,12119566,-13250805,29016247,-5365589,31280319,14396151,-30233575,15272409 }, + }, + { + { -12288309,3169463,28813183,16658753,25116432,-5630466,-25173957,-12636138,-25014757,1950504 }, + { -26180358,9489187,11053416,-14746161,-31053720,5825630,-8384306,-8767532,15341279,8373727 }, + { 28685821,7759505,-14378516,-12002860,-31971820,4079242,298136,-10232602,-2878207,15190420 }, + }, + { + { -32932876,13806336,-14337485,-15794431,-24004620,10940928,8669718,2742393,-26033313,-6875003 }, + { -1580388,-11729417,-25979658,-11445023,-17411874,-10912854,9291594,-16247779,-12154742,6048605 }, + { -30305315,14843444,1539301,11864366,20201677,1900163,13934231,5128323,11213262,9168384 }, + }, + { + { -26280513,11007847,19408960,-940758,-18592965,-4328580,-5088060,-11105150,20470157,-16398701 }, + { -23136053,9282192,14855179,-15390078,-7362815,-14408560,-22783952,14461608,14042978,5230683 }, + { 29969567,-2741594,-16711867,-8552442,9175486,-2468974,21556951,3506042,-5933891,-12449708 }, + }, + { + { -3144746,8744661,19704003,4581278,-20430686,6830683,-21284170,8971513,-28539189,15326563 }, + { -19464629,10110288,-17262528,-3503892,-23500387,1355669,-15523050,15300988,-20514118,9168260 }, + { -5353335,4488613,-23803248,16314347,7780487,-15638939,-28948358,9601605,33087103,-9011387 }, + }, + { + { -19443170,-15512900,-20797467,-12445323,-29824447,10229461,-27444329,-15000531,-5996870,15664672 }, + { 23294591,-16632613,-22650781,-8470978,27844204,11461195,13099750,-2460356,18151676,13417686 }, + { -24722913,-4176517,-31150679,5988919,-26858785,6685065,1661597,-12551441,15271676,-15452665 }, + }, +}, +{ + { + { 11433042,-13228665,8239631,-5279517,-1985436,-725718,-18698764,2167544,-6921301,-13440182 }, + { -31436171,15575146,30436815,12192228,-22463353,9395379,-9917708,-8638997,12215110,12028277 }, + { 14098400,6555944,23007258,5757252,-15427832,-12950502,30123440,4617780,-16900089,-655628 }, + }, + { + { -4026201,-15240835,11893168,13718664,-14809462,1847385,-15819999,10154009,23973261,-12684474 }, + { -26531820,-3695990,-1908898,2534301,-31870557,-16550355,18341390,-11419951,32013174,-10103539 }, + { -25479301,10876443,-11771086,-14625140,-12369567,1838104,21911214,6354752,4425632,-837822 }, + }, + { + { -10433389,-14612966,22229858,-3091047,-13191166,776729,-17415375,-12020462,4725005,14044970 }, + { 19268650,-7304421,1555349,8692754,-21474059,-9910664,6347390,-1411784,-19522291,-16109756 }, + { -24864089,12986008,-10898878,-5558584,-11312371,-148526,19541418,8180106,9282262,10282508 }, + }, + { + { -26205082,4428547,-8661196,-13194263,4098402,-14165257,15522535,8372215,5542595,-10702683 }, + { -10562541,14895633,26814552,-16673850,-17480754,-2489360,-2781891,6993761,-18093885,10114655 }, + { -20107055,-929418,31422704,10427861,-7110749,6150669,-29091755,-11529146,25953725,-106158 }, + }, + { + { -4234397,-8039292,-9119125,3046000,2101609,-12607294,19390020,6094296,-3315279,12831125 }, + { -15998678,7578152,5310217,14408357,-33548620,-224739,31575954,6326196,7381791,-2421839 }, + { -20902779,3296811,24736065,-16328389,18374254,7318640,6295303,8082724,-15362489,12339664 }, + }, + { + { 27724736,2291157,6088201,-14184798,1792727,5857634,13848414,15768922,25091167,14856294 }, + { -18866652,8331043,24373479,8541013,-701998,-9269457,12927300,-12695493,-22182473,-9012899 }, + { -11423429,-5421590,11632845,3405020,30536730,-11674039,-27260765,13866390,30146206,9142070 }, + }, + { + { 3924129,-15307516,-13817122,-10054960,12291820,-668366,-27702774,9326384,-8237858,4171294 }, + { -15921940,16037937,6713787,16606682,-21612135,2790944,26396185,3731949,345228,-5462949 }, + { -21327538,13448259,25284571,1143661,20614966,-8849387,2031539,-12391231,-16253183,-13582083 }, + }, + { + { 31016211,-16722429,26371392,-14451233,-5027349,14854137,17477601,3842657,28012650,-16405420 }, + { -5075835,9368966,-8562079,-4600902,-15249953,6970560,-9189873,16292057,-8867157,3507940 }, + { 29439664,3537914,23333589,6997794,-17555561,-11018068,-15209202,-15051267,-9164929,6580396 }, + }, +}, +{ + { + { -12185861,-7679788,16438269,10826160,-8696817,-6235611,17860444,-9273846,-2095802,9304567 }, + { 20714564,-4336911,29088195,7406487,11426967,-5095705,14792667,-14608617,5289421,-477127 }, + { -16665533,-10650790,-6160345,-13305760,9192020,-1802462,17271490,12349094,26939669,-3752294 }, + }, + { + { -12889898,9373458,31595848,16374215,21471720,13221525,-27283495,-12348559,-3698806,117887 }, + { 22263325,-6560050,3984570,-11174646,-15114008,-566785,28311253,5358056,-23319780,541964 }, + { 16259219,3261970,2309254,-15534474,-16885711,-4581916,24134070,-16705829,-13337066,-13552195 }, + }, + { + { 9378160,-13140186,-22845982,-12745264,28198281,-7244098,-2399684,-717351,690426,14876244 }, + { 24977353,-314384,-8223969,-13465086,28432343,-1176353,-13068804,-12297348,-22380984,6618999 }, + { -1538174,11685646,12944378,13682314,-24389511,-14413193,8044829,-13817328,32239829,-5652762 }, + }, + { + { -18603066,4762990,-926250,8885304,-28412480,-3187315,9781647,-10350059,32779359,5095274 }, + { -33008130,-5214506,-32264887,-3685216,9460461,-9327423,-24601656,14506724,21639561,-2630236 }, + { -16400943,-13112215,25239338,15531969,3987758,-4499318,-1289502,-6863535,17874574,558605 }, + }, + { + { -13600129,10240081,9171883,16131053,-20869254,9599700,33499487,5080151,2085892,5119761 }, + { -22205145,-2519528,-16381601,414691,-25019550,2170430,30634760,-8363614,-31999993,-5759884 }, + { -6845704,15791202,8550074,-1312654,29928809,-12092256,27534430,-7192145,-22351378,12961482 }, + }, + { + { -24492060,-9570771,10368194,11582341,-23397293,-2245287,16533930,8206996,-30194652,-5159638 }, + { -11121496,-3382234,2307366,6362031,-135455,8868177,-16835630,7031275,7589640,8945490 }, + { -32152748,8917967,6661220,-11677616,-1192060,-15793393,7251489,-11182180,24099109,-14456170 }, + }, + { + { 5019558,-7907470,4244127,-14714356,-26933272,6453165,-19118182,-13289025,-6231896,-10280736 }, + { 10853594,10721687,26480089,5861829,-22995819,1972175,-1866647,-10557898,-3363451,-6441124 }, + { -17002408,5906790,221599,-6563147,7828208,-13248918,24362661,-2008168,-13866408,7421392 }, + }, + { + { 8139927,-6546497,32257646,-5890546,30375719,1886181,-21175108,15441252,28826358,-4123029 }, + { 6267086,9695052,7709135,-16603597,-32869068,-1886135,14795160,-7840124,13746021,-1742048 }, + { 28584902,7787108,-6732942,-15050729,22846041,-7571236,-3181936,-363524,4771362,-8419958 }, + }, +}, +{ + { + { 24949256,6376279,-27466481,-8174608,-18646154,-9930606,33543569,-12141695,3569627,11342593 }, + { 26514989,4740088,27912651,3697550,19331575,-11472339,6809886,4608608,7325975,-14801071 }, + { -11618399,-14554430,-24321212,7655128,-1369274,5214312,-27400540,10258390,-17646694,-8186692 }, + }, + { + { 11431204,15823007,26570245,14329124,18029990,4796082,-31446179,15580664,9280358,-3973687 }, + { -160783,-10326257,-22855316,-4304997,-20861367,-13621002,-32810901,-11181622,-15545091,4387441 }, + { -20799378,12194512,3937617,-5805892,-27154820,9340370,-24513992,8548137,20617071,-7482001 }, + }, + { + { -938825,-3930586,-8714311,16124718,24603125,-6225393,-13775352,-11875822,24345683,10325460 }, + { -19855277,-1568885,-22202708,8714034,14007766,6928528,16318175,-1010689,4766743,3552007 }, + { -21751364,-16730916,1351763,-803421,-4009670,3950935,3217514,14481909,10988822,-3994762 }, + }, + { + { 15564307,-14311570,3101243,5684148,30446780,-8051356,12677127,-6505343,-8295852,13296005 }, + { -9442290,6624296,-30298964,-11913677,-4670981,-2057379,31521204,9614054,-30000824,12074674 }, + { 4771191,-135239,14290749,-13089852,27992298,14998318,-1413936,-1556716,29832613,-16391035 }, + }, + { + { 7064884,-7541174,-19161962,-5067537,-18891269,-2912736,25825242,5293297,-27122660,13101590 }, + { -2298563,2439670,-7466610,1719965,-27267541,-16328445,32512469,-5317593,-30356070,-4190957 }, + { -30006540,10162316,-33180176,3981723,-16482138,-13070044,14413974,9515896,19568978,9628812 }, + }, + { + { 33053803,199357,15894591,1583059,27380243,-4580435,-17838894,-6106839,-6291786,3437740 }, + { -18978877,3884493,19469877,12726490,15913552,13614290,-22961733,70104,7463304,4176122 }, + { -27124001,10659917,11482427,-16070381,12771467,-6635117,-32719404,-5322751,24216882,5944158 }, + }, + { + { 8894125,7450974,-2664149,-9765752,-28080517,-12389115,19345746,14680796,11632993,5847885 }, + { 26942781,-2315317,9129564,-4906607,26024105,11769399,-11518837,6367194,-9727230,4782140 }, + { 19916461,-4828410,-22910704,-11414391,25606324,-5972441,33253853,8220911,6358847,-1873857 }, + }, + { + { 801428,-2081702,16569428,11065167,29875704,96627,7908388,-4480480,-13538503,1387155 }, + { 19646058,5720633,-11416706,12814209,11607948,12749789,14147075,15156355,-21866831,11835260 }, + { 19299512,1155910,28703737,14890794,2925026,7269399,26121523,15467869,-26560550,5052483 }, + }, +}, +{ + { + { -3017432,10058206,1980837,3964243,22160966,12322533,-6431123,-12618185,12228557,-7003677 }, + { 32944382,14922211,-22844894,5188528,21913450,-8719943,4001465,13238564,-6114803,8653815 }, + { 22865569,-4652735,27603668,-12545395,14348958,8234005,24808405,5719875,28483275,2841751 }, + }, + { + { -16420968,-1113305,-327719,-12107856,21886282,-15552774,-1887966,-315658,19932058,-12739203 }, + { -11656086,10087521,-8864888,-5536143,-19278573,-3055912,3999228,13239134,-4777469,-13910208 }, + { 1382174,-11694719,17266790,9194690,-13324356,9720081,20403944,11284705,-14013818,3093230 }, + }, + { + { 16650921,-11037932,-1064178,1570629,-8329746,7352753,-302424,16271225,-24049421,-6691850 }, + { -21911077,-5927941,-4611316,-5560156,-31744103,-10785293,24123614,15193618,-21652117,-16739389 }, + { -9935934,-4289447,-25279823,4372842,2087473,10399484,31870908,14690798,17361620,11864968 }, + }, + { + { -11307610,6210372,13206574,5806320,-29017692,-13967200,-12331205,-7486601,-25578460,-16240689 }, + { 14668462,-12270235,26039039,15305210,25515617,4542480,10453892,6577524,9145645,-6443880 }, + { 5974874,3053895,-9433049,-10385191,-31865124,3225009,-7972642,3936128,-5652273,-3050304 }, + }, + { + { 30625386,-4729400,-25555961,-12792866,-20484575,7695099,17097188,-16303496,-27999779,1803632 }, + { -3553091,9865099,-5228566,4272701,-5673832,-16689700,14911344,12196514,-21405489,7047412 }, + { 20093277,9920966,-11138194,-5343857,13161587,12044805,-32856851,4124601,-32343828,-10257566 }, + }, + { + { -20788824,14084654,-13531713,7842147,19119038,-13822605,4752377,-8714640,-21679658,2288038 }, + { -26819236,-3283715,29965059,3039786,-14473765,2540457,29457502,14625692,-24819617,12570232 }, + { -1063558,-11551823,16920318,12494842,1278292,-5869109,-21159943,-3498680,-11974704,4724943 }, + }, + { + { 17960970,-11775534,-4140968,-9702530,-8876562,-1410617,-12907383,-8659932,-29576300,1903856 }, + { 23134274,-14279132,-10681997,-1611936,20684485,15770816,-12989750,3190296,26955097,14109738 }, + { 15308788,5320727,-30113809,-14318877,22902008,7767164,29425325,-11277562,31960942,11934971 }, + }, + { + { -27395711,8435796,4109644,12222639,-24627868,14818669,20638173,4875028,10491392,1379718 }, + { -13159415,9197841,3875503,-8936108,-1383712,-5879801,33518459,16176658,21432314,12180697 }, + { -11787308,11500838,13787581,-13832590,-22430679,10140205,1465425,12689540,-10301319,-13872883 }, + }, +}, +{ + { + { 5414091,-15386041,-21007664,9643570,12834970,1186149,-2622916,-1342231,26128231,6032912 }, + { -26337395,-13766162,32496025,-13653919,17847801,-12669156,3604025,8316894,-25875034,-10437358 }, + { 3296484,6223048,24680646,-12246460,-23052020,5903205,-8862297,-4639164,12376617,3188849 }, + }, + { + { 29190488,-14659046,27549113,-1183516,3520066,-10697301,32049515,-7309113,-16109234,-9852307 }, + { -14744486,-9309156,735818,-598978,-20407687,-5057904,25246078,-15795669,18640741,-960977 }, + { -6928835,-16430795,10361374,5642961,4910474,12345252,-31638386,-494430,10530747,1053335 }, + }, + { + { -29265967,-14186805,-13538216,-12117373,-19457059,-10655384,-31462369,-2948985,24018831,15026644 }, + { -22592535,-3145277,-2289276,5953843,-13440189,9425631,25310643,13003497,-2314791,-15145616 }, + { -27419985,-603321,-8043984,-1669117,-26092265,13987819,-27297622,187899,-23166419,-2531735 }, + }, + { + { -21744398,-13810475,1844840,5021428,-10434399,-15911473,9716667,16266922,-5070217,726099 }, + { 29370922,-6053998,7334071,-15342259,9385287,2247707,-13661962,-4839461,30007388,-15823341 }, + { -936379,16086691,23751945,-543318,-1167538,-5189036,9137109,730663,9835848,4555336 }, + }, + { + { -23376435,1410446,-22253753,-12899614,30867635,15826977,17693930,544696,-11985298,12422646 }, + { 31117226,-12215734,-13502838,6561947,-9876867,-12757670,-5118685,-4096706,29120153,13924425 }, + { -17400879,-14233209,19675799,-2734756,-11006962,-5858820,-9383939,-11317700,7240931,-237388 }, + }, + { + { -31361739,-11346780,-15007447,-5856218,-22453340,-12152771,1222336,4389483,3293637,-15551743 }, + { -16684801,-14444245,11038544,11054958,-13801175,-3338533,-24319580,7733547,12796905,-6335822 }, + { -8759414,-10817836,-25418864,10783769,-30615557,-9746811,-28253339,3647836,3222231,-11160462 }, + }, + { + { 18606113,1693100,-25448386,-15170272,4112353,10045021,23603893,-2048234,-7550776,2484985 }, + { 9255317,-3131197,-12156162,-1004256,13098013,-9214866,16377220,-2102812,-19802075,-3034702 }, + { -22729289,7496160,-5742199,11329249,19991973,-3347502,-31718148,9936966,-30097688,-10618797 }, + }, + { + { 21878590,-5001297,4338336,13643897,-3036865,13160960,19708896,5415497,-7360503,-4109293 }, + { 27736861,10103576,12500508,8502413,-3413016,-9633558,10436918,-1550276,-23659143,-8132100 }, + { 19492550,-12104365,-29681976,-852630,-3208171,12403437,30066266,8367329,13243957,8709688 }, + }, +}, +{ + { + { 12015105,2801261,28198131,10151021,24818120,-4743133,-11194191,-5645734,5150968,7274186 }, + { 2831366,-12492146,1478975,6122054,23825128,-12733586,31097299,6083058,31021603,-9793610 }, + { -2529932,-2229646,445613,10720828,-13849527,-11505937,-23507731,16354465,15067285,-14147707 }, + }, + { + { 7840942,14037873,-33364863,15934016,-728213,-3642706,21403988,1057586,-19379462,-12403220 }, + { 915865,-16469274,15608285,-8789130,-24357026,6060030,-17371319,8410997,-7220461,16527025 }, + { 32922597,-556987,20336074,-16184568,10903705,-5384487,16957574,52992,23834301,6588044 }, + }, + { + { 32752030,11232950,3381995,-8714866,22652988,-10744103,17159699,16689107,-20314580,-1305992 }, + { -4689649,9166776,-25710296,-10847306,11576752,12733943,7924251,-2752281,1976123,-7249027 }, + { 21251222,16309901,-2983015,-6783122,30810597,12967303,156041,-3371252,12331345,-8237197 }, + }, + { + { 8651614,-4477032,-16085636,-4996994,13002507,2950805,29054427,-5106970,10008136,-4667901 }, + { 31486080,15114593,-14261250,12951354,14369431,-7387845,16347321,-13662089,8684155,-10532952 }, + { 19443825,11385320,24468943,-9659068,-23919258,2187569,-26263207,-6086921,31316348,14219878 }, + }, + { + { -28594490,1193785,32245219,11392485,31092169,15722801,27146014,6992409,29126555,9207390 }, + { 32382935,1110093,18477781,11028262,-27411763,-7548111,-4980517,10843782,-7957600,-14435730 }, + { 2814918,7836403,27519878,-7868156,-20894015,-11553689,-21494559,8550130,28346258,1994730 }, + }, + { + { -19578299,8085545,-14000519,-3948622,2785838,-16231307,-19516951,7174894,22628102,8115180 }, + { -30405132,955511,-11133838,-15078069,-32447087,-13278079,-25651578,3317160,-9943017,930272 }, + { -15303681,-6833769,28856490,1357446,23421993,1057177,24091212,-1388970,-22765376,-10650715 }, + }, + { + { -22751231,-5303997,-12907607,-12768866,-15811511,-7797053,-14839018,-16554220,-1867018,8398970 }, + { -31969310,2106403,-4736360,1362501,12813763,16200670,22981545,-6291273,18009408,-15772772 }, + { -17220923,-9545221,-27784654,14166835,29815394,7444469,29551787,-3727419,19288549,1325865 }, + }, + { + { 15100157,-15835752,-23923978,-1005098,-26450192,15509408,12376730,-3479146,33166107,-8042750 }, + { 20909231,13023121,-9209752,16251778,-5778415,-8094914,12412151,10018715,2213263,-13878373 }, + { 32529814,-11074689,30361439,-16689753,-9135940,1513226,22922121,6382134,-5766928,8371348 }, + }, +}, +{ + { + { 9923462,11271500,12616794,3544722,-29998368,-1721626,12891687,-8193132,-26442943,10486144 }, + { -22597207,-7012665,8587003,-8257861,4084309,-12970062,361726,2610596,-23921530,-11455195 }, + { 5408411,-1136691,-4969122,10561668,24145918,14240566,31319731,-4235541,19985175,-3436086 }, + }, + { + { -13994457,16616821,14549246,3341099,32155958,13648976,-17577068,8849297,65030,8370684 }, + { -8320926,-12049626,31204563,5839400,-20627288,-1057277,-19442942,6922164,12743482,-9800518 }, + { -2361371,12678785,28815050,4759974,-23893047,4884717,23783145,11038569,18800704,255233 }, + }, + { + { -5269658,-1773886,13957886,7990715,23132995,728773,13393847,9066957,19258688,-14753793 }, + { -2936654,-10827535,-10432089,14516793,-3640786,4372541,-31934921,2209390,-1524053,2055794 }, + { 580882,16705327,5468415,-2683018,-30926419,-14696000,-7203346,-8994389,-30021019,7394435 }, + }, + { + { 23838809,1822728,-15738443,15242727,8318092,-3733104,-21672180,-3492205,-4821741,14799921 }, + { 13345610,9759151,3371034,-16137791,16353039,8577942,31129804,13496856,-9056018,7402518 }, + { 2286874,-4435931,-20042458,-2008336,-13696227,5038122,11006906,-15760352,8205061,1607563 }, + }, + { + { 14414086,-8002132,3331830,-3208217,22249151,-5594188,18364661,-2906958,30019587,-9029278 }, + { -27688051,1585953,-10775053,931069,-29120221,-11002319,-14410829,12029093,9944378,8024 }, + { 4368715,-3709630,29874200,-15022983,-20230386,-11410704,-16114594,-999085,-8142388,5640030 }, + }, + { + { 10299610,13746483,11661824,16234854,7630238,5998374,9809887,-16694564,15219798,-14327783 }, + { 27425505,-5719081,3055006,10660664,23458024,595578,-15398605,-1173195,-18342183,9742717 }, + { 6744077,2427284,26042789,2720740,-847906,1118974,32324614,7406442,12420155,1994844 }, + }, + { + { 14012521,-5024720,-18384453,-9578469,-26485342,-3936439,-13033478,-10909803,24319929,-6446333 }, + { 16412690,-4507367,10772641,15929391,-17068788,-4658621,10555945,-10484049,-30102368,-4739048 }, + { 22397382,-7767684,-9293161,-12792868,17166287,-9755136,-27333065,6199366,21880021,-12250760 }, + }, + { + { -4283307,5368523,-31117018,8163389,-30323063,3209128,16557151,8890729,8840445,4957760 }, + { -15447727,709327,-6919446,-10870178,-29777922,6522332,-21720181,12130072,-14796503,5005757 }, + { -2114751,-14308128,23019042,15765735,-25269683,6002752,10183197,-13239326,-16395286,-2176112 }, + }, +}, +{ + { + { -19025756,1632005,13466291,-7995100,-23640451,16573537,-32013908,-3057104,22208662,2000468 }, + { 3065073,-1412761,-25598674,-361432,-17683065,-5703415,-8164212,11248527,-3691214,-7414184 }, + { 10379208,-6045554,8877319,1473647,-29291284,-12507580,16690915,2553332,-3132688,16400289 }, + }, + { + { 15716668,1254266,-18472690,7446274,-8448918,6344164,-22097271,-7285580,26894937,9132066 }, + { 24158887,12938817,11085297,-8177598,-28063478,-4457083,-30576463,64452,-6817084,-2692882 }, + { 13488534,7794716,22236231,5989356,25426474,-12578208,2350710,-3418511,-4688006,2364226 }, + }, + { + { 16335052,9132434,25640582,6678888,1725628,8517937,-11807024,-11697457,15445875,-7798101 }, + { 29004207,-7867081,28661402,-640412,-12794003,-7943086,31863255,-4135540,-278050,-15759279 }, + { -6122061,-14866665,-28614905,14569919,-10857999,-3591829,10343412,-6976290,-29828287,-10815811 }, + }, + { + { 27081650,3463984,14099042,-4517604,1616303,-6205604,29542636,15372179,17293797,960709 }, + { 20263915,11434237,-5765435,11236810,13505955,-10857102,-16111345,6493122,-19384511,7639714 }, + { -2830798,-14839232,25403038,-8215196,-8317012,-16173699,18006287,-16043750,29994677,-15808121 }, + }, + { + { 9769828,5202651,-24157398,-13631392,-28051003,-11561624,-24613141,-13860782,-31184575,709464 }, + { 12286395,13076066,-21775189,-1176622,-25003198,4057652,-32018128,-8890874,16102007,13205847 }, + { 13733362,5599946,10557076,3195751,-5557991,8536970,-25540170,8525972,10151379,10394400 }, + }, + { + { 4024660,-16137551,22436262,12276534,-9099015,-2686099,19698229,11743039,-33302334,8934414 }, + { -15879800,-4525240,-8580747,-2934061,14634845,-698278,-9449077,3137094,-11536886,11721158 }, + { 17555939,-5013938,8268606,2331751,-22738815,9761013,9319229,8835153,-9205489,-1280045 }, + }, + { + { -461409,-7830014,20614118,16688288,-7514766,-4807119,22300304,505429,6108462,-6183415 }, + { -5070281,12367917,-30663534,3234473,32617080,-8422642,29880583,-13483331,-26898490,-7867459 }, + { -31975283,5726539,26934134,10237677,-3173717,-605053,24199304,3795095,7592688,-14992079 }, + }, + { + { 21594432,-14964228,17466408,-4077222,32537084,2739898,6407723,12018833,-28256052,4298412 }, + { -20650503,-11961496,-27236275,570498,3767144,-1717540,13891942,-1569194,13717174,10805743 }, + { -14676630,-15644296,15287174,11927123,24177847,-8175568,-796431,14860609,-26938930,-5863836 }, + }, +}, +{ + { + { 12962541,5311799,-10060768,11658280,18855286,-7954201,13286263,-12808704,-4381056,9882022 }, + { 18512079,11319350,-20123124,15090309,18818594,5271736,-22727904,3666879,-23967430,-3299429 }, + { -6789020,-3146043,16192429,13241070,15898607,-14206114,-10084880,-6661110,-2403099,5276065 }, + }, + { + { 30169808,-5317648,26306206,-11750859,27814964,7069267,7152851,3684982,1449224,13082861 }, + { 10342826,3098505,2119311,193222,25702612,12233820,23697382,15056736,-21016438,-8202000 }, + { -33150110,3261608,22745853,7948688,19370557,-15177665,-26171976,6482814,-10300080,-11060101 }, + }, + { + { 32869458,-5408545,25609743,15678670,-10687769,-15471071,26112421,2521008,-22664288,6904815 }, + { 29506923,4457497,3377935,-9796444,-30510046,12935080,1561737,3841096,-29003639,-6657642 }, + { 10340844,-6630377,-18656632,-2278430,12621151,-13339055,30878497,-11824370,-25584551,5181966 }, + }, + { + { 25940115,-12658025,17324188,-10307374,-8671468,15029094,24396252,-16450922,-2322852,-12388574 }, + { -21765684,9916823,-1300409,4079498,-1028346,11909559,1782390,12641087,20603771,-6561742 }, + { -18882287,-11673380,24849422,11501709,13161720,-4768874,1925523,11914390,4662781,7820689 }, + }, + { + { 12241050,-425982,8132691,9393934,32846760,-1599620,29749456,12172924,16136752,15264020 }, + { -10349955,-14680563,-8211979,2330220,-17662549,-14545780,10658213,6671822,19012087,3772772 }, + { 3753511,-3421066,10617074,2028709,14841030,-6721664,28718732,-15762884,20527771,12988982 }, + }, + { + { -14822485,-5797269,-3707987,12689773,-898983,-10914866,-24183046,-10564943,3299665,-12424953 }, + { -16777703,-15253301,-9642417,4978983,3308785,8755439,6943197,6461331,-25583147,8991218 }, + { -17226263,1816362,-1673288,-6086439,31783888,-8175991,-32948145,7417950,-30242287,1507265 }, + }, + { + { 29692663,6829891,-10498800,4334896,20945975,-11906496,-28887608,8209391,14606362,-10647073 }, + { -3481570,8707081,32188102,5672294,22096700,1711240,-33020695,9761487,4170404,-2085325 }, + { -11587470,14855945,-4127778,-1531857,-26649089,15084046,22186522,16002000,-14276837,-8400798 }, + }, + { + { -4811456,13761029,-31703877,-2483919,-3312471,7869047,-7113572,-9620092,13240845,10965870 }, + { -7742563,-8256762,-14768334,-13656260,-23232383,12387166,4498947,14147411,29514390,4302863 }, + { -13413405,-12407859,20757302,-13801832,14785143,8976368,-5061276,-2144373,17846988,-13971927 }, + }, +}, +{ + { + { -2244452,-754728,-4597030,-1066309,-6247172,1455299,-21647728,-9214789,-5222701,12650267 }, + { -9906797,-16070310,21134160,12198166,-27064575,708126,387813,13770293,-19134326,10958663 }, + { 22470984,12369526,23446014,-5441109,-21520802,-9698723,-11772496,-11574455,-25083830,4271862 }, + }, + { + { -25169565,-10053642,-19909332,15361595,-5984358,2159192,75375,-4278529,-32526221,8469673 }, + { 15854970,4148314,-8893890,7259002,11666551,13824734,-30531198,2697372,24154791,-9460943 }, + { 15446137,-15806644,29759747,14019369,30811221,-9610191,-31582008,12840104,24913809,9815020 }, + }, + { + { -4709286,-5614269,-31841498,-12288893,-14443537,10799414,-9103676,13438769,18735128,9466238 }, + { 11933045,9281483,5081055,-5183824,-2628162,-4905629,-7727821,-10896103,-22728655,16199064 }, + { 14576810,379472,-26786533,-8317236,-29426508,-10812974,-102766,1876699,30801119,2164795 }, + }, + { + { 15995086,3199873,13672555,13712240,-19378835,-4647646,-13081610,-15496269,-13492807,1268052 }, + { -10290614,-3659039,-3286592,10948818,23037027,3794475,-3470338,-12600221,-17055369,3565904 }, + { 29210088,-9419337,-5919792,-4952785,10834811,-13327726,-16512102,-10820713,-27162222,-14030531 }, + }, + { + { -13161890,15508588,16663704,-8156150,-28349942,9019123,-29183421,-3769423,2244111,-14001979 }, + { -5152875,-3800936,-9306475,-6071583,16243069,14684434,-25673088,-16180800,13491506,4641841 }, + { 10813417,643330,-19188515,-728916,30292062,-16600078,27548447,-7721242,14476989,-12767431 }, + }, + { + { 10292079,9984945,6481436,8279905,-7251514,7032743,27282937,-1644259,-27912810,12651324 }, + { -31185513,-813383,22271204,11835308,10201545,15351028,17099662,3988035,21721536,-3148940 }, + { 10202177,-6545839,-31373232,-9574638,-32150642,-8119683,-12906320,3852694,13216206,14842320 }, + }, + { + { -15815640,-10601066,-6538952,-7258995,-6984659,-6581778,-31500847,13765824,-27434397,9900184 }, + { 14465505,-13833331,-32133984,-14738873,-27443187,12990492,33046193,15796406,-7051866,-8040114 }, + { 30924417,-8279620,6359016,-12816335,16508377,9071735,-25488601,15413635,9524356,-7018878 }, + }, + { + { 12274201,-13175547,32627641,-1785326,6736625,13267305,5237659,-5109483,15663516,4035784 }, + { -2951309,8903985,17349946,601635,-16432815,-4612556,-13732739,-15889334,-22258478,4659091 }, + { -16916263,-4952973,-30393711,-15158821,20774812,15897498,5736189,15026997,-2178256,-13455585 }, + }, +}, +{ + { + { -8858980,-2219056,28571666,-10155518,-474467,-10105698,-3801496,278095,23440562,-290208 }, + { 10226241,-5928702,15139956,120818,-14867693,5218603,32937275,11551483,-16571960,-7442864 }, + { 17932739,-12437276,-24039557,10749060,11316803,7535897,22503767,5561594,-3646624,3898661 }, + }, + { + { 7749907,-969567,-16339731,-16464,-25018111,15122143,-1573531,7152530,21831162,1245233 }, + { 26958459,-14658026,4314586,8346991,-5677764,11960072,-32589295,-620035,-30402091,-16716212 }, + { -12165896,9166947,33491384,13673479,29787085,13096535,6280834,14587357,-22338025,13987525 }, + }, + { + { -24349909,7778775,21116000,15572597,-4833266,-5357778,-4300898,-5124639,-7469781,-2858068 }, + { 9681908,-6737123,-31951644,13591838,-6883821,386950,31622781,6439245,-14581012,4091397 }, + { -8426427,1470727,-28109679,-1596990,3978627,-5123623,-19622683,12092163,29077877,-14741988 }, + }, + { + { 5269168,-6859726,-13230211,-8020715,25932563,1763552,-5606110,-5505881,-20017847,2357889 }, + { 32264008,-15407652,-5387735,-1160093,-2091322,-3946900,23104804,-12869908,5727338,189038 }, + { 14609123,-8954470,-6000566,-16622781,-14577387,-7743898,-26745169,10942115,-25888931,-14884697 }, + }, + { + { 20513500,5557931,-15604613,7829531,26413943,-2019404,-21378968,7471781,13913677,-5137875 }, + { -25574376,11967826,29233242,12948236,-6754465,4713227,-8940970,14059180,12878652,8511905 }, + { -25656801,3393631,-2955415,-7075526,-2250709,9366908,-30223418,6812974,5568676,-3127656 }, + }, + { + { 11630004,12144454,2116339,13606037,27378885,15676917,-17408753,-13504373,-14395196,8070818 }, + { 27117696,-10007378,-31282771,-5570088,1127282,12772488,-29845906,10483306,-11552749,-1028714 }, + { 10637467,-5688064,5674781,1072708,-26343588,-6982302,-1683975,9177853,-27493162,15431203 }, + }, + { + { 20525145,10892566,-12742472,12779443,-29493034,16150075,-28240519,14943142,-15056790,-7935931 }, + { -30024462,5626926,-551567,-9981087,753598,11981191,25244767,-3239766,-3356550,9594024 }, + { -23752644,2636870,-5163910,-10103818,585134,7877383,11345683,-6492290,13352335,-10977084 }, + }, + { + { -1931799,-5407458,3304649,-12884869,17015806,-4877091,-29783850,-7752482,-13215537,-319204 }, + { 20239939,6607058,6203985,3483793,-18386976,-779229,-20723742,15077870,-22750759,14523817 }, + { 27406042,-6041657,27423596,-4497394,4996214,10002360,-28842031,-4545494,-30172742,-4805667 }, + }, +}, +{ + { + { 11374242,12660715,17861383,-12540833,10935568,1099227,-13886076,-9091740,-27727044,11358504 }, + { -12730809,10311867,1510375,10778093,-2119455,-9145702,32676003,11149336,-26123651,4985768 }, + { -19096303,341147,-6197485,-239033,15756973,-8796662,-983043,13794114,-19414307,-15621255 }, + }, + { + { 6490081,11940286,25495923,-7726360,8668373,-8751316,3367603,6970005,-1691065,-9004790 }, + { 1656497,13457317,15370807,6364910,13605745,8362338,-19174622,-5475723,-16796596,-5031438 }, + { -22273315,-13524424,-64685,-4334223,-18605636,-10921968,-20571065,-7007978,-99853,-10237333 }, + }, + { + { 17747465,10039260,19368299,-4050591,-20630635,-16041286,31992683,-15857976,-29260363,-5511971 }, + { 31932027,-4986141,-19612382,16366580,22023614,88450,11371999,-3744247,4882242,-10626905 }, + { 29796507,37186,19818052,10115756,-11829032,3352736,18551198,3272828,-5190932,-4162409 }, + }, + { + { 12501286,4044383,-8612957,-13392385,-32430052,5136599,-19230378,-3529697,330070,-3659409 }, + { 6384877,2899513,17807477,7663917,-2358888,12363165,25366522,-8573892,-271295,12071499 }, + { -8365515,-4042521,25133448,-4517355,-6211027,2265927,-32769618,1936675,-5159697,3829363 }, + }, + { + { 28425966,-5835433,-577090,-4697198,-14217555,6870930,7921550,-6567787,26333140,14267664 }, + { -11067219,11871231,27385719,-10559544,-4585914,-11189312,10004786,-8709488,-21761224,8930324 }, + { -21197785,-16396035,25654216,-1725397,12282012,11008919,1541940,4757911,-26491501,-16408940 }, + }, + { + { 13537262,-7759490,-20604840,10961927,-5922820,-13218065,-13156584,6217254,-15943699,13814990 }, + { -17422573,15157790,18705543,29619,24409717,-260476,27361681,9257833,-1956526,-1776914 }, + { -25045300,-10191966,15366585,15166509,-13105086,8423556,-29171540,12361135,-18685978,4578290 }, + }, + { + { 24579768,3711570,1342322,-11180126,-27005135,14124956,-22544529,14074919,21964432,8235257 }, + { -6528613,-2411497,9442966,-5925588,12025640,-1487420,-2981514,-1669206,13006806,2355433 }, + { -16304899,-13605259,-6632427,-5142349,16974359,-10911083,27202044,1719366,1141648,-12796236 }, + }, + { + { -12863944,-13219986,-8318266,-11018091,-6810145,-4843894,13475066,-3133972,32674895,13715045 }, + { 11423335,-5468059,32344216,8962751,24989809,9241752,-13265253,16086212,-28740881,-15642093 }, + { -1409668,12530728,-6368726,10847387,19531186,-14132160,-11709148,7791794,-27245943,4383347 }, + }, +}, +{ + { + { -28970898,5271447,-1266009,-9736989,-12455236,16732599,-4862407,-4906449,27193557,6245191 }, + { -15193956,5362278,-1783893,2695834,4960227,12840725,23061898,3260492,22510453,8577507 }, + { -12632451,11257346,-32692994,13548177,-721004,10879011,31168030,13952092,-29571492,-3635906 }, + }, + { + { 3877321,-9572739,32416692,5405324,-11004407,-13656635,3759769,11935320,5611860,8164018 }, + { -16275802,14667797,15906460,12155291,-22111149,-9039718,32003002,-8832289,5773085,-8422109 }, + { -23788118,-8254300,1950875,8937633,18686727,16459170,-905725,12376320,31632953,190926 }, + }, + { + { -24593607,-16138885,-8423991,13378746,14162407,6901328,-8288749,4508564,-25341555,-3627528 }, + { 8884438,-5884009,6023974,10104341,-6881569,-4941533,18722941,-14786005,-1672488,827625 }, + { -32720583,-16289296,-32503547,7101210,13354605,2659080,-1800575,-14108036,-24878478,1541286 }, + }, + { + { 2901347,-1117687,3880376,-10059388,-17620940,-3612781,-21802117,-3567481,20456845,-1885033 }, + { 27019610,12299467,-13658288,-1603234,-12861660,-4861471,-19540150,-5016058,29439641,15138866 }, + { 21536104,-6626420,-32447818,-10690208,-22408077,5175814,-5420040,-16361163,7779328,109896 }, + }, + { + { 30279744,14648750,-8044871,6425558,13639621,-743509,28698390,12180118,23177719,-554075 }, + { 26572847,3405927,-31701700,12890905,-19265668,5335866,-6493768,2378492,4439158,-13279347 }, + { -22716706,3489070,-9225266,-332753,18875722,-1140095,14819434,-12731527,-17717757,-5461437 }, + }, + { + { -5056483,16566551,15953661,3767752,-10436499,15627060,-820954,2177225,8550082,-15114165 }, + { -18473302,16596775,-381660,15663611,22860960,15585581,-27844109,-3582739,-23260460,-8428588 }, + { -32480551,15707275,-8205912,-5652081,29464558,2713815,-22725137,15860482,-21902570,1494193 }, + }, + { + { -19562091,-14087393,-25583872,-9299552,13127842,759709,21923482,16529112,8742704,12967017 }, + { -28464899,1553205,32536856,-10473729,-24691605,-406174,-8914625,-2933896,-29903758,15553883 }, + { 21877909,3230008,9881174,10539357,-4797115,2841332,11543572,14513274,19375923,-12647961 }, + }, + { + { 8832269,-14495485,13253511,5137575,5037871,4078777,24880818,-6222716,2862653,9455043 }, + { 29306751,5123106,20245049,-14149889,9592566,8447059,-2077124,-2990080,15511449,4789663 }, + { -20679756,7004547,8824831,-9434977,-4045704,-3750736,-5754762,108893,23513200,16652362 }, + }, +}, +{ + { + { -33256173,4144782,-4476029,-6579123,10770039,-7155542,-6650416,-12936300,-18319198,10212860 }, + { 2756081,8598110,7383731,-6859892,22312759,-1105012,21179801,2600940,-9988298,-12506466 }, + { -24645692,13317462,-30449259,-15653928,21365574,-10869657,11344424,864440,-2499677,-16710063 }, + }, + { + { -26432803,6148329,-17184412,-14474154,18782929,-275997,-22561534,211300,2719757,4940997 }, + { -1323882,3911313,-6948744,14759765,-30027150,7851207,21690126,8518463,26699843,5276295 }, + { -13149873,-6429067,9396249,365013,24703301,-10488939,1321586,149635,-15452774,7159369 }, + }, + { + { 9987780,-3404759,17507962,9505530,9731535,-2165514,22356009,8312176,22477218,-8403385 }, + { 18155857,-16504990,19744716,9006923,15154154,-10538976,24256460,-4864995,-22548173,9334109 }, + { 2986088,-4911893,10776628,-3473844,10620590,-7083203,-21413845,14253545,-22587149,536906 }, + }, + { + { 4377756,8115836,24567078,15495314,11625074,13064599,7390551,10589625,10838060,-15420424 }, + { -19342404,867880,9277171,-3218459,-14431572,-1986443,19295826,-15796950,6378260,699185 }, + { 7895026,4057113,-7081772,-13077756,-17886831,-323126,-716039,15693155,-5045064,-13373962 }, + }, + { + { -7737563,-5869402,-14566319,-7406919,11385654,13201616,31730678,-10962840,-3918636,-9669325 }, + { 10188286,-15770834,-7336361,13427543,22223443,14896287,30743455,7116568,-21786507,5427593 }, + { 696102,13206899,27047647,-10632082,15285305,-9853179,10798490,-4578720,19236243,12477404 }, + }, + { + { -11229439,11243796,-17054270,-8040865,-788228,-8167967,-3897669,11180504,-23169516,7733644 }, + { 17800790,-14036179,-27000429,-11766671,23887827,3149671,23466177,-10538171,10322027,15313801 }, + { 26246234,11968874,32263343,-5468728,6830755,-13323031,-15794704,-101982,-24449242,10890804 }, + }, + { + { -31365647,10271363,-12660625,-6267268,16690207,-13062544,-14982212,16484931,25180797,-5334884 }, + { -586574,10376444,-32586414,-11286356,19801893,10997610,2276632,9482883,316878,13820577 }, + { -9882808,-4510367,-2115506,16457136,-11100081,11674996,30756178,-7515054,30696930,-3712849 }, + }, + { + { 32988917,-9603412,12499366,7910787,-10617257,-11931514,-7342816,-9985397,-32349517,7392473 }, + { -8855661,15927861,9866406,-3649411,-2396914,-16655781,-30409476,-9134995,25112947,-2926644 }, + { -2504044,-436966,25621774,-5678772,15085042,-5479877,-24884878,-13526194,5537438,-13914319 }, + }, +}, +{ + { + { -11225584,2320285,-9584280,10149187,-33444663,5808648,-14876251,-1729667,31234590,6090599 }, + { -9633316,116426,26083934,2897444,-6364437,-2688086,609721,15878753,-6970405,-9034768 }, + { -27757857,247744,-15194774,-9002551,23288161,-10011936,-23869595,6503646,20650474,1804084 }, + }, + { + { -27589786,15456424,8972517,8469608,15640622,4439847,3121995,-10329713,27842616,-202328 }, + { -15306973,2839644,22530074,10026331,4602058,5048462,28248656,5031932,-11375082,12714369 }, + { 20807691,-7270825,29286141,11421711,-27876523,-13868230,-21227475,1035546,-19733229,12796920 }, + }, + { + { 12076899,-14301286,-8785001,-11848922,-25012791,16400684,-17591495,-12899438,3480665,-15182815 }, + { -32361549,5457597,28548107,7833186,7303070,-11953545,-24363064,-15921875,-33374054,2771025 }, + { -21389266,421932,26597266,6860826,22486084,-6737172,-17137485,-4210226,-24552282,15673397 }, + }, + { + { -20184622,2338216,19788685,-9620956,-4001265,-8740893,-20271184,4733254,3727144,-12934448 }, + { 6120119,814863,-11794402,-622716,6812205,-15747771,2019594,7975683,31123697,-10958981 }, + { 30069250,-11435332,30434654,2958439,18399564,-976289,12296869,9204260,-16432438,9648165 }, + }, + { + { 32705432,-1550977,30705658,7451065,-11805606,9631813,3305266,5248604,-26008332,-11377501 }, + { 17219865,2375039,-31570947,-5575615,-19459679,9219903,294711,15298639,2662509,-16297073 }, + { -1172927,-7558695,-4366770,-4287744,-21346413,-8434326,32087529,-1222777,32247248,-14389861 }, + }, + { + { 14312628,1221556,17395390,-8700143,-4945741,-8684635,-28197744,-9637817,-16027623,-13378845 }, + { -1428825,-9678990,-9235681,6549687,-7383069,-468664,23046502,9803137,17597934,2346211 }, + { 18510800,15337574,26171504,981392,-22241552,7827556,-23491134,-11323352,3059833,-11782870 }, + }, + { + { 10141598,6082907,17829293,-1947643,9830092,13613136,-25556636,-5544586,-33502212,3592096 }, + { 33114168,-15889352,-26525686,-13343397,33076705,8716171,1151462,1521897,-982665,-6837803 }, + { -32939165,-4255815,23947181,-324178,-33072974,-12305637,-16637686,3891704,26353178,693168 }, + }, + { + { 30374239,1595580,-16884039,13186931,4600344,406904,9585294,-400668,31375464,14369965 }, + { -14370654,-7772529,1510301,6434173,-18784789,-6262728,32732230,-13108839,17901441,16011505 }, + { 18171223,-11934626,-12500402,15197122,-11038147,-15230035,-19172240,-16046376,8764035,12309598 }, + }, +}, +{ + { + { 5975908,-5243188,-19459362,-9681747,-11541277,14015782,-23665757,1228319,17544096,-10593782 }, + { 5811932,-1715293,3442887,-2269310,-18367348,-8359541,-18044043,-15410127,-5565381,12348900 }, + { -31399660,11407555,25755363,6891399,-3256938,14872274,-24849353,8141295,-10632534,-585479 }, + }, + { + { -12675304,694026,-5076145,13300344,14015258,-14451394,-9698672,-11329050,30944593,1130208 }, + { 8247766,-6710942,-26562381,-7709309,-14401939,-14648910,4652152,2488540,23550156,-271232 }, + { 17294316,-3788438,7026748,15626851,22990044,113481,2267737,-5908146,-408818,-137719 }, + }, + { + { 16091085,-16253926,18599252,7340678,2137637,-1221657,-3364161,14550936,3260525,-7166271 }, + { -4910104,-13332887,18550887,10864893,-16459325,-7291596,-23028869,-13204905,-12748722,2701326 }, + { -8574695,16099415,4629974,-16340524,-20786213,-6005432,-10018363,9276971,11329923,1862132 }, + }, + { + { 14763076,-15903608,-30918270,3689867,3511892,10313526,-21951088,12219231,-9037963,-940300 }, + { 8894987,-3446094,6150753,3013931,301220,15693451,-31981216,-2909717,-15438168,11595570 }, + { 15214962,3537601,-26238722,-14058872,4418657,-15230761,13947276,10730794,-13489462,-4363670 }, + }, + { + { -2538306,7682793,32759013,263109,-29984731,-7955452,-22332124,-10188635,977108,699994 }, + { -12466472,4195084,-9211532,550904,-15565337,12917920,19118110,-439841,-30534533,-14337913 }, + { 31788461,-14507657,4799989,7372237,8808585,-14747943,9408237,-10051775,12493932,-5409317 }, + }, + { + { -25680606,5260744,-19235809,-6284470,-3695942,16566087,27218280,2607121,29375955,6024730 }, + { 842132,-2794693,-4763381,-8722815,26332018,-12405641,11831880,6985184,-9940361,2854096 }, + { -4847262,-7969331,2516242,-5847713,9695691,-7221186,16512645,960770,12121869,16648078 }, + }, + { + { -15218652,14667096,-13336229,2013717,30598287,-464137,-31504922,-7882064,20237806,2838411 }, + { -19288047,4453152,15298546,-16178388,22115043,-15972604,12544294,-13470457,1068881,-12499905 }, + { -9558883,-16518835,33238498,13506958,30505848,-1114596,-8486907,-2630053,12521378,4845654 }, + }, + { + { -28198521,10744108,-2958380,10199664,7759311,-13088600,3409348,-873400,-6482306,-12885870 }, + { -23561822,6230156,-20382013,10655314,-24040585,-11621172,10477734,-1240216,-3113227,13974498 }, + { 12966261,15550616,-32038948,-1615346,21025980,-629444,5642325,7188737,18895762,12629579 }, + }, +}, +{ + { + { 14741879,-14946887,22177208,-11721237,1279741,8058600,11758140,789443,32195181,3895677 }, + { 10758205,15755439,-4509950,9243698,-4879422,6879879,-2204575,-3566119,-8982069,4429647 }, + { -2453894,15725973,-20436342,-10410672,-5803908,-11040220,-7135870,-11642895,18047436,-15281743 }, + }, + { + { -25173001,-11307165,29759956,11776784,-22262383,-15820455,10993114,-12850837,-17620701,-9408468 }, + { 21987233,700364,-24505048,14972008,-7774265,-5718395,32155026,2581431,-29958985,8773375 }, + { -25568350,454463,-13211935,16126715,25240068,8594567,20656846,12017935,-7874389,-13920155 }, + }, + { + { 6028182,6263078,-31011806,-11301710,-818919,2461772,-31841174,-5468042,-1721788,-2776725 }, + { -12278994,16624277,987579,-5922598,32908203,1248608,7719845,-4166698,28408820,6816612 }, + { -10358094,-8237829,19549651,-12169222,22082623,16147817,20613181,13982702,-10339570,5067943 }, + }, + { + { -30505967,-3821767,12074681,13582412,-19877972,2443951,-19719286,12746132,5331210,-10105944 }, + { 30528811,3601899,-1957090,4619785,-27361822,-15436388,24180793,-12570394,27679908,-1648928 }, + { 9402404,-13957065,32834043,10838634,-26580150,-13237195,26653274,-8685565,22611444,-12715406 }, + }, + { + { 22190590,1118029,22736441,15130463,-30460692,-5991321,19189625,-4648942,4854859,6622139 }, + { -8310738,-2953450,-8262579,-3388049,-10401731,-271929,13424426,-3567227,26404409,13001963 }, + { -31241838,-15415700,-2994250,8939346,11562230,-12840670,-26064365,-11621720,-15405155,11020693 }, + }, + { + { 1866042,-7949489,-7898649,-10301010,12483315,13477547,3175636,-12424163,28761762,1406734 }, + { -448555,-1777666,13018551,3194501,-9580420,-11161737,24760585,-4347088,25577411,-13378680 }, + { -24290378,4759345,-690653,-1852816,2066747,10693769,-29595790,9884936,-9368926,4745410 }, + }, + { + { -9141284,6049714,-19531061,-4341411,-31260798,9944276,-15462008,-11311852,10931924,-11931931 }, + { -16561513,14112680,-8012645,4817318,-8040464,-11414606,-22853429,10856641,-20470770,13434654 }, + { 22759489,-10073434,-16766264,-1871422,13637442,-10168091,1765144,-12654326,28445307,-5364710 }, + }, + { + { 29875063,12493613,2795536,-3786330,1710620,15181182,-10195717,-8788675,9074234,1167180 }, + { -26205683,11014233,-9842651,-2635485,-26908120,7532294,-18716888,-9535498,3843903,9367684 }, + { -10969595,-6403711,9591134,9582310,11349256,108879,16235123,8601684,-139197,4242895 }, + }, +}, +{ + { + { 22092954,-13191123,-2042793,-11968512,32186753,-11517388,-6574341,2470660,-27417366,16625501 }, + { -11057722,3042016,13770083,-9257922,584236,-544855,-7770857,2602725,-27351616,14247413 }, + { 6314175,-10264892,-32772502,15957557,-10157730,168750,-8618807,14290061,27108877,-1180880 }, + }, + { + { -8586597,-7170966,13241782,10960156,-32991015,-13794596,33547976,-11058889,-27148451,981874 }, + { 22833440,9293594,-32649448,-13618667,-9136966,14756819,-22928859,-13970780,-10479804,-16197962 }, + { -7768587,3326786,-28111797,10783824,19178761,14905060,22680049,13906969,-15933690,3797899 }, + }, + { + { 21721356,-4212746,-12206123,9310182,-3882239,-13653110,23740224,-2709232,20491983,-8042152 }, + { 9209270,-15135055,-13256557,-6167798,-731016,15289673,25947805,15286587,30997318,-6703063 }, + { 7392032,16618386,23946583,-8039892,-13265164,-1533858,-14197445,-2321576,17649998,-250080 }, + }, + { + { -9301088,-14193827,30609526,-3049543,-25175069,-1283752,-15241566,-9525724,-2233253,7662146 }, + { -17558673,1763594,-33114336,15908610,-30040870,-12174295,7335080,-8472199,-3174674,3440183 }, + { -19889700,-5977008,-24111293,-9688870,10799743,-16571957,40450,-4431835,4862400,1133 }, + }, + { + { -32856209,-7873957,-5422389,14860950,-16319031,7956142,7258061,311861,-30594991,-7379421 }, + { -3773428,-1565936,28985340,7499440,24445838,9325937,29727763,16527196,18278453,15405622 }, + { -4381906,8508652,-19898366,-3674424,-5984453,15149970,-13313598,843523,-21875062,13626197 }, + }, + { + { 2281448,-13487055,-10915418,-2609910,1879358,16164207,-10783882,3953792,13340839,15928663 }, + { 31727126,-7179855,-18437503,-8283652,2875793,-16390330,-25269894,-7014826,-23452306,5964753 }, + { 4100420,-5959452,-17179337,6017714,-18705837,12227141,-26684835,11344144,2538215,-7570755 }, + }, + { + { -9433605,6123113,11159803,-2156608,30016280,14966241,-20474983,1485421,-629256,-15958862 }, + { -26804558,4260919,11851389,9658551,-32017107,16367492,-20205425,-13191288,11659922,-11115118 }, + { 26180396,10015009,-30844224,-8581293,5418197,9480663,2231568,-10170080,33100372,-1306171 }, + }, + { + { 15121113,-5201871,-10389905,15427821,-27509937,-15992507,21670947,4486675,-5931810,-14466380 }, + { 16166486,-9483733,-11104130,6023908,-31926798,-1364923,2340060,-16254968,-10735770,-10039824 }, + { 28042865,-3557089,-12126526,12259706,-3717498,-6945899,6766453,-8689599,18036436,5803270 }, + }, +}, +{ + { + { -817581,6763912,11803561,1585585,10958447,-2671165,23855391,4598332,-6159431,-14117438 }, + { -31031306,-14256194,17332029,-2383520,31312682,-5967183,696309,50292,-20095739,11763584 }, + { -594563,-2514283,-32234153,12643980,12650761,14811489,665117,-12613632,-19773211,-10713562 }, + }, + { + { 30464590,-11262872,-4127476,-12734478,19835327,-7105613,-24396175,2075773,-17020157,992471 }, + { 18357185,-6994433,7766382,16342475,-29324918,411174,14578841,8080033,-11574335,-10601610 }, + { 19598397,10334610,12555054,2555664,18821899,-10339780,21873263,16014234,26224780,16452269 }, + }, + { + { -30223925,5145196,5944548,16385966,3976735,2009897,-11377804,-7618186,-20533829,3698650 }, + { 14187449,3448569,-10636236,-10810935,-22663880,-3433596,7268410,-10890444,27394301,12015369 }, + { 19695761,16087646,28032085,12999827,6817792,11427614,20244189,-1312777,-13259127,-3402461 }, + }, + { + { 30860103,12735208,-1888245,-4699734,-16974906,2256940,-8166013,12298312,-8550524,-10393462 }, + { -5719826,-11245325,-1910649,15569035,26642876,-7587760,-5789354,-15118654,-4976164,12651793 }, + { -2848395,9953421,11531313,-5282879,26895123,-12697089,-13118820,-16517902,9768698,-2533218 }, + }, + { + { -24719459,1894651,-287698,-4704085,15348719,-8156530,32767513,12765450,4940095,10678226 }, + { 18860224,15980149,-18987240,-1562570,-26233012,-11071856,-7843882,13944024,-24372348,16582019 }, + { -15504260,4970268,-29893044,4175593,-20993212,-2199756,-11704054,15444560,-11003761,7989037 }, + }, + { + { 31490452,5568061,-2412803,2182383,-32336847,4531686,-32078269,6200206,-19686113,-14800171 }, + { -17308668,-15879940,-31522777,-2831,-32887382,16375549,8680158,-16371713,28550068,-6857132 }, + { -28126887,-5688091,16837845,-1820458,-6850681,12700016,-30039981,4364038,1155602,5988841 }, + }, + { + { 21890435,-13272907,-12624011,12154349,-7831873,15300496,23148983,-4470481,24618407,8283181 }, + { -33136107,-10512751,9975416,6841041,-31559793,16356536,3070187,-7025928,1466169,10740210 }, + { -1509399,-15488185,-13503385,-10655916,32799044,909394,-13938903,-5779719,-32164649,-15327040 }, + }, + { + { 3960823,-14267803,-28026090,-15918051,-19404858,13146868,15567327,951507,-3260321,-573935 }, + { 24740841,5052253,-30094131,8961361,25877428,6165135,-24368180,14397372,-7380369,-6144105 }, + { -28888365,3510803,-28103278,-1158478,-11238128,-10631454,-15441463,-14453128,-1625486,-6494814 }, + }, +}, +{ + { + { 793299,-9230478,8836302,-6235707,-27360908,-2369593,33152843,-4885251,-9906200,-621852 }, + { 5666233,525582,20782575,-8038419,-24538499,14657740,16099374,1468826,-6171428,-15186581 }, + { -4859255,-3779343,-2917758,-6748019,7778750,11688288,-30404353,-9871238,-1558923,-9863646 }, + }, + { + { 10896332,-7719704,824275,472601,-19460308,3009587,25248958,14783338,-30581476,-15757844 }, + { 10566929,12612572,-31944212,11118703,-12633376,12362879,21752402,8822496,24003793,14264025 }, + { 27713862,-7355973,-11008240,9227530,27050101,2504721,23886875,-13117525,13958495,-5732453 }, + }, + { + { -23481610,4867226,-27247128,3900521,29838369,-8212291,-31889399,-10041781,7340521,-15410068 }, + { 4646514,-8011124,-22766023,-11532654,23184553,8566613,31366726,-1381061,-15066784,-10375192 }, + { -17270517,12723032,-16993061,14878794,21619651,-6197576,27584817,3093888,-8843694,3849921 }, + }, + { + { -9064912,2103172,25561640,-15125738,-5239824,9582958,32477045,-9017955,5002294,-15550259 }, + { -12057553,-11177906,21115585,-13365155,8808712,-12030708,16489530,13378448,-25845716,12741426 }, + { -5946367,10645103,-30911586,15390284,-3286982,-7118677,24306472,15852464,28834118,-7646072 }, + }, + { + { -17335748,-9107057,-24531279,9434953,-8472084,-583362,-13090771,455841,20461858,5491305 }, + { 13669248,-16095482,-12481974,-10203039,-14569770,-11893198,-24995986,11293807,-28588204,-9421832 }, + { 28497928,6272777,-33022994,14470570,8906179,-1225630,18504674,-14165166,29867745,-8795943 }, + }, + { + { -16207023,13517196,-27799630,-13697798,24009064,-6373891,-6367600,-13175392,22853429,-4012011 }, + { 24191378,16712145,-13931797,15217831,14542237,1646131,18603514,-11037887,12876623,-2112447 }, + { 17902668,4518229,-411702,-2829247,26878217,5258055,-12860753,608397,16031844,3723494 }, + }, + { + { -28632773,12763728,-20446446,7577504,33001348,-13017745,17558842,-7872890,23896954,-4314245 }, + { -20005381,-12011952,31520464,605201,2543521,5991821,-2945064,7229064,-9919646,-8826859 }, + { 28816045,298879,-28165016,-15920938,19000928,-1665890,-12680833,-2949325,-18051778,-2082915 }, + }, + { + { 16000882,-344896,3493092,-11447198,-29504595,-13159789,12577740,16041268,-19715240,7847707 }, + { 10151868,10572098,27312476,7922682,14825339,4723128,-32855931,-6519018,-10020567,3852848 }, + { -11430470,15697596,-21121557,-4420647,5386314,15063598,16514493,-15932110,29330899,-15076224 }, + }, +}, +{ + { + { -25499735,-4378794,-15222908,-6901211,16615731,2051784,3303702,15490,-27548796,12314391 }, + { 15683520,-6003043,18109120,-9980648,15337968,-5997823,-16717435,15921866,16103996,-3731215 }, + { -23169824,-10781249,13588192,-1628807,-3798557,-1074929,-19273607,5402699,-29815713,-9841101 }, + }, + { + { 23190676,2384583,-32714340,3462154,-29903655,-1529132,-11266856,8911517,-25205859,2739713 }, + { 21374101,-3554250,-33524649,9874411,15377179,11831242,-33529904,6134907,4931255,11987849 }, + { -7732,-2978858,-16223486,7277597,105524,-322051,-31480539,13861388,-30076310,10117930 }, + }, + { + { -29501170,-10744872,-26163768,13051539,-25625564,5089643,-6325503,6704079,12890019,15728940 }, + { -21972360,-11771379,-951059,-4418840,14704840,2695116,903376,-10428139,12885167,8311031 }, + { -17516482,5352194,10384213,-13811658,7506451,13453191,26423267,4384730,1888765,-5435404 }, + }, + { + { -25817338,-3107312,-13494599,-3182506,30896459,-13921729,-32251644,-12707869,-19464434,-3340243 }, + { -23607977,-2665774,-526091,4651136,5765089,4618330,6092245,14845197,17151279,-9854116 }, + { -24830458,-12733720,-15165978,10367250,-29530908,-265356,22825805,-7087279,-16866484,16176525 }, + }, + { + { -23583256,6564961,20063689,3798228,-4740178,7359225,2006182,-10363426,-28746253,-10197509 }, + { -10626600,-4486402,-13320562,-5125317,3432136,-6393229,23632037,-1940610,32808310,1099883 }, + { 15030977,5768825,-27451236,-2887299,-6427378,-15361371,-15277896,-6809350,2051441,-15225865 }, + }, + { + { -3362323,-7239372,7517890,9824992,23555850,295369,5148398,-14154188,-22686354,16633660 }, + { 4577086,-16752288,13249841,-15304328,19958763,-14537274,18559670,-10759549,8402478,-9864273 }, + { -28406330,-1051581,-26790155,-907698,-17212414,-11030789,9453451,-14980072,17983010,9967138 }, + }, + { + { -25762494,6524722,26585488,9969270,24709298,1220360,-1677990,7806337,17507396,3651560 }, + { -10420457,-4118111,14584639,15971087,-15768321,8861010,26556809,-5574557,-18553322,-11357135 }, + { 2839101,14284142,4029895,3472686,14402957,12689363,-26642121,8459447,-5605463,-7621941 }, + }, + { + { -4839289,-3535444,9744961,2871048,25113978,3187018,-25110813,-849066,17258084,-7977739 }, + { 18164541,-10595176,-17154882,-1542417,19237078,-9745295,23357533,-15217008,26908270,12150756 }, + { -30264870,-7647865,5112249,-7036672,-1499807,-6974257,43168,-5537701,-32302074,16215819 }, + }, +}, +{ + { + { -6898905,9824394,-12304779,-4401089,-31397141,-6276835,32574489,12532905,-7503072,-8675347 }, + { -27343522,-16515468,-27151524,-10722951,946346,16291093,254968,7168080,21676107,-1943028 }, + { 21260961,-8424752,-16831886,-11920822,-23677961,3968121,-3651949,-6215466,-3556191,-7913075 }, + }, + { + { 16544754,13250366,-16804428,15546242,-4583003,12757258,-2462308,-8680336,-18907032,-9662799 }, + { -2415239,-15577728,18312303,4964443,-15272530,-12653564,26820651,16690659,25459437,-4564609 }, + { -25144690,11425020,28423002,-11020557,-6144921,-15826224,9142795,-2391602,-6432418,-1644817 }, + }, + { + { -23104652,6253476,16964147,-3768872,-25113972,-12296437,-27457225,-16344658,6335692,7249989 }, + { -30333227,13979675,7503222,-12368314,-11956721,-4621693,-30272269,2682242,25993170,-12478523 }, + { 4364628,5930691,32304656,-10044554,-8054781,15091131,22857016,-10598955,31820368,15075278 }, + }, + { + { 31879134,-8918693,17258761,90626,-8041836,-4917709,24162788,-9650886,-17970238,12833045 }, + { 19073683,14851414,-24403169,-11860168,7625278,11091125,-19619190,2074449,-9413939,14905377 }, + { 24483667,-11935567,-2518866,-11547418,-1553130,15355506,-25282080,9253129,27628530,-7555480 }, + }, + { + { 17597607,8340603,19355617,552187,26198470,-3176583,4593324,-9157582,-14110875,15297016 }, + { 510886,14337390,-31785257,16638632,6328095,2713355,-20217417,-11864220,8683221,2921426 }, + { 18606791,11874196,27155355,-5281482,-24031742,6265446,-25178240,-1278924,4674690,13890525 }, + }, + { + { 13609624,13069022,-27372361,-13055908,24360586,9592974,14977157,9835105,4389687,288396 }, + { 9922506,-519394,13613107,5883594,-18758345,-434263,-12304062,8317628,23388070,16052080 }, + { 12720016,11937594,-31970060,-5028689,26900120,8561328,-20155687,-11632979,-14754271,-10812892 }, + }, + { + { 15961858,14150409,26716931,-665832,-22794328,13603569,11829573,7467844,-28822128,929275 }, + { 11038231,-11582396,-27310482,-7316562,-10498527,-16307831,-23479533,-9371869,-21393143,2465074 }, + { 20017163,-4323226,27915242,1529148,12396362,15675764,13817261,-9658066,2463391,-4622140 }, + }, + { + { -16358878,-12663911,-12065183,4996454,-1256422,1073572,9583558,12851107,4003896,12673717 }, + { -1731589,-15155870,-3262930,16143082,19294135,13385325,14741514,-9103726,7903886,2348101 }, + { 24536016,-16515207,12715592,-3862155,1511293,10047386,-3842346,-7129159,-28377538,10048127 }, + }, +}, +{ + { + { -12622226,-6204820,30718825,2591312,-10617028,12192840,18873298,-7297090,-32297756,15221632 }, + { -26478122,-11103864,11546244,-1852483,9180880,7656409,-21343950,2095755,29769758,6593415 }, + { -31994208,-2907461,4176912,3264766,12538965,-868111,26312345,-6118678,30958054,8292160 }, + }, + { + { 31429822,-13959116,29173532,15632448,12174511,-2760094,32808831,3977186,26143136,-3148876 }, + { 22648901,1402143,-22799984,13746059,7936347,365344,-8668633,-1674433,-3758243,-2304625 }, + { -15491917,8012313,-2514730,-12702462,-23965846,-10254029,-1612713,-1535569,-16664475,8194478 }, + }, + { + { 27338066,-7507420,-7414224,10140405,-19026427,-6589889,27277191,8855376,28572286,3005164 }, + { 26287124,4821776,25476601,-4145903,-3764513,-15788984,-18008582,1182479,-26094821,-13079595 }, + { -7171154,3178080,23970071,6201893,-17195577,-4489192,-21876275,-13982627,32208683,-1198248 }, + }, + { + { -16657702,2817643,-10286362,14811298,6024667,13349505,-27315504,-10497842,-27672585,-11539858 }, + { 15941029,-9405932,-21367050,8062055,31876073,-238629,-15278393,-1444429,15397331,-4130193 }, + { 8934485,-13485467,-23286397,-13423241,-32446090,14047986,31170398,-1441021,-27505566,15087184 }, + }, + { + { -18357243,-2156491,24524913,-16677868,15520427,-6360776,-15502406,11461896,16788528,-5868942 }, + { -1947386,16013773,21750665,3714552,-17401782,-16055433,-3770287,-10323320,31322514,-11615635 }, + { 21426655,-5650218,-13648287,-5347537,-28812189,-4920970,-18275391,-14621414,13040862,-12112948 }, + }, + { + { 11293895,12478086,-27136401,15083750,-29307421,14748872,14555558,-13417103,1613711,4896935 }, + { -25894883,15323294,-8489791,-8057900,25967126,-13425460,2825960,-4897045,-23971776,-11267415 }, + { -15924766,-5229880,-17443532,6410664,3622847,10243618,20615400,12405433,-23753030,-8436416 }, + }, + { + { -7091295,12556208,-20191352,9025187,-17072479,4333801,4378436,2432030,23097949,-566018 }, + { 4565804,-16025654,20084412,-7842817,1724999,189254,24767264,10103221,-18512313,2424778 }, + { 366633,-11976806,8173090,-6890119,30788634,5745705,-7168678,1344109,-3642553,12412659 }, + }, + { + { -24001791,7690286,14929416,-168257,-32210835,-13412986,24162697,-15326504,-3141501,11179385 }, + { 18289522,-14724954,8056945,16430056,-21729724,7842514,-6001441,-1486897,-18684645,-11443503 }, + { 476239,6601091,-6152790,-9723375,17503545,-4863900,27672959,13403813,11052904,5219329 }, + }, +}, +{ + { + { 20678546,-8375738,-32671898,8849123,-5009758,14574752,31186971,-3973730,9014762,-8579056 }, + { -13644050,-10350239,-15962508,5075808,-1514661,-11534600,-33102500,9160280,8473550,-3256838 }, + { 24900749,14435722,17209120,-15292541,-22592275,9878983,-7689309,-16335821,-24568481,11788948 }, + }, + { + { -3118155,-11395194,-13802089,14797441,9652448,-6845904,-20037437,10410733,-24568470,-1458691 }, + { -15659161,16736706,-22467150,10215878,-9097177,7563911,11871841,-12505194,-18513325,8464118 }, + { -23400612,8348507,-14585951,-861714,-3950205,-6373419,14325289,8628612,33313881,-8370517 }, + }, + { + { -20186973,-4967935,22367356,5271547,-1097117,-4788838,-24805667,-10236854,-8940735,-5818269 }, + { -6948785,-1795212,-32625683,-16021179,32635414,-7374245,15989197,-12838188,28358192,-4253904 }, + { -23561781,-2799059,-32351682,-1661963,-9147719,10429267,-16637684,4072016,-5351664,5596589 }, + }, + { + { -28236598,-3390048,12312896,6213178,3117142,16078565,29266239,2557221,1768301,15373193 }, + { -7243358,-3246960,-4593467,-7553353,-127927,-912245,-1090902,-4504991,-24660491,3442910 }, + { -30210571,5124043,14181784,8197961,18964734,-11939093,22597931,7176455,-18585478,13365930 }, + }, + { + { -7877390,-1499958,8324673,4690079,6261860,890446,24538107,-8570186,-9689599,-3031667 }, + { 25008904,-10771599,-4305031,-9638010,16265036,15721635,683793,-11823784,15723479,-15163481 }, + { -9660625,12374379,-27006999,-7026148,-7724114,-12314514,11879682,5400171,519526,-1235876 }, + }, + { + { 22258397,-16332233,-7869817,14613016,-22520255,-2950923,-20353881,7315967,16648397,7605640 }, + { -8081308,-8464597,-8223311,9719710,19259459,-15348212,23994942,-5281555,-9468848,4763278 }, + { -21699244,9220969,-15730624,1084137,-25476107,-2852390,31088447,-7764523,-11356529,728112 }, + }, + { + { 26047220,-11751471,-6900323,-16521798,24092068,9158119,-4273545,-12555558,-29365436,-5498272 }, + { 17510331,-322857,5854289,8403524,17133918,-3112612,-28111007,12327945,10750447,10014012 }, + { -10312768,3936952,9156313,-8897683,16498692,-994647,-27481051,-666732,3424691,7540221 }, + }, + { + { 30322361,-6964110,11361005,-4143317,7433304,4989748,-7071422,-16317219,-9244265,15258046 }, + { 13054562,-2779497,19155474,469045,-12482797,4566042,5631406,2711395,1062915,-5136345 }, + { -19240248,-11254599,-29509029,-7499965,-5835763,13005411,-6066489,12194497,32960380,1459310 }, + }, +}, +{ + { + { 19852034,7027924,23669353,10020366,8586503,-6657907,394197,-6101885,18638003,-11174937 }, + { 31395534,15098109,26581030,8030562,-16527914,-5007134,9012486,-7584354,-6643087,-5442636 }, + { -9192165,-2347377,-1997099,4529534,25766844,607986,-13222,9677543,-32294889,-6456008 }, + }, + { + { -2444496,-149937,29348902,8186665,1873760,12489863,-30934579,-7839692,-7852844,-8138429 }, + { -15236356,-15433509,7766470,746860,26346930,-10221762,-27333451,10754588,-9431476,5203576 }, + { 31834314,14135496,-770007,5159118,20917671,-16768096,-7467973,-7337524,31809243,7347066 }, + }, + { + { -9606723,-11874240,20414459,13033986,13716524,-11691881,19797970,-12211255,15192876,-2087490 }, + { -12663563,-2181719,1168162,-3804809,26747877,-14138091,10609330,12694420,33473243,-13382104 }, + { 33184999,11180355,15832085,-11385430,-1633671,225884,15089336,-11023903,-6135662,14480053 }, + }, + { + { 31308717,-5619998,31030840,-1897099,15674547,-6582883,5496208,13685227,27595050,8737275 }, + { -20318852,-15150239,10933843,-16178022,8335352,-7546022,-31008351,-12610604,26498114,66511 }, + { 22644454,-8761729,-16671776,4884562,-3105614,-13559366,30540766,-4286747,-13327787,-7515095 }, + }, + { + { -28017847,9834845,18617207,-2681312,-3401956,-13307506,8205540,13585437,-17127465,15115439 }, + { 23711543,-672915,31206561,-8362711,6164647,-9709987,-33535882,-1426096,8236921,16492939 }, + { -23910559,-13515526,-26299483,-4503841,25005590,-7687270,19574902,10071562,6708380,-6222424 }, + }, + { + { 2101391,-4930054,19702731,2367575,-15427167,1047675,5301017,9328700,29955601,-11678310 }, + { 3096359,9271816,-21620864,-15521844,-14847996,-7592937,-25892142,-12635595,-9917575,6216608 }, + { -32615849,338663,-25195611,2510422,-29213566,-13820213,24822830,-6146567,-26767480,7525079 }, + }, + { + { -23066649,-13985623,16133487,-7896178,-3389565,778788,-910336,-2782495,-19386633,11994101 }, + { 21691500,-13624626,-641331,-14367021,3285881,-3483596,-25064666,9718258,-7477437,13381418 }, + { 18445390,-4202236,14979846,11622458,-1727110,-3582980,23111648,-6375247,28535282,15779576 }, + }, + { + { 30098053,3089662,-9234387,16662135,-21306940,11308411,-14068454,12021730,9955285,-16303356 }, + { 9734894,-14576830,-7473633,-9138735,2060392,11313496,-18426029,9924399,20194861,13380996 }, + { -26378102,-7965207,-22167821,15789297,-18055342,-6168792,-1984914,15707771,26342023,10146099 }, + }, +}, +{ + { + { -26016874,-219943,21339191,-41388,19745256,-2878700,-29637280,2227040,21612326,-545728 }, + { -13077387,1184228,23562814,-5970442,-20351244,-6348714,25764461,12243797,-20856566,11649658 }, + { -10031494,11262626,27384172,2271902,26947504,-15997771,39944,6114064,33514190,2333242 }, + }, + { + { -21433588,-12421821,8119782,7219913,-21830522,-9016134,-6679750,-12670638,24350578,-13450001 }, + { -4116307,-11271533,-23886186,4843615,-30088339,690623,-31536088,-10406836,8317860,12352766 }, + { 18200138,-14475911,-33087759,-2696619,-23702521,-9102511,-23552096,-2287550,20712163,6719373 }, + }, + { + { 26656208,6075253,-7858556,1886072,-28344043,4262326,11117530,-3763210,26224235,-3297458 }, + { -17168938,-14854097,-3395676,-16369877,-19954045,14050420,21728352,9493610,18620611,-16428628 }, + { -13323321,13325349,11432106,5964811,18609221,6062965,-5269471,-9725556,-30701573,-16479657 }, + }, + { + { -23860538,-11233159,26961357,1640861,-32413112,-16737940,12248509,-5240639,13735342,1934062 }, + { 25089769,6742589,17081145,-13406266,21909293,-16067981,-15136294,-3765346,-21277997,5473616 }, + { 31883677,-7961101,1083432,-11572403,22828471,13290673,-7125085,12469656,29111212,-5451014 }, + }, + { + { 24244947,-15050407,-26262976,2791540,-14997599,16666678,24367466,6388839,-10295587,452383 }, + { -25640782,-3417841,5217916,16224624,19987036,-4082269,-24236251,-5915248,15766062,8407814 }, + { -20406999,13990231,15495425,16395525,5377168,15166495,-8917023,-4388953,-8067909,2276718 }, + }, + { + { 30157918,12924066,-17712050,9245753,19895028,3368142,-23827587,5096219,22740376,-7303417 }, + { 2041139,-14256350,7783687,13876377,-25946985,-13352459,24051124,13742383,-15637599,13295222 }, + { 33338237,-8505733,12532113,7977527,9106186,-1715251,-17720195,-4612972,-4451357,-14669444 }, + }, + { + { -20045281,5454097,-14346548,6447146,28862071,1883651,-2469266,-4141880,7770569,9620597 }, + { 23208068,7979712,33071466,8149229,1758231,-10834995,30945528,-1694323,-33502340,-14767970 }, + { 1439958,-16270480,-1079989,-793782,4625402,10647766,-5043801,1220118,30494170,-11440799 }, + }, + { + { -5037580,-13028295,-2970559,-3061767,15640974,-6701666,-26739026,926050,-1684339,-13333647 }, + { 13908495,-3549272,30919928,-6273825,-21521863,7989039,9021034,9078865,3353509,4033511 }, + { -29663431,-15113610,32259991,-344482,24295849,-12912123,23161163,8839127,27485041,7356032 }, + }, +}, +{ + { + { 9661027,705443,11980065,-5370154,-1628543,14661173,-6346142,2625015,28431036,-16771834 }, + { -23839233,-8311415,-25945511,7480958,-17681669,-8354183,-22545972,14150565,15970762,4099461 }, + { 29262576,16756590,26350592,-8793563,8529671,-11208050,13617293,-9937143,11465739,8317062 }, + }, + { + { -25493081,-6962928,32500200,-9419051,-23038724,-2302222,14898637,3848455,20969334,-5157516 }, + { -20384450,-14347713,-18336405,13884722,-33039454,2842114,-21610826,-3649888,11177095,14989547 }, + { -24496721,-11716016,16959896,2278463,12066309,10137771,13515641,2581286,-28487508,9930240 }, + }, + { + { -17751622,-2097826,16544300,-13009300,-15914807,-14949081,18345767,-13403753,16291481,-5314038 }, + { -33229194,2553288,32678213,9875984,8534129,6889387,-9676774,6957617,4368891,9788741 }, + { 16660756,7281060,-10830758,12911820,20108584,-8101676,-21722536,-8613148,16250552,-11111103 }, + }, + { + { -19765507,2390526,-16551031,14161980,1905286,6414907,4689584,10604807,-30190403,4782747 }, + { -1354539,14736941,-7367442,-13292886,7710542,-14155590,-9981571,4383045,22546403,437323 }, + { 31665577,-12180464,-16186830,1491339,-18368625,3294682,27343084,2786261,-30633590,-14097016 }, + }, + { + { -14467279,-683715,-33374107,7448552,19294360,14334329,-19690631,2355319,-19284671,-6114373 }, + { 15121312,-15796162,6377020,-6031361,-10798111,-12957845,18952177,15496498,-29380133,11754228 }, + { -2637277,-13483075,8488727,-14303896,12728761,-1622493,7141596,11724556,22761615,-10134141 }, + }, + { + { 16918416,11729663,-18083579,3022987,-31015732,-13339659,-28741185,-12227393,32851222,11717399 }, + { 11166634,7338049,-6722523,4531520,-29468672,-7302055,31474879,3483633,-1193175,-4030831 }, + { -185635,9921305,31456609,-13536438,-12013818,13348923,33142652,6546660,-19985279,-3948376 }, + }, + { + { -32460596,11266712,-11197107,-7899103,31703694,3855903,-8537131,-12833048,-30772034,-15486313 }, + { -18006477,12709068,3991746,-6479188,-21491523,-10550425,-31135347,-16049879,10928917,3011958 }, + { -6957757,-15594337,31696059,334240,29576716,14796075,-30831056,-12805180,18008031,10258577 }, + }, + { + { -22448644,15655569,7018479,-4410003,-30314266,-1201591,-1853465,1367120,25127874,6671743 }, + { 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684 }, + { -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476 }, + }, +}, diff --git a/src/ext/ed25519/ref10/base.py b/src/ext/ed25519/ref10/base.py new file mode 100644 index 0000000000..84accc8580 --- /dev/null +++ b/src/ext/ed25519/ref10/base.py @@ -0,0 +1,65 @@ +b = 256 +q = 2**255 - 19 +l = 2**252 + 27742317777372353535851937790883648493 + +def expmod(b,e,m): + if e == 0: return 1 + t = expmod(b,e/2,m)**2 % m + if e & 1: t = (t*b) % m + return t + +def inv(x): + return expmod(x,q-2,q) + +d = -121665 * inv(121666) +I = expmod(2,(q-1)/4,q) + +def xrecover(y): + xx = (y*y-1) * inv(d*y*y+1) + x = expmod(xx,(q+3)/8,q) + if (x*x - xx) % q != 0: x = (x*I) % q + if x % 2 != 0: x = q-x + return x + +By = 4 * inv(5) +Bx = xrecover(By) +B = [Bx % q,By % q] + +def edwards(P,Q): + x1 = P[0] + y1 = P[1] + x2 = Q[0] + y2 = Q[1] + x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2) + y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2) + return [x3 % q,y3 % q] + +def radix255(x): + x = x % q + if x + x > q: x -= q + x = [x,0,0,0,0,0,0,0,0,0] + bits = [26,25,26,25,26,25,26,25,26,25] + for i in range(9): + carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i] + x[i] -= carry * 2**bits[i] + x[i + 1] += carry + result = "" + for i in range(9): + result = result+str(x[i])+"," + result = result+str(x[9]) + return result + +Bi = B +for i in range(32): + print "{" + Bij = Bi + for j in range(8): + print " {" + print " {",radix255(Bij[1]+Bij[0]),"}," + print " {",radix255(Bij[1]-Bij[0]),"}," + print " {",radix255(2*d*Bij[0]*Bij[1]),"}," + Bij = edwards(Bij,Bi) + print " }," + print "}," + for k in range(8): + Bi = edwards(Bi,Bi) diff --git a/src/ext/ed25519/ref10/base2.h b/src/ext/ed25519/ref10/base2.h new file mode 100644 index 0000000000..8c538440ff --- /dev/null +++ b/src/ext/ed25519/ref10/base2.h @@ -0,0 +1,40 @@ + { + { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, + { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, + { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, + }, + { + { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, + { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, + { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, + }, + { + { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, + { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, + { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, + }, + { + { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, + { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, + { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, + }, + { + { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 }, + { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 }, + { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 }, + }, + { + { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 }, + { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 }, + { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 }, + }, + { + { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 }, + { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 }, + { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 }, + }, + { + { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 }, + { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 }, + { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, + }, diff --git a/src/ext/ed25519/ref10/base2.py b/src/ext/ed25519/ref10/base2.py new file mode 100644 index 0000000000..5e4e8739d0 --- /dev/null +++ b/src/ext/ed25519/ref10/base2.py @@ -0,0 +1,60 @@ +b = 256 +q = 2**255 - 19 +l = 2**252 + 27742317777372353535851937790883648493 + +def expmod(b,e,m): + if e == 0: return 1 + t = expmod(b,e/2,m)**2 % m + if e & 1: t = (t*b) % m + return t + +def inv(x): + return expmod(x,q-2,q) + +d = -121665 * inv(121666) +I = expmod(2,(q-1)/4,q) + +def xrecover(y): + xx = (y*y-1) * inv(d*y*y+1) + x = expmod(xx,(q+3)/8,q) + if (x*x - xx) % q != 0: x = (x*I) % q + if x % 2 != 0: x = q-x + return x + +By = 4 * inv(5) +Bx = xrecover(By) +B = [Bx % q,By % q] + +def edwards(P,Q): + x1 = P[0] + y1 = P[1] + x2 = Q[0] + y2 = Q[1] + x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2) + y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2) + return [x3 % q,y3 % q] + +def radix255(x): + x = x % q + if x + x > q: x -= q + x = [x,0,0,0,0,0,0,0,0,0] + bits = [26,25,26,25,26,25,26,25,26,25] + for i in range(9): + carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i] + x[i] -= carry * 2**bits[i] + x[i + 1] += carry + result = "" + for i in range(9): + result = result+str(x[i])+"," + result = result+str(x[9]) + return result + +Bi = B + +for i in range(8): + print " {" + print " {",radix255(Bi[1]+Bi[0]),"}," + print " {",radix255(Bi[1]-Bi[0]),"}," + print " {",radix255(2*d*Bi[0]*Bi[1]),"}," + print " }," + Bi = edwards(B,edwards(B,Bi)) diff --git a/src/ext/ed25519/ref10/blinding.c b/src/ext/ed25519/ref10/blinding.c new file mode 100644 index 0000000000..4d9a9cbbe7 --- /dev/null +++ b/src/ext/ed25519/ref10/blinding.c @@ -0,0 +1,76 @@ +/* Added to ref10 for Tor. We place this in the public domain. Alternatively, + * you may have it under the Creative Commons 0 "CC0" license. */ +//#include "fe.h" +#include "ge.h" +#include "sc.h" +#include "crypto_hash_sha512.h" +#include "ed25519_ref10.h" + +#include <string.h> +#include "crypto.h" + +static void +gettweak(unsigned char *out, const unsigned char *param) +{ + const char str[] = "Derive temporary signing key"; + crypto_hash_sha512_2(out, (const unsigned char*)str, strlen(str), param, 32); + out[0] &= 248; /* Is this necessary necessary ? */ + out[31] &= 63; + out[31] |= 64; +} + +int ed25519_ref10_blind_secret_key(unsigned char *out, + const unsigned char *inp, + const unsigned char *param) +{ + const char str[] = "Derive temporary signing key hash input"; + unsigned char tweak[64]; + unsigned char zero[32]; + gettweak(tweak, param); + + memset(zero, 0, 32); + sc_muladd(out, inp, tweak, zero); + + crypto_hash_sha512_2(tweak, (const unsigned char *)str, strlen(str), + inp+32, 32); + memcpy(out+32, tweak, 32); + + memwipe(tweak, 0, sizeof(tweak)); + + return 0; +} + +int ed25519_ref10_blind_public_key(unsigned char *out, + const unsigned char *inp, + const unsigned char *param) +{ + unsigned char tweak[64]; + unsigned char zero[32]; + unsigned char pkcopy[32]; + ge_p3 A; + ge_p2 Aprime; + + gettweak(tweak, param); + + memset(zero, 0, sizeof(zero)); + /* Not the greatest implementation of all of this. I wish I had + * better-suited primitives to work with here... (but I don't wish that so + * strongly that I'm about to code my own ge_scalarmult_vartime). */ + + /* We negate the public key first, so that we can pass it to + * frombytes_negate_vartime, which negates it again. If there were a + * "ge_frombytes", we'd use that, but there isn't. */ + memcpy(pkcopy, inp, 32); + pkcopy[31] ^= (1<<7); + ge_frombytes_negate_vartime(&A, pkcopy); + /* There isn't a regular ge_scalarmult -- we have to do tweak*A + zero*B. */ + ge_double_scalarmult_vartime(&Aprime, tweak, &A, zero); + ge_tobytes(out, &Aprime); + + memwipe(tweak, 0, sizeof(tweak)); + memwipe(&A, 0, sizeof(A)); + memwipe(&Aprime, 0, sizeof(Aprime)); + memwipe(pkcopy, 0, sizeof(pkcopy)); + + return 0; +} diff --git a/src/ext/ed25519/ref10/crypto_hash_sha512.h b/src/ext/ed25519/ref10/crypto_hash_sha512.h new file mode 100644 index 0000000000..0278571522 --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_hash_sha512.h @@ -0,0 +1,30 @@ +/* Added for Tor. */ +#include <openssl/sha.h> + +/* Set 'out' to the 512-bit SHA512 hash of the 'len'-byte string in 'inp' */ +#define crypto_hash_sha512(out, inp, len) \ + SHA512((inp), (len), (out)) + +/* Set 'out' to the 512-bit SHA512 hash of the 'len1'-byte string in 'inp1', + * concatenated with the 'len2'-byte string in 'inp2'. */ +#define crypto_hash_sha512_2(out, inp1, len1, inp2, len2) \ + do { \ + SHA512_CTX sha_ctx_; \ + SHA512_Init(&sha_ctx_); \ + SHA512_Update(&sha_ctx_, (inp1), (len1)); \ + SHA512_Update(&sha_ctx_, (inp2), (len2)); \ + SHA512_Final((out), &sha_ctx_); \ + } while(0) + +/* Set 'out' to the 512-bit SHA512 hash of the 'len1'-byte string in 'inp1', + * concatenated with the 'len2'-byte string in 'inp2', concatenated with + * the 'len3'-byte string in 'len3'. */ +#define crypto_hash_sha512_3(out, inp1, len1, inp2, len2, inp3, len3) \ + do { \ + SHA512_CTX sha_ctx_; \ + SHA512_Init(&sha_ctx_); \ + SHA512_Update(&sha_ctx_, (inp1), (len1)); \ + SHA512_Update(&sha_ctx_, (inp2), (len2)); \ + SHA512_Update(&sha_ctx_, (inp3), (len3)); \ + SHA512_Final((out), &sha_ctx_); \ + } while(0) diff --git a/src/ext/ed25519/ref10/crypto_int32.h b/src/ext/ed25519/ref10/crypto_int32.h new file mode 100644 index 0000000000..dd13c91bd0 --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_int32.h @@ -0,0 +1,25 @@ +/* Added for Tor. */ + +#ifndef CRYPTO_INT32_H +#define CRYPTO_INT32_H + +#include "torint.h" +#define crypto_int32 int32_t +#define crypto_uint32 uint32_t + +/* + Stop signed left shifts overflowing + by using unsigned types for bitwise operations + */ + +#ifndef OVERFLOW_SAFE_SIGNED_LSHIFT +#define OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, utype, stype) \ + ((stype)((utype)(s) << (utype)(lshift))) +#endif + +#define SHL32(s, lshift) \ + OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, crypto_uint32, crypto_int32) +#define SHL8(s, lshift) \ + OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, unsigned char, signed char) + +#endif /* CRYPTO_INT32_H */ diff --git a/src/ext/ed25519/ref10/crypto_int64.h b/src/ext/ed25519/ref10/crypto_int64.h new file mode 100644 index 0000000000..46e8852ed0 --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_int64.h @@ -0,0 +1,23 @@ +/* Added for Tor. */ + +#ifndef CRYPTO_INT64_H +#define CRYPTO_INT64_H + +#include "torint.h" +#define crypto_int64 int64_t +#define crypto_uint64 uint64_t + +/* + Stop signed left shifts overflowing + by using unsigned types for bitwise operations + */ + +#ifndef OVERFLOW_SAFE_SIGNED_LSHIFT +#define OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, utype, stype) \ + ((stype)((utype)(s) << (utype)(lshift))) +#endif + +#define SHL64(s, lshift) \ + OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, crypto_uint64, crypto_int64) + +#endif /* CRYPTO_INT64_H */ diff --git a/src/ext/ed25519/ref10/crypto_sign.h b/src/ext/ed25519/ref10/crypto_sign.h new file mode 100644 index 0000000000..549626793a --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_sign.h @@ -0,0 +1,9 @@ +/* Added for Tor */ +#define crypto_sign ed25519_ref10_sign +#define crypto_sign_keypair ed25519_ref10_keygen +#define crypto_sign_seckey ed25519_ref10_seckey +#define crypto_sign_seckey_expand ed25519_ref10_seckey_expand +#define crypto_sign_pubkey ed25519_ref10_pubkey +#define crypto_sign_open ed25519_ref10_open + +#include "ed25519_ref10.h" diff --git a/src/ext/ed25519/ref10/crypto_uint32.h b/src/ext/ed25519/ref10/crypto_uint32.h new file mode 100644 index 0000000000..62655a5b66 --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_uint32.h @@ -0,0 +1,3 @@ +/* Added for Tor. */ +#include "torint.h" +#define crypto_uint32 uint32_t diff --git a/src/ext/ed25519/ref10/crypto_uint64.h b/src/ext/ed25519/ref10/crypto_uint64.h new file mode 100644 index 0000000000..cbda882a6a --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_uint64.h @@ -0,0 +1,3 @@ +/* Added for Tor. */ +#include "torint.h" +#define crypto_uint64 uint64_t diff --git a/src/ext/ed25519/ref10/crypto_verify_32.h b/src/ext/ed25519/ref10/crypto_verify_32.h new file mode 100644 index 0000000000..0f63efc7a3 --- /dev/null +++ b/src/ext/ed25519/ref10/crypto_verify_32.h @@ -0,0 +1,5 @@ +/* Added for Tor. */ +#include "di_ops.h" +#define crypto_verify_32(a,b) \ + (! tor_memeq((a), (b), 32)) + diff --git a/src/ext/ed25519/ref10/d.h b/src/ext/ed25519/ref10/d.h new file mode 100644 index 0000000000..e25f578350 --- /dev/null +++ b/src/ext/ed25519/ref10/d.h @@ -0,0 +1 @@ +-10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116 diff --git a/src/ext/ed25519/ref10/d.py b/src/ext/ed25519/ref10/d.py new file mode 100644 index 0000000000..8995bb86a3 --- /dev/null +++ b/src/ext/ed25519/ref10/d.py @@ -0,0 +1,28 @@ +q = 2**255 - 19 + +def expmod(b,e,m): + if e == 0: return 1 + t = expmod(b,e/2,m)**2 % m + if e & 1: t = (t*b) % m + return t + +def inv(x): + return expmod(x,q-2,q) + +def radix255(x): + x = x % q + if x + x > q: x -= q + x = [x,0,0,0,0,0,0,0,0,0] + bits = [26,25,26,25,26,25,26,25,26,25] + for i in range(9): + carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i] + x[i] -= carry * 2**bits[i] + x[i + 1] += carry + result = "" + for i in range(9): + result = result+str(x[i])+"," + result = result+str(x[9]) + return result + +d = -121665 * inv(121666) +print radix255(d) diff --git a/src/ext/ed25519/ref10/d2.h b/src/ext/ed25519/ref10/d2.h new file mode 100644 index 0000000000..01aaec7512 --- /dev/null +++ b/src/ext/ed25519/ref10/d2.h @@ -0,0 +1 @@ +-21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199 diff --git a/src/ext/ed25519/ref10/d2.py b/src/ext/ed25519/ref10/d2.py new file mode 100644 index 0000000000..79841758be --- /dev/null +++ b/src/ext/ed25519/ref10/d2.py @@ -0,0 +1,28 @@ +q = 2**255 - 19 + +def expmod(b,e,m): + if e == 0: return 1 + t = expmod(b,e/2,m)**2 % m + if e & 1: t = (t*b) % m + return t + +def inv(x): + return expmod(x,q-2,q) + +def radix255(x): + x = x % q + if x + x > q: x -= q + x = [x,0,0,0,0,0,0,0,0,0] + bits = [26,25,26,25,26,25,26,25,26,25] + for i in range(9): + carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i] + x[i] -= carry * 2**bits[i] + x[i + 1] += carry + result = "" + for i in range(9): + result = result+str(x[i])+"," + result = result+str(x[9]) + return result + +d = -121665 * inv(121666) +print radix255(d*2) diff --git a/src/ext/ed25519/ref10/ed25519_ref10.h b/src/ext/ed25519/ref10/ed25519_ref10.h new file mode 100644 index 0000000000..af7e21a2ad --- /dev/null +++ b/src/ext/ed25519/ref10/ed25519_ref10.h @@ -0,0 +1,30 @@ +/* Added for Tor */ +#ifndef SRC_EXT_ED25519_REF10_H_INCLUDED_ +#define SRC_EXT_ED25519_REF10_H_INCLUDED_ +#include <torint.h> + +int ed25519_ref10_seckey(unsigned char *sk); +int ed25519_ref10_seckey_expand(unsigned char *sk, const unsigned char *sk_seed); +int ed25519_ref10_pubkey(unsigned char *pk,const unsigned char *sk); +int ed25519_ref10_keygen(unsigned char *pk,unsigned char *sk); +int ed25519_ref10_open( + const unsigned char *signature, + const unsigned char *m, size_t mlen, + const unsigned char *pk); +int ed25519_ref10_sign( + unsigned char *sig, + const unsigned char *m, size_t mlen, + const unsigned char *sk, const unsigned char *pk); + +/* Added in Tor */ +int ed25519_ref10_pubkey_from_curve25519_pubkey(unsigned char *out, + const unsigned char *inp, + int signbit); +int ed25519_ref10_blind_secret_key(unsigned char *out, + const unsigned char *inp, + const unsigned char *param); +int ed25519_ref10_blind_public_key(unsigned char *out, + const unsigned char *inp, + const unsigned char *param); + +#endif diff --git a/src/ext/ed25519/ref10/fe.h b/src/ext/ed25519/ref10/fe.h new file mode 100644 index 0000000000..60c308ba46 --- /dev/null +++ b/src/ext/ed25519/ref10/fe.h @@ -0,0 +1,56 @@ +#ifndef FE_H +#define FE_H + +#include "crypto_int32.h" + +typedef crypto_int32 fe[10]; + +/* +fe means field element. +Here the field is \Z/(2^255-19). +An element t, entries t[0]...t[9], represents the integer +t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. +Bounds on each t[i] vary depending on context. +*/ + +#define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes +#define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes +#define fe_copy crypto_sign_ed25519_ref10_fe_copy +#define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero +#define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative +#define fe_0 crypto_sign_ed25519_ref10_fe_0 +#define fe_1 crypto_sign_ed25519_ref10_fe_1 +#define fe_cswap crypto_sign_ed25519_ref10_fe_cswap +#define fe_cmov crypto_sign_ed25519_ref10_fe_cmov +#define fe_add crypto_sign_ed25519_ref10_fe_add +#define fe_sub crypto_sign_ed25519_ref10_fe_sub +#define fe_neg crypto_sign_ed25519_ref10_fe_neg +#define fe_mul crypto_sign_ed25519_ref10_fe_mul +#define fe_sq crypto_sign_ed25519_ref10_fe_sq +#define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2 +#define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666 +#define fe_invert crypto_sign_ed25519_ref10_fe_invert +#define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523 + +extern void fe_frombytes(fe,const unsigned char *); +extern void fe_tobytes(unsigned char *,const fe); + +extern void fe_copy(fe,const fe); +extern int fe_isnonzero(const fe); +extern int fe_isnegative(const fe); +extern void fe_0(fe); +extern void fe_1(fe); +extern void fe_cswap(fe,fe,unsigned int); +extern void fe_cmov(fe,const fe,unsigned int); + +extern void fe_add(fe,const fe,const fe); +extern void fe_sub(fe,const fe,const fe); +extern void fe_neg(fe,const fe); +extern void fe_mul(fe,const fe,const fe); +extern void fe_sq(fe,const fe); +extern void fe_sq2(fe,const fe); +extern void fe_mul121666(fe,const fe); +extern void fe_invert(fe,const fe); +extern void fe_pow22523(fe,const fe); + +#endif diff --git a/src/ext/ed25519/ref10/fe_0.c b/src/ext/ed25519/ref10/fe_0.c new file mode 100644 index 0000000000..ec879d7337 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_0.c @@ -0,0 +1,19 @@ +#include "fe.h" + +/* +h = 0 +*/ + +void fe_0(fe h) +{ + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} diff --git a/src/ext/ed25519/ref10/fe_1.c b/src/ext/ed25519/ref10/fe_1.c new file mode 100644 index 0000000000..8cf7784844 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_1.c @@ -0,0 +1,19 @@ +#include "fe.h" + +/* +h = 1 +*/ + +void fe_1(fe h) +{ + h[0] = 1; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} diff --git a/src/ext/ed25519/ref10/fe_add.c b/src/ext/ed25519/ref10/fe_add.c new file mode 100644 index 0000000000..e6a81da202 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_add.c @@ -0,0 +1,57 @@ +#include "fe.h" + +/* +h = f + g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_add(fe h,const fe f,const fe g) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 g0 = g[0]; + crypto_int32 g1 = g[1]; + crypto_int32 g2 = g[2]; + crypto_int32 g3 = g[3]; + crypto_int32 g4 = g[4]; + crypto_int32 g5 = g[5]; + crypto_int32 g6 = g[6]; + crypto_int32 g7 = g[7]; + crypto_int32 g8 = g[8]; + crypto_int32 g9 = g[9]; + crypto_int32 h0 = f0 + g0; + crypto_int32 h1 = f1 + g1; + crypto_int32 h2 = f2 + g2; + crypto_int32 h3 = f3 + g3; + crypto_int32 h4 = f4 + g4; + crypto_int32 h5 = f5 + g5; + crypto_int32 h6 = f6 + g6; + crypto_int32 h7 = f7 + g7; + crypto_int32 h8 = f8 + g8; + crypto_int32 h9 = f9 + g9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} diff --git a/src/ext/ed25519/ref10/fe_cmov.c b/src/ext/ed25519/ref10/fe_cmov.c new file mode 100644 index 0000000000..8ca584fb19 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_cmov.c @@ -0,0 +1,63 @@ +#include "fe.h" + +/* +Replace (f,g) with (g,g) if b == 1; +replace (f,g) with (f,g) if b == 0. + +Preconditions: b in {0,1}. +*/ + +void fe_cmov(fe f,const fe g,unsigned int b) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 g0 = g[0]; + crypto_int32 g1 = g[1]; + crypto_int32 g2 = g[2]; + crypto_int32 g3 = g[3]; + crypto_int32 g4 = g[4]; + crypto_int32 g5 = g[5]; + crypto_int32 g6 = g[6]; + crypto_int32 g7 = g[7]; + crypto_int32 g8 = g[8]; + crypto_int32 g9 = g[9]; + crypto_int32 x0 = f0 ^ g0; + crypto_int32 x1 = f1 ^ g1; + crypto_int32 x2 = f2 ^ g2; + crypto_int32 x3 = f3 ^ g3; + crypto_int32 x4 = f4 ^ g4; + crypto_int32 x5 = f5 ^ g5; + crypto_int32 x6 = f6 ^ g6; + crypto_int32 x7 = f7 ^ g7; + crypto_int32 x8 = f8 ^ g8; + crypto_int32 x9 = f9 ^ g9; + b = -b; + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + f[0] = f0 ^ x0; + f[1] = f1 ^ x1; + f[2] = f2 ^ x2; + f[3] = f3 ^ x3; + f[4] = f4 ^ x4; + f[5] = f5 ^ x5; + f[6] = f6 ^ x6; + f[7] = f7 ^ x7; + f[8] = f8 ^ x8; + f[9] = f9 ^ x9; +} diff --git a/src/ext/ed25519/ref10/fe_copy.c b/src/ext/ed25519/ref10/fe_copy.c new file mode 100644 index 0000000000..9c5bf865a2 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_copy.c @@ -0,0 +1,29 @@ +#include "fe.h" + +/* +h = f +*/ + +void fe_copy(fe h,const fe f) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + h[0] = f0; + h[1] = f1; + h[2] = f2; + h[3] = f3; + h[4] = f4; + h[5] = f5; + h[6] = f6; + h[7] = f7; + h[8] = f8; + h[9] = f9; +} diff --git a/src/ext/ed25519/ref10/fe_frombytes.c b/src/ext/ed25519/ref10/fe_frombytes.c new file mode 100644 index 0000000000..98b8e5f7c1 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_frombytes.c @@ -0,0 +1,73 @@ +#include "fe.h" +#include "crypto_int64.h" +#include "crypto_uint64.h" + +static crypto_uint64 load_3(const unsigned char *in) +{ + crypto_uint64 result; + result = (crypto_uint64) in[0]; + result |= ((crypto_uint64) in[1]) << 8; + result |= ((crypto_uint64) in[2]) << 16; + return result; +} + +static crypto_uint64 load_4(const unsigned char *in) +{ + crypto_uint64 result; + result = (crypto_uint64) in[0]; + result |= ((crypto_uint64) in[1]) << 8; + result |= ((crypto_uint64) in[2]) << 16; + result |= ((crypto_uint64) in[3]) << 24; + return result; +} + +/* +Ignores top bit of h. +*/ + +void fe_frombytes(fe h,const unsigned char *s) +{ + crypto_int64 h0 = load_4(s); + crypto_int64 h1 = load_3(s + 4) << 6; + crypto_int64 h2 = load_3(s + 7) << 5; + crypto_int64 h3 = load_3(s + 10) << 3; + crypto_int64 h4 = load_3(s + 13) << 2; + crypto_int64 h5 = load_4(s + 16); + crypto_int64 h6 = load_3(s + 20) << 7; + crypto_int64 h7 = load_3(s + 23) << 5; + crypto_int64 h8 = load_3(s + 26) << 4; + crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2; + crypto_int64 carry0; + crypto_int64 carry1; + crypto_int64 carry2; + crypto_int64 carry3; + crypto_int64 carry4; + crypto_int64 carry5; + crypto_int64 carry6; + crypto_int64 carry7; + crypto_int64 carry8; + crypto_int64 carry9; + + carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25); + carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25); + carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25); + carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25); + carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25); + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26); + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26); + carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26); + + h[0] = (crypto_int32) h0; + h[1] = (crypto_int32) h1; + h[2] = (crypto_int32) h2; + h[3] = (crypto_int32) h3; + h[4] = (crypto_int32) h4; + h[5] = (crypto_int32) h5; + h[6] = (crypto_int32) h6; + h[7] = (crypto_int32) h7; + h[8] = (crypto_int32) h8; + h[9] = (crypto_int32) h9; +} diff --git a/src/ext/ed25519/ref10/fe_invert.c b/src/ext/ed25519/ref10/fe_invert.c new file mode 100644 index 0000000000..bcfdb8ff87 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_invert.c @@ -0,0 +1,14 @@ +#include "fe.h" + +void fe_invert(fe out,const fe z) +{ + fe t0; + fe t1; + fe t2; + fe t3; + int i; + +#include "pow225521.h" + + return; +} diff --git a/src/ext/ed25519/ref10/fe_isnegative.c b/src/ext/ed25519/ref10/fe_isnegative.c new file mode 100644 index 0000000000..3b2c8b8d52 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_isnegative.c @@ -0,0 +1,16 @@ +#include "fe.h" + +/* +return 1 if f is in {1,3,5,...,q-2} +return 0 if f is in {0,2,4,...,q-1} + +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +int fe_isnegative(const fe f) +{ + unsigned char s[32]; + fe_tobytes(s,f); + return s[0] & 1; +} diff --git a/src/ext/ed25519/ref10/fe_isnonzero.c b/src/ext/ed25519/ref10/fe_isnonzero.c new file mode 100644 index 0000000000..47568001ce --- /dev/null +++ b/src/ext/ed25519/ref10/fe_isnonzero.c @@ -0,0 +1,19 @@ +#include "fe.h" +#include "crypto_verify_32.h" + +/* +return 1 if f == 0 +return 0 if f != 0 + +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +static const unsigned char zero[32]; + +int fe_isnonzero(const fe f) +{ + unsigned char s[32]; + fe_tobytes(s,f); + return crypto_verify_32(s,zero); +} diff --git a/src/ext/ed25519/ref10/fe_mul.c b/src/ext/ed25519/ref10/fe_mul.c new file mode 100644 index 0000000000..ace63e64c1 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_mul.c @@ -0,0 +1,253 @@ +#include "fe.h" +#include "crypto_int64.h" + +/* +h = f * g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +Notes on implementation strategy: + +Using schoolbook multiplication. +Karatsuba would save a little in some cost models. + +Most multiplications by 2 and 19 are 32-bit precomputations; +cheaper than 64-bit postcomputations. + +There is one remaining multiplication by 19 in the carry chain; +one *19 precomputation can be merged into this, +but the resulting data flow is considerably less clean. + +There are 12 carries below. +10 of them are 2-way parallelizable and vectorizable. +Can get away with 11 carries, but then data flow is much deeper. + +With tighter constraints on inputs can squeeze carries into int32. +*/ + +void fe_mul(fe h,const fe f,const fe g) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 g0 = g[0]; + crypto_int32 g1 = g[1]; + crypto_int32 g2 = g[2]; + crypto_int32 g3 = g[3]; + crypto_int32 g4 = g[4]; + crypto_int32 g5 = g[5]; + crypto_int32 g6 = g[6]; + crypto_int32 g7 = g[7]; + crypto_int32 g8 = g[8]; + crypto_int32 g9 = g[9]; + crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */ + crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + crypto_int32 g3_19 = 19 * g3; + crypto_int32 g4_19 = 19 * g4; + crypto_int32 g5_19 = 19 * g5; + crypto_int32 g6_19 = 19 * g6; + crypto_int32 g7_19 = 19 * g7; + crypto_int32 g8_19 = 19 * g8; + crypto_int32 g9_19 = 19 * g9; + crypto_int32 f1_2 = 2 * f1; + crypto_int32 f3_2 = 2 * f3; + crypto_int32 f5_2 = 2 * f5; + crypto_int32 f7_2 = 2 * f7; + crypto_int32 f9_2 = 2 * f9; + crypto_int64 f0g0 = f0 * (crypto_int64) g0; + crypto_int64 f0g1 = f0 * (crypto_int64) g1; + crypto_int64 f0g2 = f0 * (crypto_int64) g2; + crypto_int64 f0g3 = f0 * (crypto_int64) g3; + crypto_int64 f0g4 = f0 * (crypto_int64) g4; + crypto_int64 f0g5 = f0 * (crypto_int64) g5; + crypto_int64 f0g6 = f0 * (crypto_int64) g6; + crypto_int64 f0g7 = f0 * (crypto_int64) g7; + crypto_int64 f0g8 = f0 * (crypto_int64) g8; + crypto_int64 f0g9 = f0 * (crypto_int64) g9; + crypto_int64 f1g0 = f1 * (crypto_int64) g0; + crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1; + crypto_int64 f1g2 = f1 * (crypto_int64) g2; + crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3; + crypto_int64 f1g4 = f1 * (crypto_int64) g4; + crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5; + crypto_int64 f1g6 = f1 * (crypto_int64) g6; + crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7; + crypto_int64 f1g8 = f1 * (crypto_int64) g8; + crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19; + crypto_int64 f2g0 = f2 * (crypto_int64) g0; + crypto_int64 f2g1 = f2 * (crypto_int64) g1; + crypto_int64 f2g2 = f2 * (crypto_int64) g2; + crypto_int64 f2g3 = f2 * (crypto_int64) g3; + crypto_int64 f2g4 = f2 * (crypto_int64) g4; + crypto_int64 f2g5 = f2 * (crypto_int64) g5; + crypto_int64 f2g6 = f2 * (crypto_int64) g6; + crypto_int64 f2g7 = f2 * (crypto_int64) g7; + crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19; + crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19; + crypto_int64 f3g0 = f3 * (crypto_int64) g0; + crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1; + crypto_int64 f3g2 = f3 * (crypto_int64) g2; + crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3; + crypto_int64 f3g4 = f3 * (crypto_int64) g4; + crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5; + crypto_int64 f3g6 = f3 * (crypto_int64) g6; + crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19; + crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19; + crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19; + crypto_int64 f4g0 = f4 * (crypto_int64) g0; + crypto_int64 f4g1 = f4 * (crypto_int64) g1; + crypto_int64 f4g2 = f4 * (crypto_int64) g2; + crypto_int64 f4g3 = f4 * (crypto_int64) g3; + crypto_int64 f4g4 = f4 * (crypto_int64) g4; + crypto_int64 f4g5 = f4 * (crypto_int64) g5; + crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19; + crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19; + crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19; + crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19; + crypto_int64 f5g0 = f5 * (crypto_int64) g0; + crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1; + crypto_int64 f5g2 = f5 * (crypto_int64) g2; + crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3; + crypto_int64 f5g4 = f5 * (crypto_int64) g4; + crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19; + crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19; + crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19; + crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19; + crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19; + crypto_int64 f6g0 = f6 * (crypto_int64) g0; + crypto_int64 f6g1 = f6 * (crypto_int64) g1; + crypto_int64 f6g2 = f6 * (crypto_int64) g2; + crypto_int64 f6g3 = f6 * (crypto_int64) g3; + crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19; + crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19; + crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19; + crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19; + crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19; + crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19; + crypto_int64 f7g0 = f7 * (crypto_int64) g0; + crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1; + crypto_int64 f7g2 = f7 * (crypto_int64) g2; + crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19; + crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19; + crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19; + crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19; + crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19; + crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19; + crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19; + crypto_int64 f8g0 = f8 * (crypto_int64) g0; + crypto_int64 f8g1 = f8 * (crypto_int64) g1; + crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19; + crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19; + crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19; + crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19; + crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19; + crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19; + crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19; + crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19; + crypto_int64 f9g0 = f9 * (crypto_int64) g0; + crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19; + crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19; + crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19; + crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19; + crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19; + crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19; + crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19; + crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19; + crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19; + crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; + crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; + crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; + crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; + crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; + crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; + crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; + crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; + crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; + crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; + crypto_int64 carry0; + crypto_int64 carry1; + crypto_int64 carry2; + crypto_int64 carry3; + crypto_int64 carry4; + crypto_int64 carry5; + crypto_int64 carry6; + crypto_int64 carry7; + crypto_int64 carry8; + crypto_int64 carry9; + + /* + |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) + i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 + |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) + i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 + */ + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + /* |h0| <= 2^25 */ + /* |h4| <= 2^25 */ + /* |h1| <= 1.71*2^59 */ + /* |h5| <= 1.71*2^59 */ + + carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25); + carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25); + /* |h1| <= 2^24; from now on fits into int32 */ + /* |h5| <= 2^24; from now on fits into int32 */ + /* |h2| <= 1.41*2^60 */ + /* |h6| <= 1.41*2^60 */ + + carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26); + carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26); + /* |h2| <= 2^25; from now on fits into int32 unchanged */ + /* |h6| <= 2^25; from now on fits into int32 unchanged */ + /* |h3| <= 1.71*2^59 */ + /* |h7| <= 1.71*2^59 */ + + carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25); + carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25); + /* |h3| <= 2^24; from now on fits into int32 unchanged */ + /* |h7| <= 2^24; from now on fits into int32 unchanged */ + /* |h4| <= 1.72*2^34 */ + /* |h8| <= 1.41*2^60 */ + + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26); + /* |h4| <= 2^25; from now on fits into int32 unchanged */ + /* |h8| <= 2^25; from now on fits into int32 unchanged */ + /* |h5| <= 1.01*2^24 */ + /* |h9| <= 1.71*2^59 */ + + carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25); + /* |h9| <= 2^24; from now on fits into int32 unchanged */ + /* |h0| <= 1.1*2^39 */ + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + /* |h0| <= 2^25; from now on fits into int32 unchanged */ + /* |h1| <= 1.01*2^24 */ + + h[0] = (crypto_int32) h0; + h[1] = (crypto_int32) h1; + h[2] = (crypto_int32) h2; + h[3] = (crypto_int32) h3; + h[4] = (crypto_int32) h4; + h[5] = (crypto_int32) h5; + h[6] = (crypto_int32) h6; + h[7] = (crypto_int32) h7; + h[8] = (crypto_int32) h8; + h[9] = (crypto_int32) h9; +} diff --git a/src/ext/ed25519/ref10/fe_neg.c b/src/ext/ed25519/ref10/fe_neg.c new file mode 100644 index 0000000000..2078ce5284 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_neg.c @@ -0,0 +1,45 @@ +#include "fe.h" + +/* +h = -f + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +*/ + +void fe_neg(fe h,const fe f) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 h0 = -f0; + crypto_int32 h1 = -f1; + crypto_int32 h2 = -f2; + crypto_int32 h3 = -f3; + crypto_int32 h4 = -f4; + crypto_int32 h5 = -f5; + crypto_int32 h6 = -f6; + crypto_int32 h7 = -f7; + crypto_int32 h8 = -f8; + crypto_int32 h9 = -f9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} diff --git a/src/ext/ed25519/ref10/fe_pow22523.c b/src/ext/ed25519/ref10/fe_pow22523.c new file mode 100644 index 0000000000..56675a5902 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_pow22523.c @@ -0,0 +1,13 @@ +#include "fe.h" + +void fe_pow22523(fe out,const fe z) +{ + fe t0; + fe t1; + fe t2; + int i; + +#include "pow22523.h" + + return; +} diff --git a/src/ext/ed25519/ref10/fe_sq.c b/src/ext/ed25519/ref10/fe_sq.c new file mode 100644 index 0000000000..0022a17510 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_sq.c @@ -0,0 +1,149 @@ +#include "fe.h" +#include "crypto_int64.h" + +/* +h = f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq(fe h,const fe f) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 f0_2 = 2 * f0; + crypto_int32 f1_2 = 2 * f1; + crypto_int32 f2_2 = 2 * f2; + crypto_int32 f3_2 = 2 * f3; + crypto_int32 f4_2 = 2 * f4; + crypto_int32 f5_2 = 2 * f5; + crypto_int32 f6_2 = 2 * f6; + crypto_int32 f7_2 = 2 * f7; + crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ + crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ + crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ + crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ + crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ + crypto_int64 f0f0 = f0 * (crypto_int64) f0; + crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; + crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; + crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; + crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; + crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; + crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; + crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; + crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; + crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; + crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; + crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; + crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; + crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; + crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; + crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; + crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; + crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; + crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; + crypto_int64 f2f2 = f2 * (crypto_int64) f2; + crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; + crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; + crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; + crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; + crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; + crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; + crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; + crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; + crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; + crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; + crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; + crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; + crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; + crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; + crypto_int64 f4f4 = f4 * (crypto_int64) f4; + crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; + crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; + crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; + crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; + crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; + crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; + crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; + crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; + crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; + crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; + crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; + crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; + crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; + crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; + crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; + crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; + crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; + crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; + crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; + crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; + crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; + crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; + crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; + crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; + crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; + crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; + crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; + crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; + crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; + crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; + crypto_int64 carry0; + crypto_int64 carry1; + crypto_int64 carry2; + crypto_int64 carry3; + crypto_int64 carry4; + crypto_int64 carry5; + crypto_int64 carry6; + crypto_int64 carry7; + crypto_int64 carry8; + crypto_int64 carry9; + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + + carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25); + carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25); + + carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26); + carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26); + + carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25); + carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25); + + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26); + + carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25); + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + + h[0] = (crypto_int32) h0; + h[1] = (crypto_int32) h1; + h[2] = (crypto_int32) h2; + h[3] = (crypto_int32) h3; + h[4] = (crypto_int32) h4; + h[5] = (crypto_int32) h5; + h[6] = (crypto_int32) h6; + h[7] = (crypto_int32) h7; + h[8] = (crypto_int32) h8; + h[9] = (crypto_int32) h9; +} diff --git a/src/ext/ed25519/ref10/fe_sq2.c b/src/ext/ed25519/ref10/fe_sq2.c new file mode 100644 index 0000000000..e8faa69ec9 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_sq2.c @@ -0,0 +1,160 @@ +#include "fe.h" +#include "crypto_int64.h" + +/* +h = 2 * f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq2(fe h,const fe f) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 f0_2 = 2 * f0; + crypto_int32 f1_2 = 2 * f1; + crypto_int32 f2_2 = 2 * f2; + crypto_int32 f3_2 = 2 * f3; + crypto_int32 f4_2 = 2 * f4; + crypto_int32 f5_2 = 2 * f5; + crypto_int32 f6_2 = 2 * f6; + crypto_int32 f7_2 = 2 * f7; + crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ + crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ + crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ + crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ + crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ + crypto_int64 f0f0 = f0 * (crypto_int64) f0; + crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; + crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; + crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; + crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; + crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; + crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; + crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; + crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; + crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; + crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; + crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; + crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; + crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; + crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; + crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; + crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; + crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; + crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; + crypto_int64 f2f2 = f2 * (crypto_int64) f2; + crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; + crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; + crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; + crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; + crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; + crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; + crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; + crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; + crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; + crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; + crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; + crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; + crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; + crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; + crypto_int64 f4f4 = f4 * (crypto_int64) f4; + crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; + crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; + crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; + crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; + crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; + crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; + crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; + crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; + crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; + crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; + crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; + crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; + crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; + crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; + crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; + crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; + crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; + crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; + crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; + crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; + crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; + crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; + crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; + crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; + crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; + crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; + crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; + crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; + crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; + crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; + crypto_int64 carry0; + crypto_int64 carry1; + crypto_int64 carry2; + crypto_int64 carry3; + crypto_int64 carry4; + crypto_int64 carry5; + crypto_int64 carry6; + crypto_int64 carry7; + crypto_int64 carry8; + crypto_int64 carry9; + + h0 += h0; + h1 += h1; + h2 += h2; + h3 += h3; + h4 += h4; + h5 += h5; + h6 += h6; + h7 += h7; + h8 += h8; + h9 += h9; + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + + carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25); + carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25); + + carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26); + carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26); + + carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25); + carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25); + + carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26); + carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26); + + carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25); + + carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26); + + h[0] = (crypto_int32) h0; + h[1] = (crypto_int32) h1; + h[2] = (crypto_int32) h2; + h[3] = (crypto_int32) h3; + h[4] = (crypto_int32) h4; + h[5] = (crypto_int32) h5; + h[6] = (crypto_int32) h6; + h[7] = (crypto_int32) h7; + h[8] = (crypto_int32) h8; + h[9] = (crypto_int32) h9; +} diff --git a/src/ext/ed25519/ref10/fe_sub.c b/src/ext/ed25519/ref10/fe_sub.c new file mode 100644 index 0000000000..6e26b7df8f --- /dev/null +++ b/src/ext/ed25519/ref10/fe_sub.c @@ -0,0 +1,57 @@ +#include "fe.h" + +/* +h = f - g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_sub(fe h,const fe f,const fe g) +{ + crypto_int32 f0 = f[0]; + crypto_int32 f1 = f[1]; + crypto_int32 f2 = f[2]; + crypto_int32 f3 = f[3]; + crypto_int32 f4 = f[4]; + crypto_int32 f5 = f[5]; + crypto_int32 f6 = f[6]; + crypto_int32 f7 = f[7]; + crypto_int32 f8 = f[8]; + crypto_int32 f9 = f[9]; + crypto_int32 g0 = g[0]; + crypto_int32 g1 = g[1]; + crypto_int32 g2 = g[2]; + crypto_int32 g3 = g[3]; + crypto_int32 g4 = g[4]; + crypto_int32 g5 = g[5]; + crypto_int32 g6 = g[6]; + crypto_int32 g7 = g[7]; + crypto_int32 g8 = g[8]; + crypto_int32 g9 = g[9]; + crypto_int32 h0 = f0 - g0; + crypto_int32 h1 = f1 - g1; + crypto_int32 h2 = f2 - g2; + crypto_int32 h3 = f3 - g3; + crypto_int32 h4 = f4 - g4; + crypto_int32 h5 = f5 - g5; + crypto_int32 h6 = f6 - g6; + crypto_int32 h7 = f7 - g7; + crypto_int32 h8 = f8 - g8; + crypto_int32 h9 = f9 - g9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} diff --git a/src/ext/ed25519/ref10/fe_tobytes.c b/src/ext/ed25519/ref10/fe_tobytes.c new file mode 100644 index 0000000000..3c7f389622 --- /dev/null +++ b/src/ext/ed25519/ref10/fe_tobytes.c @@ -0,0 +1,119 @@ +#include "fe.h" + +/* +Preconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + +Write p=2^255-19; q=floor(h/p). +Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). + +Proof: + Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. + Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. + + Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). + Then 0<y<1. + + Write r=h-pq. + Have 0<=r<=p-1=2^255-20. + Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1. + + Write x=r+19(2^-255)r+y. + Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q. + + Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1)) + so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q. +*/ + +void fe_tobytes(unsigned char *s,const fe h) +{ + crypto_int32 h0 = h[0]; + crypto_int32 h1 = h[1]; + crypto_int32 h2 = h[2]; + crypto_int32 h3 = h[3]; + crypto_int32 h4 = h[4]; + crypto_int32 h5 = h[5]; + crypto_int32 h6 = h[6]; + crypto_int32 h7 = h[7]; + crypto_int32 h8 = h[8]; + crypto_int32 h9 = h[9]; + crypto_int32 q; + crypto_int32 carry0; + crypto_int32 carry1; + crypto_int32 carry2; + crypto_int32 carry3; + crypto_int32 carry4; + crypto_int32 carry5; + crypto_int32 carry6; + crypto_int32 carry7; + crypto_int32 carry8; + crypto_int32 carry9; + + q = (19 * h9 + (((crypto_int32) 1) << 24)) >> 25; + q = (h0 + q) >> 26; + q = (h1 + q) >> 25; + q = (h2 + q) >> 26; + q = (h3 + q) >> 25; + q = (h4 + q) >> 26; + q = (h5 + q) >> 25; + q = (h6 + q) >> 26; + q = (h7 + q) >> 25; + q = (h8 + q) >> 26; + q = (h9 + q) >> 25; + + /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ + h0 += 19 * q; + /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ + + carry0 = h0 >> 26; h1 += carry0; h0 -= SHL32(carry0,26); + carry1 = h1 >> 25; h2 += carry1; h1 -= SHL32(carry1,25); + carry2 = h2 >> 26; h3 += carry2; h2 -= SHL32(carry2,26); + carry3 = h3 >> 25; h4 += carry3; h3 -= SHL32(carry3,25); + carry4 = h4 >> 26; h5 += carry4; h4 -= SHL32(carry4,26); + carry5 = h5 >> 25; h6 += carry5; h5 -= SHL32(carry5,25); + carry6 = h6 >> 26; h7 += carry6; h6 -= SHL32(carry6,26); + carry7 = h7 >> 25; h8 += carry7; h7 -= SHL32(carry7,25); + carry8 = h8 >> 26; h9 += carry8; h8 -= SHL32(carry8,26); + carry9 = h9 >> 25; h9 -= SHL32(carry9,25); + /* h10 = carry9 */ + + /* + Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + Have h0+...+2^230 h9 between 0 and 2^255-1; + evidently 2^255 h10-2^255 q = 0. + Goal: Output h0+...+2^230 h9. + */ + + s[0] = h0 >> 0; + s[1] = h0 >> 8; + s[2] = h0 >> 16; + s[3] = (h0 >> 24) | SHL32(h1,2); + s[4] = h1 >> 6; + s[5] = h1 >> 14; + s[6] = (h1 >> 22) | SHL32(h2,3); + s[7] = h2 >> 5; + s[8] = h2 >> 13; + s[9] = (h2 >> 21) | SHL32(h3,5); + s[10] = h3 >> 3; + s[11] = h3 >> 11; + s[12] = (h3 >> 19) | SHL32(h4,6); + s[13] = h4 >> 2; + s[14] = h4 >> 10; + s[15] = h4 >> 18; + s[16] = h5 >> 0; + s[17] = h5 >> 8; + s[18] = h5 >> 16; + s[19] = (h5 >> 24) | SHL32(h6,1); + s[20] = h6 >> 7; + s[21] = h6 >> 15; + s[22] = (h6 >> 23) | SHL32(h7,3); + s[23] = h7 >> 5; + s[24] = h7 >> 13; + s[25] = (h7 >> 21) | SHL32(h8,4); + s[26] = h8 >> 4; + s[27] = h8 >> 12; + s[28] = (h8 >> 20) | SHL32(h9,6); + s[29] = h9 >> 2; + s[30] = h9 >> 10; + s[31] = h9 >> 18; +} diff --git a/src/ext/ed25519/ref10/ge.h b/src/ext/ed25519/ref10/ge.h new file mode 100644 index 0000000000..55e95f95b6 --- /dev/null +++ b/src/ext/ed25519/ref10/ge.h @@ -0,0 +1,95 @@ +#ifndef GE_H +#define GE_H + +/* +ge means group element. + +Here the group is the set of pairs (x,y) of field elements (see fe.h) +satisfying -x^2 + y^2 = 1 + d x^2y^2 +where d = -121665/121666. + +Representations: + ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + ge_precomp (Duif): (y+x,y-x,2dxy) +*/ + +#include "fe.h" + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +#define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime +#define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes +#define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes + +#define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0 +#define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0 +#define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0 +#define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2 +#define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached +#define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2 +#define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3 +#define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl +#define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl + +#define ge_madd crypto_sign_ed25519_ref10_ge_madd +#define ge_msub crypto_sign_ed25519_ref10_ge_msub +#define ge_add crypto_sign_ed25519_ref10_ge_add +#define ge_sub crypto_sign_ed25519_ref10_ge_sub +#define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base +#define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime + +extern void ge_tobytes(unsigned char *,const ge_p2 *); +extern void ge_p3_tobytes(unsigned char *,const ge_p3 *); +extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); + +extern void ge_p2_0(ge_p2 *); +extern void ge_p3_0(ge_p3 *); +extern void ge_precomp_0(ge_precomp *); +extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *); +extern void ge_p3_to_cached(ge_cached *,const ge_p3 *); +extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); +extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); +extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); +extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); + +extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); +extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); +extern void ge_scalarmult_base(ge_p3 *,const unsigned char *); +extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *); + +#endif diff --git a/src/ext/ed25519/ref10/ge_add.c b/src/ext/ed25519/ref10/ge_add.c new file mode 100644 index 0000000000..da7ff5d2eb --- /dev/null +++ b/src/ext/ed25519/ref10/ge_add.c @@ -0,0 +1,11 @@ +#include "ge.h" + +/* +r = p + q +*/ + +void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +{ + fe t0; +#include "ge_add.h" +} diff --git a/src/ext/ed25519/ref10/ge_add.h b/src/ext/ed25519/ref10/ge_add.h new file mode 100644 index 0000000000..7481f8ffbe --- /dev/null +++ b/src/ext/ed25519/ref10/ge_add.h @@ -0,0 +1,97 @@ + +/* qhasm: enter ge_add */ + +/* qhasm: fe X1 */ + +/* qhasm: fe Y1 */ + +/* qhasm: fe Z1 */ + +/* qhasm: fe Z2 */ + +/* qhasm: fe T1 */ + +/* qhasm: fe ZZ */ + +/* qhasm: fe YpX2 */ + +/* qhasm: fe YmX2 */ + +/* qhasm: fe T2d2 */ + +/* qhasm: fe X3 */ + +/* qhasm: fe Y3 */ + +/* qhasm: fe Z3 */ + +/* qhasm: fe T3 */ + +/* qhasm: fe YpX1 */ + +/* qhasm: fe YmX1 */ + +/* qhasm: fe A */ + +/* qhasm: fe B */ + +/* qhasm: fe C */ + +/* qhasm: fe D */ + +/* qhasm: YpX1 = Y1+X1 */ +/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */ +fe_add(r->X,p->Y,p->X); + +/* qhasm: YmX1 = Y1-X1 */ +/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */ +fe_sub(r->Y,p->Y,p->X); + +/* qhasm: A = YpX1*YpX2 */ +/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<YpX2=fe#15); */ +/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<YpX2=q->YplusX); */ +fe_mul(r->Z,r->X,q->YplusX); + +/* qhasm: B = YmX1*YmX2 */ +/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<YmX2=fe#16); */ +/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<YmX2=q->YminusX); */ +fe_mul(r->Y,r->Y,q->YminusX); + +/* qhasm: C = T2d2*T1 */ +/* asm 1: fe_mul(>C=fe#4,<T2d2=fe#18,<T1=fe#14); */ +/* asm 2: fe_mul(>C=r->T,<T2d2=q->T2d,<T1=p->T); */ +fe_mul(r->T,q->T2d,p->T); + +/* qhasm: ZZ = Z1*Z2 */ +/* asm 1: fe_mul(>ZZ=fe#1,<Z1=fe#13,<Z2=fe#17); */ +/* asm 2: fe_mul(>ZZ=r->X,<Z1=p->Z,<Z2=q->Z); */ +fe_mul(r->X,p->Z,q->Z); + +/* qhasm: D = 2*ZZ */ +/* asm 1: fe_add(>D=fe#5,<ZZ=fe#1,<ZZ=fe#1); */ +/* asm 2: fe_add(>D=t0,<ZZ=r->X,<ZZ=r->X); */ +fe_add(t0,r->X,r->X); + +/* qhasm: X3 = A-B */ +/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */ +fe_sub(r->X,r->Z,r->Y); + +/* qhasm: Y3 = A+B */ +/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */ +fe_add(r->Y,r->Z,r->Y); + +/* qhasm: Z3 = D+C */ +/* asm 1: fe_add(>Z3=fe#3,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_add(>Z3=r->Z,<D=t0,<C=r->T); */ +fe_add(r->Z,t0,r->T); + +/* qhasm: T3 = D-C */ +/* asm 1: fe_sub(>T3=fe#4,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_sub(>T3=r->T,<D=t0,<C=r->T); */ +fe_sub(r->T,t0,r->T); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/ge_add.q b/src/ext/ed25519/ref10/ge_add.q new file mode 100644 index 0000000000..a6572ab0f8 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_add.q @@ -0,0 +1,49 @@ +:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->YplusX:q->YminusX:q->Z:q->T2d: +fe r:var/r=fe: + +enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>YpX2=fe#15:>YmX2=fe#16:>Z2=fe#17:>T2d2=fe#18: +return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave: + +h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);: +h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);: +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);: +h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);: + +: + +enter ge_add + +fe X1 +fe Y1 +fe Z1 +fe Z2 +fe T1 +fe ZZ +fe YpX2 +fe YmX2 +fe T2d2 +fe X3 +fe Y3 +fe Z3 +fe T3 +fe YpX1 +fe YmX1 +fe A +fe B +fe C +fe D + +YpX1 = Y1+X1 +YmX1 = Y1-X1 +A = YpX1*YpX2 +B = YmX1*YmX2 +C = T2d2*T1 +ZZ = Z1*Z2 +D = 2*ZZ +X3 = A-B +Y3 = A+B +Z3 = D+C +T3 = D-C + +return diff --git a/src/ext/ed25519/ref10/ge_double_scalarmult.c b/src/ext/ed25519/ref10/ge_double_scalarmult.c new file mode 100644 index 0000000000..f8bf4bf775 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_double_scalarmult.c @@ -0,0 +1,96 @@ +#include "ge.h" + +static void slide(signed char *r,const unsigned char *a) +{ + int i; + int b; + int k; + + for (i = 0;i < 256;++i) + r[i] = 1 & (a[i >> 3] >> (i & 7)); + + for (i = 0;i < 256;++i) + if (r[i]) { + for (b = 1;b <= 6 && i + b < 256;++b) { + if (r[i + b]) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (k = i + b;k < 256;++k) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else + break; + } + } + } + +} + +static ge_precomp Bi[8] = { +#include "base2.h" +} ; + +/* +r = a * A + b * B +where a = a[0]+256*a[1]+...+256^31 a[31]. +and b = b[0]+256*b[1]+...+256^31 b[31]. +B is the Ed25519 base point (x,4/5) with x positive. +*/ + +void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b) +{ + signed char aslide[256]; + signed char bslide[256]; + ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ + ge_p1p1 t; + ge_p3 u; + ge_p3 A2; + int i; + + slide(aslide,a); + slide(bslide,b); + + ge_p3_to_cached(&Ai[0],A); + ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); + ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); + ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); + ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); + ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); + ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); + ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); + ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); + + ge_p2_0(r); + + for (i = 255;i >= 0;--i) { + if (aslide[i] || bslide[i]) break; + } + + for (;i >= 0;--i) { + ge_p2_dbl(&t,r); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u,&t); + ge_add(&t,&u,&Ai[aslide[i]/2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u,&t); + ge_sub(&t,&u,&Ai[(-aslide[i])/2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u,&t); + ge_madd(&t,&u,&Bi[bslide[i]/2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u,&t); + ge_msub(&t,&u,&Bi[(-bslide[i])/2]); + } + + ge_p1p1_to_p2(r,&t); + } +} diff --git a/src/ext/ed25519/ref10/ge_frombytes.c b/src/ext/ed25519/ref10/ge_frombytes.c new file mode 100644 index 0000000000..1a059ee93f --- /dev/null +++ b/src/ext/ed25519/ref10/ge_frombytes.c @@ -0,0 +1,50 @@ +#include "ge.h" + +static const fe d = { +#include "d.h" +} ; + +static const fe sqrtm1 = { +#include "sqrtm1.h" +} ; + +int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) +{ + fe u; + fe v; + fe v3; + fe vxx; + fe check; + + fe_frombytes(h->Y,s); + fe_1(h->Z); + fe_sq(u,h->Y); + fe_mul(v,u,d); + fe_sub(u,u,h->Z); /* u = y^2-1 */ + fe_add(v,v,h->Z); /* v = dy^2+1 */ + + fe_sq(v3,v); + fe_mul(v3,v3,v); /* v3 = v^3 */ + fe_sq(h->X,v3); + fe_mul(h->X,h->X,v); + fe_mul(h->X,h->X,u); /* x = uv^7 */ + + fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ + fe_mul(h->X,h->X,v3); + fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ + + fe_sq(vxx,h->X); + fe_mul(vxx,vxx,v); + fe_sub(check,vxx,u); /* vx^2-u */ + if (fe_isnonzero(check)) { + fe_add(check,vxx,u); /* vx^2+u */ + if (fe_isnonzero(check)) return -1; + fe_mul(h->X,h->X,sqrtm1); + } + + if (fe_isnegative(h->X) == (s[31] >> 7)) + fe_neg(h->X,h->X); + + fe_mul(h->T,h->X,h->Y); + return 0; +} diff --git a/src/ext/ed25519/ref10/ge_madd.c b/src/ext/ed25519/ref10/ge_madd.c new file mode 100644 index 0000000000..622571774b --- /dev/null +++ b/src/ext/ed25519/ref10/ge_madd.c @@ -0,0 +1,11 @@ +#include "ge.h" + +/* +r = p + q +*/ + +void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +{ + fe t0; +#include "ge_madd.h" +} diff --git a/src/ext/ed25519/ref10/ge_madd.h b/src/ext/ed25519/ref10/ge_madd.h new file mode 100644 index 0000000000..ecae84952b --- /dev/null +++ b/src/ext/ed25519/ref10/ge_madd.h @@ -0,0 +1,88 @@ + +/* qhasm: enter ge_madd */ + +/* qhasm: fe X1 */ + +/* qhasm: fe Y1 */ + +/* qhasm: fe Z1 */ + +/* qhasm: fe T1 */ + +/* qhasm: fe ypx2 */ + +/* qhasm: fe ymx2 */ + +/* qhasm: fe xy2d2 */ + +/* qhasm: fe X3 */ + +/* qhasm: fe Y3 */ + +/* qhasm: fe Z3 */ + +/* qhasm: fe T3 */ + +/* qhasm: fe YpX1 */ + +/* qhasm: fe YmX1 */ + +/* qhasm: fe A */ + +/* qhasm: fe B */ + +/* qhasm: fe C */ + +/* qhasm: fe D */ + +/* qhasm: YpX1 = Y1+X1 */ +/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */ +fe_add(r->X,p->Y,p->X); + +/* qhasm: YmX1 = Y1-X1 */ +/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */ +fe_sub(r->Y,p->Y,p->X); + +/* qhasm: A = YpX1*ypx2 */ +/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<ypx2=fe#15); */ +/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<ypx2=q->yplusx); */ +fe_mul(r->Z,r->X,q->yplusx); + +/* qhasm: B = YmX1*ymx2 */ +/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<ymx2=fe#16); */ +/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<ymx2=q->yminusx); */ +fe_mul(r->Y,r->Y,q->yminusx); + +/* qhasm: C = xy2d2*T1 */ +/* asm 1: fe_mul(>C=fe#4,<xy2d2=fe#17,<T1=fe#14); */ +/* asm 2: fe_mul(>C=r->T,<xy2d2=q->xy2d,<T1=p->T); */ +fe_mul(r->T,q->xy2d,p->T); + +/* qhasm: D = 2*Z1 */ +/* asm 1: fe_add(>D=fe#5,<Z1=fe#13,<Z1=fe#13); */ +/* asm 2: fe_add(>D=t0,<Z1=p->Z,<Z1=p->Z); */ +fe_add(t0,p->Z,p->Z); + +/* qhasm: X3 = A-B */ +/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */ +fe_sub(r->X,r->Z,r->Y); + +/* qhasm: Y3 = A+B */ +/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */ +fe_add(r->Y,r->Z,r->Y); + +/* qhasm: Z3 = D+C */ +/* asm 1: fe_add(>Z3=fe#3,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_add(>Z3=r->Z,<D=t0,<C=r->T); */ +fe_add(r->Z,t0,r->T); + +/* qhasm: T3 = D-C */ +/* asm 1: fe_sub(>T3=fe#4,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_sub(>T3=r->T,<D=t0,<C=r->T); */ +fe_sub(r->T,t0,r->T); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/ge_madd.q b/src/ext/ed25519/ref10/ge_madd.q new file mode 100644 index 0000000000..aa3db454e6 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_madd.q @@ -0,0 +1,46 @@ +:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->yplusx:q->yminusx:q->xy2d: +fe r:var/r=fe: + +enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>ypx2=fe#15:>ymx2=fe#16:>xy2d2=fe#17: +return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave: + +h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);: +h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);: +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);: +h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);: + +: + +enter ge_madd + +fe X1 +fe Y1 +fe Z1 +fe T1 +fe ypx2 +fe ymx2 +fe xy2d2 +fe X3 +fe Y3 +fe Z3 +fe T3 +fe YpX1 +fe YmX1 +fe A +fe B +fe C +fe D + +YpX1 = Y1+X1 +YmX1 = Y1-X1 +A = YpX1*ypx2 +B = YmX1*ymx2 +C = xy2d2*T1 +D = 2*Z1 +X3 = A-B +Y3 = A+B +Z3 = D+C +T3 = D-C + +return diff --git a/src/ext/ed25519/ref10/ge_msub.c b/src/ext/ed25519/ref10/ge_msub.c new file mode 100644 index 0000000000..741ecbf113 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_msub.c @@ -0,0 +1,11 @@ +#include "ge.h" + +/* +r = p - q +*/ + +void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +{ + fe t0; +#include "ge_msub.h" +} diff --git a/src/ext/ed25519/ref10/ge_msub.h b/src/ext/ed25519/ref10/ge_msub.h new file mode 100644 index 0000000000..500f986ba0 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_msub.h @@ -0,0 +1,88 @@ + +/* qhasm: enter ge_msub */ + +/* qhasm: fe X1 */ + +/* qhasm: fe Y1 */ + +/* qhasm: fe Z1 */ + +/* qhasm: fe T1 */ + +/* qhasm: fe ypx2 */ + +/* qhasm: fe ymx2 */ + +/* qhasm: fe xy2d2 */ + +/* qhasm: fe X3 */ + +/* qhasm: fe Y3 */ + +/* qhasm: fe Z3 */ + +/* qhasm: fe T3 */ + +/* qhasm: fe YpX1 */ + +/* qhasm: fe YmX1 */ + +/* qhasm: fe A */ + +/* qhasm: fe B */ + +/* qhasm: fe C */ + +/* qhasm: fe D */ + +/* qhasm: YpX1 = Y1+X1 */ +/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */ +fe_add(r->X,p->Y,p->X); + +/* qhasm: YmX1 = Y1-X1 */ +/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */ +fe_sub(r->Y,p->Y,p->X); + +/* qhasm: A = YpX1*ymx2 */ +/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<ymx2=fe#16); */ +/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<ymx2=q->yminusx); */ +fe_mul(r->Z,r->X,q->yminusx); + +/* qhasm: B = YmX1*ypx2 */ +/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<ypx2=fe#15); */ +/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<ypx2=q->yplusx); */ +fe_mul(r->Y,r->Y,q->yplusx); + +/* qhasm: C = xy2d2*T1 */ +/* asm 1: fe_mul(>C=fe#4,<xy2d2=fe#17,<T1=fe#14); */ +/* asm 2: fe_mul(>C=r->T,<xy2d2=q->xy2d,<T1=p->T); */ +fe_mul(r->T,q->xy2d,p->T); + +/* qhasm: D = 2*Z1 */ +/* asm 1: fe_add(>D=fe#5,<Z1=fe#13,<Z1=fe#13); */ +/* asm 2: fe_add(>D=t0,<Z1=p->Z,<Z1=p->Z); */ +fe_add(t0,p->Z,p->Z); + +/* qhasm: X3 = A-B */ +/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */ +fe_sub(r->X,r->Z,r->Y); + +/* qhasm: Y3 = A+B */ +/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */ +fe_add(r->Y,r->Z,r->Y); + +/* qhasm: Z3 = D-C */ +/* asm 1: fe_sub(>Z3=fe#3,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_sub(>Z3=r->Z,<D=t0,<C=r->T); */ +fe_sub(r->Z,t0,r->T); + +/* qhasm: T3 = D+C */ +/* asm 1: fe_add(>T3=fe#4,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_add(>T3=r->T,<D=t0,<C=r->T); */ +fe_add(r->T,t0,r->T); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/ge_msub.q b/src/ext/ed25519/ref10/ge_msub.q new file mode 100644 index 0000000000..e3cadd882d --- /dev/null +++ b/src/ext/ed25519/ref10/ge_msub.q @@ -0,0 +1,46 @@ +:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->yplusx:q->yminusx:q->xy2d: +fe r:var/r=fe: + +enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>ypx2=fe#15:>ymx2=fe#16:>xy2d2=fe#17: +return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave: + +h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);: +h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);: +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);: +h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);: + +: + +enter ge_msub + +fe X1 +fe Y1 +fe Z1 +fe T1 +fe ypx2 +fe ymx2 +fe xy2d2 +fe X3 +fe Y3 +fe Z3 +fe T3 +fe YpX1 +fe YmX1 +fe A +fe B +fe C +fe D + +YpX1 = Y1+X1 +YmX1 = Y1-X1 +A = YpX1*ymx2 +B = YmX1*ypx2 +C = xy2d2*T1 +D = 2*Z1 +X3 = A-B +Y3 = A+B +Z3 = D-C +T3 = D+C + +return diff --git a/src/ext/ed25519/ref10/ge_p1p1_to_p2.c b/src/ext/ed25519/ref10/ge_p1p1_to_p2.c new file mode 100644 index 0000000000..9bb5013d66 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p1p1_to_p2.c @@ -0,0 +1,12 @@ +#include "ge.h" + +/* +r = p +*/ + +extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) +{ + fe_mul(r->X,p->X,p->T); + fe_mul(r->Y,p->Y,p->Z); + fe_mul(r->Z,p->Z,p->T); +} diff --git a/src/ext/ed25519/ref10/ge_p1p1_to_p3.c b/src/ext/ed25519/ref10/ge_p1p1_to_p3.c new file mode 100644 index 0000000000..2f57b10968 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p1p1_to_p3.c @@ -0,0 +1,13 @@ +#include "ge.h" + +/* +r = p +*/ + +extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) +{ + fe_mul(r->X,p->X,p->T); + fe_mul(r->Y,p->Y,p->Z); + fe_mul(r->Z,p->Z,p->T); + fe_mul(r->T,p->X,p->Y); +} diff --git a/src/ext/ed25519/ref10/ge_p2_0.c b/src/ext/ed25519/ref10/ge_p2_0.c new file mode 100644 index 0000000000..6191d1e6e4 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p2_0.c @@ -0,0 +1,8 @@ +#include "ge.h" + +void ge_p2_0(ge_p2 *h) +{ + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); +} diff --git a/src/ext/ed25519/ref10/ge_p2_dbl.c b/src/ext/ed25519/ref10/ge_p2_dbl.c new file mode 100644 index 0000000000..2e332b5cee --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p2_dbl.c @@ -0,0 +1,11 @@ +#include "ge.h" + +/* +r = 2 * p +*/ + +void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) +{ + fe t0; +#include "ge_p2_dbl.h" +} diff --git a/src/ext/ed25519/ref10/ge_p2_dbl.h b/src/ext/ed25519/ref10/ge_p2_dbl.h new file mode 100644 index 0000000000..128efed907 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p2_dbl.h @@ -0,0 +1,73 @@ + +/* qhasm: enter ge_p2_dbl */ + +/* qhasm: fe X1 */ + +/* qhasm: fe Y1 */ + +/* qhasm: fe Z1 */ + +/* qhasm: fe A */ + +/* qhasm: fe AA */ + +/* qhasm: fe XX */ + +/* qhasm: fe YY */ + +/* qhasm: fe B */ + +/* qhasm: fe X3 */ + +/* qhasm: fe Y3 */ + +/* qhasm: fe Z3 */ + +/* qhasm: fe T3 */ + +/* qhasm: XX=X1^2 */ +/* asm 1: fe_sq(>XX=fe#1,<X1=fe#11); */ +/* asm 2: fe_sq(>XX=r->X,<X1=p->X); */ +fe_sq(r->X,p->X); + +/* qhasm: YY=Y1^2 */ +/* asm 1: fe_sq(>YY=fe#3,<Y1=fe#12); */ +/* asm 2: fe_sq(>YY=r->Z,<Y1=p->Y); */ +fe_sq(r->Z,p->Y); + +/* qhasm: B=2*Z1^2 */ +/* asm 1: fe_sq2(>B=fe#4,<Z1=fe#13); */ +/* asm 2: fe_sq2(>B=r->T,<Z1=p->Z); */ +fe_sq2(r->T,p->Z); + +/* qhasm: A=X1+Y1 */ +/* asm 1: fe_add(>A=fe#2,<X1=fe#11,<Y1=fe#12); */ +/* asm 2: fe_add(>A=r->Y,<X1=p->X,<Y1=p->Y); */ +fe_add(r->Y,p->X,p->Y); + +/* qhasm: AA=A^2 */ +/* asm 1: fe_sq(>AA=fe#5,<A=fe#2); */ +/* asm 2: fe_sq(>AA=t0,<A=r->Y); */ +fe_sq(t0,r->Y); + +/* qhasm: Y3=YY+XX */ +/* asm 1: fe_add(>Y3=fe#2,<YY=fe#3,<XX=fe#1); */ +/* asm 2: fe_add(>Y3=r->Y,<YY=r->Z,<XX=r->X); */ +fe_add(r->Y,r->Z,r->X); + +/* qhasm: Z3=YY-XX */ +/* asm 1: fe_sub(>Z3=fe#3,<YY=fe#3,<XX=fe#1); */ +/* asm 2: fe_sub(>Z3=r->Z,<YY=r->Z,<XX=r->X); */ +fe_sub(r->Z,r->Z,r->X); + +/* qhasm: X3=AA-Y3 */ +/* asm 1: fe_sub(>X3=fe#1,<AA=fe#5,<Y3=fe#2); */ +/* asm 2: fe_sub(>X3=r->X,<AA=t0,<Y3=r->Y); */ +fe_sub(r->X,t0,r->Y); + +/* qhasm: T3=B-Z3 */ +/* asm 1: fe_sub(>T3=fe#4,<B=fe#4,<Z3=fe#3); */ +/* asm 2: fe_sub(>T3=r->T,<B=r->T,<Z3=r->Z); */ +fe_sub(r->T,r->T,r->Z); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/ge_p2_dbl.q b/src/ext/ed25519/ref10/ge_p2_dbl.q new file mode 100644 index 0000000000..170d42f9a7 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p2_dbl.q @@ -0,0 +1,41 @@ +:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z: +fe r:var/r=fe: + +enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13: +return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave: + +h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);: +h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);: +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);: +h=2*f^2:<f=fe:>h=fe:asm/fe_sq2(>h,<f);: +h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);: + +: + +enter ge_p2_dbl + +fe X1 +fe Y1 +fe Z1 +fe A +fe AA +fe XX +fe YY +fe B +fe X3 +fe Y3 +fe Z3 +fe T3 + +XX=X1^2 +YY=Y1^2 +B=2*Z1^2 +A=X1+Y1 +AA=A^2 +Y3=YY+XX +Z3=YY-XX +X3=AA-Y3 +T3=B-Z3 + +return diff --git a/src/ext/ed25519/ref10/ge_p3_0.c b/src/ext/ed25519/ref10/ge_p3_0.c new file mode 100644 index 0000000000..401b2935a1 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p3_0.c @@ -0,0 +1,9 @@ +#include "ge.h" + +void ge_p3_0(ge_p3 *h) +{ + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); + fe_0(h->T); +} diff --git a/src/ext/ed25519/ref10/ge_p3_dbl.c b/src/ext/ed25519/ref10/ge_p3_dbl.c new file mode 100644 index 0000000000..0d8a05915d --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p3_dbl.c @@ -0,0 +1,12 @@ +#include "ge.h" + +/* +r = 2 * p +*/ + +void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) +{ + ge_p2 q; + ge_p3_to_p2(&q,p); + ge_p2_dbl(r,&q); +} diff --git a/src/ext/ed25519/ref10/ge_p3_to_cached.c b/src/ext/ed25519/ref10/ge_p3_to_cached.c new file mode 100644 index 0000000000..bde64228cf --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p3_to_cached.c @@ -0,0 +1,17 @@ +#include "ge.h" + +/* +r = p +*/ + +static const fe d2 = { +#include "d2.h" +} ; + +extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) +{ + fe_add(r->YplusX,p->Y,p->X); + fe_sub(r->YminusX,p->Y,p->X); + fe_copy(r->Z,p->Z); + fe_mul(r->T2d,p->T,d2); +} diff --git a/src/ext/ed25519/ref10/ge_p3_to_p2.c b/src/ext/ed25519/ref10/ge_p3_to_p2.c new file mode 100644 index 0000000000..e532a9e4cb --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p3_to_p2.c @@ -0,0 +1,12 @@ +#include "ge.h" + +/* +r = p +*/ + +extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) +{ + fe_copy(r->X,p->X); + fe_copy(r->Y,p->Y); + fe_copy(r->Z,p->Z); +} diff --git a/src/ext/ed25519/ref10/ge_p3_tobytes.c b/src/ext/ed25519/ref10/ge_p3_tobytes.c new file mode 100644 index 0000000000..21cb2fc656 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_p3_tobytes.c @@ -0,0 +1,14 @@ +#include "ge.h" + +void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) +{ + fe recip; + fe x; + fe y; + + fe_invert(recip,h->Z); + fe_mul(x,h->X,recip); + fe_mul(y,h->Y,recip); + fe_tobytes(s,y); + s[31] ^= fe_isnegative(x) << 7; +} diff --git a/src/ext/ed25519/ref10/ge_precomp_0.c b/src/ext/ed25519/ref10/ge_precomp_0.c new file mode 100644 index 0000000000..2e218861d8 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_precomp_0.c @@ -0,0 +1,8 @@ +#include "ge.h" + +void ge_precomp_0(ge_precomp *h) +{ + fe_1(h->yplusx); + fe_1(h->yminusx); + fe_0(h->xy2d); +} diff --git a/src/ext/ed25519/ref10/ge_scalarmult_base.c b/src/ext/ed25519/ref10/ge_scalarmult_base.c new file mode 100644 index 0000000000..5292f83221 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_scalarmult_base.c @@ -0,0 +1,109 @@ +#include "ge.h" +#include "crypto_uint32.h" + +/* Rename this so as not to interfere with select() which torint.h apparently + * grabs. :p */ +#define select ed25519_ref10_select + +static unsigned char equal(signed char b,signed char c) +{ + unsigned char ub = b; + unsigned char uc = c; + unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ + crypto_uint32 y = x; /* 0: yes; 1..255: no */ + y -= 1; /* 4294967295: yes; 0..254: no */ + y >>= 31; /* 1: yes; 0: no */ + return y; +} + +static unsigned char negative(signed char b) +{ + uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ + x >>= 63; /* 1: yes; 0: no */ + return x; +} + +static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b) +{ + fe_cmov(t->yplusx,u->yplusx,b); + fe_cmov(t->yminusx,u->yminusx,b); + fe_cmov(t->xy2d,u->xy2d,b); +} + +/* base[i][j] = (j+1)*256^i*B */ +static ge_precomp base[32][8] = { +#include "base.h" +} ; + +static void select(ge_precomp *t,int pos,signed char b) +{ + ge_precomp minust; + unsigned char bnegative = negative(b); + unsigned char babs = b - SHL8( (-bnegative) & (unsigned char)b, 1); + + ge_precomp_0(t); + cmov(t,&base[pos][0],equal(babs,1)); + cmov(t,&base[pos][1],equal(babs,2)); + cmov(t,&base[pos][2],equal(babs,3)); + cmov(t,&base[pos][3],equal(babs,4)); + cmov(t,&base[pos][4],equal(babs,5)); + cmov(t,&base[pos][5],equal(babs,6)); + cmov(t,&base[pos][6],equal(babs,7)); + cmov(t,&base[pos][7],equal(babs,8)); + fe_copy(minust.yplusx,t->yminusx); + fe_copy(minust.yminusx,t->yplusx); + fe_neg(minust.xy2d,t->xy2d); + cmov(t,&minust,bnegative); +} + +/* +h = a * B +where a = a[0]+256*a[1]+...+256^31 a[31] +B is the Ed25519 base point (x,4/5) with x positive. + +Preconditions: + a[31] <= 127 +*/ + +void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) +{ + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0;i < 32;++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + + carry = 0; + for (i = 0;i < 63;++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= SHL8(carry,4); + } + e[63] += carry; + /* each e[i] is between -8 and 8 */ + + ge_p3_0(h); + for (i = 1;i < 64;i += 2) { + select(&t,i / 2,e[i]); + ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); + } + + ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r); + ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); + ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); + ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); + + for (i = 0;i < 64;i += 2) { + select(&t,i / 2,e[i]); + ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); + } +} diff --git a/src/ext/ed25519/ref10/ge_sub.c b/src/ext/ed25519/ref10/ge_sub.c new file mode 100644 index 0000000000..69f3d54062 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_sub.c @@ -0,0 +1,11 @@ +#include "ge.h" + +/* +r = p - q +*/ + +void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +{ + fe t0; +#include "ge_sub.h" +} diff --git a/src/ext/ed25519/ref10/ge_sub.h b/src/ext/ed25519/ref10/ge_sub.h new file mode 100644 index 0000000000..b4ef1f5dd0 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_sub.h @@ -0,0 +1,97 @@ + +/* qhasm: enter ge_sub */ + +/* qhasm: fe X1 */ + +/* qhasm: fe Y1 */ + +/* qhasm: fe Z1 */ + +/* qhasm: fe Z2 */ + +/* qhasm: fe T1 */ + +/* qhasm: fe ZZ */ + +/* qhasm: fe YpX2 */ + +/* qhasm: fe YmX2 */ + +/* qhasm: fe T2d2 */ + +/* qhasm: fe X3 */ + +/* qhasm: fe Y3 */ + +/* qhasm: fe Z3 */ + +/* qhasm: fe T3 */ + +/* qhasm: fe YpX1 */ + +/* qhasm: fe YmX1 */ + +/* qhasm: fe A */ + +/* qhasm: fe B */ + +/* qhasm: fe C */ + +/* qhasm: fe D */ + +/* qhasm: YpX1 = Y1+X1 */ +/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */ +fe_add(r->X,p->Y,p->X); + +/* qhasm: YmX1 = Y1-X1 */ +/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */ +/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */ +fe_sub(r->Y,p->Y,p->X); + +/* qhasm: A = YpX1*YmX2 */ +/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<YmX2=fe#16); */ +/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<YmX2=q->YminusX); */ +fe_mul(r->Z,r->X,q->YminusX); + +/* qhasm: B = YmX1*YpX2 */ +/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<YpX2=fe#15); */ +/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<YpX2=q->YplusX); */ +fe_mul(r->Y,r->Y,q->YplusX); + +/* qhasm: C = T2d2*T1 */ +/* asm 1: fe_mul(>C=fe#4,<T2d2=fe#18,<T1=fe#14); */ +/* asm 2: fe_mul(>C=r->T,<T2d2=q->T2d,<T1=p->T); */ +fe_mul(r->T,q->T2d,p->T); + +/* qhasm: ZZ = Z1*Z2 */ +/* asm 1: fe_mul(>ZZ=fe#1,<Z1=fe#13,<Z2=fe#17); */ +/* asm 2: fe_mul(>ZZ=r->X,<Z1=p->Z,<Z2=q->Z); */ +fe_mul(r->X,p->Z,q->Z); + +/* qhasm: D = 2*ZZ */ +/* asm 1: fe_add(>D=fe#5,<ZZ=fe#1,<ZZ=fe#1); */ +/* asm 2: fe_add(>D=t0,<ZZ=r->X,<ZZ=r->X); */ +fe_add(t0,r->X,r->X); + +/* qhasm: X3 = A-B */ +/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */ +fe_sub(r->X,r->Z,r->Y); + +/* qhasm: Y3 = A+B */ +/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */ +/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */ +fe_add(r->Y,r->Z,r->Y); + +/* qhasm: Z3 = D-C */ +/* asm 1: fe_sub(>Z3=fe#3,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_sub(>Z3=r->Z,<D=t0,<C=r->T); */ +fe_sub(r->Z,t0,r->T); + +/* qhasm: T3 = D+C */ +/* asm 1: fe_add(>T3=fe#4,<D=fe#5,<C=fe#4); */ +/* asm 2: fe_add(>T3=r->T,<D=t0,<C=r->T); */ +fe_add(r->T,t0,r->T); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/ge_sub.q b/src/ext/ed25519/ref10/ge_sub.q new file mode 100644 index 0000000000..2779a4a201 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_sub.q @@ -0,0 +1,49 @@ +:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->YplusX:q->YminusX:q->Z:q->T2d: +fe r:var/r=fe: + +enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>YpX2=fe#15:>YmX2=fe#16:>Z2=fe#17:>T2d2=fe#18: +return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave: + +h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);: +h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);: +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);: +h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);: + +: + +enter ge_sub + +fe X1 +fe Y1 +fe Z1 +fe Z2 +fe T1 +fe ZZ +fe YpX2 +fe YmX2 +fe T2d2 +fe X3 +fe Y3 +fe Z3 +fe T3 +fe YpX1 +fe YmX1 +fe A +fe B +fe C +fe D + +YpX1 = Y1+X1 +YmX1 = Y1-X1 +A = YpX1*YmX2 +B = YmX1*YpX2 +C = T2d2*T1 +ZZ = Z1*Z2 +D = 2*ZZ +X3 = A-B +Y3 = A+B +Z3 = D-C +T3 = D+C + +return diff --git a/src/ext/ed25519/ref10/ge_tobytes.c b/src/ext/ed25519/ref10/ge_tobytes.c new file mode 100644 index 0000000000..31b3d33e09 --- /dev/null +++ b/src/ext/ed25519/ref10/ge_tobytes.c @@ -0,0 +1,14 @@ +#include "ge.h" + +void ge_tobytes(unsigned char *s,const ge_p2 *h) +{ + fe recip; + fe x; + fe y; + + fe_invert(recip,h->Z); + fe_mul(x,h->X,recip); + fe_mul(y,h->Y,recip); + fe_tobytes(s,y); + s[31] ^= fe_isnegative(x) << 7; +} diff --git a/src/ext/ed25519/ref10/keyconv.c b/src/ext/ed25519/ref10/keyconv.c new file mode 100644 index 0000000000..854b150d69 --- /dev/null +++ b/src/ext/ed25519/ref10/keyconv.c @@ -0,0 +1,37 @@ +/* Added to ref10 for Tor. We place this in the public domain. Alternatively, + * you may have it under the Creative Commons 0 "CC0" license. */ +#include "fe.h" +#include "ed25519_ref10.h" + +int ed25519_ref10_pubkey_from_curve25519_pubkey(unsigned char *out, + const unsigned char *inp, + int signbit) +{ + fe u; + fe one; + fe y; + fe uplus1; + fe uminus1; + fe inv_uplus1; + + /* From prop228: + + Given a curve25519 x-coordinate (u), we can get the y coordinate + of the ed25519 key using + + y = (u-1)/(u+1) + */ + fe_frombytes(u, inp); + fe_1(one); + fe_sub(uminus1, u, one); + fe_add(uplus1, u, one); + fe_invert(inv_uplus1, uplus1); + fe_mul(y, uminus1, inv_uplus1); + + fe_tobytes(out, y); + + /* propagate sign. */ + out[31] |= (!!signbit) << 7; + + return 0; +} diff --git a/src/ext/ed25519/ref10/keypair.c b/src/ext/ed25519/ref10/keypair.c new file mode 100644 index 0000000000..7ddbaa971e --- /dev/null +++ b/src/ext/ed25519/ref10/keypair.c @@ -0,0 +1,51 @@ +/* Modified for Tor: new API, 64-byte secret keys. */ +#include <string.h> +#include "randombytes.h" +#include "crypto_sign.h" +#include "crypto_hash_sha512.h" +#include "ge.h" + +int +crypto_sign_seckey(unsigned char *sk) +{ + unsigned char seed[32]; + + if (randombytes(seed,32) < 0) + return -1; + + crypto_sign_seckey_expand(sk, seed); + + memwipe(seed, 0, 32); + + return 0; +} + +int crypto_sign_seckey_expand(unsigned char *sk, const unsigned char *skseed) +{ + crypto_hash_sha512(sk,skseed,32); + sk[0] &= 248; + sk[31] &= 63; + sk[31] |= 64; + + return 0; +} + +int crypto_sign_pubkey(unsigned char *pk,const unsigned char *sk) +{ + ge_p3 A; + + ge_scalarmult_base(&A,sk); + ge_p3_tobytes(pk,&A); + + return 0; +} + + +int crypto_sign_keypair(unsigned char *pk,unsigned char *sk) +{ + crypto_sign_seckey(sk); + crypto_sign_pubkey(pk, sk); + + return 0; +} + diff --git a/src/ext/ed25519/ref10/open.c b/src/ext/ed25519/ref10/open.c new file mode 100644 index 0000000000..9dbeb4cdd0 --- /dev/null +++ b/src/ext/ed25519/ref10/open.c @@ -0,0 +1,42 @@ +/* (Modified by Tor to verify signature separately from message) */ +#include <string.h> +#include "crypto_sign.h" +#include "crypto_hash_sha512.h" +#include "crypto_verify_32.h" +#include "ge.h" +#include "sc.h" + +/* 'signature' must be 64-bytes long. */ +int crypto_sign_open( + const unsigned char *signature, + const unsigned char *m, size_t mlen, + const unsigned char *pk +) +{ + unsigned char pkcopy[32]; + unsigned char rcopy[32]; + unsigned char scopy[32]; + unsigned char h[64]; + unsigned char rcheck[32]; + ge_p3 A; + ge_p2 R; + + if (signature[63] & 224) goto badsig; + if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig; + + memmove(pkcopy,pk,32); + memmove(rcopy,signature,32); + memmove(scopy,signature + 32,32); + + crypto_hash_sha512_3(h, rcopy, 32, pkcopy, 32, m, mlen); + sc_reduce(h); + + ge_double_scalarmult_vartime(&R,h,&A,scopy); + ge_tobytes(rcheck,&R); + if (crypto_verify_32(rcheck,rcopy) == 0) { + return 0; + } + +badsig: + return -1; +} diff --git a/src/ext/ed25519/ref10/pow22523.h b/src/ext/ed25519/ref10/pow22523.h new file mode 100644 index 0000000000..9204ff838f --- /dev/null +++ b/src/ext/ed25519/ref10/pow22523.h @@ -0,0 +1,161 @@ +/* Modified by Tor: pointless loops removed to appease analysis tools */ + +/* qhasm: fe z1 */ + +/* qhasm: fe z2 */ + +/* qhasm: fe z8 */ + +/* qhasm: fe z9 */ + +/* qhasm: fe z11 */ + +/* qhasm: fe z22 */ + +/* qhasm: fe z_5_0 */ + +/* qhasm: fe z_10_5 */ + +/* qhasm: fe z_10_0 */ + +/* qhasm: fe z_20_10 */ + +/* qhasm: fe z_20_0 */ + +/* qhasm: fe z_40_20 */ + +/* qhasm: fe z_40_0 */ + +/* qhasm: fe z_50_10 */ + +/* qhasm: fe z_50_0 */ + +/* qhasm: fe z_100_50 */ + +/* qhasm: fe z_100_0 */ + +/* qhasm: fe z_200_100 */ + +/* qhasm: fe z_200_0 */ + +/* qhasm: fe z_250_50 */ + +/* qhasm: fe z_250_0 */ + +/* qhasm: fe z_252_2 */ + +/* qhasm: fe z_252_3 */ + +/* qhasm: enter pow22523 */ + +/* qhasm: z2 = z1^2^1 */ +/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */ +/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */ +fe_sq(t0,z); /* DEADCODE This loop has no effect: for (i = 1;i < 1;++i) fe_sq(t0,t0); */ + +/* qhasm: z8 = z2^2^2 */ +/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */ +/* asm 2: fe_sq(>z8=t1,<z2=t0); for (i = 1;i < 2;++i) fe_sq(>z8=t1,>z8=t1); */ +fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); + +/* qhasm: z9 = z1*z8 */ +/* asm 1: fe_mul(>z9=fe#2,<z1=fe#11,<z8=fe#2); */ +/* asm 2: fe_mul(>z9=t1,<z1=z,<z8=t1); */ +fe_mul(t1,z,t1); + +/* qhasm: z11 = z2*z9 */ +/* asm 1: fe_mul(>z11=fe#1,<z2=fe#1,<z9=fe#2); */ +/* asm 2: fe_mul(>z11=t0,<z2=t0,<z9=t1); */ +fe_mul(t0,t0,t1); + +/* qhasm: z22 = z11^2^1 */ +/* asm 1: fe_sq(>z22=fe#1,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#1,>z22=fe#1); */ +/* asm 2: fe_sq(>z22=t0,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t0,>z22=t0); */ +fe_sq(t0,t0); /* DEADCODE This loop has no effect: for (i = 1;i < 1;++i) fe_sq(t0,t0); */ + +/* qhasm: z_5_0 = z9*z22 */ +/* asm 1: fe_mul(>z_5_0=fe#1,<z9=fe#2,<z22=fe#1); */ +/* asm 2: fe_mul(>z_5_0=t0,<z9=t1,<z22=t0); */ +fe_mul(t0,t1,t0); + +/* qhasm: z_10_5 = z_5_0^2^5 */ +/* asm 1: fe_sq(>z_10_5=fe#2,<z_5_0=fe#1); for (i = 1;i < 5;++i) fe_sq(>z_10_5=fe#2,>z_10_5=fe#2); */ +/* asm 2: fe_sq(>z_10_5=t1,<z_5_0=t0); for (i = 1;i < 5;++i) fe_sq(>z_10_5=t1,>z_10_5=t1); */ +fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1); + +/* qhasm: z_10_0 = z_10_5*z_5_0 */ +/* asm 1: fe_mul(>z_10_0=fe#1,<z_10_5=fe#2,<z_5_0=fe#1); */ +/* asm 2: fe_mul(>z_10_0=t0,<z_10_5=t1,<z_5_0=t0); */ +fe_mul(t0,t1,t0); + +/* qhasm: z_20_10 = z_10_0^2^10 */ +/* asm 1: fe_sq(>z_20_10=fe#2,<z_10_0=fe#1); for (i = 1;i < 10;++i) fe_sq(>z_20_10=fe#2,>z_20_10=fe#2); */ +/* asm 2: fe_sq(>z_20_10=t1,<z_10_0=t0); for (i = 1;i < 10;++i) fe_sq(>z_20_10=t1,>z_20_10=t1); */ +fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1); + +/* qhasm: z_20_0 = z_20_10*z_10_0 */ +/* asm 1: fe_mul(>z_20_0=fe#2,<z_20_10=fe#2,<z_10_0=fe#1); */ +/* asm 2: fe_mul(>z_20_0=t1,<z_20_10=t1,<z_10_0=t0); */ +fe_mul(t1,t1,t0); + +/* qhasm: z_40_20 = z_20_0^2^20 */ +/* asm 1: fe_sq(>z_40_20=fe#3,<z_20_0=fe#2); for (i = 1;i < 20;++i) fe_sq(>z_40_20=fe#3,>z_40_20=fe#3); */ +/* asm 2: fe_sq(>z_40_20=t2,<z_20_0=t1); for (i = 1;i < 20;++i) fe_sq(>z_40_20=t2,>z_40_20=t2); */ +fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2); + +/* qhasm: z_40_0 = z_40_20*z_20_0 */ +/* asm 1: fe_mul(>z_40_0=fe#2,<z_40_20=fe#3,<z_20_0=fe#2); */ +/* asm 2: fe_mul(>z_40_0=t1,<z_40_20=t2,<z_20_0=t1); */ +fe_mul(t1,t2,t1); + +/* qhasm: z_50_10 = z_40_0^2^10 */ +/* asm 1: fe_sq(>z_50_10=fe#2,<z_40_0=fe#2); for (i = 1;i < 10;++i) fe_sq(>z_50_10=fe#2,>z_50_10=fe#2); */ +/* asm 2: fe_sq(>z_50_10=t1,<z_40_0=t1); for (i = 1;i < 10;++i) fe_sq(>z_50_10=t1,>z_50_10=t1); */ +fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1); + +/* qhasm: z_50_0 = z_50_10*z_10_0 */ +/* asm 1: fe_mul(>z_50_0=fe#1,<z_50_10=fe#2,<z_10_0=fe#1); */ +/* asm 2: fe_mul(>z_50_0=t0,<z_50_10=t1,<z_10_0=t0); */ +fe_mul(t0,t1,t0); + +/* qhasm: z_100_50 = z_50_0^2^50 */ +/* asm 1: fe_sq(>z_100_50=fe#2,<z_50_0=fe#1); for (i = 1;i < 50;++i) fe_sq(>z_100_50=fe#2,>z_100_50=fe#2); */ +/* asm 2: fe_sq(>z_100_50=t1,<z_50_0=t0); for (i = 1;i < 50;++i) fe_sq(>z_100_50=t1,>z_100_50=t1); */ +fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1); + +/* qhasm: z_100_0 = z_100_50*z_50_0 */ +/* asm 1: fe_mul(>z_100_0=fe#2,<z_100_50=fe#2,<z_50_0=fe#1); */ +/* asm 2: fe_mul(>z_100_0=t1,<z_100_50=t1,<z_50_0=t0); */ +fe_mul(t1,t1,t0); + +/* qhasm: z_200_100 = z_100_0^2^100 */ +/* asm 1: fe_sq(>z_200_100=fe#3,<z_100_0=fe#2); for (i = 1;i < 100;++i) fe_sq(>z_200_100=fe#3,>z_200_100=fe#3); */ +/* asm 2: fe_sq(>z_200_100=t2,<z_100_0=t1); for (i = 1;i < 100;++i) fe_sq(>z_200_100=t2,>z_200_100=t2); */ +fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2); + +/* qhasm: z_200_0 = z_200_100*z_100_0 */ +/* asm 1: fe_mul(>z_200_0=fe#2,<z_200_100=fe#3,<z_100_0=fe#2); */ +/* asm 2: fe_mul(>z_200_0=t1,<z_200_100=t2,<z_100_0=t1); */ +fe_mul(t1,t2,t1); + +/* qhasm: z_250_50 = z_200_0^2^50 */ +/* asm 1: fe_sq(>z_250_50=fe#2,<z_200_0=fe#2); for (i = 1;i < 50;++i) fe_sq(>z_250_50=fe#2,>z_250_50=fe#2); */ +/* asm 2: fe_sq(>z_250_50=t1,<z_200_0=t1); for (i = 1;i < 50;++i) fe_sq(>z_250_50=t1,>z_250_50=t1); */ +fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1); + +/* qhasm: z_250_0 = z_250_50*z_50_0 */ +/* asm 1: fe_mul(>z_250_0=fe#1,<z_250_50=fe#2,<z_50_0=fe#1); */ +/* asm 2: fe_mul(>z_250_0=t0,<z_250_50=t1,<z_50_0=t0); */ +fe_mul(t0,t1,t0); + +/* qhasm: z_252_2 = z_250_0^2^2 */ +/* asm 1: fe_sq(>z_252_2=fe#1,<z_250_0=fe#1); for (i = 1;i < 2;++i) fe_sq(>z_252_2=fe#1,>z_252_2=fe#1); */ +/* asm 2: fe_sq(>z_252_2=t0,<z_250_0=t0); for (i = 1;i < 2;++i) fe_sq(>z_252_2=t0,>z_252_2=t0); */ +fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0); + +/* qhasm: z_252_3 = z_252_2*z1 */ +/* asm 1: fe_mul(>z_252_3=fe#12,<z_252_2=fe#1,<z1=fe#11); */ +/* asm 2: fe_mul(>z_252_3=out,<z_252_2=t0,<z1=z); */ +fe_mul(out,t0,z); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/pow22523.q b/src/ext/ed25519/ref10/pow22523.q new file mode 100644 index 0000000000..2ce1da9d4d --- /dev/null +++ b/src/ext/ed25519/ref10/pow22523.q @@ -0,0 +1,61 @@ +:name:fe:t0:t1:t2:t3:t4:t5:t6:t7:t8:t9:z:out: +fe r:var/r=fe: + +enter f:enter/f:>z1=fe#11: +return:nofallthrough:<z_252_3=fe#12:leave: + +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2^k:<f=fe:>h=fe:#k:asm/fe_sq(>h,<f); for (i = 1;i !lt; #k;++i) fe_sq(>h,>h);: + +: + +fe z1 +fe z2 +fe z8 +fe z9 +fe z11 +fe z22 +fe z_5_0 +fe z_10_5 +fe z_10_0 +fe z_20_10 +fe z_20_0 +fe z_40_20 +fe z_40_0 +fe z_50_10 +fe z_50_0 +fe z_100_50 +fe z_100_0 +fe z_200_100 +fe z_200_0 +fe z_250_50 +fe z_250_0 +fe z_252_2 +fe z_252_3 + +enter pow22523 + +z2 = z1^2^1 +z8 = z2^2^2 +z9 = z1*z8 +z11 = z2*z9 +z22 = z11^2^1 +z_5_0 = z9*z22 +z_10_5 = z_5_0^2^5 +z_10_0 = z_10_5*z_5_0 +z_20_10 = z_10_0^2^10 +z_20_0 = z_20_10*z_10_0 +z_40_20 = z_20_0^2^20 +z_40_0 = z_40_20*z_20_0 +z_50_10 = z_40_0^2^10 +z_50_0 = z_50_10*z_10_0 +z_100_50 = z_50_0^2^50 +z_100_0 = z_100_50*z_50_0 +z_200_100 = z_100_0^2^100 +z_200_0 = z_200_100*z_100_0 +z_250_50 = z_200_0^2^50 +z_250_0 = z_250_50*z_50_0 +z_252_2 = z_250_0^2^2 +z_252_3 = z_252_2*z1 + +return diff --git a/src/ext/ed25519/ref10/pow225521.h b/src/ext/ed25519/ref10/pow225521.h new file mode 100644 index 0000000000..fe2af94c03 --- /dev/null +++ b/src/ext/ed25519/ref10/pow225521.h @@ -0,0 +1,161 @@ +/* Modified by Tor: pointless loops removed to appease analysis tools */ + +/* qhasm: fe z1 */ + +/* qhasm: fe z2 */ + +/* qhasm: fe z8 */ + +/* qhasm: fe z9 */ + +/* qhasm: fe z11 */ + +/* qhasm: fe z22 */ + +/* qhasm: fe z_5_0 */ + +/* qhasm: fe z_10_5 */ + +/* qhasm: fe z_10_0 */ + +/* qhasm: fe z_20_10 */ + +/* qhasm: fe z_20_0 */ + +/* qhasm: fe z_40_20 */ + +/* qhasm: fe z_40_0 */ + +/* qhasm: fe z_50_10 */ + +/* qhasm: fe z_50_0 */ + +/* qhasm: fe z_100_50 */ + +/* qhasm: fe z_100_0 */ + +/* qhasm: fe z_200_100 */ + +/* qhasm: fe z_200_0 */ + +/* qhasm: fe z_250_50 */ + +/* qhasm: fe z_250_0 */ + +/* qhasm: fe z_255_5 */ + +/* qhasm: fe z_255_21 */ + +/* qhasm: enter pow225521 */ + +/* qhasm: z2 = z1^2^1 */ +/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */ +/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */ +fe_sq(t0,z); /* DEADCODE This loop has no effect: for (i = 1;i < 1;++i) fe_sq(t0,t0); */ + +/* qhasm: z8 = z2^2^2 */ +/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */ +/* asm 2: fe_sq(>z8=t1,<z2=t0); for (i = 1;i < 2;++i) fe_sq(>z8=t1,>z8=t1); */ +fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); + +/* qhasm: z9 = z1*z8 */ +/* asm 1: fe_mul(>z9=fe#2,<z1=fe#11,<z8=fe#2); */ +/* asm 2: fe_mul(>z9=t1,<z1=z,<z8=t1); */ +fe_mul(t1,z,t1); + +/* qhasm: z11 = z2*z9 */ +/* asm 1: fe_mul(>z11=fe#1,<z2=fe#1,<z9=fe#2); */ +/* asm 2: fe_mul(>z11=t0,<z2=t0,<z9=t1); */ +fe_mul(t0,t0,t1); + +/* qhasm: z22 = z11^2^1 */ +/* asm 1: fe_sq(>z22=fe#3,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#3,>z22=fe#3); */ +/* asm 2: fe_sq(>z22=t2,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t2,>z22=t2); */ +fe_sq(t2,t0); /* DEADCODE This loop has no effect for (i = 1;i < 1;++i) fe_sq(t2,t2); */ + +/* qhasm: z_5_0 = z9*z22 */ +/* asm 1: fe_mul(>z_5_0=fe#2,<z9=fe#2,<z22=fe#3); */ +/* asm 2: fe_mul(>z_5_0=t1,<z9=t1,<z22=t2); */ +fe_mul(t1,t1,t2); + +/* qhasm: z_10_5 = z_5_0^2^5 */ +/* asm 1: fe_sq(>z_10_5=fe#3,<z_5_0=fe#2); for (i = 1;i < 5;++i) fe_sq(>z_10_5=fe#3,>z_10_5=fe#3); */ +/* asm 2: fe_sq(>z_10_5=t2,<z_5_0=t1); for (i = 1;i < 5;++i) fe_sq(>z_10_5=t2,>z_10_5=t2); */ +fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2); + +/* qhasm: z_10_0 = z_10_5*z_5_0 */ +/* asm 1: fe_mul(>z_10_0=fe#2,<z_10_5=fe#3,<z_5_0=fe#2); */ +/* asm 2: fe_mul(>z_10_0=t1,<z_10_5=t2,<z_5_0=t1); */ +fe_mul(t1,t2,t1); + +/* qhasm: z_20_10 = z_10_0^2^10 */ +/* asm 1: fe_sq(>z_20_10=fe#3,<z_10_0=fe#2); for (i = 1;i < 10;++i) fe_sq(>z_20_10=fe#3,>z_20_10=fe#3); */ +/* asm 2: fe_sq(>z_20_10=t2,<z_10_0=t1); for (i = 1;i < 10;++i) fe_sq(>z_20_10=t2,>z_20_10=t2); */ +fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2); + +/* qhasm: z_20_0 = z_20_10*z_10_0 */ +/* asm 1: fe_mul(>z_20_0=fe#3,<z_20_10=fe#3,<z_10_0=fe#2); */ +/* asm 2: fe_mul(>z_20_0=t2,<z_20_10=t2,<z_10_0=t1); */ +fe_mul(t2,t2,t1); + +/* qhasm: z_40_20 = z_20_0^2^20 */ +/* asm 1: fe_sq(>z_40_20=fe#4,<z_20_0=fe#3); for (i = 1;i < 20;++i) fe_sq(>z_40_20=fe#4,>z_40_20=fe#4); */ +/* asm 2: fe_sq(>z_40_20=t3,<z_20_0=t2); for (i = 1;i < 20;++i) fe_sq(>z_40_20=t3,>z_40_20=t3); */ +fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3); + +/* qhasm: z_40_0 = z_40_20*z_20_0 */ +/* asm 1: fe_mul(>z_40_0=fe#3,<z_40_20=fe#4,<z_20_0=fe#3); */ +/* asm 2: fe_mul(>z_40_0=t2,<z_40_20=t3,<z_20_0=t2); */ +fe_mul(t2,t3,t2); + +/* qhasm: z_50_10 = z_40_0^2^10 */ +/* asm 1: fe_sq(>z_50_10=fe#3,<z_40_0=fe#3); for (i = 1;i < 10;++i) fe_sq(>z_50_10=fe#3,>z_50_10=fe#3); */ +/* asm 2: fe_sq(>z_50_10=t2,<z_40_0=t2); for (i = 1;i < 10;++i) fe_sq(>z_50_10=t2,>z_50_10=t2); */ +fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2); + +/* qhasm: z_50_0 = z_50_10*z_10_0 */ +/* asm 1: fe_mul(>z_50_0=fe#2,<z_50_10=fe#3,<z_10_0=fe#2); */ +/* asm 2: fe_mul(>z_50_0=t1,<z_50_10=t2,<z_10_0=t1); */ +fe_mul(t1,t2,t1); + +/* qhasm: z_100_50 = z_50_0^2^50 */ +/* asm 1: fe_sq(>z_100_50=fe#3,<z_50_0=fe#2); for (i = 1;i < 50;++i) fe_sq(>z_100_50=fe#3,>z_100_50=fe#3); */ +/* asm 2: fe_sq(>z_100_50=t2,<z_50_0=t1); for (i = 1;i < 50;++i) fe_sq(>z_100_50=t2,>z_100_50=t2); */ +fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2); + +/* qhasm: z_100_0 = z_100_50*z_50_0 */ +/* asm 1: fe_mul(>z_100_0=fe#3,<z_100_50=fe#3,<z_50_0=fe#2); */ +/* asm 2: fe_mul(>z_100_0=t2,<z_100_50=t2,<z_50_0=t1); */ +fe_mul(t2,t2,t1); + +/* qhasm: z_200_100 = z_100_0^2^100 */ +/* asm 1: fe_sq(>z_200_100=fe#4,<z_100_0=fe#3); for (i = 1;i < 100;++i) fe_sq(>z_200_100=fe#4,>z_200_100=fe#4); */ +/* asm 2: fe_sq(>z_200_100=t3,<z_100_0=t2); for (i = 1;i < 100;++i) fe_sq(>z_200_100=t3,>z_200_100=t3); */ +fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3); + +/* qhasm: z_200_0 = z_200_100*z_100_0 */ +/* asm 1: fe_mul(>z_200_0=fe#3,<z_200_100=fe#4,<z_100_0=fe#3); */ +/* asm 2: fe_mul(>z_200_0=t2,<z_200_100=t3,<z_100_0=t2); */ +fe_mul(t2,t3,t2); + +/* qhasm: z_250_50 = z_200_0^2^50 */ +/* asm 1: fe_sq(>z_250_50=fe#3,<z_200_0=fe#3); for (i = 1;i < 50;++i) fe_sq(>z_250_50=fe#3,>z_250_50=fe#3); */ +/* asm 2: fe_sq(>z_250_50=t2,<z_200_0=t2); for (i = 1;i < 50;++i) fe_sq(>z_250_50=t2,>z_250_50=t2); */ +fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2); + +/* qhasm: z_250_0 = z_250_50*z_50_0 */ +/* asm 1: fe_mul(>z_250_0=fe#2,<z_250_50=fe#3,<z_50_0=fe#2); */ +/* asm 2: fe_mul(>z_250_0=t1,<z_250_50=t2,<z_50_0=t1); */ +fe_mul(t1,t2,t1); + +/* qhasm: z_255_5 = z_250_0^2^5 */ +/* asm 1: fe_sq(>z_255_5=fe#2,<z_250_0=fe#2); for (i = 1;i < 5;++i) fe_sq(>z_255_5=fe#2,>z_255_5=fe#2); */ +/* asm 2: fe_sq(>z_255_5=t1,<z_250_0=t1); for (i = 1;i < 5;++i) fe_sq(>z_255_5=t1,>z_255_5=t1); */ +fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1); + +/* qhasm: z_255_21 = z_255_5*z11 */ +/* asm 1: fe_mul(>z_255_21=fe#12,<z_255_5=fe#2,<z11=fe#1); */ +/* asm 2: fe_mul(>z_255_21=out,<z_255_5=t1,<z11=t0); */ +fe_mul(out,t1,t0); + +/* qhasm: return */ diff --git a/src/ext/ed25519/ref10/pow225521.q b/src/ext/ed25519/ref10/pow225521.q new file mode 100644 index 0000000000..45be57c08a --- /dev/null +++ b/src/ext/ed25519/ref10/pow225521.q @@ -0,0 +1,61 @@ +:name:fe:t0:t1:t2:t3:t4:t5:t6:t7:t8:t9:z:out: +fe r:var/r=fe: + +enter f:enter/f:>z1=fe#11: +return:nofallthrough:<z_255_21=fe#12:leave: + +h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);: +h=f^2^k:<f=fe:>h=fe:#k:asm/fe_sq(>h,<f); for (i = 1;i !lt; #k;++i) fe_sq(>h,>h);: + +: + +fe z1 +fe z2 +fe z8 +fe z9 +fe z11 +fe z22 +fe z_5_0 +fe z_10_5 +fe z_10_0 +fe z_20_10 +fe z_20_0 +fe z_40_20 +fe z_40_0 +fe z_50_10 +fe z_50_0 +fe z_100_50 +fe z_100_0 +fe z_200_100 +fe z_200_0 +fe z_250_50 +fe z_250_0 +fe z_255_5 +fe z_255_21 + +enter pow225521 + +z2 = z1^2^1 +z8 = z2^2^2 +z9 = z1*z8 +z11 = z2*z9 +z22 = z11^2^1 +z_5_0 = z9*z22 +z_10_5 = z_5_0^2^5 +z_10_0 = z_10_5*z_5_0 +z_20_10 = z_10_0^2^10 +z_20_0 = z_20_10*z_10_0 +z_40_20 = z_20_0^2^20 +z_40_0 = z_40_20*z_20_0 +z_50_10 = z_40_0^2^10 +z_50_0 = z_50_10*z_10_0 +z_100_50 = z_50_0^2^50 +z_100_0 = z_100_50*z_50_0 +z_200_100 = z_100_0^2^100 +z_200_0 = z_200_100*z_100_0 +z_250_50 = z_200_0^2^50 +z_250_0 = z_250_50*z_50_0 +z_255_5 = z_250_0^2^5 +z_255_21 = z_255_5*z11 + +return diff --git a/src/ext/ed25519/ref10/q2h.sh b/src/ext/ed25519/ref10/q2h.sh new file mode 100755 index 0000000000..47ec5110e8 --- /dev/null +++ b/src/ext/ed25519/ref10/q2h.sh @@ -0,0 +1,4 @@ +#!/bin/sh +sed 's/^#.*//' \ +| qhasm-generic \ +| sed 's_//\(.*\)$_/*\1 */_' diff --git a/src/ext/ed25519/ref10/randombytes.h b/src/ext/ed25519/ref10/randombytes.h new file mode 100644 index 0000000000..fc709fcefc --- /dev/null +++ b/src/ext/ed25519/ref10/randombytes.h @@ -0,0 +1,4 @@ +/* Added for Tor. */ +#include "crypto.h" +#define randombytes(b, n) \ + (crypto_strongest_rand((b), (n))) diff --git a/src/ext/ed25519/ref10/sc.h b/src/ext/ed25519/ref10/sc.h new file mode 100644 index 0000000000..d32ed2e8ca --- /dev/null +++ b/src/ext/ed25519/ref10/sc.h @@ -0,0 +1,15 @@ +#ifndef SC_H +#define SC_H + +/* +The set of scalars is \Z/l +where l = 2^252 + 27742317777372353535851937790883648493. +*/ + +#define sc_reduce crypto_sign_ed25519_ref10_sc_reduce +#define sc_muladd crypto_sign_ed25519_ref10_sc_muladd + +extern void sc_reduce(unsigned char *); +extern void sc_muladd(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); + +#endif diff --git a/src/ext/ed25519/ref10/sc_muladd.c b/src/ext/ed25519/ref10/sc_muladd.c new file mode 100644 index 0000000000..20b94c1049 --- /dev/null +++ b/src/ext/ed25519/ref10/sc_muladd.c @@ -0,0 +1,368 @@ +#include "sc.h" +#include "crypto_int64.h" +#include "crypto_uint32.h" +#include "crypto_uint64.h" + +static crypto_uint64 load_3(const unsigned char *in) +{ + crypto_uint64 result; + result = (crypto_uint64) in[0]; + result |= ((crypto_uint64) in[1]) << 8; + result |= ((crypto_uint64) in[2]) << 16; + return result; +} + +static crypto_uint64 load_4(const unsigned char *in) +{ + crypto_uint64 result; + result = (crypto_uint64) in[0]; + result |= ((crypto_uint64) in[1]) << 8; + result |= ((crypto_uint64) in[2]) << 16; + result |= ((crypto_uint64) in[3]) << 24; + return result; +} + +/* +Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + +Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + where l = 2^252 + 27742317777372353535851937790883648493. +*/ + +void sc_muladd(unsigned char *s,const unsigned char *a,const unsigned char *b,const unsigned char *c) +{ + crypto_int64 a0 = 2097151 & load_3(a); + crypto_int64 a1 = 2097151 & (load_4(a + 2) >> 5); + crypto_int64 a2 = 2097151 & (load_3(a + 5) >> 2); + crypto_int64 a3 = 2097151 & (load_4(a + 7) >> 7); + crypto_int64 a4 = 2097151 & (load_4(a + 10) >> 4); + crypto_int64 a5 = 2097151 & (load_3(a + 13) >> 1); + crypto_int64 a6 = 2097151 & (load_4(a + 15) >> 6); + crypto_int64 a7 = 2097151 & (load_3(a + 18) >> 3); + crypto_int64 a8 = 2097151 & load_3(a + 21); + crypto_int64 a9 = 2097151 & (load_4(a + 23) >> 5); + crypto_int64 a10 = 2097151 & (load_3(a + 26) >> 2); + crypto_int64 a11 = (load_4(a + 28) >> 7); + crypto_int64 b0 = 2097151 & load_3(b); + crypto_int64 b1 = 2097151 & (load_4(b + 2) >> 5); + crypto_int64 b2 = 2097151 & (load_3(b + 5) >> 2); + crypto_int64 b3 = 2097151 & (load_4(b + 7) >> 7); + crypto_int64 b4 = 2097151 & (load_4(b + 10) >> 4); + crypto_int64 b5 = 2097151 & (load_3(b + 13) >> 1); + crypto_int64 b6 = 2097151 & (load_4(b + 15) >> 6); + crypto_int64 b7 = 2097151 & (load_3(b + 18) >> 3); + crypto_int64 b8 = 2097151 & load_3(b + 21); + crypto_int64 b9 = 2097151 & (load_4(b + 23) >> 5); + crypto_int64 b10 = 2097151 & (load_3(b + 26) >> 2); + crypto_int64 b11 = (load_4(b + 28) >> 7); + crypto_int64 c0 = 2097151 & load_3(c); + crypto_int64 c1 = 2097151 & (load_4(c + 2) >> 5); + crypto_int64 c2 = 2097151 & (load_3(c + 5) >> 2); + crypto_int64 c3 = 2097151 & (load_4(c + 7) >> 7); + crypto_int64 c4 = 2097151 & (load_4(c + 10) >> 4); + crypto_int64 c5 = 2097151 & (load_3(c + 13) >> 1); + crypto_int64 c6 = 2097151 & (load_4(c + 15) >> 6); + crypto_int64 c7 = 2097151 & (load_3(c + 18) >> 3); + crypto_int64 c8 = 2097151 & load_3(c + 21); + crypto_int64 c9 = 2097151 & (load_4(c + 23) >> 5); + crypto_int64 c10 = 2097151 & (load_3(c + 26) >> 2); + crypto_int64 c11 = (load_4(c + 28) >> 7); + crypto_int64 s0; + crypto_int64 s1; + crypto_int64 s2; + crypto_int64 s3; + crypto_int64 s4; + crypto_int64 s5; + crypto_int64 s6; + crypto_int64 s7; + crypto_int64 s8; + crypto_int64 s9; + crypto_int64 s10; + crypto_int64 s11; + crypto_int64 s12; + crypto_int64 s13; + crypto_int64 s14; + crypto_int64 s15; + crypto_int64 s16; + crypto_int64 s17; + crypto_int64 s18; + crypto_int64 s19; + crypto_int64 s20; + crypto_int64 s21; + crypto_int64 s22; + crypto_int64 s23; + crypto_int64 carry0; + crypto_int64 carry1; + crypto_int64 carry2; + crypto_int64 carry3; + crypto_int64 carry4; + crypto_int64 carry5; + crypto_int64 carry6; + crypto_int64 carry7; + crypto_int64 carry8; + crypto_int64 carry9; + crypto_int64 carry10; + crypto_int64 carry11; + crypto_int64 carry12; + crypto_int64 carry13; + crypto_int64 carry14; + crypto_int64 carry15; + crypto_int64 carry16; + crypto_int64 carry17; + crypto_int64 carry18; + crypto_int64 carry19; + crypto_int64 carry20; + crypto_int64 carry21; + crypto_int64 carry22; + + s0 = c0 + a0*b0; + s1 = c1 + a0*b1 + a1*b0; + s2 = c2 + a0*b2 + a1*b1 + a2*b0; + s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0; + s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0; + s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0; + s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0; + s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0; + s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0; + s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0; + s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0; + s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0; + s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1; + s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2; + s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3; + s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4; + s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5; + s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6; + s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7; + s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8; + s20 = a9*b11 + a10*b10 + a11*b9; + s21 = a10*b11 + a11*b10; + s22 = a11*b11; + s23 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21); + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21); + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21); + carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= SHL64(carry18,21); + carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= SHL64(carry20,21); + carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= SHL64(carry22,21); + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21); + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21); + carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= SHL64(carry17,21); + carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= SHL64(carry19,21); + carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= SHL64(carry21,21); + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21); + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21); + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21); + + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21); + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + carry11 = s11 >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | SHL64(s1,5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | SHL64(s2,2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | SHL64(s3,7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | SHL64(s4,4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | SHL64(s5,1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | SHL64(s6,6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | SHL64(s7,3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | SHL64(s9,5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | SHL64(s10,2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | SHL64(s11,7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} diff --git a/src/ext/ed25519/ref10/sc_reduce.c b/src/ext/ed25519/ref10/sc_reduce.c new file mode 100644 index 0000000000..c5afa53741 --- /dev/null +++ b/src/ext/ed25519/ref10/sc_reduce.c @@ -0,0 +1,275 @@ +#include "sc.h" +#include "crypto_int64.h" +#include "crypto_uint32.h" +#include "crypto_uint64.h" + +static crypto_uint64 load_3(const unsigned char *in) +{ + crypto_uint64 result; + result = (crypto_uint64) in[0]; + result |= ((crypto_uint64) in[1]) << 8; + result |= ((crypto_uint64) in[2]) << 16; + return result; +} + +static crypto_uint64 load_4(const unsigned char *in) +{ + crypto_uint64 result; + result = (crypto_uint64) in[0]; + result |= ((crypto_uint64) in[1]) << 8; + result |= ((crypto_uint64) in[2]) << 16; + result |= ((crypto_uint64) in[3]) << 24; + return result; +} + +/* +Input: + s[0]+256*s[1]+...+256^63*s[63] = s + +Output: + s[0]+256*s[1]+...+256^31*s[31] = s mod l + where l = 2^252 + 27742317777372353535851937790883648493. + Overwrites s in place. +*/ + +void sc_reduce(unsigned char *s) +{ + crypto_int64 s0 = 2097151 & load_3(s); + crypto_int64 s1 = 2097151 & (load_4(s + 2) >> 5); + crypto_int64 s2 = 2097151 & (load_3(s + 5) >> 2); + crypto_int64 s3 = 2097151 & (load_4(s + 7) >> 7); + crypto_int64 s4 = 2097151 & (load_4(s + 10) >> 4); + crypto_int64 s5 = 2097151 & (load_3(s + 13) >> 1); + crypto_int64 s6 = 2097151 & (load_4(s + 15) >> 6); + crypto_int64 s7 = 2097151 & (load_3(s + 18) >> 3); + crypto_int64 s8 = 2097151 & load_3(s + 21); + crypto_int64 s9 = 2097151 & (load_4(s + 23) >> 5); + crypto_int64 s10 = 2097151 & (load_3(s + 26) >> 2); + crypto_int64 s11 = 2097151 & (load_4(s + 28) >> 7); + crypto_int64 s12 = 2097151 & (load_4(s + 31) >> 4); + crypto_int64 s13 = 2097151 & (load_3(s + 34) >> 1); + crypto_int64 s14 = 2097151 & (load_4(s + 36) >> 6); + crypto_int64 s15 = 2097151 & (load_3(s + 39) >> 3); + crypto_int64 s16 = 2097151 & load_3(s + 42); + crypto_int64 s17 = 2097151 & (load_4(s + 44) >> 5); + crypto_int64 s18 = 2097151 & (load_3(s + 47) >> 2); + crypto_int64 s19 = 2097151 & (load_4(s + 49) >> 7); + crypto_int64 s20 = 2097151 & (load_4(s + 52) >> 4); + crypto_int64 s21 = 2097151 & (load_3(s + 55) >> 1); + crypto_int64 s22 = 2097151 & (load_4(s + 57) >> 6); + crypto_int64 s23 = (load_4(s + 60) >> 3); + crypto_int64 carry0; + crypto_int64 carry1; + crypto_int64 carry2; + crypto_int64 carry3; + crypto_int64 carry4; + crypto_int64 carry5; + crypto_int64 carry6; + crypto_int64 carry7; + crypto_int64 carry8; + crypto_int64 carry9; + crypto_int64 carry10; + crypto_int64 carry11; + crypto_int64 carry12; + crypto_int64 carry13; + crypto_int64 carry14; + crypto_int64 carry15; + crypto_int64 carry16; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21); + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21); + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21); + + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21); + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + carry11 = s11 >> 21; s12 += carry11; s11 -= SHL64(carry11,21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); + carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); + carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); + carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); + carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); + carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); + carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); + carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); + carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); + carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); + carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | SHL64(s1,5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | SHL64(s2,2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | SHL64(s3,7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | SHL64(s4,4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | SHL64(s5,1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | SHL64(s6,6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | SHL64(s7,3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | SHL64(s9,5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | SHL64(s10,2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | SHL64(s11,7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} diff --git a/src/ext/ed25519/ref10/sign.c b/src/ext/ed25519/ref10/sign.c new file mode 100644 index 0000000000..1190a0fc99 --- /dev/null +++ b/src/ext/ed25519/ref10/sign.c @@ -0,0 +1,29 @@ +/* (Modified by Tor to generate detached signatures.) */ +#include <string.h> +#include "crypto_sign.h" +#include "crypto_hash_sha512.h" +#include "ge.h" +#include "sc.h" + +int crypto_sign( + unsigned char *sig, + const unsigned char *m, size_t mlen, + const unsigned char *sk,const unsigned char *pk +) +{ + unsigned char nonce[64]; + unsigned char hram[64]; + ge_p3 R; + + crypto_hash_sha512_2(nonce, sk+32, 32, m, mlen); + + sc_reduce(nonce); + ge_scalarmult_base(&R,nonce); + ge_p3_tobytes(sig,&R); + + crypto_hash_sha512_3(hram, sig, 32, pk, 32, m, mlen); + sc_reduce(hram); + sc_muladd(sig + 32,hram,sk,nonce); + + return 0; +} diff --git a/src/ext/ed25519/ref10/sqrtm1.h b/src/ext/ed25519/ref10/sqrtm1.h new file mode 100644 index 0000000000..d8caa23b6a --- /dev/null +++ b/src/ext/ed25519/ref10/sqrtm1.h @@ -0,0 +1 @@ +-32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482 diff --git a/src/ext/ed25519/ref10/sqrtm1.py b/src/ext/ed25519/ref10/sqrtm1.py new file mode 100644 index 0000000000..9a47fbc12a --- /dev/null +++ b/src/ext/ed25519/ref10/sqrtm1.py @@ -0,0 +1,28 @@ +q = 2**255 - 19 + +def expmod(b,e,m): + if e == 0: return 1 + t = expmod(b,e/2,m)**2 % m + if e & 1: t = (t*b) % m + return t + +def inv(x): + return expmod(x,q-2,q) + +def radix255(x): + x = x % q + if x + x > q: x -= q + x = [x,0,0,0,0,0,0,0,0,0] + bits = [26,25,26,25,26,25,26,25,26,25] + for i in range(9): + carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i] + x[i] -= carry * 2**bits[i] + x[i + 1] += carry + result = "" + for i in range(9): + result = result+str(x[i])+"," + result = result+str(x[9]) + return result + +I = expmod(2,(q-1)/4,q) +print radix255(I) diff --git a/src/ext/ht.h b/src/ext/ht.h index 838710784f..61e9719224 100644 --- a/src/ext/ht.h +++ b/src/ext/ht.h @@ -302,8 +302,8 @@ ht_string_hash(const char *s) } \ } -#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \ - reallocfn, freefn) \ +#define HT_GENERATE2(name, type, field, hashfn, eqfn, load, reallocarrayfn, \ + freefn) \ /* Primes that aren't too far from powers of two. We stop at */ \ /* P=402653189 because P*sizeof(void*) is less than SSIZE_MAX */ \ /* even on a 32-bit platform. */ \ @@ -336,7 +336,7 @@ ht_string_hash(const char *s) new_load_limit = (unsigned)(load*new_len); \ } while (new_load_limit <= size && \ prime_idx < (int)name##_N_PRIMES); \ - if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \ + if ((new_table = reallocarrayfn(NULL, new_len, sizeof(struct type*)))) { \ unsigned b; \ memset(new_table, 0, new_len*sizeof(struct type*)); \ for (b = 0; b < head->hth_table_length; ++b) { \ @@ -356,7 +356,7 @@ ht_string_hash(const char *s) head->hth_table = new_table; \ } else { \ unsigned b, b2; \ - new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \ + new_table = reallocarrayfn(head->hth_table, new_len, sizeof(struct type*)); \ if (!new_table) return -1; \ memset(new_table + head->hth_table_length, 0, \ (new_len - head->hth_table_length)*sizeof(struct type*)); \ @@ -427,6 +427,21 @@ ht_string_hash(const char *s) return 0; \ } +#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \ + reallocfn, freefn) \ + static void * \ + name##_reallocarray(void *arg, size_t a, size_t b) \ + { \ + if ((b) && (a) > SIZE_MAX / (b)) \ + return NULL; \ + if (arg) \ + return reallocfn((arg),(a)*(b)); \ + else \ + return mallocfn((a)*(b)); \ + } \ + HT_GENERATE2(name, type, field, hashfn, eqfn, load, \ + name##_reallocarray, freefn) + /** Implements an over-optimized "find and insert if absent" block; * not meant for direct usage by typical code, or usage outside the critical * path.*/ diff --git a/src/ext/include.am b/src/ext/include.am index 26e194e88e..576fd4efb8 100644 --- a/src/ext/include.am +++ b/src/ext/include.am @@ -15,4 +15,80 @@ EXTHEADERS = \ noinst_HEADERS+= $(EXTHEADERS) +src_ext_ed25519_ref10_libed25519_ref10_a_CFLAGS= + +src_ext_ed25519_ref10_libed25519_ref10_a_SOURCES= \ + src/ext/ed25519/ref10/fe_0.c \ + src/ext/ed25519/ref10/fe_1.c \ + src/ext/ed25519/ref10/fe_add.c \ + src/ext/ed25519/ref10/fe_cmov.c \ + src/ext/ed25519/ref10/fe_copy.c \ + src/ext/ed25519/ref10/fe_frombytes.c \ + src/ext/ed25519/ref10/fe_invert.c \ + src/ext/ed25519/ref10/fe_isnegative.c \ + src/ext/ed25519/ref10/fe_isnonzero.c \ + src/ext/ed25519/ref10/fe_mul.c \ + src/ext/ed25519/ref10/fe_neg.c \ + src/ext/ed25519/ref10/fe_pow22523.c \ + src/ext/ed25519/ref10/fe_sq.c \ + src/ext/ed25519/ref10/fe_sq2.c \ + src/ext/ed25519/ref10/fe_sub.c \ + src/ext/ed25519/ref10/fe_tobytes.c \ + src/ext/ed25519/ref10/ge_add.c \ + src/ext/ed25519/ref10/ge_double_scalarmult.c \ + src/ext/ed25519/ref10/ge_frombytes.c \ + src/ext/ed25519/ref10/ge_madd.c \ + src/ext/ed25519/ref10/ge_msub.c \ + src/ext/ed25519/ref10/ge_p1p1_to_p2.c \ + src/ext/ed25519/ref10/ge_p1p1_to_p3.c \ + src/ext/ed25519/ref10/ge_p2_0.c \ + src/ext/ed25519/ref10/ge_p2_dbl.c \ + src/ext/ed25519/ref10/ge_p3_0.c \ + src/ext/ed25519/ref10/ge_p3_dbl.c \ + src/ext/ed25519/ref10/ge_p3_to_cached.c \ + src/ext/ed25519/ref10/ge_p3_to_p2.c \ + src/ext/ed25519/ref10/ge_p3_tobytes.c \ + src/ext/ed25519/ref10/ge_precomp_0.c \ + src/ext/ed25519/ref10/ge_scalarmult_base.c \ + src/ext/ed25519/ref10/ge_sub.c \ + src/ext/ed25519/ref10/ge_tobytes.c \ + src/ext/ed25519/ref10/keypair.c \ + src/ext/ed25519/ref10/open.c \ + src/ext/ed25519/ref10/sc_muladd.c \ + src/ext/ed25519/ref10/sc_reduce.c \ + src/ext/ed25519/ref10/sign.c \ + src/ext/ed25519/ref10/keyconv.c \ + src/ext/ed25519/ref10/blinding.c + +ED25519_REF10_HDRS = \ + src/ext/ed25519/ref10/api.h \ + src/ext/ed25519/ref10/base.h \ + src/ext/ed25519/ref10/base2.h \ + src/ext/ed25519/ref10/crypto_hash_sha512.h \ + src/ext/ed25519/ref10/crypto_int32.h \ + src/ext/ed25519/ref10/crypto_int64.h \ + src/ext/ed25519/ref10/crypto_sign.h \ + src/ext/ed25519/ref10/crypto_uint32.h \ + src/ext/ed25519/ref10/crypto_uint64.h \ + src/ext/ed25519/ref10/crypto_verify_32.h \ + src/ext/ed25519/ref10/d.h \ + src/ext/ed25519/ref10/d2.h \ + src/ext/ed25519/ref10/ed25519_ref10.h \ + src/ext/ed25519/ref10/fe.h \ + src/ext/ed25519/ref10/ge.h \ + src/ext/ed25519/ref10/ge_add.h \ + src/ext/ed25519/ref10/ge_madd.h \ + src/ext/ed25519/ref10/ge_msub.h \ + src/ext/ed25519/ref10/ge_p2_dbl.h \ + src/ext/ed25519/ref10/ge_sub.h \ + src/ext/ed25519/ref10/pow22523.h \ + src/ext/ed25519/ref10/pow225521.h \ + src/ext/ed25519/ref10/randombytes.h \ + src/ext/ed25519/ref10/sc.h \ + src/ext/ed25519/ref10/sqrtm1.h + +noinst_HEADERS += $(ED25519_REF10_HDRS) + +LIBED25519_REF10=src/ext/ed25519/ref10/libed25519_ref10.a +noinst_LIBRARIES += $(LIBED25519_REF10) diff --git a/src/ext/trunnel/trunnel-impl.h b/src/ext/trunnel/trunnel-impl.h new file mode 100644 index 0000000000..c88ee3988e --- /dev/null +++ b/src/ext/trunnel/trunnel-impl.h @@ -0,0 +1,310 @@ +/* trunnel-impl.h -- copied from Trunnel v1.2 + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +/* trunnel-impl.h -- Implementation helpers for trunnel, included by + * generated trunnel files + * + * Copyright 2014, The Tor Project, Inc. + * See license at the end of this file for copying information. + */ + +#ifndef TRUNNEL_IMPL_H_INCLUDED_ +#define TRUNNEL_IMPL_H_INCLUDED_ +#include "trunnel.h" +#include <assert.h> +#include <string.h> +#ifdef TRUNNEL_LOCAL_H +#include "trunnel-local.h" +#endif + +#ifdef _MSC_VER +#define uint8_t unsigned char +#define uint16_t unsigned short +#define uint32_t unsigned int +#define uint64_t unsigned __int64 +#define inline __inline +#else +#include <stdint.h> +#endif + +#ifdef _WIN32 +uint32_t trunnel_htonl(uint32_t a); +uint32_t trunnel_ntohl(uint32_t a); +uint16_t trunnel_htons(uint16_t a); +uint16_t trunnel_ntohs(uint16_t a); +#else +#include <arpa/inet.h> +#define trunnel_htonl(x) htonl(x) +#define trunnel_htons(x) htons(x) +#define trunnel_ntohl(x) ntohl(x) +#define trunnel_ntohs(x) ntohs(x) +#endif +uint64_t trunnel_htonll(uint64_t a); +uint64_t trunnel_ntohll(uint64_t a); + +#ifndef trunnel_assert +#define trunnel_assert(x) assert(x) +#endif + +static inline void +trunnel_set_uint64(void *p, uint64_t v) { + memcpy(p, &v, 8); +} +static inline void +trunnel_set_uint32(void *p, uint32_t v) { + memcpy(p, &v, 4); +} +static inline void +trunnel_set_uint16(void *p, uint16_t v) { + memcpy(p, &v, 2); +} +static inline void +trunnel_set_uint8(void *p, uint8_t v) { + memcpy(p, &v, 1); +} + +static inline uint64_t +trunnel_get_uint64(const void *p) { + uint64_t x; + memcpy(&x, p, 8); + return x; +} +static inline uint32_t +trunnel_get_uint32(const void *p) { + uint32_t x; + memcpy(&x, p, 4); + return x; +} +static inline uint16_t +trunnel_get_uint16(const void *p) { + uint16_t x; + memcpy(&x, p, 2); + return x; +} +static inline uint8_t +trunnel_get_uint8(const void *p) { + return *(const uint8_t*)p; +} + + +#ifdef TRUNNEL_DEBUG_FAILING_ALLOC +extern int trunnel_provoke_alloc_failure; + +static inline void * +trunnel_malloc(size_t n) +{ + if (trunnel_provoke_alloc_failure) { + if (--trunnel_provoke_alloc_failure == 0) + return NULL; + } + return malloc(n); +} +static inline void * +trunnel_calloc(size_t a, size_t b) +{ + if (trunnel_provoke_alloc_failure) { + if (--trunnel_provoke_alloc_failure == 0) + return NULL; + } + return calloc(a,b); +} +static inline char * +trunnel_strdup(const char *s) +{ + if (trunnel_provoke_alloc_failure) { + if (--trunnel_provoke_alloc_failure == 0) + return NULL; + } + return strdup(s); +} +#else +#ifndef trunnel_malloc +#define trunnel_malloc(x) (malloc((x))) +#endif +#ifndef trunnel_calloc +#define trunnel_calloc(a,b) (calloc((a),(b))) +#endif +#ifndef trunnel_strdup +#define trunnel_strdup(s) (strdup((s))) +#endif +#endif + +#ifndef trunnel_realloc +#define trunnel_realloc(a,b) realloc((a),(b)) +#endif + +#ifndef trunnel_free_ +#define trunnel_free_(x) (free(x)) +#endif +#define trunnel_free(x) ((x) ? (trunnel_free_(x),0) : (0)) + +#ifndef trunnel_abort +#define trunnel_abort() abort() +#endif + +#ifndef trunnel_memwipe +#define trunnel_memwipe(mem, len) ((void)0) +#define trunnel_wipestr(s) ((void)0) +#else +#define trunnel_wipestr(s) do { \ + if (s) \ + trunnel_memwipe(s, strlen(s)); \ + } while (0) +#endif + +/* ====== dynamic arrays ======== */ + +#ifdef NDEBUG +#define TRUNNEL_DYNARRAY_GET(da, n) \ + ((da)->elts_[(n)]) +#else +/** Return the 'n'th element of 'da'. */ +#define TRUNNEL_DYNARRAY_GET(da, n) \ + (((n) >= (da)->n_ ? (trunnel_abort(),0) : 0), (da)->elts_[(n)]) +#endif + +/** Change the 'n'th element of 'da' to 'v'. */ +#define TRUNNEL_DYNARRAY_SET(da, n, v) do { \ + trunnel_assert((n) < (da)->n_); \ + (da)->elts_[(n)] = (v); \ + } while (0) + +/** Expand the dynamic array 'da' of 'elttype' so that it can hold at least + * 'howmanymore' elements than its current capacity. Always tries to increase + * the length of the array. On failure, run the code in 'on_fail' and goto + * trunnel_alloc_failed. */ +#define TRUNNEL_DYNARRAY_EXPAND(elttype, da, howmanymore, on_fail) do { \ + elttype *newarray; \ + newarray = trunnel_dynarray_expand(&(da)->allocated_, \ + (da)->elts_, (howmanymore), \ + sizeof(elttype)); \ + if (newarray == NULL) { \ + on_fail; \ + goto trunnel_alloc_failed; \ + } \ + (da)->elts_ = newarray; \ + } while (0) + +/** Add 'v' to the end of the dynamic array 'da' of 'elttype', expanding it if + * necessary. code in 'on_fail' and goto trunnel_alloc_failed. */ +#define TRUNNEL_DYNARRAY_ADD(elttype, da, v, on_fail) do { \ + if ((da)->n_ == (da)->allocated_) { \ + TRUNNEL_DYNARRAY_EXPAND(elttype, da, 1, on_fail); \ + } \ + (da)->elts_[(da)->n_++] = (v); \ + } while (0) + +/** Return the number of elements in 'da'. */ +#define TRUNNEL_DYNARRAY_LEN(da) ((da)->n_) + +/** Remove all storage held by 'da' and set it to be empty. Does not free + * storage held by the elements themselves. */ +#define TRUNNEL_DYNARRAY_CLEAR(da) do { \ + trunnel_free((da)->elts_); \ + (da)->elts_ = NULL; \ + (da)->n_ = (da)->allocated_ = 0; \ + } while (0) + +/** Remove all storage held by 'da' and set it to be empty. Does not free + * storage held by the elements themselves. */ +#define TRUNNEL_DYNARRAY_WIPE(da) do { \ + trunnel_memwipe((da)->elts_, (da)->allocated_ * sizeof((da)->elts_[0])); \ + } while (0) + +/** Helper: wraps or implements an OpenBSD-style reallocarray. Behaves + * as realloc(a, x*y), but verifies that no overflow will occur in the + * multiplication. Returns NULL on failure. */ +#ifndef trunnel_reallocarray +void *trunnel_reallocarray(void *a, size_t x, size_t y); +#endif + +/** Helper to expand a dynamic array. Behaves as TRUNNEL_DYNARRAY_EXPAND(), + * taking the array of elements in 'ptr', a pointer to thethe current number + * of allocated elements in allocated_p, the minimum numbeer of elements to + * add in 'howmanymore', and the size of a single element in 'eltsize'. + * + * On success, adjust *allocated_p, and return the new value for the array of + * elements. On failure, adjust nothing and return NULL. + */ +void *trunnel_dynarray_expand(size_t *allocated_p, void *ptr, + size_t howmanymore, size_t eltsize); + +/** Type for a function to free members of a dynarray of pointers. */ +typedef void (*trunnel_free_fn_t)(void *); + +/** + * Helper to change the length of a dynamic array. Takes pointers to the + * current allocated and n fields of the array in 'allocated_p' and 'len_p', + * and the current array of elements in 'ptr'; takes the length of a single + * element in 'eltsize'. Changes the length to 'newlen'. If 'newlen' is + * greater than the current length, pads the new elements with 0. If newlen + * is less than the current length, and free_fn is non-NULL, treat the + * array as an array of void *, and invoke free_fn() on each removed element. + * + * On success, adjust *allocated_p and *len_p, and return the new value for + * the array of elements. On failure, adjust nothing, set *errcode_ptr to 1, + * and return NULL. + */ +void *trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p, + void *ptr, size_t newlen, + size_t eltsize, trunnel_free_fn_t free_fn, + uint8_t *errcode_ptr); + +/** + * Helper: return a pointer to the value of 'str' as a NUL-terminated string. + * Might have to reallocate the storage for 'str' in order to fit in the final + * NUL character. On allocation failure, return NULL. + */ +const char *trunnel_string_getstr(trunnel_string_t *str); + +/** + * Helper: change the contents of 'str' to hold the 'len'-byte string in + * 'inp'. Adjusts the storage to have a terminating NUL that doesn't count + * towards the length of the string. On success, return 0. On failure, set + * *errcode_ptr to 1 and return -1. + */ +int trunnel_string_setstr0(trunnel_string_t *str, const char *inp, size_t len, + uint8_t *errcode_ptr); + +/** + * As trunnel_dynarray_setlen, but adjusts a string rather than a dynamic + * array, and ensures that the new string is NUL-terminated. + */ +int trunnel_string_setlen(trunnel_string_t *str, size_t newlen, + uint8_t *errcode_ptr); + +#endif + + +/* +Copyright 2014 The Tor Project, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the names of the copyright owners nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff --git a/src/ext/trunnel/trunnel.c b/src/ext/trunnel/trunnel.c new file mode 100644 index 0000000000..da4885ca01 --- /dev/null +++ b/src/ext/trunnel/trunnel.c @@ -0,0 +1,246 @@ +/* trunnel.c -- copied from Trunnel v1.2 + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +/* trunnel.c -- Helper functions to implement trunnel. + * + * Copyright 2014, The Tor Project, Inc. + * See license at the end of this file for copying information. + * + * See trunnel-impl.h for documentation of these functions. + */ + +#include <stdlib.h> +#include <string.h> +#include "trunnel-impl.h" + +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define IS_LITTLE_ENDIAN 1 +#elif defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ + BYTE_ORDER == __ORDER_LITTLE_ENDIAN +# define IS_LITTLE_ENDIAN 1 +#elif defined(_WIN32) +# define IS_LITTLE_ENDIAN 1 +#elif defined(__APPLE__) +# include <libkern/OSByteOrder.h> +# define BSWAP64(x) OSSwapLittleToHostInt64(x) +#elif defined(sun) || defined(__sun) +# include <sys/byteorder.h> +# ifndef _BIG_ENDIAN +# define IS_LITTLE_ENDIAN +# endif +#else +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include <sys/endian.h> +# else +# include <endian.h> +# endif +# if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN +# define IS_LITTLE_ENDIAN +# endif +#endif + +#ifdef _WIN32 +uint16_t +trunnel_htons(uint16_t s) +{ + return (s << 8) | (s >> 8); +} +uint16_t +trunnel_ntohs(uint16_t s) +{ + return (s << 8) | (s >> 8); +} +uint32_t +trunnel_htonl(uint32_t s) +{ + return (s << 24) | + ((s << 8)&0xff0000) | + ((s >> 8)&0xff00) | + (s >> 24); +} +uint32_t +trunnel_ntohl(uint32_t s) +{ + return (s << 24) | + ((s << 8)&0xff0000) | + ((s >> 8)&0xff00) | + (s >> 24); +} +#endif + +uint64_t +trunnel_htonll(uint64_t a) +{ +#ifdef IS_LITTLE_ENDIAN + return trunnel_htonl(a>>32) | (((uint64_t)trunnel_htonl(a))<<32); +#else + return a; +#endif +} + +uint64_t +trunnel_ntohll(uint64_t a) +{ + return trunnel_htonll(a); +} + +#ifdef TRUNNEL_DEBUG_FAILING_ALLOC +/** Used for debugging and running tricky test cases: Makes the nth + * memoryation allocation call from now fail. + */ +int trunnel_provoke_alloc_failure = 0; +#endif + +void * +trunnel_dynarray_expand(size_t *allocated_p, void *ptr, + size_t howmanymore, size_t eltsize) +{ + size_t newsize = howmanymore + *allocated_p; + void *newarray = NULL; + if (newsize < 8) + newsize = 8; + if (newsize < *allocated_p * 2) + newsize = *allocated_p * 2; + if (newsize <= *allocated_p || newsize < howmanymore) + return NULL; + newarray = trunnel_reallocarray(ptr, newsize, eltsize); + if (newarray == NULL) + return NULL; + + *allocated_p = newsize; + return newarray; +} + +#ifndef trunnel_reallocarray +void * +trunnel_reallocarray(void *a, size_t x, size_t y) +{ +#ifdef TRUNNEL_DEBUG_FAILING_ALLOC + if (trunnel_provoke_alloc_failure) { + if (--trunnel_provoke_alloc_failure == 0) + return NULL; + } +#endif + if (x > SIZE_MAX / y) + return NULL; + return trunnel_realloc(a, x * y); +} +#endif + +const char * +trunnel_string_getstr(trunnel_string_t *str) +{ + trunnel_assert(str->allocated_ >= str->n_); + if (str->allocated_ == str->n_) { + TRUNNEL_DYNARRAY_EXPAND(char, str, 1, {}); + } + str->elts_[str->n_] = 0; + return str->elts_; +trunnel_alloc_failed: + return NULL; +} + +int +trunnel_string_setstr0(trunnel_string_t *str, const char *val, size_t len, + uint8_t *errcode_ptr) +{ + if (len == SIZE_MAX) + goto trunnel_alloc_failed; + if (str->allocated_ <= len) { + TRUNNEL_DYNARRAY_EXPAND(char, str, len + 1 - str->allocated_, {}); + } + memcpy(str->elts_, val, len); + str->n_ = len; + str->elts_[len] = 0; + return 0; +trunnel_alloc_failed: + *errcode_ptr = 1; + return -1; +} + +int +trunnel_string_setlen(trunnel_string_t *str, size_t newlen, + uint8_t *errcode_ptr) +{ + if (newlen == SIZE_MAX) + goto trunnel_alloc_failed; + if (str->allocated_ < newlen + 1) { + TRUNNEL_DYNARRAY_EXPAND(char, str, newlen + 1 - str->allocated_, {}); + } + if (str->n_ < newlen) { + memset(& (str->elts_[str->n_]), 0, (newlen - str->n_)); + } + str->n_ = newlen; + str->elts_[newlen] = 0; + return 0; + + trunnel_alloc_failed: + *errcode_ptr = 1; + return -1; +} + +void * +trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p, + void *ptr, size_t newlen, + size_t eltsize, trunnel_free_fn_t free_fn, + uint8_t *errcode_ptr) +{ + if (*allocated_p < newlen) { + void *newptr = trunnel_dynarray_expand(allocated_p, ptr, + newlen - *allocated_p, eltsize); + if (newptr == NULL) + goto trunnel_alloc_failed; + ptr = newptr; + } + if (free_fn && *len_p > newlen) { + size_t i; + void **elts = (void **) ptr; + for (i = newlen; i < *len_p; ++i) { + free_fn(elts[i]); + elts[i] = NULL; + } + } + if (*len_p < newlen) { + memset( ((char*)ptr) + (eltsize * *len_p), 0, (newlen - *len_p) * eltsize); + } + *len_p = newlen; + return ptr; + trunnel_alloc_failed: + *errcode_ptr = 1; + return NULL; +} + +/* +Copyright 2014 The Tor Project, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the names of the copyright owners nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff --git a/src/ext/trunnel/trunnel.h b/src/ext/trunnel/trunnel.h new file mode 100644 index 0000000000..f51cade03f --- /dev/null +++ b/src/ext/trunnel/trunnel.h @@ -0,0 +1,64 @@ +/* trunnel.h -- copied from Trunnel v1.2 + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +/* trunnel.h -- Public declarations for trunnel, to be included + * in trunnel header files. + + * Copyright 2014, The Tor Project, Inc. + * See license at the end of this file for copying information. + */ + +#ifndef TRUNNEL_H_INCLUDED_ +#define TRUNNEL_H_INCLUDED_ + +#include <sys/types.h> + +/** Macro to declare a variable-length dynamically allocated array. Trunnel + * uses these to store all variable-length arrays. */ +#define TRUNNEL_DYNARRAY_HEAD(name, elttype) \ + struct name { \ + size_t n_; \ + size_t allocated_; \ + elttype *elts_; \ + } + +/** Initializer for a dynamic array of a given element type. */ +#define TRUNNEL_DYNARRAY_INIT(elttype) { 0, 0, (elttype*)NULL } + +/** Typedef used for storing variable-length arrays of char. */ +typedef TRUNNEL_DYNARRAY_HEAD(trunnel_string_st, char) trunnel_string_t; + +#endif + +/* +Copyright 2014 The Tor Project, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the names of the copyright owners nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff --git a/src/include.am b/src/include.am index d0693e25b0..c468af3649 100644 --- a/src/include.am +++ b/src/include.am @@ -1,7 +1,9 @@ include src/ext/include.am +include src/trunnel/include.am include src/common/include.am include src/or/include.am include src/test/include.am include src/tools/include.am include src/win32/include.am include src/config/include.am + diff --git a/src/or/buffers.c b/src/or/buffers.c index 033f86288e..d174f8147a 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -55,6 +55,9 @@ * forever. */ +static void socks_request_set_socks5_error(socks_request_t *req, + socks5_reply_status_t reason); + static int parse_socks(const char *data, size_t datalen, socks_request_t *req, int log_sockstype, int safe_socks, ssize_t *drain_out, size_t *want_length_out); @@ -1831,6 +1834,21 @@ fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out) } #endif +/** Create a SOCKS5 reply message with <b>reason</b> in its REP field and + * have Tor send it as error response to <b>req</b>. + */ +static void +socks_request_set_socks5_error(socks_request_t *req, + socks5_reply_status_t reason) +{ + req->replylen = 10; + memset(req->reply,0,10); + + req->reply[0] = 0x05; // VER field. + req->reply[1] = reason; // REP field. + req->reply[3] = 0x01; // ATYP field. +} + /** Implementation helper to implement fetch_from_*_socks. Instead of looking * at a buffer's contents, we look at the <b>datalen</b> bytes of data in * <b>data</b>. Instead of removing data from the buffer, we set @@ -1966,6 +1984,8 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, req->command != SOCKS_COMMAND_RESOLVE && req->command != SOCKS_COMMAND_RESOLVE_PTR) { /* not a connect or resolve or a resolve_ptr? we don't support it. */ + socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED); + log_warn(LD_APP,"socks5: command %d not recognized. Rejecting.", req->command); return -1; diff --git a/src/or/channel.c b/src/or/channel.c index b2b670e4fb..c8c92633b1 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -108,8 +108,8 @@ channel_idmap_eq(const channel_idmap_entry_t *a, HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, channel_idmap_eq); -HT_GENERATE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, - channel_idmap_eq, 0.5, tor_malloc, tor_realloc, tor_free_); +HT_GENERATE2(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, + channel_idmap_eq, 0.5, tor_reallocarray_, tor_free_); static cell_queue_entry_t * cell_queue_entry_dup(cell_queue_entry_t *q); static void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off); diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c index 51a75cf502..59024abd12 100644 --- a/src/or/circpathbias.c +++ b/src/or/circpathbias.c @@ -1140,11 +1140,10 @@ pathbias_count_circs_in_states(entry_guard_t *guard, path_state_t from, path_state_t to) { - circuit_t *circ; int open_circuits = 0; /* Count currently open circuits. Give them the benefit of the doubt. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { origin_circuit_t *ocirc = NULL; if (!CIRCUIT_IS_ORIGIN(circ) || /* didn't originate here */ circ->marked_for_close) /* already counted */ @@ -1167,6 +1166,7 @@ pathbias_count_circs_in_states(entry_guard_t *guard, open_circuits++; } } + SMARTLIST_FOREACH_END(circ); return open_circuits; } diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 897f90fe4c..edf7d2863e 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1564,7 +1564,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) * -1 means "Don't use this router at all." */ the_nodes = nodelist_get_list(); - n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes)); + n_supported = tor_calloc(sizeof(int), smartlist_len(the_nodes)); SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) { const int i = node_sl_idx; if (router_digest_is_me(node->identity)) { diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index f3a83503ef..9d72ea1111 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -21,6 +21,7 @@ #include "connection_edge.h" #include "connection_or.h" #include "control.h" +#include "main.h" #include "networkstatus.h" #include "nodelist.h" #include "onion.h" @@ -38,8 +39,7 @@ /********* START VARIABLES **********/ /** A global list of all circuits at this hop. */ -struct global_circuitlist_s global_circuitlist = - TOR_LIST_HEAD_INITIALIZER(global_circuitlist); +static smartlist_t *global_circuitlist = NULL; /** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */ static smartlist_t *circuits_pending_chans = NULL; @@ -94,9 +94,9 @@ static HT_HEAD(chan_circid_map, chan_circid_circuit_map_t) chan_circid_map = HT_INITIALIZER(); HT_PROTOTYPE(chan_circid_map, chan_circid_circuit_map_t, node, chan_circid_entry_hash_, chan_circid_entries_eq_) -HT_GENERATE(chan_circid_map, chan_circid_circuit_map_t, node, - chan_circid_entry_hash_, chan_circid_entries_eq_, 0.6, - malloc, realloc, free) +HT_GENERATE2(chan_circid_map, chan_circid_circuit_map_t, node, + chan_circid_entry_hash_, chan_circid_entries_eq_, 0.6, + tor_reallocarray_, tor_free_) /** The most recently returned entry from circuit_get_by_circid_chan; * used to improve performance when many cells arrive in a row from the @@ -451,17 +451,25 @@ circuit_count_pending_on_channel(channel_t *chan) void circuit_close_all_marked(void) { - circuit_t *circ, *tmp; - TOR_LIST_FOREACH_SAFE(circ, &global_circuitlist, head, tmp) - if (circ->marked_for_close) + smartlist_t *lst = circuit_get_global_list(); + SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, circ) { + /* Fix up index if SMARTLIST_DEL_CURRENT just moved this one. */ + circ->global_circuitlist_idx = circ_sl_idx; + if (circ->marked_for_close) { + circ->global_circuitlist_idx = -1; circuit_free(circ); + SMARTLIST_DEL_CURRENT(lst, circ); + } + } SMARTLIST_FOREACH_END(circ); } /** Return the head of the global linked list of circuits. */ -MOCK_IMPL(struct global_circuitlist_s *, +MOCK_IMPL(smartlist_t *, circuit_get_global_list,(void)) { - return &global_circuitlist; + if (NULL == global_circuitlist) + global_circuitlist = smartlist_new(); + return global_circuitlist; } /** Function to make circ-\>state human-readable */ @@ -678,7 +686,8 @@ init_circuit_base(circuit_t *circ) circ->deliver_window = CIRCWINDOW_START; cell_queue_init(&circ->n_chan_cells); - TOR_LIST_INSERT_HEAD(&global_circuitlist, circ, head); + smartlist_add(circuit_get_global_list(), circ); + circ->global_circuitlist_idx = smartlist_len(circuit_get_global_list()) - 1; } /** Allocate space for a new circuit, initializing with <b>p_circ_id</b> @@ -799,7 +808,16 @@ circuit_free(circuit_t *circ) extend_info_free(circ->n_hop); tor_free(circ->n_chan_create_cell); - TOR_LIST_REMOVE(circ, head); + if (circ->global_circuitlist_idx != -1) { + int idx = circ->global_circuitlist_idx; + circuit_t *c2 = smartlist_get(global_circuitlist, idx); + tor_assert(c2 == circ); + smartlist_del(global_circuitlist, idx); + if (idx < smartlist_len(global_circuitlist)) { + c2 = smartlist_get(global_circuitlist, idx); + c2->global_circuitlist_idx = idx; + } + } /* Remove from map. */ circuit_set_n_circid_chan(circ, 0, NULL); @@ -841,9 +859,9 @@ circuit_clear_cpath(origin_circuit_t *circ) void circuit_free_all(void) { - circuit_t *tmp, *tmp2; + smartlist_t *lst = circuit_get_global_list(); - TOR_LIST_FOREACH_SAFE(tmp, &global_circuitlist, head, tmp2) { + SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, tmp) { if (! CIRCUIT_IS_ORIGIN(tmp)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(tmp); while (or_circ->resolving_streams) { @@ -853,8 +871,13 @@ circuit_free_all(void) or_circ->resolving_streams = next_conn; } } + tmp->global_circuitlist_idx = -1; circuit_free(tmp); - } + SMARTLIST_DEL_CURRENT(lst, tmp); + } SMARTLIST_FOREACH_END(tmp); + + smartlist_free(lst); + global_circuitlist = NULL; smartlist_free(circuits_pending_chans); circuits_pending_chans = NULL; @@ -932,10 +955,9 @@ circuit_dump_conn_details(int severity, void circuit_dump_by_conn(connection_t *conn, int severity) { - circuit_t *circ; edge_connection_t *tmpconn; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; if (circ->marked_for_close) { @@ -966,6 +988,7 @@ circuit_dump_by_conn(connection_t *conn, int severity) } } } + SMARTLIST_FOREACH_END(circ); } /** Return the circuit whose global ID is <b>id</b>, or NULL if no @@ -973,8 +996,7 @@ circuit_dump_by_conn(connection_t *conn, int severity) origin_circuit_t * circuit_get_by_global_id(uint32_t id) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) { if (circ->marked_for_close) @@ -983,6 +1005,7 @@ circuit_get_by_global_id(uint32_t id) return TO_ORIGIN_CIRCUIT(circ); } } + SMARTLIST_FOREACH_END(circ); return NULL; } @@ -1151,17 +1174,17 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason) #ifdef DEBUG_CIRCUIT_UNLINK_ALL { - circuit_t *circ; smartlist_t *detached_2 = smartlist_new(); int mismatch = 0, badlen = 0; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->n_chan == chan || (!CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_chan == chan)) { smartlist_add(detached_2, circ); } } + SMARTLIST_FOREACH_END(circ); if (smartlist_len(detached) != smartlist_len(detached_2)) { log_warn(LD_BUG, "List of detached circuits had the wrong length! " @@ -1235,8 +1258,7 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason) origin_circuit_t * circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); @@ -1249,6 +1271,7 @@ circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data) return ocirc; } } + SMARTLIST_FOREACH_END(circ); return NULL; } @@ -1261,14 +1284,17 @@ origin_circuit_t * circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, const char *digest, uint8_t purpose) { - circuit_t *circ; + int idx; + smartlist_t *lst = circuit_get_global_list(); tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose)); if (start == NULL) - circ = TOR_LIST_FIRST(&global_circuitlist); + idx = 0; else - circ = TOR_LIST_NEXT(TO_CIRCUIT(start), head); + idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1; + + for ( ; idx < smartlist_len(lst); ++idx) { + circuit_t *circ = smartlist_get(lst, idx); - for ( ; circ; circ = TOR_LIST_NEXT(circ, head)) { if (circ->marked_for_close) continue; if (circ->purpose != purpose) @@ -1469,7 +1495,6 @@ origin_circuit_t * circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int flags) { - circuit_t *circ_; origin_circuit_t *best=NULL; int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0; int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; @@ -1485,7 +1510,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, "capacity %d, internal %d", purpose, need_uptime, need_capacity, internal); - TOR_LIST_FOREACH(circ_, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) { if (CIRCUIT_IS_ORIGIN(circ_) && circ_->state == CIRCUIT_STATE_OPEN && !circ_->marked_for_close && @@ -1535,6 +1560,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, } } } + SMARTLIST_FOREACH_END(circ_); return best; } @@ -1574,13 +1600,13 @@ circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum) void circuit_mark_all_unused_circs(void) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && !circ->timestamp_dirty) circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } + SMARTLIST_FOREACH_END(circ); } /** Go through the circuitlist; for each circuit that starts at us @@ -1593,14 +1619,14 @@ circuit_mark_all_unused_circs(void) void circuit_mark_all_dirty_circs_as_unusable(void) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && circ->timestamp_dirty) { mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ)); } } + SMARTLIST_FOREACH_END(circ); } /** Mark <b>circ</b> to be closed next time we call @@ -1799,6 +1825,29 @@ marked_circuit_free_cells(circuit_t *circ) cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_chan_cells); } +static size_t +single_conn_free_bytes(connection_t *conn) +{ + size_t result = 0; + if (conn->inbuf) { + result += buf_allocation(conn->inbuf); + buf_clear(conn->inbuf); + } + if (conn->outbuf) { + result += buf_allocation(conn->outbuf); + buf_clear(conn->outbuf); + } + if (conn->type == CONN_TYPE_DIR) { + dir_connection_t *dir_conn = TO_DIR_CONN(conn); + if (dir_conn->zlib_state) { + result += tor_zlib_state_size(dir_conn->zlib_state); + tor_zlib_free(dir_conn->zlib_state); + dir_conn->zlib_state = NULL; + } + } + return result; +} + /** Aggressively free buffer contents on all the buffers of all streams in the * list starting at <b>stream</b>. Return the number of bytes recovered. */ static size_t @@ -1807,13 +1856,9 @@ marked_circuit_streams_free_bytes(edge_connection_t *stream) size_t result = 0; for ( ; stream; stream = stream->next_stream) { connection_t *conn = TO_CONN(stream); - if (conn->inbuf) { - result += buf_allocation(conn->inbuf); - buf_clear(conn->inbuf); - } - if (conn->outbuf) { - result += buf_allocation(conn->outbuf); - buf_clear(conn->outbuf); + result += single_conn_free_bytes(conn); + if (conn->linked_conn) { + result += single_conn_free_bytes(conn->linked_conn); } } return result; @@ -1871,6 +1916,28 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) return age; } +/** Return the age in milliseconds of the oldest buffer chunk on <b>conn</b>, + * where age is taken in milliseconds before the time <b>now</b> (in truncated + * milliseconds since the epoch). If the connection has no data, treat + * it as having age zero. + **/ +static uint32_t +conn_get_buffer_age(const connection_t *conn, uint32_t now) +{ + uint32_t age = 0, age2; + if (conn->outbuf) { + age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now); + if (age2 > age) + age = age2; + } + if (conn->inbuf) { + age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now); + if (age2 > age) + age = age2; + } + return age; +} + /** Return the age in milliseconds of the oldest buffer chunk on any stream in * the linked list <b>stream</b>, where age is taken in milliseconds before * the time <b>now</b> (in truncated milliseconds since the epoch). */ @@ -1880,18 +1947,15 @@ circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) uint32_t age = 0, age2; for (; stream; stream = stream->next_stream) { const connection_t *conn = TO_CONN(stream); - if (conn->outbuf) { - age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now); - if (age2 > age) - age = age2; - } - if (conn->inbuf) { - age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now); + age2 = conn_get_buffer_age(conn, now); + if (age2 > age) + age = age2; + if (conn->linked_conn) { + age2 = conn_get_buffer_age(conn->linked_conn, now); if (age2 > age) age = age2; } } - return age; } @@ -1942,6 +2006,26 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) return -1; } +static uint32_t now_ms_for_buf_cmp; + +/** Helper to sort a list of circuit_t by age of oldest item, in descending + * order. */ +static int +conns_compare_by_buffer_age_(const void **a_, const void **b_) +{ + const connection_t *a = *a_; + const connection_t *b = *b_; + time_t age_a = conn_get_buffer_age(a, now_ms_for_buf_cmp); + time_t age_b = conn_get_buffer_age(b, now_ms_for_buf_cmp); + + if (age_a < age_b) + return 1; + else if (age_a == age_b) + return 0; + else + return -1; +} + #define FRACTION_OF_DATA_TO_RETAIN_ON_OOM 0.90 /** We're out of memory for cells, having allocated <b>current_allocation</b> @@ -1950,12 +2034,13 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) void circuits_handle_oom(size_t current_allocation) { - /* Let's hope there's enough slack space for this allocation here... */ - smartlist_t *circlist = smartlist_new(); - circuit_t *circ; + smartlist_t *circlist; + smartlist_t *connection_array = get_connection_array(); + int conn_idx; size_t mem_to_recover; size_t mem_recovered=0; int n_circuits_killed=0; + int n_dirconns_killed=0; struct timeval now; uint32_t now_ms; log_notice(LD_GENERAL, "We're low on memory. Killing circuits with " @@ -1984,22 +2069,61 @@ circuits_handle_oom(size_t current_allocation) tor_gettimeofday_cached_monotonic(&now); now_ms = (uint32_t)tv_to_msec(&now); - /* This algorithm itself assumes that you've got enough memory slack - * to actually run it. */ - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + circlist = circuit_get_global_list(); + SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { circ->age_tmp = circuit_max_queued_item_age(circ, now_ms); - smartlist_add(circlist, circ); - } + } SMARTLIST_FOREACH_END(circ); /* This is O(n log n); there are faster algorithms we could use instead. * Let's hope this doesn't happen enough to be in the critical path. */ smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_); - /* Okay, now the worst circuits are at the front of the list. Let's mark - * them, and reclaim their storage aggressively. */ + /* Fix up the indices before we run into trouble */ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { - size_t n = n_cells_in_circ_queues(circ); + circ->global_circuitlist_idx = circ_sl_idx; + } SMARTLIST_FOREACH_END(circ); + + /* Now sort the connection array ... */ + now_ms_for_buf_cmp = now_ms; + smartlist_sort(connection_array, conns_compare_by_buffer_age_); + now_ms_for_buf_cmp = 0; + + /* Fix up the connection array to its new order. */ + SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { + conn->conn_array_index = conn_sl_idx; + } SMARTLIST_FOREACH_END(conn); + + /* Okay, now the worst circuits and connections are at the front of their + * respective lists. Let's mark them, and reclaim their storage + * aggressively. */ + conn_idx = 0; + SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { + size_t n; size_t freed; + + /* Free storage in any non-linked directory connections that have buffered + * data older than this circuit. */ + while (conn_idx < smartlist_len(connection_array)) { + connection_t *conn = smartlist_get(connection_array, conn_idx); + uint32_t conn_age = conn_get_buffer_age(conn, now_ms); + if (conn_age < circ->age_tmp) { + break; + } + if (conn->type == CONN_TYPE_DIR && conn->linked_conn == NULL) { + if (!conn->marked_for_close) + connection_mark_for_close(conn); + mem_recovered += single_conn_free_bytes(conn); + + ++n_dirconns_killed; + + if (mem_recovered >= mem_to_recover) + goto done_recovering_mem; + } + ++conn_idx; + } + + /* Now, kill the circuit. */ + n = n_cells_in_circ_queues(circ); if (! circ->marked_for_close) { circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); } @@ -2012,9 +2136,11 @@ circuits_handle_oom(size_t current_allocation) mem_recovered += freed; if (mem_recovered >= mem_to_recover) - break; + goto done_recovering_mem; } SMARTLIST_FOREACH_END(circ); + done_recovering_mem: + #ifdef ENABLE_MEMPOOLS clean_cell_pool(); /* In case this helps. */ #endif /* ENABLE_MEMPOOLS */ @@ -2022,12 +2148,12 @@ circuits_handle_oom(size_t current_allocation) chunks. */ log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits; " - "%d circuits remain alive.", + "%d circuits remain alive. Also killed %d non-linked directory " + "connections.", U64_PRINTF_ARG(mem_recovered), n_circuits_killed, - smartlist_len(circlist) - n_circuits_killed); - - smartlist_free(circlist); + smartlist_len(circlist) - n_circuits_killed, + n_dirconns_killed); } /** Verify that cpath layer <b>cp</b> has all of its invariants diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h index d48d7c3963..03934f971e 100644 --- a/src/or/circuitlist.h +++ b/src/or/circuitlist.h @@ -14,9 +14,7 @@ #include "testsupport.h" -TOR_LIST_HEAD(global_circuitlist_s, circuit_t); - -MOCK_DECL(struct global_circuitlist_s*, circuit_get_global_list, (void)); +MOCK_DECL(smartlist_t *, circuit_get_global_list, (void)); const char *circuit_state_to_string(int state); const char *circuit_purpose_to_controller_string(uint8_t purpose); const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose); diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c index e4571ff944..3ca33b03ce 100644 --- a/src/or/circuitmux.c +++ b/src/or/circuitmux.c @@ -363,9 +363,9 @@ HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t); /* Emit a bunch of hash table stuff */ HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, chanid_circid_entry_hash, chanid_circid_entries_eq); -HT_GENERATE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, - chanid_circid_entry_hash, chanid_circid_entries_eq, 0.6, - malloc, realloc, free); +HT_GENERATE2(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, + chanid_circid_entry_hash, chanid_circid_entries_eq, 0.6, + tor_reallocarray_, tor_free_) /* * Circuitmux alloc/free functions diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c index e362b1b49e..5336e4046e 100644 --- a/src/or/circuitstats.c +++ b/src/or/circuitstats.c @@ -404,7 +404,7 @@ circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, * distress anyway, so memory correctness here is paramount over * doing acrobatics to preserve the array. */ - recent_circs = tor_malloc_zero(sizeof(int8_t)*num); + recent_circs = tor_calloc(sizeof(int8_t), num); if (cbt->liveness.timeouts_after_firsthop && cbt->liveness.num_recent_circs > 0) { memcpy(recent_circs, cbt->liveness.timeouts_after_firsthop, @@ -508,7 +508,7 @@ circuit_build_times_init(circuit_build_times_t *cbt) cbt->liveness.num_recent_circs = circuit_build_times_recent_circuit_count(NULL); cbt->liveness.timeouts_after_firsthop = - tor_malloc_zero(sizeof(int8_t)*cbt->liveness.num_recent_circs); + tor_calloc(sizeof(int8_t), cbt->liveness.num_recent_circs); } else { cbt->liveness.num_recent_circs = 0; cbt->liveness.timeouts_after_firsthop = NULL; @@ -649,7 +649,7 @@ circuit_build_times_create_histogram(const circuit_build_times_t *cbt, int i, c; *nbins = 1 + (max_build_time / CBT_BIN_WIDTH); - histogram = tor_malloc_zero(*nbins * sizeof(build_time_t)); + histogram = tor_calloc(*nbins, sizeof(build_time_t)); // calculate histogram for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { @@ -691,7 +691,7 @@ circuit_build_times_get_xm(circuit_build_times_t *cbt) if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE) num_modes = 1; - nth_max_bin = (build_time_t*)tor_malloc_zero(num_modes*sizeof(build_time_t)); + nth_max_bin = tor_calloc(num_modes, sizeof(build_time_t)); /* Determine the N most common build times */ for (i = 0; i < nbins; i++) { @@ -873,7 +873,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt, } /* build_time_t 0 means uninitialized */ - loaded_times = tor_malloc_zero(sizeof(build_time_t)*state->TotalBuildTimes); + loaded_times = tor_calloc(sizeof(build_time_t), state->TotalBuildTimes); for (line = state->BuildtimeHistogram; line; line = line->next) { smartlist_t *args = smartlist_new(); @@ -1085,7 +1085,21 @@ circuit_build_times_calculate_timeout(circuit_build_times_t *cbt, tor_assert(1.0-quantile > 0); tor_assert(cbt->Xm > 0); - ret = cbt->Xm/pow(1.0-quantile,1.0/cbt->alpha); + /* If either alpha or p are 0, we would divide by zero, yielding an + * infinite (double) result; which would be clamped to INT32_MAX. + * Instead, initialise ret to INT32_MAX, and skip over these + * potentially illegal/trapping divides by zero. + */ + ret = INT32_MAX; + + if (cbt->alpha > 0) { + double p; + p = pow(1.0-quantile,1.0/cbt->alpha); + if (p > 0) { + ret = cbt->Xm/p; + } + } + if (ret > INT32_MAX) { ret = INT32_MAX; } @@ -1371,10 +1385,11 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt) } cbt->liveness.after_firsthop_idx = 0; +#define MAX_TIMEOUT ((int32_t) (INT32_MAX/2)) /* Check to see if this has happened before. If so, double the timeout * to give people on abysmally bad network connections a shot at access */ if (cbt->timeout_ms >= circuit_build_times_get_initial_timeout()) { - if (cbt->timeout_ms > INT32_MAX/2 || cbt->close_ms > INT32_MAX/2) { + if (cbt->timeout_ms > MAX_TIMEOUT || cbt->close_ms > MAX_TIMEOUT) { log_warn(LD_CIRC, "Insanely large circuit build timeout value. " "(timeout = %fmsec, close = %fmsec)", cbt->timeout_ms, cbt->close_ms); @@ -1386,6 +1401,7 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt) cbt->close_ms = cbt->timeout_ms = circuit_build_times_get_initial_timeout(); } +#undef MAX_TIMEOUT cbt_control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 714754a672..9ea0023568 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -268,7 +268,6 @@ circuit_get_best(const entry_connection_t *conn, int must_be_open, uint8_t purpose, int need_uptime, int need_internal) { - circuit_t *circ; origin_circuit_t *best=NULL; struct timeval now; int intro_going_on_but_too_old = 0; @@ -281,7 +280,7 @@ circuit_get_best(const entry_connection_t *conn, tor_gettimeofday(&now); - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { origin_circuit_t *origin_circ; if (!CIRCUIT_IS_ORIGIN(circ)) continue; @@ -305,6 +304,7 @@ circuit_get_best(const entry_connection_t *conn, if (!best || circuit_is_better(origin_circ,best,conn)) best = origin_circ; } + SMARTLIST_FOREACH_END(circ); if (!best && intro_going_on_but_too_old) log_info(LD_REND|LD_CIRC, "There is an intro circuit being created " @@ -318,11 +318,9 @@ circuit_get_best(const entry_connection_t *conn, static int count_pending_general_client_circuits(void) { - const circuit_t *circ; - int count = 0; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->marked_for_close || circ->state == CIRCUIT_STATE_OPEN || circ->purpose != CIRCUIT_PURPOSE_C_GENERAL || @@ -331,6 +329,7 @@ count_pending_general_client_circuits(void) ++count; } + SMARTLIST_FOREACH_END(circ); return count; } @@ -370,7 +369,6 @@ circuit_conforms_to_options(const origin_circuit_t *circ, void circuit_expire_building(void) { - circuit_t *victim, *next_circ; /* circ_times.timeout_ms and circ_times.close_ms are from * circuit_build_times_get_initial_timeout() if we haven't computed * custom timeouts yet */ @@ -388,7 +386,7 @@ circuit_expire_building(void) * we want to be more lenient with timeouts, in case the * user has relocated and/or changed network connections. * See bug #3443. */ - TOR_LIST_FOREACH(next_circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, next_circ) { if (!CIRCUIT_IS_ORIGIN(next_circ) || /* didn't originate here */ next_circ->marked_for_close) { /* don't mess with marked circs */ continue; @@ -402,7 +400,7 @@ circuit_expire_building(void) any_opened_circs = 1; break; } - } + } SMARTLIST_FOREACH_END(next_circ); #define SET_CUTOFF(target, msec) do { \ long ms = tor_lround(msec); \ @@ -473,9 +471,8 @@ circuit_expire_building(void) MAX(get_circuit_build_close_time_ms()*2 + 1000, options->SocksTimeout * 1000)); - TOR_LIST_FOREACH(next_circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *,victim) { struct timeval cutoff; - victim = next_circ; if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */ victim->marked_for_close) /* don't mess with marked circs */ continue; @@ -780,7 +777,7 @@ circuit_expire_building(void) circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim)); - } + } SMARTLIST_FOREACH_END(victim); } /** For debugging #8387: track when we last called @@ -800,9 +797,8 @@ circuit_log_ancient_one_hop_circuits(int age) time_t cutoff = now - age; int n_found = 0; smartlist_t *log_these = smartlist_new(); - const circuit_t *circ; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { const origin_circuit_t *ocirc; if (! CIRCUIT_IS_ORIGIN(circ)) continue; @@ -817,6 +813,7 @@ circuit_log_ancient_one_hop_circuits(int age) smartlist_add(log_these, (origin_circuit_t*) ocirc); } } + SMARTLIST_FOREACH_END(circ); if (n_found == 0) goto done; @@ -831,7 +828,7 @@ circuit_log_ancient_one_hop_circuits(int age) int stream_num; const edge_connection_t *conn; char *dirty = NULL; - circ = TO_CIRCUIT(ocirc); + const circuit_t *circ = TO_CIRCUIT(ocirc); format_local_iso_time(created, (time_t)circ->timestamp_created.tv_sec); @@ -938,7 +935,6 @@ int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port, int min) { - circuit_t *circ; const node_t *exitnode; int num=0; time_t now = time(NULL); @@ -946,7 +942,7 @@ circuit_stream_is_being_handled(entry_connection_t *conn, get_options()->LongLivedPorts, conn ? conn->socks_request->port : port); - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && @@ -976,6 +972,7 @@ circuit_stream_is_being_handled(entry_connection_t *conn, } } } + SMARTLIST_FOREACH_END(circ); return 0; } @@ -989,7 +986,6 @@ circuit_stream_is_being_handled(entry_connection_t *conn, static void circuit_predict_and_launch_new(void) { - circuit_t *circ; int num=0, num_internal=0, num_uptime_internal=0; int hidserv_needs_uptime=0, hidserv_needs_capacity=1; int port_needs_uptime=0, port_needs_capacity=1; @@ -997,7 +993,7 @@ circuit_predict_and_launch_new(void) int flags = 0; /* First, count how many of each type of circuit we have already. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { cpath_build_state_t *build_state; origin_circuit_t *origin_circ; if (!CIRCUIT_IS_ORIGIN(circ)) @@ -1020,6 +1016,7 @@ circuit_predict_and_launch_new(void) if (build_state->need_uptime && build_state->is_internal) num_uptime_internal++; } + SMARTLIST_FOREACH_END(circ); /* If that's enough, then stop now. */ if (num >= MAX_UNUSED_OPEN_CIRCUITS) @@ -1223,7 +1220,6 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) static void circuit_expire_old_circuits_clientside(void) { - circuit_t *circ; struct timeval cutoff, now; tor_gettimeofday(&now); @@ -1239,7 +1235,7 @@ circuit_expire_old_circuits_clientside(void) cutoff.tv_sec -= get_options()->CircuitIdleTimeout; } - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->marked_for_close || !CIRCUIT_IS_ORIGIN(circ)) continue; /* If the circuit has been dirty for too long, and there are no streams @@ -1291,7 +1287,7 @@ circuit_expire_old_circuits_clientside(void) } } } - } + } SMARTLIST_FOREACH_END(circ); } /** How long do we wait before killing circuits with the properties @@ -1318,11 +1314,10 @@ circuit_expire_old_circuits_clientside(void) void circuit_expire_old_circuits_serverside(time_t now) { - circuit_t *circ; or_circuit_t *or_circ; time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ)) continue; or_circ = TO_OR_CIRCUIT(circ); @@ -1339,6 +1334,7 @@ circuit_expire_old_circuits_serverside(time_t now) circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } } + SMARTLIST_FOREACH_END(circ); } /** Number of testing circuits we want open before testing our bandwidth. */ @@ -1363,18 +1359,18 @@ reset_bandwidth_test(void) int circuit_enough_testing_circs(void) { - circuit_t *circ; int num = 0; if (have_performed_bandwidth_test) return 1; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && CIRCUIT_IS_ORIGIN(circ) && circ->purpose == CIRCUIT_PURPOSE_TESTING && circ->state == CIRCUIT_STATE_OPEN) num++; } + SMARTLIST_FOREACH_END(circ); return num >= NUM_PARALLEL_TESTING_CIRCS; } @@ -2074,7 +2070,7 @@ static void link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, crypt_path_t *cpath) { - const node_t *exitnode; + const node_t *exitnode = NULL; /* add it into the linked list of streams on this circuit */ log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %u.", @@ -2108,23 +2104,25 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, circ->isolation_any_streams_attached = 1; connection_edge_update_circuit_isolation(apconn, circ, 0); + /* Compute the exitnode if possible, for logging below */ + if (cpath->extend_info) + exitnode = node_get_by_id(cpath->extend_info->identity_digest); + /* See if we can use optimistic data on this circuit */ - if (cpath->extend_info && - (exitnode = node_get_by_id(cpath->extend_info->identity_digest)) && - exitnode->rs) { - /* Okay; we know what exit node this is. */ - if (optimistic_data_enabled() && - circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL && - exitnode->rs->version_supports_optimistic_data) - apconn->may_use_optimistic_data = 1; - else - apconn->may_use_optimistic_data = 0; - log_info(LD_APP, "Looks like completed circuit to %s %s allow " - "optimistic data for connection to %s", - safe_str_client(node_describe(exitnode)), - apconn->may_use_optimistic_data ? "does" : "doesn't", - safe_str_client(apconn->socks_request->address)); - } + if (optimistic_data_enabled() && + (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL || + circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED)) + apconn->may_use_optimistic_data = 1; + else + apconn->may_use_optimistic_data = 0; + log_info(LD_APP, "Looks like completed circuit to %s %s allow " + "optimistic data for connection to %s", + circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ? + /* node_describe() does the right thing if exitnode is NULL */ + safe_str_client(node_describe(exitnode)) : + "hidden service", + apconn->may_use_optimistic_data ? "does" : "doesn't", + safe_str_client(apconn->socks_request->address)); } /** Return true iff <b>address</b> is matched by one of the entries in diff --git a/src/or/config.c b/src/or/config.c index 39b85aa1ab..d620f585fe 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -99,8 +99,6 @@ static config_abbrev_t option_abbrevs_[] = { { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0}, { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0}, { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0}, - { "StrictEntryNodes", "StrictNodes", 0, 1}, - { "StrictExitNodes", "StrictNodes", 0, 1}, { "VirtualAddrNetwork", "VirtualAddrNetworkIPv4", 0, 0}, { "_UseFilteringSSLBufferevents", "UseFilteringSSLBufferevents", 0, 1}, { NULL, NULL, 0, 0}, @@ -127,8 +125,8 @@ static config_abbrev_t option_abbrevs_[] = { * be chosen first. */ static config_var_t option_vars_[] = { - OBSOLETE("AccountingMaxKB"), V(AccountingMax, MEMUNIT, "0 bytes"), + VAR("AccountingRule", STRING, AccountingRule_option, "max"), V(AccountingStart, STRING, NULL), V(Address, STRING, NULL), V(AllowDotExit, BOOL, "0"), @@ -140,8 +138,8 @@ static config_var_t option_vars_[] = { V(AlternateDirAuthority, LINELIST, NULL), OBSOLETE("AlternateHSAuthority"), V(AssumeReachable, BOOL, "0"), - V(AuthDirBadDir, LINELIST, NULL), - V(AuthDirBadDirCCs, CSV, ""), + OBSOLETE("AuthDirBadDir"), + OBSOLETE("AuthDirBadDirCCs"), V(AuthDirBadExit, LINELIST, NULL), V(AuthDirBadExitCCs, CSV, ""), V(AuthDirInvalid, LINELIST, NULL), @@ -150,8 +148,8 @@ static config_var_t option_vars_[] = { V(AuthDirGuardBWGuarantee, MEMUNIT, "2 MB"), V(AuthDirReject, LINELIST, NULL), V(AuthDirRejectCCs, CSV, ""), - V(AuthDirRejectUnlisted, BOOL, "0"), - V(AuthDirListBadDirs, BOOL, "0"), + OBSOLETE("AuthDirRejectUnlisted"), + OBSOLETE("AuthDirListBadDirs"), V(AuthDirListBadExits, BOOL, "0"), V(AuthDirMaxServersPerAddr, UINT, "2"), V(AuthDirMaxServersPerAuthAddr,UINT, "5"), @@ -196,21 +194,14 @@ static config_var_t option_vars_[] = { V(CookieAuthFile, STRING, NULL), V(CountPrivateBandwidth, BOOL, "0"), V(DataDirectory, FILENAME, NULL), - OBSOLETE("DebugLogFile"), V(DisableNetwork, BOOL, "0"), V(DirAllowPrivateAddresses, BOOL, "0"), V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"), V(DirListenAddress, LINELIST, NULL), - OBSOLETE("DirFetchPeriod"), V(DirPolicy, LINELIST, NULL), VPORT(DirPort, LINELIST, NULL), V(DirPortFrontPage, FILENAME, NULL), - OBSOLETE("DirPostPeriod"), - OBSOLETE("DirRecordUsageByCountry"), - OBSOLETE("DirRecordUsageGranularity"), - OBSOLETE("DirRecordUsageRetainIPs"), - OBSOLETE("DirRecordUsageSaveInterval"), - V(DirReqStatistics, BOOL, "1"), + VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"), VAR("DirAuthority", LINELIST, DirAuthorities, NULL), V(DirAuthorityFallbackRate, DOUBLE, "1.0"), V(DisableAllSwap, BOOL, "0"), @@ -262,7 +253,6 @@ static config_var_t option_vars_[] = { V(GeoIPv6File, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), #endif - OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"), OBSOLETE("Group"), V(GuardLifetime, INTERVAL, "0 minutes"), V(HardwareAccel, BOOL, "0"), @@ -272,15 +262,11 @@ static config_var_t option_vars_[] = { V(HashedControlPassword, LINELIST, NULL), V(HidServDirectoryV2, BOOL, "1"), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), - OBSOLETE("HiddenServiceExcludeNodes"), - OBSOLETE("HiddenServiceNodes"), VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL), V(HidServAuth, LINELIST, NULL), - OBSOLETE("HSAuthoritativeDir"), - OBSOLETE("HSAuthorityRecordStats"), V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"), V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"), V(HTTPProxy, STRING, NULL), @@ -295,14 +281,11 @@ static config_var_t option_vars_[] = { V(Socks5Proxy, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL), V(Socks5ProxyPassword, STRING, NULL), - OBSOLETE("IgnoreVersion"), V(KeepalivePeriod, INTERVAL, "5 minutes"), VAR("Log", LINELIST, Logs, NULL), V(LogMessageDomains, BOOL, "0"), - OBSOLETE("LinkPadding"), - OBSOLETE("LogLevel"), - OBSOLETE("LogFile"), V(LogTimeGranularity, MSEC_INTERVAL, "1 second"), + V(TruncateLogFile, BOOL, "0"), V(LongLivedPorts, CSV, "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"), VAR("MapAddress", LINELIST, AddressMap, NULL), @@ -313,16 +296,14 @@ static config_var_t option_vars_[] = { OBSOLETE("MaxOnionsPending"), V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"), V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"), - OBSOLETE("MonthlyAccountingStart"), V(MyFamily, STRING, NULL), V(NewCircuitPeriod, INTERVAL, "30 seconds"), - VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"), + OBSOLETE("NamingAuthoritativeDirectory"), V(NATDListenAddress, LINELIST, NULL), VPORT(NATDPort, LINELIST, NULL), V(Nickname, STRING, NULL), V(PredictedPortsRelevanceTime, INTERVAL, "1 hour"), V(WarnUnsafeSocks, BOOL, "1"), - OBSOLETE("NoPublish"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), V(NumCPUs, UINT, "0"), V(NumDirectoryGuards, UINT, "0"), @@ -348,7 +329,6 @@ static config_var_t option_vars_[] = { V(PathBiasScaleUseThreshold, INT, "-1"), V(PathsNeededToBuildCircuits, DOUBLE, "-1"), - OBSOLETE("PathlenCoinWeight"), V(PerConnBWBurst, MEMUNIT, "0"), V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), @@ -368,18 +348,13 @@ static config_var_t option_vars_[] = { V(RecommendedVersions, LINELIST, NULL), V(RecommendedClientVersions, LINELIST, NULL), V(RecommendedServerVersions, LINELIST, NULL), - OBSOLETE("RedirectExit"), V(RefuseUnknownExits, AUTOBOOL, "auto"), V(RejectPlaintextPorts, CSV, ""), V(RelayBandwidthBurst, MEMUNIT, "0"), V(RelayBandwidthRate, MEMUNIT, "0"), - OBSOLETE("RendExcludeNodes"), - OBSOLETE("RendNodes"), V(RendPostPeriod, INTERVAL, "1 hour"), V(RephistTrackTime, INTERVAL, "24 hours"), - OBSOLETE("RouterFile"), V(RunAsDaemon, BOOL, "0"), -// V(RunTesting, BOOL, "0"), OBSOLETE("RunTesting"), // currently unused V(Sandbox, BOOL, "0"), V(SafeLogging, STRING, "1"), @@ -398,18 +373,16 @@ static config_var_t option_vars_[] = { VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), V(SSLKeyLifetime, INTERVAL, "0"), - OBSOLETE("StatusFetchPeriod"), + OBSOLETE("StrictEntryNodes"), + OBSOLETE("StrictExitNodes"), V(StrictNodes, BOOL, "0"), V(Support022HiddenServices, AUTOBOOL, "auto"), - OBSOLETE("SysLog"), V(TestSocks, BOOL, "0"), - OBSOLETE("TestVia"), V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), V(Tor2webMode, BOOL, "0"), V(TLSECGroup, STRING, NULL), V(TrackHostExits, CSV, NULL), V(TrackHostExitsExpire, INTERVAL, "30 minutes"), - OBSOLETE("TrafficShaping"), V(TransListenAddress, LINELIST, NULL), VPORT(TransPort, LINELIST, NULL), V(TransProxyType, STRING, "default"), @@ -558,7 +531,8 @@ static int check_server_ports(const smartlist_t *ports, static int validate_data_directory(or_options_t *options); static int write_configuration_file(const char *fname, const or_options_t *options); -static int options_init_logs(or_options_t *options, int validate_only); +static int options_init_logs(const or_options_t *old_options, + or_options_t *options, int validate_only); static void init_libevent(const or_options_t *options); static int opt_streq(const char *s1, const char *s2); @@ -1146,7 +1120,8 @@ options_act_reversible(const or_options_t *old_options, char **msg) mark_logs_temp(); /* Close current logs once new logs are open. */ logs_marked = 1; - if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */ + /* Configure the tor_log(s) */ + if (options_init_logs(old_options, options, 0)<0) { *msg = tor_strdup("Failed to init Log options. See logs for details."); goto rollback; } @@ -1425,24 +1400,26 @@ options_act(const or_options_t *old_options) mark_transport_list(); pt_prepare_proxy_list_for_config_read(); - if (options->ClientTransportPlugin) { - for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_client_transport_line(options, cl->value, 0)<0) { - log_warn(LD_BUG, - "Previously validated ClientTransportPlugin line " - "could not be added!"); - return -1; + if (!options->DisableNetwork) { + if (options->ClientTransportPlugin) { + for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { + if (parse_client_transport_line(options, cl->value, 0)<0) { + log_warn(LD_BUG, + "Previously validated ClientTransportPlugin line " + "could not be added!"); + return -1; + } } } - } - if (options->ServerTransportPlugin && server_mode(options)) { - for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_server_transport_line(options, cl->value, 0)<0) { - log_warn(LD_BUG, - "Previously validated ServerTransportPlugin line " - "could not be added!"); - return -1; + if (options->ServerTransportPlugin && server_mode(options)) { + for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { + if (parse_server_transport_line(options, cl->value, 0)<0) { + log_warn(LD_BUG, + "Previously validated ServerTransportPlugin line " + "could not be added!"); + return -1; + } } } } @@ -1593,6 +1570,20 @@ options_act(const or_options_t *old_options) return -1; } + config_maybe_load_geoip_files_(options, old_options); + + if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { + /* ExcludeUnknown is true or "auto" */ + const int is_auto = options->GeoIPExcludeUnknown == -1; + int changed; + + changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); + changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); + + if (changed) + routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); + } + /* Check for transitions that need action. */ if (old_options) { int revise_trackexithosts = 0; @@ -1688,19 +1679,9 @@ options_act(const or_options_t *old_options) connection_or_update_token_buckets(get_connection_array(), options); } - config_maybe_load_geoip_files_(options, old_options); - - if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { - /* ExcludeUnknown is true or "auto" */ - const int is_auto = options->GeoIPExcludeUnknown == -1; - int changed; - - changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); - changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); - - if (changed) - routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); - } + /* Only collect directory-request statistics on relays and bridges. */ + options->DirReqStatistics = options->DirReqStatistics_option && + server_mode(options); if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || @@ -1709,11 +1690,6 @@ options_act(const or_options_t *old_options) time_t now = time(NULL); int print_notice = 0; - /* Only collect directory-request statistics on relays and bridges. */ - if (!server_mode(options)) { - options->DirReqStatistics = 0; - } - /* Only collect other relay-only statistics on relays. */ if (!public_server_mode(options)) { options->CellStatistics = 0; @@ -1732,8 +1708,8 @@ options_act(const or_options_t *old_options) geoip_dirreq_stats_init(now); print_notice = 1; } else { + /* disable statistics collection since we have no geoip file */ options->DirReqStatistics = 0; - /* Don't warn Tor clients, they don't use statistics */ if (options->ORPort_set) log_notice(LD_CONFIG, "Configured to measure directory request " "statistics, but no GeoIP database found. " @@ -2549,7 +2525,8 @@ options_validate(or_options_t *old_options, or_options_t *options, config_line_append(&options->Logs, "Log", "warn stdout"); } - if (options_init_logs(options, 1)<0) /* Validate the tor_log(s) */ + /* Validate the tor_log(s) */ + if (options_init_logs(old_options, options, 1)<0) REJECT("Failed to validate Log options. See logs for details."); if (authdir_mode(options)) { @@ -3135,6 +3112,16 @@ options_validate(or_options_t *old_options, or_options_t *options, } } + options->AccountingRule = ACCT_MAX; + if (options->AccountingRule_option) { + if (!strcmp(options->AccountingRule_option, "sum")) + options->AccountingRule = ACCT_SUM; + else if (!strcmp(options->AccountingRule_option, "max")) + options->AccountingRule = ACCT_MAX; + else + REJECT("AccountingRule must be 'sum' or 'max'"); + } + if (options->HTTPProxy) { /* parse it now */ if (tor_addr_port_lookup(options->HTTPProxy, &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0) @@ -3183,11 +3170,11 @@ options_validate(or_options_t *old_options, or_options_t *options, } } - /* Check if more than one proxy type has been enabled. */ + /* Check if more than one exclusive proxy type has been enabled. */ if (!!options->Socks4Proxy + !!options->Socks5Proxy + - !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1) + !!options->HTTPSProxy > 1) REJECT("You have configured more than one proxy type. " - "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)"); + "(Socks4Proxy|Socks5Proxy|HTTPSProxy)"); /* Check if the proxies will give surprising behavior. */ if (options->HTTPProxy && !(options->Socks4Proxy || @@ -4455,7 +4442,8 @@ addressmap_register_auto(const char *from, const char *to, * Initialize the logs based on the configuration file. */ static int -options_init_logs(or_options_t *options, int validate_only) +options_init_logs(const or_options_t *old_options, or_options_t *options, + int validate_only) { config_line_t *opt; int ok; @@ -4548,7 +4536,21 @@ options_init_logs(or_options_t *options, int validate_only) !strcasecmp(smartlist_get(elts,0), "file")) { if (!validate_only) { char *fname = expand_filename(smartlist_get(elts, 1)); - if (add_file_log(severity, fname) < 0) { + /* Truncate if TruncateLogFile is set and we haven't seen this option + line before. */ + int truncate = 0; + if (options->TruncateLogFile) { + truncate = 1; + if (old_options) { + config_line_t *opt2; + for (opt2 = old_options->Logs; opt2; opt2 = opt2->next) + if (!strcmp(opt->value, opt2->value)) { + truncate = 0; + break; + } + } + } + if (add_file_log(severity, fname, truncate) < 0) { log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s", opt->value, strerror(errno)); ok = 0; @@ -4837,7 +4839,7 @@ parse_client_transport_line(const or_options_t *options, if (!validate_only && !is_useless_proxy) { proxy_argc = line_length-2; tor_assert(proxy_argc > 0); - proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + proxy_argv = tor_calloc(sizeof(char *), (proxy_argc + 1)); tmp = proxy_argv; for (i=0;i<proxy_argc;i++) { /* store arguments */ *tmp++ = smartlist_get(items, 2); @@ -4849,6 +4851,13 @@ parse_client_transport_line(const or_options_t *options, pt_kickstart_client_proxy(transport_list, proxy_argv); } } else { /* external */ + /* ClientTransportPlugins connecting through a proxy is managed only. */ + if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) { + log_warn(LD_CONFIG, "You have configured an external proxy with another " + "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)"); + goto err; + } + if (smartlist_len(transport_list) != 1) { log_warn(LD_CONFIG, "You can't have an external proxy with " "more than one transports."); @@ -5117,7 +5126,7 @@ parse_server_transport_line(const or_options_t *options, if (!validate_only) { proxy_argc = line_length-2; tor_assert(proxy_argc > 0); - proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + proxy_argv = tor_calloc(sizeof(char *), (proxy_argc + 1)); tmp = proxy_argv; for (i=0;i<proxy_argc;i++) { /* store arguments */ diff --git a/src/or/connection.c b/src/or/connection.c index 276dca2818..4a3bd2cf03 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1688,14 +1688,14 @@ get_proxy_type(void) { const or_options_t *options = get_options(); - if (options->HTTPSProxy) + if (options->ClientTransportPlugin) + return PROXY_PLUGGABLE; + else if (options->HTTPSProxy) return PROXY_CONNECT; else if (options->Socks4Proxy) return PROXY_SOCKS4; else if (options->Socks5Proxy) return PROXY_SOCKS5; - else if (options->ClientTransportPlugin) - return PROXY_PLUGGABLE; else return PROXY_NONE; } @@ -3716,9 +3716,15 @@ connection_handle_write_impl(connection_t *conn, int force) if (connection_state_is_connecting(conn)) { if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { log_warn(LD_BUG, "getsockopt() syscall failed"); - if (CONN_IS_EDGE(conn)) - connection_edge_end_errno(TO_EDGE_CONN(conn)); - connection_mark_for_close(conn); + if (conn->type == CONN_TYPE_OR) { + or_connection_t *orconn = TO_OR_CONN(conn); + connection_or_close_for_error(orconn, 0); + } else { + if (CONN_IS_EDGE(conn)) { + connection_edge_end_errno(TO_EDGE_CONN(conn)); + } + connection_mark_for_close(conn); + } return -1; } if (e) { @@ -4781,6 +4787,27 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, { const or_options_t *options = get_options(); + /* Client Transport Plugins can use another proxy, but that should be hidden + * from the rest of tor (as the plugin is responsible for dealing with the + * proxy), check it first, then check the rest of the proxy types to allow + * the config to have unused ClientTransportPlugin entries. + */ + if (options->ClientTransportPlugin) { + const transport_t *transport = NULL; + int r; + r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport); + if (r<0) + return -1; + if (transport) { /* transport found */ + tor_addr_copy(addr, &transport->addr); + *port = transport->port; + *proxy_type = transport->socks_version; + return 0; + } + + /* Unused ClientTransportPlugin. */ + } + if (options->HTTPSProxy) { tor_addr_copy(addr, &options->HTTPSProxyAddr); *port = options->HTTPSProxyPort; @@ -4796,19 +4823,6 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, *port = options->Socks5ProxyPort; *proxy_type = PROXY_SOCKS5; return 0; - } else if (options->ClientTransportPlugin || - options->Bridges) { - const transport_t *transport = NULL; - int r; - r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport); - if (r<0) - return -1; - if (transport) { /* transport found */ - tor_addr_copy(addr, &transport->addr); - *port = transport->port; - *proxy_type = transport->socks_version; - return 0; - } } tor_addr_make_unspec(addr); @@ -4832,7 +4846,7 @@ log_failed_proxy_connection(connection_t *conn) log_warn(LD_NET, "The connection to the %s proxy server at %s just failed. " "Make sure that the proxy server is up and running.", - proxy_type_to_string(get_proxy_type()), + proxy_type_to_string(proxy_type), fmt_addrport(&proxy_addr, proxy_port)); } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 49f9ba4978..522807d7ba 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1767,7 +1767,8 @@ connection_ap_supports_optimistic_data(const entry_connection_t *conn) general circuit. */ if (edge_conn->on_circuit == NULL || edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN || - edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL) + (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL && + edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)) return 0; return conn->may_use_optimistic_data; @@ -2764,7 +2765,6 @@ connection_exit_connect(edge_connection_t *edge_conn) /* also, deliver a 'connected' cell back through the circuit. */ if (connection_edge_is_rendezvous_stream(edge_conn)) { - /* rendezvous stream */ /* don't send an address back! */ connection_edge_send_command(edge_conn, RELAY_COMMAND_CONNECTED, diff --git a/src/or/connection_or.c b/src/or/connection_or.c index c372270b4c..7fcc5b24d6 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -908,18 +908,11 @@ connection_or_init_conn_from_address(or_connection_t *conn, tor_free(conn->base_.address); conn->base_.address = tor_dup_addr(&node_ap.addr); } else { - const char *n; - /* If we're an authoritative directory server, we may know a - * nickname for this router. */ - n = dirserv_get_nickname_by_digest(id_digest); - if (n) { - conn->nickname = tor_strdup(n); - } else { - conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); - conn->nickname[0] = '$'; - base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, - conn->identity_digest, DIGEST_LEN); - } + conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); + conn->nickname[0] = '$'; + base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, + conn->identity_digest, DIGEST_LEN); + tor_free(conn->base_.address); conn->base_.address = tor_dup_addr(addr); } diff --git a/src/or/control.c b/src/or/control.c index 9378f38f40..92dd2309ed 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -47,6 +47,7 @@ #include <sys/resource.h> #endif +#include "crypto_s2k.h" #include "procmon.h" /** Yield true iff <b>s</b> is the state of a control_connection_t that has @@ -194,14 +195,14 @@ log_severity_to_event(int severity) static void clear_circ_bw_fields(void) { - circuit_t *circ; origin_circuit_t *ocirc; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!CIRCUIT_IS_ORIGIN(circ)) continue; ocirc = TO_ORIGIN_CIRCUIT(circ); ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0; } + SMARTLIST_FOREACH_END(circ); } /** Set <b>global_event_mask*</b> to the bitwise OR of each live control @@ -949,7 +950,7 @@ static int handle_control_setevents(control_connection_t *conn, uint32_t len, const char *body) { - int event_code = -1; + int event_code; event_mask_t event_mask = 0; smartlist_t *events = smartlist_new(); @@ -963,6 +964,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, continue; } else { int i; + event_code = -1; + for (i = 0; control_event_table[i].event_name != NULL; ++i) { if (!strcasecmp(ev, control_event_table[i].event_name)) { event_code = control_event_table[i].event_code; @@ -993,7 +996,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, /** Decode the hashed, base64'd passwords stored in <b>passwords</b>. * Return a smartlist of acceptable passwords (unterminated strings of - * length S2K_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on failure. + * length S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on + * failure. */ smartlist_t * decode_hashed_passwords(config_line_t *passwords) @@ -1009,16 +1013,17 @@ decode_hashed_passwords(config_line_t *passwords) if (!strcmpstart(hashed, "16:")) { if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))<0 - || strlen(hashed+3) != (S2K_SPECIFIER_LEN+DIGEST_LEN)*2) { + || strlen(hashed+3) != (S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN)*2) { goto err; } } else { if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed)) - != S2K_SPECIFIER_LEN+DIGEST_LEN) { + != S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) { goto err; } } - smartlist_add(sl, tor_memdup(decoded, S2K_SPECIFIER_LEN+DIGEST_LEN)); + smartlist_add(sl, + tor_memdup(decoded, S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN)); } return sl; @@ -1039,7 +1044,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, { int used_quoted_string = 0; const or_options_t *options = get_options(); - const char *errstr = NULL; + const char *errstr = "Unknown error"; char *password; size_t password_len; const char *cp; @@ -1160,22 +1165,27 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, } if (bad) { if (!also_cookie) { - log_warn(LD_CONTROL, + log_warn(LD_BUG, "Couldn't decode HashedControlPassword: invalid base16"); errstr="Couldn't decode HashedControlPassword value in configuration."; + goto err; } bad_password = 1; SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_free(sl); + sl = NULL; } else { SMARTLIST_FOREACH(sl, char *, expected, { - secret_to_key(received,DIGEST_LEN,password,password_len,expected); - if (tor_memeq(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN)) + secret_to_key_rfc2440(received,DIGEST_LEN, + password,password_len,expected); + if (tor_memeq(expected + S2K_RFC2440_SPECIFIER_LEN, + received, DIGEST_LEN)) goto ok; }); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_free(sl); + sl = NULL; if (used_quoted_string) errstr = "Password did not match HashedControlPassword value from " @@ -1198,9 +1208,12 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, err: tor_free(password); - connection_printf_to_buf(conn, "515 Authentication failed: %s\r\n", - errstr ? errstr : "Unknown reason."); + connection_printf_to_buf(conn, "515 Authentication failed: %s\r\n", errstr); connection_mark_for_close(TO_CONN(conn)); + if (sl) { /* clean up */ + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); + } return 0; ok: log_info(LD_CONTROL, "Authenticated control connection ("TOR_SOCKET_T_FORMAT @@ -1879,9 +1892,8 @@ getinfo_helper_events(control_connection_t *control_conn, { (void) control_conn; if (!strcmp(question, "circuit-status")) { - circuit_t *circ_; smartlist_t *status = smartlist_new(); - TOR_LIST_FOREACH(circ_, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) { origin_circuit_t *circ; char *circdesc; const char *state; @@ -1903,6 +1915,7 @@ getinfo_helper_events(control_connection_t *control_conn, state, *circdesc ? " " : "", circdesc); tor_free(circdesc); } + SMARTLIST_FOREACH_END(circ_); *answer = smartlist_join_strings(status, "\r\n", 0, NULL); SMARTLIST_FOREACH(status, char *, cp, tor_free(cp)); smartlist_free(status); @@ -3909,12 +3922,11 @@ control_event_stream_bandwidth_used(void) int control_event_circ_bandwidth_used(void) { - circuit_t *circ; origin_circuit_t *ocirc; if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED)) return 0; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!CIRCUIT_IS_ORIGIN(circ)) continue; ocirc = TO_ORIGIN_CIRCUIT(circ); @@ -3927,6 +3939,7 @@ control_event_circ_bandwidth_used(void) (unsigned long)ocirc->n_written_circ_bw); ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0; } + SMARTLIST_FOREACH_END(circ); return 0; } @@ -4091,14 +4104,13 @@ format_cell_stats(char **event_string, circuit_t *circ, int control_event_circuit_cell_stats(void) { - circuit_t *circ; cell_stats_t *cell_stats; char *event_string; if (!get_options()->TestingEnableCellStatsEvent || !EVENT_IS_INTERESTING(EVENT_CELL_STATS)) return 0; cell_stats = tor_malloc(sizeof(cell_stats_t));; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->testing_cell_stats) continue; sum_up_cell_stats_by_command(circ, cell_stats); @@ -4107,6 +4119,7 @@ control_event_circuit_cell_stats(void) "650 CELL_STATS %s\r\n", event_string); tor_free(event_string); } + SMARTLIST_FOREACH_END(circ); tor_free(cell_stats); return 0; } diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 61b2c29b38..94138f8c1e 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -414,12 +414,6 @@ cpuworker_main(void *data) cpuworker_reply_t rpl; fd = fdarray[1]; /* this side is ours */ -#ifndef TOR_IS_MULTITHREADED - tor_close_socket(fdarray[0]); /* this is the side of the socketpair the - * parent uses */ - tor_free_all(1); /* so the child doesn't hold the parent's fd's open */ - handle_signals(0); /* ignore interrupts from the keyboard, etc */ -#endif tor_free(data); setup_server_onion_keys(&onion_keys); @@ -516,7 +510,7 @@ spawn_cpuworker(void) connection_t *conn; int err; - fdarray = tor_malloc(sizeof(tor_socket_t)*2); + fdarray = tor_calloc(sizeof(tor_socket_t), 2); if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fdarray)) < 0) { log_warn(LD_NET, "Couldn't construct socketpair for cpuworker: %s", tor_socket_strerror(-err)); @@ -535,10 +529,6 @@ spawn_cpuworker(void) return -1; } log_debug(LD_OR,"just spawned a cpu worker."); -#ifndef TOR_IS_MULTITHREADED - tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */ - tor_free(fdarray); -#endif conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX); diff --git a/src/or/directory.c b/src/or/directory.c index 298271f366..1aaa75ccee 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -197,9 +197,9 @@ dir_conn_purpose_to_string(int purpose) return "(unknown)"; } -/** Return true iff <b>identity_digest</b> is the digest of a router we - * believe to support extrainfo downloads. (If <b>is_authority</b> we do - * additional checking that's only valid for authorities.) */ +/** Return true iff <b>identity_digest</b> is the digest of a router which + * says that it caches extrainfos. (If <b>is_authority</b> we always + * believe that to be true.) */ int router_supports_extrainfo(const char *identity_digest, int is_authority) { diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 49fafafab2..374cfa6f40 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -56,13 +56,11 @@ static int routers_with_measured_bw = 0; static void directory_remove_invalid(void); static char *format_versions_list(config_line_t *ln); struct authdir_config_t; -static int add_fingerprint_to_dir(const char *nickname, const char *fp, - struct authdir_config_t *list); static uint32_t dirserv_get_status_impl(const char *fp, const char *nickname, uint32_t addr, uint16_t or_port, - const char *platform, const char *contact, - const char **msg, int should_log); + const char *platform, const char **msg, + int should_log); static void clear_cached_dir(cached_dir_t *d); static const signed_descriptor_t *get_signed_descriptor_by_fp( const char *fp, @@ -75,19 +73,19 @@ static uint32_t dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri); /************** Fingerprint handling code ************/ -#define FP_NAMED 1 /**< Listed in fingerprint file. */ +/* 1 Historically used to indicate Named */ #define FP_INVALID 2 /**< Believed invalid. */ #define FP_REJECT 4 /**< We will not publish this router. */ -#define FP_BADDIR 8 /**< We'll tell clients to avoid using this as a dir. */ +/* 8 Historically used to avoid using this as a dir. */ #define FP_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */ -#define FP_UNNAMED 32 /**< Another router has this name in fingerprint file. */ +/* 32 Historically used to indicade Unnamed */ -/** Encapsulate a nickname and an FP_* status; target of status_by_digest - * map. */ -typedef struct router_status_t { - char nickname[MAX_NICKNAME_LEN+1]; - uint32_t status; -} router_status_t; +/** Target of status_by_digest map. */ +typedef uint32_t router_status_t; + +static void add_fingerprint_to_dir(const char *fp, + struct authdir_config_t *list, + router_status_t add_status); /** List of nickname-\>identity fingerprint mappings for all the routers * that we name. Used to prevent router impersonation. */ @@ -109,18 +107,17 @@ authdir_config_new(void) return list; } -/** Add the fingerprint <b>fp</b> for <b>nickname</b> to - * the smartlist of fingerprint_entry_t's <b>list</b>. Return 0 if it's - * new, or 1 if we replaced the old value. +/** Add the fingerprint <b>fp</b> to the smartlist of fingerprint_entry_t's + * <b>list</b>, or-ing the currently set status flags with + * <b>add_status</b>. */ -/* static */ int -add_fingerprint_to_dir(const char *nickname, const char *fp, - authdir_config_t *list) +/* static */ void +add_fingerprint_to_dir(const char *fp, authdir_config_t *list, + router_status_t add_status) { char *fingerprint; char d[DIGEST_LEN]; router_status_t *status; - tor_assert(nickname); tor_assert(fp); tor_assert(list); @@ -130,14 +127,7 @@ add_fingerprint_to_dir(const char *nickname, const char *fp, log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"", escaped(fp)); tor_free(fingerprint); - return 0; - } - - if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) { - log_warn(LD_DIRSERV, "Tried to add a mapping for reserved nickname %s", - UNNAMED_ROUTER_NICKNAME); - tor_free(fingerprint); - return 0; + return; } status = digestmap_get(list->status_by_digest, d); @@ -146,35 +136,15 @@ add_fingerprint_to_dir(const char *nickname, const char *fp, digestmap_set(list->status_by_digest, d, status); } - if (nickname[0] != '!') { - char *old_fp = strmap_get_lc(list->fp_by_name, nickname); - if (old_fp && !strcasecmp(fingerprint, old_fp)) { - tor_free(fingerprint); - } else { - tor_free(old_fp); - strmap_set_lc(list->fp_by_name, nickname, fingerprint); - } - status->status |= FP_NAMED; - strlcpy(status->nickname, nickname, sizeof(status->nickname)); - } else { - tor_free(fingerprint); - if (!strcasecmp(nickname, "!reject")) { - status->status |= FP_REJECT; - } else if (!strcasecmp(nickname, "!invalid")) { - status->status |= FP_INVALID; - } else if (!strcasecmp(nickname, "!baddir")) { - status->status |= FP_BADDIR; - } else if (!strcasecmp(nickname, "!badexit")) { - status->status |= FP_BADEXIT; - } - } - return 0; + tor_free(fingerprint); + *status |= add_status; + return; } -/** Add the nickname and fingerprint for this OR to the - * global list of recognized identity key fingerprints. */ +/** Add the fingerprint for this OR to the global list of recognized + * identity key fingerprints. */ int -dirserv_add_own_fingerprint(const char *nickname, crypto_pk_t *pk) +dirserv_add_own_fingerprint(crypto_pk_t *pk) { char fp[FINGERPRINT_LEN+1]; if (crypto_pk_get_fingerprint(pk, fp, 0)<0) { @@ -183,7 +153,7 @@ dirserv_add_own_fingerprint(const char *nickname, crypto_pk_t *pk) } if (!fingerprint_list) fingerprint_list = authdir_config_new(); - add_fingerprint_to_dir(nickname, fp, fingerprint_list); + add_fingerprint_to_dir(fp, fingerprint_list, 0); return 0; } @@ -201,7 +171,6 @@ dirserv_load_fingerprint_file(void) authdir_config_t *fingerprint_list_new; int result; config_line_t *front=NULL, *list; - const or_options_t *options = get_options(); fname = get_datadir_fname("approved-routers"); log_info(LD_GENERAL, @@ -209,15 +178,9 @@ dirserv_load_fingerprint_file(void) cf = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); if (!cf) { - if (options->NamingAuthoritativeDir) { - log_warn(LD_FS, "Cannot open fingerprint file '%s'. Failing.", fname); - tor_free(fname); - return -1; - } else { - log_info(LD_FS, "Cannot open fingerprint file '%s'. That's ok.", fname); - tor_free(fname); - return 0; - } + log_warn(LD_FS, "Cannot open fingerprint file '%s'. That's ok.", fname); + tor_free(fname); + return 0; } tor_free(fname); @@ -232,22 +195,8 @@ dirserv_load_fingerprint_file(void) for (list=front; list; list=list->next) { char digest_tmp[DIGEST_LEN]; + router_status_t add_status = 0; nickname = list->key; fingerprint = list->value; - if (strlen(nickname) > MAX_NICKNAME_LEN) { - log_notice(LD_CONFIG, - "Nickname '%s' too long in fingerprint file. Skipping.", - nickname); - continue; - } - if (!is_legal_nickname(nickname) && - strcasecmp(nickname, "!reject") && - strcasecmp(nickname, "!invalid") && - strcasecmp(nickname, "!badexit")) { - log_notice(LD_CONFIG, - "Invalid nickname '%s' in fingerprint file. Skipping.", - nickname); - continue; - } tor_strstrip(fingerprint, " "); /* remove spaces */ if (strlen(fingerprint) != HEX_DIGEST_LEN || base16_decode(digest_tmp, sizeof(digest_tmp), @@ -258,26 +207,14 @@ dirserv_load_fingerprint_file(void) nickname, fingerprint); continue; } - if (0==strcasecmp(nickname, DEFAULT_CLIENT_NICKNAME)) { - /* If you approved an OR called "client", then clients who use - * the default nickname could all be rejected. That's no good. */ - log_notice(LD_CONFIG, - "Authorizing nickname '%s' would break " - "many clients; skipping.", - DEFAULT_CLIENT_NICKNAME); - continue; - } - if (0==strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) { - /* If you approved an OR called "unnamed", then clients will be - * confused. */ - log_notice(LD_CONFIG, - "Authorizing nickname '%s' is not allowed; skipping.", - UNNAMED_ROUTER_NICKNAME); - continue; + if (!strcasecmp(nickname, "!reject")) { + add_status = FP_REJECT; + } else if (!strcasecmp(nickname, "!badexit")) { + add_status = FP_BADEXIT; + } else if (!strcasecmp(nickname, "!invalid")) { + add_status = FP_INVALID; } - if (add_fingerprint_to_dir(nickname, fingerprint, fingerprint_list_new) - != 0) - log_notice(LD_CONFIG, "Duplicate nickname '%s'.", nickname); + add_fingerprint_to_dir(fingerprint, fingerprint_list_new, add_status); } config_free_lines(front); @@ -308,8 +245,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg) return dirserv_get_status_impl(d, router->nickname, router->addr, router->or_port, - router->platform, router->contact_info, - msg, 1); + router->platform, msg, 1); } /** Return true if there is no point in downloading the router described by @@ -321,37 +257,14 @@ dirserv_would_reject_router(const routerstatus_t *rs) res = dirserv_get_status_impl(rs->identity_digest, rs->nickname, rs->addr, rs->or_port, - NULL, NULL, - NULL, 0); + NULL, NULL, 0); return (res & FP_REJECT) != 0; } -/** Helper: Based only on the ID/Nickname combination, - * return FP_UNNAMED (unnamed), FP_NAMED (named), or 0 (neither). - */ -static uint32_t -dirserv_get_name_status(const char *id_digest, const char *nickname) -{ - char fp[HEX_DIGEST_LEN+1]; - char *fp_by_name; - - base16_encode(fp, sizeof(fp), id_digest, DIGEST_LEN); - - if ((fp_by_name = - strmap_get_lc(fingerprint_list->fp_by_name, nickname))) { - if (!strcasecmp(fp, fp_by_name)) { - return FP_NAMED; - } else { - return FP_UNNAMED; /* Wrong fingerprint. */ - } - } - return 0; -} - /** Helper: As dirserv_router_get_status, but takes the router fingerprint * (hex, no spaces), nickname, address (used for logging only), IP address, OR - * port, platform (logging only) and contact info (logging only) as arguments. + * port and platform (logging only) as arguments. * * If should_log is false, do not log messages. (There's not much point in * logging that we're rejecting servers we'll not download.) @@ -359,11 +272,9 @@ dirserv_get_name_status(const char *id_digest, const char *nickname) static uint32_t dirserv_get_status_impl(const char *id_digest, const char *nickname, uint32_t addr, uint16_t or_port, - const char *platform, const char *contact, - const char **msg, int should_log) + const char *platform, const char **msg, int should_log) { - int reject_unlisted = get_options()->AuthDirRejectUnlisted; - uint32_t result; + uint32_t result = 0; router_status_t *status_by_digest; if (!fingerprint_list) @@ -381,43 +292,11 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, *msg = "Tor version is insecure or unsupported. Please upgrade!"; return FP_REJECT; } -#if 0 - else if (platform && tor_version_as_new_as(platform,"0.2.3.0-alpha")) { - /* Versions from 0.2.3-alpha...0.2.3.9-alpha have known security - * issues that make them unusable for the current network */ - if (!tor_version_as_new_as(platform, "0.2.3.10-alpha")) { - if (msg) - *msg = "Tor version is insecure or unsupported. Please upgrade!"; - return FP_REJECT; - } - } -#endif - - result = dirserv_get_name_status(id_digest, nickname); - if (result & FP_NAMED) { - if (should_log) - log_debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname); - } - if (result & FP_UNNAMED) { - if (should_log) { - char *esc_contact = esc_for_log(contact); - log_info(LD_DIRSERV, - "Mismatched fingerprint for '%s'. " - "ContactInfo '%s', platform '%s'.)", - nickname, - esc_contact, - platform ? escaped(platform) : ""); - tor_free(esc_contact); - } - if (msg) - *msg = "Rejected: There is already a named server with this nickname " - "and a different fingerprint."; - } status_by_digest = digestmap_get(fingerprint_list->status_by_digest, id_digest); if (status_by_digest) - result |= (status_by_digest->status & ~FP_NAMED); + result |= *status_by_digest; if (result & FP_REJECT) { if (msg) @@ -428,14 +307,6 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, *msg = "Fingerprint is marked invalid"; } - if (authdir_policy_baddir_address(addr, or_port)) { - if (should_log) - log_info(LD_DIRSERV, - "Marking '%s' as bad directory because of address '%s'", - nickname, fmt_addr32(addr)); - result |= FP_BADDIR; - } - if (authdir_policy_badexit_address(addr, or_port)) { if (should_log) log_info(LD_DIRSERV, "Marking '%s' as bad exit because of address '%s'", @@ -443,46 +314,24 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, result |= FP_BADEXIT; } - if (!(result & FP_NAMED)) { - if (!authdir_policy_permits_address(addr, or_port)) { - if (should_log) - log_info(LD_DIRSERV, "Rejecting '%s' because of address '%s'", - nickname, fmt_addr32(addr)); - if (msg) - *msg = "Authdir is rejecting routers in this range."; - return FP_REJECT; - } - if (!authdir_policy_valid_address(addr, or_port)) { - if (should_log) - log_info(LD_DIRSERV, "Not marking '%s' valid because of address '%s'", - nickname, fmt_addr32(addr)); - result |= FP_INVALID; - } - if (reject_unlisted) { - if (msg) - *msg = "Authdir rejects unknown routers."; - return FP_REJECT; - } + if (!authdir_policy_permits_address(addr, or_port)) { + if (should_log) + log_info(LD_DIRSERV, "Rejecting '%s' because of address '%s'", + nickname, fmt_addr32(addr)); + if (msg) + *msg = "Authdir is rejecting routers in this range."; + return FP_REJECT; + } + if (!authdir_policy_valid_address(addr, or_port)) { + if (should_log) + log_info(LD_DIRSERV, "Not marking '%s' valid because of address '%s'", + nickname, fmt_addr32(addr)); + result |= FP_INVALID; } return result; } -/** If we are an authoritative dirserver, and the list of approved - * servers contains one whose identity key digest is <b>digest</b>, - * return that router's nickname. Otherwise return NULL. */ -const char * -dirserv_get_nickname_by_digest(const char *digest) -{ - router_status_t *status; - if (!fingerprint_list) - return NULL; - tor_assert(digest); - - status = digestmap_get(fingerprint_list->status_by_digest, digest); - return status ? status->nickname : NULL; -} - /** Clear the current fingerprint list. */ void dirserv_free_fingerprint_list(void) @@ -519,7 +368,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri) } /** Check whether we, as a directory server, want to accept <b>ri</b>. If so, - * set its is_valid,named,running fields and return 0. Otherwise, return -1. + * set its is_valid,running fields and return 0. Otherwise, return -1. * * If the router is rejected, set *<b>msg</b> to an explanation of why. * @@ -584,7 +433,6 @@ dirserv_set_node_flags_from_authoritative_status(node_t *node, uint32_t authstatus) { node->is_valid = (authstatus & FP_INVALID) ? 0 : 1; - node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0; node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0; } @@ -816,7 +664,7 @@ directory_remove_invalid(void) smartlist_add_all(nodes, nodelist_get_list()); SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) { - const char *msg; + const char *msg = NULL; routerinfo_t *ent = node->ri; char description[NODE_DESC_BUF_LEN]; uint32_t r; @@ -830,30 +678,11 @@ directory_remove_invalid(void) routerlist_remove(rl, ent, 0, time(NULL)); continue; } -#if 0 - if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) { - log_info(LD_DIRSERV, - "Router %s is now %snamed.", description, - (r&FP_NAMED)?"":"un"); - ent->is_named = (r&FP_NAMED)?1:0; - } - if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) { - log_info(LD_DIRSERV, - "Router '%s' is now %snamed. (FP_UNNAMED)", description, - (r&FP_NAMED)?"":"un"); - ent->is_named = (r&FP_NUNAMED)?0:1; - } -#endif if (bool_neq((r & FP_INVALID), !node->is_valid)) { log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description, (r&FP_INVALID) ? "in" : ""); node->is_valid = (r&FP_INVALID)?0:1; } - if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) { - log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description, - (r & FP_BADDIR) ? "bad" : "good"); - node->is_bad_directory = (r&FP_BADDIR) ? 1: 0; - } if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) { log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description, (r & FP_BADEXIT) ? "bad" : "good"); @@ -1051,7 +880,8 @@ format_versions_list(config_line_t *ln) } /** Return 1 if <b>ri</b>'s descriptor is "active" -- running, valid, - * not hibernating, and not too old. Else return 0. + * not hibernating, having observed bw greater 0, and not too old. Else + * return 0. */ static int router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) @@ -1061,6 +891,8 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) return 0; if (!node->is_running || !node->is_valid || ri->is_hibernating) return 0; + if (!ri->bandwidthcapacity) + return 0; return 1; } @@ -1468,7 +1300,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, * to fix the bug was 0.2.2.25-alpha. */ return (router->wants_to_be_hs_dir && router->dir_port && uptime >= get_options()->MinUptimeHidServDirectoryV2 && - node->is_running); + router_is_active(router, node, now)); } /** Don't consider routers with less bandwidth than this when computing @@ -1537,18 +1369,18 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, * sort them and use that to compute thresholds. */ n_active = n_active_nonexit = 0; /* Uptime for every active router. */ - uptimes = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + uptimes = tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers)); /* Bandwidth for every active router. */ - bandwidths_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + bandwidths_kb = tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers)); /* Bandwidth for every active non-exit router. */ bandwidths_excluding_exits_kb = - tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers)); /* Weighted mean time between failure for each active router. */ - mtbfs = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); + mtbfs = tor_calloc(sizeof(double), smartlist_len(rl->routers)); /* Time-known for each active router. */ - tks = tor_malloc(sizeof(long)*smartlist_len(rl->routers)); + tks = tor_calloc(sizeof(long), smartlist_len(rl->routers)); /* Weighted fractional uptime for each active router. */ - wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); + wfus = tor_calloc(sizeof(double), smartlist_len(rl->routers)); nodelist_assert_ok(); @@ -1563,6 +1395,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, routerinfo_t *ri = node->ri; const char *id = node->identity; uint32_t bw_kb; + /* resolve spurious clang shallow analysis null pointer errors */ + tor_assert(ri); node->is_exit = (!router_exit_policy_rejects_all(ri) && exit_policy_is_general_exit(ri->exit_policy)); uptimes[n_active] = (uint32_t)real_uptime(ri, now); @@ -1588,7 +1422,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, /* (Now bandwidths is sorted.) */ if (fast_bandwidth_kb < ROUTER_REQUIRED_MIN_BANDWIDTH/(2 * 1000)) fast_bandwidth_kb = bandwidths_kb[n_active/4]; - guard_bandwidth_including_exits_kb = bandwidths_kb[n_active*3/4]; + guard_bandwidth_including_exits_kb = + third_quartile_uint32(bandwidths_kb, n_active); guard_tk = find_nth_long(tks, n_active, n_active/8); } @@ -1959,13 +1794,12 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, char published[ISO_TIME_LEN+1]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; - smartlist_t *chunks = NULL; + smartlist_t *chunks = smartlist_new(); format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); - chunks = smartlist_new(); smartlist_add_asprintf(chunks, "r %s %s %s%s%s %s %d %d\n", rs->nickname, @@ -1996,19 +1830,16 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, goto done; smartlist_add_asprintf(chunks, - "s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + "s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", - rs->is_bad_directory?" BadDirectory":"", rs->is_bad_exit?" BadExit":"", rs->is_exit?" Exit":"", rs->is_fast?" Fast":"", rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", - rs->is_named?" Named":"", rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", - rs->is_unnamed?" Unnamed":"", (rs->dir_port!=0)?" V2Dir":"", rs->is_valid?" Valid":""); @@ -2090,10 +1921,8 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, result = smartlist_join_strings(chunks, "", 0, NULL); err: - if (chunks) { - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - } + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); return result; } @@ -2269,8 +2098,7 @@ is_router_version_good_for_possible_guard(const char *platform) } /** Extract status information from <b>ri</b> and from other authority - * functions and store it in <b>rs</b>>. If <b>naming</b>, consider setting - * the named flag in <b>rs</b>. + * functions and store it in <b>rs</b>>. * * We assume that ri-\>is_running has already been set, e.g. by * dirserv_set_router_is_running(ri, now); @@ -2280,8 +2108,8 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, node_t *node, routerinfo_t *ri, time_t now, - int naming, int listbadexits, - int listbaddirs, int vote_on_hsdirs) + int listbadexits, + int vote_on_hsdirs) { const or_options_t *options = get_options(); uint32_t routerbw_kb = dirserv_get_credible_bandwidth_kb(ri); @@ -2301,12 +2129,6 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); rs->is_flagged_running = node->is_running; /* computed above */ - if (naming) { - uint32_t name_status = dirserv_get_name_status( - node->identity, ri->nickname); - rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0; - rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0; - } rs->is_valid = node->is_valid; if (node->is_fast && @@ -2323,19 +2145,12 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, } else { rs->is_possible_guard = 0; } - if (options->TestingTorNetwork && - routerset_contains_routerstatus(options->TestingDirAuthVoteGuard, - rs, 0)) { - rs->is_possible_guard = 1; - } - rs->is_bad_directory = listbaddirs && node->is_bad_directory; rs->is_bad_exit = listbadexits && node->is_bad_exit; node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now); rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir; - if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME)) - rs->is_named = rs->is_unnamed = 0; + rs->is_named = rs->is_unnamed = 0; rs->published_on = ri->cache_info.published_on; memcpy(rs->identity_digest, node->identity, DIGEST_LEN); @@ -2353,6 +2168,14 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, tor_addr_copy(&rs->ipv6_addr, &ri->ipv6_addr); rs->ipv6_orport = ri->ipv6_orport; } + + /* Iff we are in a testing network, use TestingDirAuthVoteGuard to + give out Guard flags. */ + if (options->TestingTorNetwork && + routerset_contains_routerstatus(options->TestingDirAuthVoteGuard, + rs, 0)) { + rs->is_possible_guard = 1; + } } /** Routerstatus <b>rs</b> is part of a group of routers that are on @@ -2364,8 +2187,7 @@ clear_status_flags_on_sybil(routerstatus_t *rs) { rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running = rs->is_named = rs->is_valid = - rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit = - rs->is_bad_directory = 0; + rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit = 0; /* FFFF we might want some mechanism to check later on if we * missed zeroing any flags: it's easy to add a new flag but * forget to add it to this clause. */ @@ -2563,9 +2385,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, smartlist_t *routers, *routerstatuses; char identity_digest[DIGEST_LEN]; char signing_key_digest[DIGEST_LEN]; - int naming = options->NamingAuthoritativeDir; int listbadexits = options->AuthDirListBadExits; - int listbaddirs = options->AuthDirListBadDirs; int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2; routerlist_t *rl = router_get_routerlist(); time_t now = time(NULL); @@ -2657,7 +2477,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; set_routerstatus_from_routerinfo(rs, node, ri, now, - naming, listbadexits, listbaddirs, + listbadexits, vote_on_hsdirs); if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) @@ -2739,14 +2559,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); if (vote_on_reachability) smartlist_add(v3_out->known_flags, tor_strdup("Running")); - if (listbaddirs) - smartlist_add(v3_out->known_flags, tor_strdup("BadDirectory")); if (listbadexits) smartlist_add(v3_out->known_flags, tor_strdup("BadExit")); - if (naming) { - smartlist_add(v3_out->known_flags, tor_strdup("Named")); - smartlist_add(v3_out->known_flags, tor_strdup("Unnamed")); - } if (vote_on_hsdirs) smartlist_add(v3_out->known_flags, tor_strdup("HSDir")); smartlist_sort_strings(v3_out->known_flags); diff --git a/src/or/dirserv.h b/src/or/dirserv.h index 858e6e3a07..5d5ef2b732 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -34,10 +34,9 @@ int connection_dirserv_flushed_some(dir_connection_t *conn); -int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_t *pk); +int dirserv_add_own_fingerprint(crypto_pk_t *pk); int dirserv_load_fingerprint_file(void); void dirserv_free_fingerprint_list(void); -const char *dirserv_get_nickname_by_digest(const char *digest); enum was_router_added_t dirserv_add_multiple_descriptors( const char *desc, uint8_t purpose, const char *source, diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 137d6c1a8c..8a0fdf62fc 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -64,7 +64,7 @@ STATIC char * format_networkstatus_vote(crypto_pk_t *private_signing_key, networkstatus_t *v3_ns) { - smartlist_t *chunks; + smartlist_t *chunks = smartlist_new(); const char *client_versions = NULL, *server_versions = NULL; char fingerprint[FINGERPRINT_LEN+1]; char digest[DIGEST_LEN]; @@ -98,7 +98,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, server_versions_line = tor_strdup(""); } - chunks = smartlist_new(); { char published[ISO_TIME_LEN+1]; char va[ISO_TIME_LEN+1]; @@ -110,7 +109,8 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, char *params; authority_cert_t *cert = v3_ns->cert; char *methods = - make_consensus_method_list(1, MAX_SUPPORTED_CONSENSUS_METHOD, " "); + make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD, + MAX_SUPPORTED_CONSENSUS_METHOD, " "); format_iso_time(published, v3_ns->published); format_iso_time(va, v3_ns->valid_after); format_iso_time(fu, v3_ns->fresh_until); @@ -230,10 +230,9 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, done: tor_free(client_versions_line); tor_free(server_versions_line); - if (chunks) { - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - } + + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); return status; } @@ -458,8 +457,7 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, smartlist_free(alt_orports); } - if (consensus_method >= MIN_METHOD_FOR_MICRODESC && - microdesc_digest256_out) { + if (microdesc_digest256_out) { smartlist_t *digests = smartlist_new(); const char *best_microdesc_digest; SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) { @@ -541,7 +539,8 @@ compute_consensus_method(smartlist_t *votes) static int consensus_method_is_supported(int method) { - return (method >= 1) && (method <= MAX_SUPPORTED_CONSENSUS_METHOD); + return (method >= MIN_SUPPORTED_CONSENSUS_METHOD) && + (method <= MAX_SUPPORTED_CONSENSUS_METHOD); } /** Return a newly allocated string holding the numbers between low and high @@ -605,13 +604,14 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities) const int n_votes = smartlist_len(votes); smartlist_t *output; smartlist_t *param_list = smartlist_new(); + (void) method; /* We require that the parameter lists in the votes are well-formed: that is, that their keywords are unique and sorted, and that their values are between INT32_MIN and INT32_MAX inclusive. This should be guaranteed by the parsing code. */ - vals = tor_malloc(sizeof(int)*n_votes); + vals = tor_calloc(sizeof(int), n_votes); SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { if (!v->net_params) @@ -647,12 +647,13 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities) next_param = NULL; else next_param = smartlist_get(param_list, param_sl_idx+1); + /* resolve spurious clang shallow analysis null pointer errors */ + tor_assert(param); if (!next_param || strncmp(next_param, param, cur_param_len)) { /* We've reached the end of a series. */ /* Make sure enough authorities voted on this param, unless the * the consensus method we use is too old for that. */ - if (method < MIN_METHOD_FOR_MAJORITY_PARAMS || - i > total_authorities/2 || + if (i > total_authorities/2 || i >= MIN_VOTES_FOR_PARAM) { int32_t median = median_int32(vals, i); char *out_string = tor_malloc(64+cur_param_len); @@ -1005,300 +1006,6 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G, I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); return 1; } -/** - * This function computes the bandwidth weights for consensus method 9. - * - * It has been obsoleted in favor of consensus method 10. - */ -static void -networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M, - int64_t E, int64_t D, int64_t T, - int64_t weight_scale) -{ - int64_t Wgg = -1, Wgd = -1; - int64_t Wmg = -1, Wme = -1, Wmd = -1; - int64_t Wed = -1, Wee = -1; - const char *casename; - - if (G <= 0 || M <= 0 || E <= 0 || D <= 0) { - log_warn(LD_DIR, "Consensus with empty bandwidth: " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT - " D="I64_FORMAT" T="I64_FORMAT, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - return; - } - - /* - * Computed from cases in 3.4.3 of dir-spec.txt - * - * 1. Neither are scarce - * 2. Both Guard and Exit are scarce - * a. R+D <= S - * b. R+D > S - * 3. One of Guard or Exit is scarce - * a. S+D < T/3 - * b. S+D >= T/3 - */ - if (3*E >= T && 3*G >= T) { // E >= T/3 && G >= T/3 - bw_weights_error_t berr = 0; - /* Case 1: Neither are scarce. - * - * Attempt to ensure that we have a large amount of exit bandwidth - * in the middle position. - */ - casename = "Case 1 (Wme*E = Wmd*D)"; - Wgg = (weight_scale*(D+E+G+M))/(3*G); - if (D==0) Wmd = 0; - else Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); - Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); - Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); - Wgd = 0; - Wmg = weight_scale - Wgg; - Wed = weight_scale - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, - weight_scale, G, M, E, D, T, 10, 1); - - if (berr) { - log_warn(LD_DIR, "Bw Weights error %d for case %s. " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT - " D="I64_FORMAT" T="I64_FORMAT, - berr, casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - } else if (3*E < T && 3*G < T) { // E < T/3 && G < T/3 - int64_t R = MIN(E, G); - int64_t S = MAX(E, G); - /* - * Case 2: Both Guards and Exits are scarce - * Balance D between E and G, depending upon - * D capacity and scarcity. - */ - if (R+D < S) { // Subcase a - Wgg = weight_scale; - Wee = weight_scale; - Wmg = 0; - Wme = 0; - Wmd = 0; - if (E < G) { - casename = "Case 2a (E scarce)"; - Wed = weight_scale; - Wgd = 0; - } else { /* E >= G */ - casename = "Case 2a (G scarce)"; - Wed = 0; - Wgd = weight_scale; - } - } else { // Subcase b: R+D > S - bw_weights_error_t berr = 0; - casename = "Case 2b (Wme*E == Wmd*D)"; - if (D != 0) { - Wgg = weight_scale; - Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); // T/3 >= G (Ok) - Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); // T/3 >= M - Wme = (weight_scale*(D + E + G - 2*M))/(6*E); - Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); // 2E+M >= T/3 - Wmg = 0; - Wed = weight_scale - Wgd - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, - weight_scale, G, M, E, D, T, 10, 1); - } - - if (D == 0 || berr) { // Can happen if M > T/3 - casename = "Case 2b (E=G)"; - Wgg = weight_scale; - Wee = weight_scale; - Wmg = 0; - Wme = 0; - Wmd = 0; - if (D == 0) Wgd = 0; - else Wgd = (weight_scale*(D+E-G))/(2*D); - Wed = weight_scale - Wgd; - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, - Wed, weight_scale, G, M, E, D, T, 10, 1); - } - if (berr != BW_WEIGHTS_NO_ERROR && - berr != BW_WEIGHTS_BALANCE_MID_ERROR) { - log_warn(LD_DIR, "Bw Weights error %d for case %s. " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT - " D="I64_FORMAT" T="I64_FORMAT, - berr, casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - } - } else { // if (E < T/3 || G < T/3) { - int64_t S = MIN(E, G); - // Case 3: Exactly one of Guard or Exit is scarce - if (!(3*E < T || 3*G < T) || !(3*G >= T || 3*E >= T)) { - log_warn(LD_BUG, - "Bw-Weights Case 3 but with G="I64_FORMAT" M=" - I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - - if (3*(S+D) < T) { // Subcase a: S+D < T/3 - if (G < E) { - casename = "Case 3a (G scarce)"; - Wgg = Wgd = weight_scale; - Wmd = Wed = Wmg = 0; - // Minor subcase, if E is more scarce than M, - // keep its bandwidth in place. - if (E < M) Wme = 0; - else Wme = (weight_scale*(E-M))/(2*E); - Wee = weight_scale-Wme; - } else { // G >= E - casename = "Case 3a (E scarce)"; - Wee = Wed = weight_scale; - Wmd = Wgd = Wme = 0; - // Minor subcase, if G is more scarce than M, - // keep its bandwidth in place. - if (G < M) Wmg = 0; - else Wmg = (weight_scale*(G-M))/(2*G); - Wgg = weight_scale-Wmg; - } - } else { // Subcase b: S+D >= T/3 - bw_weights_error_t berr = 0; - // D != 0 because S+D >= T/3 - if (G < E) { - casename = "Case 3b (G scarce, Wme*E == Wmd*D)"; - Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); - Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); - Wme = (weight_scale*(D + E + G - 2*M))/(6*E); - Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); - Wgg = weight_scale; - Wmg = 0; - Wed = weight_scale - Wgd - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, - Wed, weight_scale, G, M, E, D, T, 10, 1); - } else { // G >= E - casename = "Case 3b (E scarce, Wme*E == Wmd*D)"; - Wgg = (weight_scale*(D + E + G + M))/(3*G); - Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); - Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); - Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); - Wgd = 0; - Wmg = weight_scale - Wgg; - Wed = weight_scale - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, - Wed, weight_scale, G, M, E, D, T, 10, 1); - } - if (berr) { - log_warn(LD_DIR, "Bw Weights error %d for case %s. " - "G="I64_FORMAT" M="I64_FORMAT - " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, - berr, casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - } - } - - /* We cast down the weights to 32 bit ints on the assumption that - * weight_scale is ~= 10000. We need to ensure a rogue authority - * doesn't break this assumption to rig our weights */ - tor_assert(0 < weight_scale && weight_scale <= INT32_MAX); - - if (Wgg < 0 || Wgg > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wgg="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wgg), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - - Wgg = MAX(MIN(Wgg, weight_scale), 0); - } - if (Wgd < 0 || Wgd > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wgd="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wgd), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wgd = MAX(MIN(Wgd, weight_scale), 0); - } - if (Wmg < 0 || Wmg > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wmg="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wmg), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wmg = MAX(MIN(Wmg, weight_scale), 0); - } - if (Wme < 0 || Wme > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wme="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wme), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wme = MAX(MIN(Wme, weight_scale), 0); - } - if (Wmd < 0 || Wmd > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wmd="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wmd), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wmd = MAX(MIN(Wmd, weight_scale), 0); - } - if (Wee < 0 || Wee > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wee="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wee), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wee = MAX(MIN(Wee, weight_scale), 0); - } - if (Wed < 0 || Wed > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wed="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wed), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wed = MAX(MIN(Wed, weight_scale), 0); - } - - // Add consensus weight keywords - smartlist_add(chunks, tor_strdup("bandwidth-weights ")); - /* - * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine - * that middle nodes need different bandwidth weights for dirport traffic, - * or that weird exit policies need special weight, or that bridges - * need special weight. - * - * NOTE: This list is sorted. - */ - smartlist_add_asprintf(chunks, - "Wbd=%d Wbe=%d Wbg=%d Wbm=%d " - "Wdb=%d " - "Web=%d Wed=%d Wee=%d Weg=%d Wem=%d " - "Wgb=%d Wgd=%d Wgg=%d Wgm=%d " - "Wmb=%d Wmd=%d Wme=%d Wmg=%d Wmm=%d\n", - (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale, - (int)weight_scale, - (int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee, - (int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg, - (int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale); - - log_notice(LD_CIRC, "Computed bandwidth weights for %s with v9: " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); -} /** Given a list of vote networkstatus_t in <b>votes</b>, our public * authority <b>identity_key</b>, our private authority <b>signing_key</b>, @@ -1350,18 +1057,18 @@ networkstatus_compute_consensus(smartlist_t *votes, log_warn(LD_DIR, "The other authorities will use consensus method %d, " "which I don't support. Maybe I should upgrade!", consensus_method); - consensus_method = 1; + consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD; } /* Compute medians of time-related things, and figure out how many * routers we might need to talk about. */ { int n_votes = smartlist_len(votes); - time_t *va_times = tor_malloc(n_votes * sizeof(time_t)); - time_t *fu_times = tor_malloc(n_votes * sizeof(time_t)); - time_t *vu_times = tor_malloc(n_votes * sizeof(time_t)); - int *votesec_list = tor_malloc(n_votes * sizeof(int)); - int *distsec_list = tor_malloc(n_votes * sizeof(int)); + time_t *va_times = tor_calloc(n_votes, sizeof(time_t)); + time_t *fu_times = tor_calloc(n_votes, sizeof(time_t)); + time_t *vu_times = tor_calloc(n_votes, sizeof(time_t)); + int *votesec_list = tor_calloc(n_votes, sizeof(int)); + int *distsec_list = tor_calloc(n_votes, sizeof(int)); int n_versioning_clients = 0, n_versioning_servers = 0; smartlist_t *combined_client_versions = smartlist_new(); smartlist_t *combined_server_versions = smartlist_new(); @@ -1441,10 +1148,8 @@ networkstatus_compute_consensus(smartlist_t *votes, flavor == FLAV_NS ? "" : " ", flavor == FLAV_NS ? "" : flavor_name); - if (consensus_method >= 2) { - smartlist_add_asprintf(chunks, "consensus-method %d\n", - consensus_method); - } + smartlist_add_asprintf(chunks, "consensus-method %d\n", + consensus_method); smartlist_add_asprintf(chunks, "valid-after %s\n" @@ -1461,14 +1166,12 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_free(flaglist); } - if (consensus_method >= MIN_METHOD_FOR_PARAMS) { - params = dirvote_compute_params(votes, consensus_method, - total_authorities); - if (params) { - smartlist_add(chunks, tor_strdup("params ")); - smartlist_add(chunks, params); - smartlist_add(chunks, tor_strdup("\n")); - } + params = dirvote_compute_params(votes, consensus_method, + total_authorities); + if (params) { + smartlist_add(chunks, tor_strdup("params ")); + smartlist_add(chunks, params); + smartlist_add(chunks, tor_strdup("\n")); } /* Sort the votes. */ @@ -1482,8 +1185,7 @@ networkstatus_compute_consensus(smartlist_t *votes, e->digest = get_voter(v)->identity_digest; e->is_legacy = 0; smartlist_add(dir_sources, e); - if (consensus_method >= 3 && - !tor_digest_is_zero(get_voter(v)->legacy_id_digest)) { + if (!tor_digest_is_zero(get_voter(v)->legacy_id_digest)) { dir_src_ent_t *e_legacy = tor_malloc_zero(sizeof(dir_src_ent_t)); e_legacy->v = v; e_legacy->digest = get_voter(v)->legacy_id_digest; @@ -1499,9 +1201,6 @@ networkstatus_compute_consensus(smartlist_t *votes, networkstatus_t *v = e->v; networkstatus_voter_info_t *voter = get_voter(v); - if (e->is_legacy) - tor_assert(consensus_method >= 2); - base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN); base16_encode(votedigest, sizeof(votedigest), voter->vote_digest, DIGEST_LEN); @@ -1559,9 +1258,9 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_t *chosen_flags = smartlist_new(); smartlist_t *versions = smartlist_new(); smartlist_t *exitsummaries = smartlist_new(); - uint32_t *bandwidths_kb = tor_malloc(sizeof(uint32_t) * + uint32_t *bandwidths_kb = tor_calloc(sizeof(uint32_t), smartlist_len(votes)); - uint32_t *measured_bws_kb = tor_malloc(sizeof(uint32_t) * + uint32_t *measured_bws_kb = tor_calloc(sizeof(uint32_t), smartlist_len(votes)); int num_bandwidths; int num_mbws; @@ -1574,7 +1273,6 @@ networkstatus_compute_consensus(smartlist_t *votes, * is the same flag as votes[j]->known_flags[b]. */ int *named_flag; /* Index of the flag "Named" for votes[j] */ int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */ - int chosen_named_idx; int n_authorities_measuring_bandwidth; strmap_t *name_to_id_map = strmap_new(); @@ -1583,16 +1281,15 @@ networkstatus_compute_consensus(smartlist_t *votes, memset(conflict, 0, sizeof(conflict)); memset(unknown, 0xff, sizeof(conflict)); - index = tor_malloc_zero(sizeof(int)*smartlist_len(votes)); - size = tor_malloc_zero(sizeof(int)*smartlist_len(votes)); - n_voter_flags = tor_malloc_zero(sizeof(int) * smartlist_len(votes)); - n_flag_voters = tor_malloc_zero(sizeof(int) * smartlist_len(flags)); - flag_map = tor_malloc_zero(sizeof(int*) * smartlist_len(votes)); - named_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes)); - unnamed_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes)); + index = tor_calloc(sizeof(int), smartlist_len(votes)); + size = tor_calloc(sizeof(int), smartlist_len(votes)); + n_voter_flags = tor_calloc(sizeof(int), smartlist_len(votes)); + n_flag_voters = tor_calloc(sizeof(int), smartlist_len(flags)); + flag_map = tor_calloc(sizeof(int *), smartlist_len(votes)); + named_flag = tor_calloc(sizeof(int), smartlist_len(votes)); + unnamed_flag = tor_calloc(sizeof(int), smartlist_len(votes)); for (i = 0; i < smartlist_len(votes); ++i) unnamed_flag[i] = named_flag[i] = -1; - chosen_named_idx = smartlist_string_pos(flags, "Named"); /* Build the flag indexes. Note that no vote can have more than 64 members * for known_flags, so no value will be greater than 63, so it's safe to @@ -1601,8 +1298,8 @@ networkstatus_compute_consensus(smartlist_t *votes, * that they're actually set before doing U64_LITERAL(1) << index with * them.*/ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { - flag_map[v_sl_idx] = tor_malloc_zero( - sizeof(int)*smartlist_len(v->known_flags)); + flag_map[v_sl_idx] = tor_calloc(sizeof(int), + smartlist_len(v->known_flags)); if (smartlist_len(v->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) { log_warn(LD_BUG, "Somehow, a vote has %d entries in known_flags", smartlist_len(v->known_flags)); @@ -1622,7 +1319,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } SMARTLIST_FOREACH_END(v); /* Named and Unnamed get treated specially */ - if (consensus_method >= 2) { + { SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { uint64_t nf; if (named_flag[v_sl_idx]<0) @@ -1682,7 +1379,7 @@ networkstatus_compute_consensus(smartlist_t *votes, ); /* Now go through all the votes */ - flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags)); + flag_counts = tor_calloc(sizeof(int), smartlist_len(flags)); while (1) { vote_routerstatus_t *rs; routerstatus_t rs_out; @@ -1791,10 +1488,7 @@ networkstatus_compute_consensus(smartlist_t *votes, strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname)); } - if (consensus_method == 1) { - is_named = chosen_named_idx >= 0 && - (!naming_conflict && flag_counts[chosen_named_idx]); - } else { + { const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname); if (!d) { is_named = is_unnamed = 0; @@ -1811,7 +1505,7 @@ networkstatus_compute_consensus(smartlist_t *votes, if (!strcmp(fl, "Named")) { if (is_named) smartlist_add(chosen_flags, (char*)fl); - } else if (!strcmp(fl, "Unnamed") && consensus_method >= 2) { + } else if (!strcmp(fl, "Unnamed")) { if (is_unnamed) smartlist_add(chosen_flags, (char*)fl); } else { @@ -1831,7 +1525,7 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Starting with consensus method 4 we do not list servers * that are not running in a consensus. See Proposal 138 */ - if (consensus_method >= 4 && !is_running) + if (!is_running) continue; /* Pick the version. */ @@ -1843,11 +1537,11 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Pick a bandwidth */ - if (consensus_method >= 6 && num_mbws > 2) { + if (num_mbws > 2) { rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 0; rs_out.bandwidth_kb = median_uint32(measured_bws_kb, num_mbws); - } else if (consensus_method >= 5 && num_bandwidths > 0) { + } else if (num_bandwidths > 0) { rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 1; rs_out.bandwidth_kb = median_uint32(bandwidths_kb, num_bandwidths); @@ -1861,11 +1555,9 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Fix bug 2203: Do not count BadExit nodes as Exits for bw weights */ - if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) { - is_exit = is_exit && !is_bad_exit; - } + is_exit = is_exit && !is_bad_exit; - if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { + { if (rs_out.has_bandwidth) { T += rs_out.bandwidth_kb; if (is_exit && is_guard) @@ -1896,7 +1588,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * the policy that was most often listed in votes, again breaking * ties like in the previous case. */ - if (consensus_method >= 5) { + { /* Okay, go through all the votes for this router. We prepared * that list previously */ const char *chosen_exitsummary = NULL; @@ -1967,7 +1659,6 @@ networkstatus_compute_consensus(smartlist_t *votes, } if (flavor == FLAV_MICRODESC && - consensus_method >= MIN_METHOD_FOR_MANDATORY_MICRODESC && tor_digest256_is_zero(microdesc_digest)) { /* With no microdescriptor digest, we omit the entry entirely. */ continue; @@ -2033,13 +1724,10 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_free(measured_bws_kb); } - if (consensus_method >= MIN_METHOD_FOR_FOOTER) { - /* Starting with consensus method 9, we clearly mark the directory - * footer region */ - smartlist_add(chunks, tor_strdup("directory-footer\n")); - } + /* Mark the directory footer region */ + smartlist_add(chunks, tor_strdup("directory-footer\n")); - if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { + { int64_t weight_scale = BW_WEIGHT_SCALE; char *bw_weight_param = NULL; @@ -2072,13 +1760,8 @@ networkstatus_compute_consensus(smartlist_t *votes, } } - if (consensus_method < 10) { - networkstatus_compute_bw_weights_v9(chunks, G, M, E, D, T, weight_scale); - added_weights = 1; - } else { - added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, - T, weight_scale); - } + added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, + T, weight_scale); } /* Add a signature. */ @@ -2119,7 +1802,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } smartlist_add(chunks, signature); - if (legacy_id_key_digest && legacy_signing_key && consensus_method >= 3) { + if (legacy_id_key_digest && legacy_signing_key) { smartlist_add(chunks, tor_strdup("directory-signature ")); base16_encode(fingerprint, sizeof(fingerprint), legacy_id_key_digest, DIGEST_LEN); @@ -2155,7 +1838,7 @@ networkstatus_compute_consensus(smartlist_t *votes, goto done; } // Verify balancing parameters - if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS && added_weights) { + if (added_weights) { networkstatus_verify_bw_weights(c, consensus_method); } networkstatus_vote_free(c); @@ -2279,8 +1962,11 @@ networkstatus_add_detached_signatures(networkstatus_t *target, if (!sig->good_signature && !sig->bad_signature) { cert = authority_cert_get_by_digests(sig->identity_digest, sig->signing_key_digest); - if (cert) - networkstatus_check_document_signature(target, sig, cert); + if (cert) { + /* Not checking the return value here, since we are going to look + * at the status of sig->good_signature in a moment. */ + (void) networkstatus_check_document_signature(target, sig, cert); + } } /* If this signature is good, or we don't have any signature yet, @@ -3664,7 +3350,7 @@ static const struct consensus_method_range_t { int low; int high; } microdesc_consensus_methods[] = { - {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1}, + {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_A_LINES - 1}, {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1}, {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1}, {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1}, diff --git a/src/or/dirvote.h b/src/or/dirvote.h index 4c57e43661..7fa4010cf8 100644 --- a/src/or/dirvote.h +++ b/src/or/dirvote.h @@ -21,28 +21,12 @@ /** Smallest allowable voting interval. */ #define MIN_VOTE_INTERVAL 300 +/** The lowest consensus method that we currently support. */ +#define MIN_SUPPORTED_CONSENSUS_METHOD 13 + /** The highest consensus method that we currently support. */ #define MAX_SUPPORTED_CONSENSUS_METHOD 18 -/** Lowest consensus method that contains a 'directory-footer' marker */ -#define MIN_METHOD_FOR_FOOTER 9 - -/** Lowest consensus method that contains bandwidth weights */ -#define MIN_METHOD_FOR_BW_WEIGHTS 9 - -/** Lowest consensus method that contains consensus params */ -#define MIN_METHOD_FOR_PARAMS 7 - -/** Lowest consensus method that generates microdescriptors */ -#define MIN_METHOD_FOR_MICRODESC 8 - -/** Lowest consensus method that doesn't count bad exits as exits for weight */ -#define MIN_METHOD_TO_CUT_BADEXIT_WEIGHT 11 - -/** Lowest consensus method that ensures a majority of authorities voted - * for a param. */ -#define MIN_METHOD_FOR_MAJORITY_PARAMS 12 - /** Lowest consensus method where microdesc consensuses omit any entry * with no microdesc. */ #define MIN_METHOD_FOR_MANDATORY_MICRODESC 13 @@ -116,8 +100,8 @@ const cached_dir_t *dirvote_get_vote(const char *fp, int flags); void set_routerstatus_from_routerinfo(routerstatus_t *rs, node_t *node, routerinfo_t *ri, time_t now, - int naming, int listbadexits, - int listbaddirs, int vote_on_hsdirs); + int listbadexits, + int vote_on_hsdirs); networkstatus_t * dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, authority_cert_t *cert); diff --git a/src/or/dns.c b/src/or/dns.c index a9c4318651..362b97033e 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -244,8 +244,8 @@ cached_resolve_hash(cached_resolve_t *a) HT_PROTOTYPE(cache_map, cached_resolve_t, node, cached_resolve_hash, cached_resolves_eq) -HT_GENERATE(cache_map, cached_resolve_t, node, cached_resolve_hash, - cached_resolves_eq, 0.6, malloc, realloc, free) +HT_GENERATE2(cache_map, cached_resolve_t, node, cached_resolve_hash, + cached_resolves_eq, 0.6, tor_reallocarray_, tor_free_) /** Initialize the DNS cache. */ static void diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 66b7201187..b1fd310f97 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -12,6 +12,8 @@ * circumvention). **/ +#define ENTRYNODES_PRIVATE + #include "or.h" #include "circpathbias.h" #include "circuitbuild.h" @@ -154,21 +156,41 @@ entry_guard_set_status(entry_guard_t *e, const node_t *node, /** Return true iff enough time has passed since we last tried to connect * to the unreachable guard <b>e</b> that we're willing to try again. */ -static int -entry_is_time_to_retry(entry_guard_t *e, time_t now) +STATIC int +entry_is_time_to_retry(const entry_guard_t *e, time_t now) { - long diff; + struct guard_retry_period_s { + time_t period_duration; + time_t interval_during_period; + }; + + struct guard_retry_period_s periods[] = { + { 6*60*60, 60*60 }, /* For first 6 hrs., retry hourly; */ + { 3*24*60*60, 4*60*60 }, /* Then retry every 4 hrs. until the + 3-day mark; */ + { 7*24*60*60, 18*60*60 }, /* After 3 days, retry every 18 hours until + 1 week mark. */ + { TIME_MAX, 36*60*60 } /* After 1 week, retry every 36 hours. */ + }; + + time_t ith_deadline_for_retry; + time_t unreachable_for; + unsigned i; + if (e->last_attempted < e->unreachable_since) return 1; - diff = now - e->unreachable_since; - if (diff < 6*60*60) - return now > (e->last_attempted + 60*60); - else if (diff < 3*24*60*60) - return now > (e->last_attempted + 4*60*60); - else if (diff < 7*24*60*60) - return now > (e->last_attempted + 18*60*60); - else - return now > (e->last_attempted + 36*60*60); + + unreachable_for = now - e->unreachable_since; + + for (i = 0; i < ARRAY_LENGTH(periods); i++) { + if (unreachable_for <= periods[i].period_duration) { + ith_deadline_for_retry = e->last_attempted + + periods[i].interval_during_period; + + return (now > ith_deadline_for_retry); + } + } + return 0; } /** Return the node corresponding to <b>e</b>, if <b>e</b> is @@ -188,12 +210,17 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now) * If need_descriptor is true, only return the node if we currently have * a descriptor (routerinfo or microdesc) for it. */ -static INLINE const node_t * -entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, - int assume_reachable, int need_descriptor, const char **msg) +STATIC const node_t * +entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags, + const char **msg) { const node_t *node; const or_options_t *options = get_options(); + int need_uptime = (flags & ENTRY_NEED_UPTIME) != 0; + int need_capacity = (flags & ENTRY_NEED_CAPACITY) != 0; + const int assume_reachable = (flags & ENTRY_ASSUME_REACHABLE) != 0; + const int need_descriptor = (flags & ENTRY_NEED_DESCRIPTOR) != 0; + tor_assert(msg); if (e->path_bias_disabled) { @@ -255,12 +282,18 @@ num_live_entry_guards(int for_directory) { int n = 0; const char *msg; + /* Set the entry node attributes we are interested in. */ + entry_is_live_flags_t entry_flags = ENTRY_NEED_CAPACITY; + if (!for_directory) { + entry_flags |= ENTRY_NEED_DESCRIPTOR; + } + if (! entry_guards) return 0; SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { if (for_directory && !entry->is_dir_cache) continue; - if (entry_is_live(entry, 0, 1, 0, !for_directory, &msg)) + if (entry_is_live(entry, entry_flags, &msg)) ++n; } SMARTLIST_FOREACH_END(entry); return n; @@ -289,7 +322,7 @@ log_entry_guards(int severity) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { const char *msg = NULL; - if (entry_is_live(e, 0, 1, 0, 0, &msg)) + if (entry_is_live(e, ENTRY_NEED_CAPACITY, &msg)) smartlist_add_asprintf(elements, "%s [%s] (up %s)", e->nickname, hex_str(e->identity, DIGEST_LEN), @@ -350,7 +383,7 @@ control_event_guard_deferred(void) * If <b>chosen</b> is defined, use that one, and if it's not * already in our entry_guards list, put it at the *beginning*. * Else, put the one we pick at the end of the list. */ -static const node_t * +STATIC const node_t * add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, int for_discovery, int for_directory) { @@ -437,7 +470,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, /** Choose how many entry guards or directory guards we'll use. If * <b>for_directory</b> is true, we return how many directory guards to * use; else we return how many entry guards to use. */ -static int +STATIC int decide_num_guards(const or_options_t *options, int for_directory) { if (for_directory) { @@ -676,7 +709,7 @@ entry_guards_compute_status(const or_options_t *options, time_t now) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *reason = digestmap_get(reasons, entry->identity); const char *live_msg = ""; - const node_t *r = entry_is_live(entry, 0, 1, 0, 0, &live_msg); + const node_t *r = entry_is_live(entry, ENTRY_NEED_CAPACITY, &live_msg); log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", entry->nickname, hex_str(entry->identity, DIGEST_LEN), @@ -794,7 +827,9 @@ entry_guard_register_connect_status(const char *digest, int succeeded, break; if (e->made_contact) { const char *msg; - const node_t *r = entry_is_live(e, 0, 1, 1, 0, &msg); + const node_t *r = entry_is_live(e, + ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, + &msg); if (r && e->unreachable_since) { refuse_conn = 1; e->can_retry = 1; @@ -847,7 +882,7 @@ update_node_guard_status(void) /** Adjust the entry guards list so that it only contains entries from * EntryNodes, adding new entries from EntryNodes to the list as needed. */ -static void +STATIC void entry_guards_set_from_config(const or_options_t *options) { smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps; @@ -1007,47 +1042,61 @@ choose_random_dirguard(dirinfo_type_t type) return choose_random_entry_impl(NULL, 1, type, NULL); } -/** Helper for choose_random{entry,dirguard}. */ -static const node_t * -choose_random_entry_impl(cpath_build_state_t *state, int for_directory, - dirinfo_type_t dirinfo_type, int *n_options_out) +/** Filter <b>all_entry_guards</b> for usable entry guards and put them + * in <b>live_entry_guards</b>. We filter based on whether the node is + * currently alive, and on whether it satisfies the restrictions + * imposed by the other arguments of this function. + * + * We don't place more guards than NumEntryGuards in <b>live_entry_guards</b>. + * + * If <b>chosen_exit</b> is set, it contains the exit node of this + * circuit. Make sure to not use it or its family as an entry guard. + * + * If <b>need_uptime</b> is set, we are looking for a stable entry guard. + * if <b>need_capacity</b> is set, we are looking for a fast entry guard. + * + * The rest of the arguments are the same as in choose_random_entry_impl(). + * + * Return 1 if we should choose a guard right away. Return 0 if we + * should try to add more nodes to our list before deciding on a + * guard. + */ +STATIC int +populate_live_entry_guards(smartlist_t *live_entry_guards, + const smartlist_t *all_entry_guards, + const node_t *chosen_exit, + dirinfo_type_t dirinfo_type, + int for_directory, + int need_uptime, int need_capacity) { const or_options_t *options = get_options(); - smartlist_t *live_entry_guards = smartlist_new(); - smartlist_t *exit_family = smartlist_new(); - const node_t *chosen_exit = - state?build_state_get_exit_node(state) : NULL; const node_t *node = NULL; - int need_uptime = state ? state->need_uptime : 0; - int need_capacity = state ? state->need_capacity : 0; - int preferred_min, consider_exit_family = 0; - int need_descriptor = !for_directory; const int num_needed = decide_num_guards(options, for_directory); + smartlist_t *exit_family = smartlist_new(); + int retval = 0; + entry_is_live_flags_t entry_flags = 0; - if (n_options_out) - *n_options_out = 0; + { /* Set the flags we want our entry node to have */ + if (need_uptime) { + entry_flags |= ENTRY_NEED_UPTIME; + } + if (need_capacity) { + entry_flags |= ENTRY_NEED_CAPACITY; + } + if (!for_directory) { + entry_flags |= ENTRY_NEED_DESCRIPTOR; + } + } + + tor_assert(all_entry_guards); if (chosen_exit) { nodelist_add_node_and_family(exit_family, chosen_exit); - consider_exit_family = 1; } - if (!entry_guards) - entry_guards = smartlist_new(); - - if (should_add_entry_nodes) - entry_guards_set_from_config(options); - - if (!entry_list_is_constrained(options) && - smartlist_len(entry_guards) < num_needed) - pick_entry_guards(options, for_directory); - - retry: - smartlist_clear(live_entry_guards); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { + SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { const char *msg; - node = entry_is_live(entry, need_uptime, need_capacity, 0, - need_descriptor, &msg); + node = entry_is_live(entry, entry_flags, &msg); if (!node) continue; /* down, no point */ if (for_directory) { @@ -1056,39 +1105,94 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, } if (node == chosen_exit) continue; /* don't pick the same node for entry and exit */ - if (consider_exit_family && smartlist_contains(exit_family, node)) + if (smartlist_contains(exit_family, node)) continue; /* avoid relays that are family members of our exit */ if (dirinfo_type != NO_DIRINFO && !node_can_handle_dirinfo(node, dirinfo_type)) continue; /* this node won't be able to answer our dir questions */ -#if 0 /* since EntryNodes is always strict now, this clause is moot */ - if (options->EntryNodes && - !routerset_contains_node(options->EntryNodes, node)) { - /* We've come to the end of our preferred entry nodes. */ - if (smartlist_len(live_entry_guards)) - goto choose_and_finish; /* only choose from the ones we like */ - if (options->StrictNodes) { - /* in theory this case should never happen, since - * entry_guards_set_from_config() drops unwanted relays */ - tor_fragile_assert(); - } else { - log_info(LD_CIRC, - "No relays from EntryNodes available. Using others."); - } - } -#endif smartlist_add(live_entry_guards, (void*)node); if (!entry->made_contact) { /* Always start with the first not-yet-contacted entry * guard. Otherwise we might add several new ones, pick * the second new one, and now we've expanded our entry * guard list without needing to. */ - goto choose_and_finish; + retval = 1; + goto done; + } + if (smartlist_len(live_entry_guards) >= num_needed) { + retval = 1; + goto done; /* We picked enough entry guards. Done! */ } - if (smartlist_len(live_entry_guards) >= num_needed) - goto choose_and_finish; /* we have enough */ } SMARTLIST_FOREACH_END(entry); + done: + smartlist_free(exit_family); + + return retval; +} + +/** Pick a node to be used as the entry guard of a circuit. + * + * If <b>state</b> is set, it contains the information we know about + * the upcoming circuit. + * + * If <b>for_directory</b> is set, we are looking for a directory guard. + * + * <b>dirinfo_type</b> contains the kind of directory information we + * are looking for in our node. + * + * If <b>n_options_out</b> is set, we set it to the number of + * candidate guard nodes we had before picking a specific guard node. + * + * On success, return the node that should be used as the entry guard + * of the circuit. Return NULL if no such node could be found. + * + * Helper for choose_random{entry,dirguard}. +*/ +static const node_t * +choose_random_entry_impl(cpath_build_state_t *state, int for_directory, + dirinfo_type_t dirinfo_type, int *n_options_out) +{ + const or_options_t *options = get_options(); + smartlist_t *live_entry_guards = smartlist_new(); + const node_t *chosen_exit = + state?build_state_get_exit_node(state) : NULL; + const node_t *node = NULL; + int need_uptime = state ? state->need_uptime : 0; + int need_capacity = state ? state->need_capacity : 0; + int preferred_min = 0; + const int num_needed = decide_num_guards(options, for_directory); + int retval = 0; + + if (n_options_out) + *n_options_out = 0; + + if (!entry_guards) + entry_guards = smartlist_new(); + + if (should_add_entry_nodes) + entry_guards_set_from_config(options); + + if (!entry_list_is_constrained(options) && + smartlist_len(entry_guards) < num_needed) + pick_entry_guards(options, for_directory); + + retry: + smartlist_clear(live_entry_guards); + + /* Populate the list of live entry guards so that we pick one of + them. */ + retval = populate_live_entry_guards(live_entry_guards, + entry_guards, + chosen_exit, + dirinfo_type, + for_directory, + need_uptime, need_capacity); + + if (retval == 1) { /* We should choose a guard right now. */ + goto choose_and_finish; + } + if (entry_list_is_constrained(options)) { /* If we prefer the entry nodes we've got, and we have at least * one choice, that's great. Use it. */ @@ -1127,18 +1231,7 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, need_capacity = 0; goto retry; } -#if 0 - /* Removing this retry logic: if we only allow one exit, and it is in the - same family as all our entries, then we are just plain not going to win - here. */ - if (!node && entry_list_is_constrained(options) && consider_exit_family) { - /* still no? if we're using bridges or have strictentrynodes - * set, and our chosen exit is in the same family as all our - * bridges/entry guards, then be flexible about families. */ - consider_exit_family = 0; - goto retry; - } -#endif + /* live_entry_guards may be empty below. Oh well, we tried. */ } @@ -1156,7 +1249,6 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, if (n_options_out) *n_options_out = smartlist_len(live_entry_guards); smartlist_free(live_entry_guards); - smartlist_free(exit_family); return node; } @@ -2199,6 +2291,13 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) node = node_get_mutable_by_id(ri->cache_info.identity_digest); tor_assert(node); rewrite_node_address_for_bridge(bridge, node); + if (tor_digest_is_zero(bridge->identity)) { + memcpy(bridge->identity,ri->cache_info.identity_digest, DIGEST_LEN); + log_notice(LD_DIR, "Learned identity %s for bridge at %s:%d", + hex_str(bridge->identity, DIGEST_LEN), + fmt_and_decorate_addr(&bridge->addr), + (int) bridge->port); + } add_an_entry_guard(node, 1, 1, 0, 0); log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname, diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index e229f3b79a..52b31a225d 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -77,6 +77,38 @@ int num_live_entry_guards(int for_directory); #endif +#ifdef ENTRYNODES_PRIVATE +STATIC const node_t *add_an_entry_guard(const node_t *chosen, + int reset_status, int prepend, + int for_discovery, int for_directory); + +STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards, + const smartlist_t *all_entry_guards, + const node_t *chosen_exit, + dirinfo_type_t dirinfo_type, + int for_directory, + int need_uptime, int need_capacity); +STATIC int decide_num_guards(const or_options_t *options, int for_directory); + +STATIC void entry_guards_set_from_config(const or_options_t *options); + +/** Flags to be passed to entry_is_live() to indicate what kind of + * entry nodes we are looking for. */ +typedef enum { + ENTRY_NEED_UPTIME = 1<<0, + ENTRY_NEED_CAPACITY = 1<<1, + ENTRY_ASSUME_REACHABLE = 1<<2, + ENTRY_NEED_DESCRIPTOR = 1<<3, +} entry_is_live_flags_t; + +STATIC const node_t *entry_is_live(const entry_guard_t *e, + entry_is_live_flags_t flags, + const char **msg); + +STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now); + +#endif + void remove_all_entry_guards(void); void entry_guards_compute_status(const or_options_t *options, time_t now); diff --git a/src/or/fp_pair.c b/src/or/fp_pair.c index 55e4c89a42..1be169609a 100644 --- a/src/or/fp_pair.c +++ b/src/or/fp_pair.c @@ -42,9 +42,9 @@ fp_pair_map_entry_hash(const fp_pair_map_entry_t *a) HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_s, node, fp_pair_map_entry_hash, fp_pair_map_entries_eq) -HT_GENERATE(fp_pair_map_impl, fp_pair_map_entry_s, node, - fp_pair_map_entry_hash, fp_pair_map_entries_eq, - 0.6, tor_malloc, tor_realloc, tor_free) +HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_s, node, + fp_pair_map_entry_hash, fp_pair_map_entries_eq, + 0.6, tor_reallocarray_, tor_free_) /** Constructor to create a new empty map from fp_pair_t to void * */ diff --git a/src/or/geoip.c b/src/or/geoip.c index f722bac468..cdf2797db0 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -58,8 +58,8 @@ static char geoip6_digest[DIGEST_LEN]; /** Return the index of the <b>country</b>'s entry in the GeoIP * country list if it is a valid 2-letter country code, otherwise * return -1. */ -country_t -geoip_get_country(const char *country) +MOCK_IMPL(country_t, +geoip_get_country,(const char *country)) { void *idxplus1_; intptr_t idx; @@ -396,8 +396,8 @@ geoip_get_country_by_ipv6(const struct in6_addr *addr) * the 'unknown country'. The return value will always be less than * geoip_get_n_countries(). To decode it, call geoip_get_country_name(). */ -int -geoip_get_country_by_addr(const tor_addr_t *addr) +MOCK_IMPL(int, +geoip_get_country_by_addr,(const tor_addr_t *addr)) { if (tor_addr_family(addr) == AF_INET) { return geoip_get_country_by_ipv4(tor_addr_to_ipv4h(addr)); @@ -409,8 +409,8 @@ geoip_get_country_by_addr(const tor_addr_t *addr) } /** Return the number of countries recognized by the GeoIP country list. */ -int -geoip_get_n_countries(void) +MOCK_IMPL(int, +geoip_get_n_countries,(void)) { if (!geoip_countries) init_geoip_countries(); @@ -430,8 +430,8 @@ geoip_get_country_name(country_t num) } /** Return true iff we have loaded a GeoIP database.*/ -int -geoip_is_loaded(sa_family_t family) +MOCK_IMPL(int, +geoip_is_loaded,(sa_family_t family)) { tor_assert(family == AF_INET || family == AF_INET6); if (geoip_countries == NULL) @@ -506,8 +506,8 @@ clientmap_entries_eq(const clientmap_entry_t *a, const clientmap_entry_t *b) HT_PROTOTYPE(clientmap, clientmap_entry_t, node, clientmap_entry_hash, clientmap_entries_eq); -HT_GENERATE(clientmap, clientmap_entry_t, node, clientmap_entry_hash, - clientmap_entries_eq, 0.6, malloc, realloc, free); +HT_GENERATE2(clientmap, clientmap_entry_t, node, clientmap_entry_hash, + clientmap_entries_eq, 0.6, tor_reallocarray_, tor_free_) /** Free all storage held by <b>ent</b>. */ static void @@ -720,8 +720,8 @@ dirreq_map_ent_hash(const dirreq_map_entry_t *entry) HT_PROTOTYPE(dirreqmap, dirreq_map_entry_t, node, dirreq_map_ent_hash, dirreq_map_ent_eq); -HT_GENERATE(dirreqmap, dirreq_map_entry_t, node, dirreq_map_ent_hash, - dirreq_map_ent_eq, 0.6, malloc, realloc, free); +HT_GENERATE2(dirreqmap, dirreq_map_entry_t, node, dirreq_map_ent_hash, + dirreq_map_ent_eq, 0.6, tor_reallocarray_, tor_free_) /** Helper: Put <b>entry</b> into map of directory requests using * <b>type</b> and <b>dirreq_id</b> as key parts. If there is @@ -963,7 +963,7 @@ geoip_get_dirreq_history(dirreq_type_t type) /* We may have rounded 'completed' up. Here we want to use the * real value. */ complete = smartlist_len(dirreq_completed); - dltimes = tor_malloc_zero(sizeof(uint32_t) * complete); + dltimes = tor_calloc(sizeof(uint32_t), complete); SMARTLIST_FOREACH_BEGIN(dirreq_completed, dirreq_map_entry_t *, ent) { uint32_t bytes_per_second; uint32_t time_diff = (uint32_t) tv_mdiff(&ent->request_time, @@ -1033,7 +1033,7 @@ geoip_get_client_history(geoip_client_action_t action, if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6)) return -1; - counts = tor_malloc_zero(sizeof(unsigned)*n_countries); + counts = tor_calloc(sizeof(unsigned), n_countries); HT_FOREACH(ent, clientmap, &client_history) { int country; if ((*ent)->action != (int)action) diff --git a/src/or/geoip.h b/src/or/geoip.h index b9b53c3006..f702617d9c 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -21,12 +21,12 @@ STATIC int geoip_get_country_by_ipv6(const struct in6_addr *addr); #endif int should_record_bridge_info(const or_options_t *options); int geoip_load_file(sa_family_t family, const char *filename); -int geoip_get_country_by_addr(const tor_addr_t *addr); -int geoip_get_n_countries(void); +MOCK_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); +MOCK_DECL(int, geoip_get_n_countries, (void)); const char *geoip_get_country_name(country_t num); -int geoip_is_loaded(sa_family_t family); +MOCK_DECL(int, geoip_is_loaded, (sa_family_t family)); const char *geoip_db_digest(sa_family_t family); -country_t geoip_get_country(const char *countrycode); +MOCK_DECL(country_t, geoip_get_country, (const char *countrycode)); void geoip_note_client_seen(geoip_client_action_t action, const tor_addr_t *addr, const char *transport_name, diff --git a/src/or/hibernate.c b/src/or/hibernate.c index c433ac1be9..b3761cfabf 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -410,6 +410,17 @@ configure_accounting(time_t now) accounting_set_wakeup_time(); } +/** Return the relevant number of bytes sent/received this interval + * based on the set AccountingRule */ +static uint64_t +get_accounting_bytes(void) +{ + if (get_options()->AccountingRule == ACCT_SUM) + return n_bytes_read_in_interval+n_bytes_written_in_interval; + else + return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval); +} + /** Set expected_bandwidth_usage based on how much we sent/received * per minute last interval (if we were up for at least 30 minutes), * or based on our declared bandwidth otherwise. */ @@ -421,6 +432,11 @@ update_expected_bandwidth(void) uint64_t max_configured = (options->RelayBandwidthRate > 0 ? options->RelayBandwidthRate : options->BandwidthRate) * 60; + /* max_configured is the larger of bytes read and bytes written + * If we are accounting based on sum, worst case is both are + * at max, doubling the expected sum of bandwidth */ + if (get_options()->AccountingRule == ACCT_SUM) + max_configured *= 2; #define MIN_TIME_FOR_MEASUREMENT (1800) @@ -439,8 +455,7 @@ update_expected_bandwidth(void) * doesn't know to store soft-limit info. Just take rate at which * we were reading/writing in the last interval as our expected rate. */ - uint64_t used = MAX(n_bytes_written_in_interval, - n_bytes_read_in_interval); + uint64_t used = get_accounting_bytes(); expected = used / (n_seconds_active_in_interval / 60); } else { /* If we haven't gotten enough data last interval, set 'expected' @@ -715,8 +730,7 @@ hibernate_hard_limit_reached(void) uint64_t hard_limit = get_options()->AccountingMax; if (!hard_limit) return 0; - return n_bytes_read_in_interval >= hard_limit - || n_bytes_written_in_interval >= hard_limit; + return get_accounting_bytes() >= hard_limit; } /** Return true iff we have sent/received almost all the bytes we are willing @@ -747,8 +761,7 @@ hibernate_soft_limit_reached(void) if (!soft_limit) return 0; - return n_bytes_read_in_interval >= soft_limit - || n_bytes_written_in_interval >= soft_limit; + return get_accounting_bytes() >= soft_limit; } /** Called when we get a SIGINT, or when bandwidth soft limit is @@ -772,8 +785,7 @@ hibernate_begin(hibernate_state_t new_state, time_t now) hibernate_state == HIBERNATE_STATE_LIVE) { soft_limit_hit_at = now; n_seconds_to_hit_soft_limit = n_seconds_active_in_interval; - n_bytes_at_soft_limit = MAX(n_bytes_read_in_interval, - n_bytes_written_in_interval); + n_bytes_at_soft_limit = get_accounting_bytes(); } /* close listeners. leave control listener(s). */ @@ -1003,13 +1015,22 @@ getinfo_helper_accounting(control_connection_t *conn, U64_PRINTF_ARG(n_bytes_written_in_interval)); } else if (!strcmp(question, "accounting/bytes-left")) { uint64_t limit = get_options()->AccountingMax; - uint64_t read_left = 0, write_left = 0; - if (n_bytes_read_in_interval < limit) - read_left = limit - n_bytes_read_in_interval; - if (n_bytes_written_in_interval < limit) - write_left = limit - n_bytes_written_in_interval; - tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, - U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left)); + if (get_options()->AccountingRule == ACCT_SUM) { + uint64_t total_left = 0; + uint64_t total_bytes = get_accounting_bytes(); + if (total_bytes < limit) + total_left = limit - total_bytes; + tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, + U64_PRINTF_ARG(total_left), U64_PRINTF_ARG(total_left)); + } else { + uint64_t read_left = 0, write_left = 0; + if (n_bytes_read_in_interval < limit) + read_left = limit - n_bytes_read_in_interval; + if (n_bytes_written_in_interval < limit) + write_left = limit - n_bytes_written_in_interval; + tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, + U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left)); + } } else if (!strcmp(question, "accounting/interval-start")) { *answer = tor_malloc(ISO_TIME_LEN+1); format_iso_time(*answer, interval_start_time); diff --git a/src/or/hibernate.h b/src/or/hibernate.h index 38ecb75129..799b582543 100644 --- a/src/or/hibernate.h +++ b/src/or/hibernate.h @@ -28,6 +28,7 @@ void consider_hibernation(time_t now); int getinfo_helper_accounting(control_connection_t *conn, const char *question, char **answer, const char **errmsg); +uint64_t get_accounting_max_total(void); #ifdef HIBERNATE_PRIVATE /** Possible values of hibernate_state */ diff --git a/src/or/main.c b/src/or/main.c index 9c1cabf037..61efc1f6f2 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -28,6 +28,7 @@ #include "connection_or.h" #include "control.h" #include "cpuworker.h" +#include "crypto_s2k.h" #include "directory.h" #include "dirserv.h" #include "dirvote.h" @@ -1861,6 +1862,10 @@ do_hup(void) return -1; } options = get_options(); /* they have changed now */ + /* Logs are only truncated the first time they are opened, but were + probably intended to be cleaned up on signal. */ + if (options->TruncateLogFile) + truncate_logs(); } else { char *msg = NULL; log_notice(LD_GENERAL, "Not reloading config file: the controller told " @@ -2670,11 +2675,11 @@ do_hash_password(void) { char output[256]; - char key[S2K_SPECIFIER_LEN+DIGEST_LEN]; + char key[S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN]; - crypto_rand(key, S2K_SPECIFIER_LEN-1); - key[S2K_SPECIFIER_LEN-1] = (uint8_t)96; /* Hash 64 K of data. */ - secret_to_key(key+S2K_SPECIFIER_LEN, DIGEST_LEN, + crypto_rand(key, S2K_RFC2440_SPECIFIER_LEN-1); + key[S2K_RFC2440_SPECIFIER_LEN-1] = (uint8_t)96; /* Hash 64 K of data. */ + secret_to_key_rfc2440(key+S2K_RFC2440_SPECIFIER_LEN, DIGEST_LEN, get_options()->command_arg, strlen(get_options()->command_arg), key); base16_encode(output, sizeof(output), key, sizeof(key)); @@ -2709,31 +2714,6 @@ do_dump_config(void) return 0; } -#if defined (WINCE) -int -find_flashcard_path(PWCHAR path, size_t size) -{ - WIN32_FIND_DATA d = {0}; - HANDLE h = NULL; - - if (!path) - return -1; - - h = FindFirstFlashCard(&d); - if (h == INVALID_HANDLE_VALUE) - return -1; - - if (wcslen(d.cFileName) == 0) { - FindClose(h); - return -1; - } - - wcsncpy(path,d.cFileName,size); - FindClose(h); - return 0; -} -#endif - static void init_addrinfo(void) { @@ -2754,43 +2734,47 @@ sandbox_init_filter(void) sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status")); - sandbox_cfg_allow_open_filename_array(&cfg, - get_datadir_fname("cached-certs"), - get_datadir_fname("cached-certs.tmp"), - get_datadir_fname("cached-consensus"), - get_datadir_fname("cached-consensus.tmp"), - get_datadir_fname("unverified-consensus"), - get_datadir_fname("unverified-consensus.tmp"), - get_datadir_fname("unverified-microdesc-consensus"), - get_datadir_fname("unverified-microdesc-consensus.tmp"), - get_datadir_fname("cached-microdesc-consensus"), - get_datadir_fname("cached-microdesc-consensus.tmp"), - get_datadir_fname("cached-microdescs"), - get_datadir_fname("cached-microdescs.tmp"), - get_datadir_fname("cached-microdescs.new"), - get_datadir_fname("cached-microdescs.new.tmp"), - get_datadir_fname("cached-descriptors"), - get_datadir_fname("cached-descriptors.new"), - get_datadir_fname("cached-descriptors.tmp"), - get_datadir_fname("cached-descriptors.new.tmp"), - get_datadir_fname("cached-descriptors.tmp.tmp"), - get_datadir_fname("cached-extrainfo"), - get_datadir_fname("cached-extrainfo.new"), - get_datadir_fname("cached-extrainfo.tmp"), - get_datadir_fname("cached-extrainfo.new.tmp"), - get_datadir_fname("cached-extrainfo.tmp.tmp"), - get_datadir_fname("state.tmp"), - get_datadir_fname("unparseable-desc.tmp"), - get_datadir_fname("unparseable-desc"), - get_datadir_fname("v3-status-votes"), - get_datadir_fname("v3-status-votes.tmp"), - tor_strdup("/dev/srandom"), - tor_strdup("/dev/urandom"), - tor_strdup("/dev/random"), - tor_strdup("/etc/hosts"), - tor_strdup("/proc/meminfo"), - NULL, 0 - ); +#define OPEN(name) \ + sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name)) + +#define OPEN_DATADIR(name) \ + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name)) + +#define OPEN_DATADIR2(name, name2) \ + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname2((name), (name2))) + +#define OPEN_DATADIR_SUFFIX(name, suffix) do { \ + OPEN_DATADIR(name); \ + OPEN_DATADIR(name suffix); \ + } while (0) + +#define OPEN_DATADIR2_SUFFIX(name, name2, suffix) do { \ + OPEN_DATADIR2(name, name2); \ + OPEN_DATADIR2(name, name2 suffix); \ + } while (0) + + OPEN_DATADIR_SUFFIX("cached-certs", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("unverified-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("unverified-microdesc-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-microdesc-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-microdescs", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-microdescs.new", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-descriptors", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-descriptors.new", ".tmp"); + OPEN_DATADIR("cached-descriptors.tmp.tmp"); + OPEN_DATADIR_SUFFIX("cached-extrainfo", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-extrainfo.new", ".tmp"); + OPEN_DATADIR("cached-extrainfo.tmp.tmp"); + OPEN_DATADIR_SUFFIX("state", ".tmp"); + OPEN_DATADIR_SUFFIX("unparseable-desc", ".tmp"); + OPEN_DATADIR_SUFFIX("v3-status-votes", ".tmp"); + OPEN("/dev/srandom"); + OPEN("/dev/urandom"); + OPEN("/dev/random"); + OPEN("/etc/hosts"); + OPEN("/proc/meminfo"); + if (options->ServerDNSResolvConfFile) sandbox_cfg_allow_open_filename(&cfg, tor_strdup(options->ServerDNSResolvConfFile)); @@ -2831,14 +2815,17 @@ sandbox_init_filter(void) RENAME_SUFFIX("unparseable-desc", ".tmp"); RENAME_SUFFIX("v3-status-votes", ".tmp"); - sandbox_cfg_allow_stat_filename_array(&cfg, - get_datadir_fname(NULL), - get_datadir_fname("lock"), - get_datadir_fname("state"), - get_datadir_fname("router-stability"), - get_datadir_fname("cached-extrainfo.new"), - NULL, 0 - ); +#define STAT_DATADIR(name) \ + sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname(name)) + +#define STAT_DATADIR2(name, name2) \ + sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname2((name), (name2))) + + STAT_DATADIR(NULL); + STAT_DATADIR("lock"); + STAT_DATADIR("state"); + STAT_DATADIR("router-stability"); + STAT_DATADIR("cached-extrainfo.new"); { smartlist_t *files = smartlist_new(); @@ -2860,7 +2847,8 @@ sandbox_init_filter(void) sandbox_cfg_allow_rename(&cfg, tor_strdup(tmp_name), tor_strdup(file_name)); /* steals references */ - sandbox_cfg_allow_open_filename_array(&cfg, file_name, tmp_name, NULL); + sandbox_cfg_allow_open_filename(&cfg, file_name); + sandbox_cfg_allow_open_filename(&cfg, tmp_name); }); SMARTLIST_FOREACH(dirs, char *, dir, { /* steals reference */ @@ -2887,38 +2875,28 @@ sandbox_init_filter(void) // orport if (server_mode(get_options())) { - sandbox_cfg_allow_open_filename_array(&cfg, - get_datadir_fname2("keys", "secret_id_key"), - get_datadir_fname2("keys", "secret_onion_key"), - get_datadir_fname2("keys", "secret_onion_key_ntor"), - get_datadir_fname2("keys", "secret_onion_key_ntor.tmp"), - get_datadir_fname2("keys", "secret_id_key.old"), - get_datadir_fname2("keys", "secret_onion_key.old"), - get_datadir_fname2("keys", "secret_onion_key_ntor.old"), - get_datadir_fname2("keys", "secret_onion_key.tmp"), - get_datadir_fname2("keys", "secret_id_key.tmp"), - get_datadir_fname2("stats", "bridge-stats"), - get_datadir_fname2("stats", "bridge-stats.tmp"), - get_datadir_fname2("stats", "dirreq-stats"), - get_datadir_fname2("stats", "dirreq-stats.tmp"), - get_datadir_fname2("stats", "entry-stats"), - get_datadir_fname2("stats", "entry-stats.tmp"), - get_datadir_fname2("stats", "exit-stats"), - get_datadir_fname2("stats", "exit-stats.tmp"), - get_datadir_fname2("stats", "buffer-stats"), - get_datadir_fname2("stats", "buffer-stats.tmp"), - get_datadir_fname2("stats", "conn-stats"), - get_datadir_fname2("stats", "conn-stats.tmp"), - get_datadir_fname("approved-routers"), - get_datadir_fname("fingerprint"), - get_datadir_fname("fingerprint.tmp"), - get_datadir_fname("hashed-fingerprint"), - get_datadir_fname("hashed-fingerprint.tmp"), - get_datadir_fname("router-stability"), - get_datadir_fname("router-stability.tmp"), - tor_strdup("/etc/resolv.conf"), - NULL, 0 - ); + + OPEN_DATADIR2_SUFFIX("keys", "secret_id_key", "tmp"); + OPEN_DATADIR2_SUFFIX("keys", "secret_onion_key", ".tmp"); + OPEN_DATADIR2_SUFFIX("keys", "secret_onion_key_ntor", ".tmp"); + OPEN_DATADIR2("keys", "secret_id_key.old"); + OPEN_DATADIR2("keys", "secret_onion_key.old"); + OPEN_DATADIR2("keys", "secret_onion_key_ntor.old"); + + OPEN_DATADIR2_SUFFIX("stats", "bridge-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "dirreq-stats", ".tmp"); + + OPEN_DATADIR2_SUFFIX("stats", "entry-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "exit-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "buffer-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "conn-stats", ".tmp"); + + OPEN_DATADIR("approved-routers"); + OPEN_DATADIR_SUFFIX("fingerprint", ".tmp"); + OPEN_DATADIR_SUFFIX("hashed-fingerprint", ".tmp"); + OPEN_DATADIR_SUFFIX("router-stability", ".tmp"); + + OPEN("/etc/resolv.conf"); RENAME_SUFFIX("fingerprint", ".tmp"); RENAME_SUFFIX2("keys", "secret_onion_key_ntor", ".tmp"); @@ -2942,12 +2920,9 @@ sandbox_init_filter(void) get_datadir_fname2("keys", "secret_onion_key_ntor"), get_datadir_fname2("keys", "secret_onion_key_ntor.old")); - sandbox_cfg_allow_stat_filename_array(&cfg, - get_datadir_fname("keys"), - get_datadir_fname("stats"), - get_datadir_fname2("stats", "dirreq-stats"), - NULL, 0 - ); + STAT_DATADIR("keys"); + STAT_DATADIR("stats"); + STAT_DATADIR2("stats", "dirreq-stats"); } init_addrinfo(); @@ -2962,31 +2937,6 @@ int tor_main(int argc, char *argv[]) { int result = 0; -#if defined (WINCE) - WCHAR path [MAX_PATH] = {0}; - WCHAR fullpath [MAX_PATH] = {0}; - PWCHAR p = NULL; - FILE* redir = NULL; - FILE* redirdbg = NULL; - - // this is to facilitate debugging by opening - // a file on a folder shared by the wm emulator. - // if no flashcard (real or emulated) is present, - // log files will be written in the root folder - if (find_flashcard_path(path,MAX_PATH) == -1) { - redir = _wfreopen( L"\\stdout.log", L"w", stdout ); - redirdbg = _wfreopen( L"\\stderr.log", L"w", stderr ); - } else { - swprintf(fullpath,L"\\%s\\tor",path); - CreateDirectory(fullpath,NULL); - - swprintf(fullpath,L"\\%s\\tor\\stdout.log",path); - redir = _wfreopen( fullpath, L"w", stdout ); - - swprintf(fullpath,L"\\%s\\tor\\stderr.log",path); - redirdbg = _wfreopen( fullpath, L"w", stderr ); - } -#endif #ifdef _WIN32 /* Call SetProcessDEPPolicy to permanently enable DEP. diff --git a/src/or/microdesc.c b/src/or/microdesc.c index fdb549a9ac..576fed0066 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -57,9 +57,9 @@ microdesc_eq_(microdesc_t *a, microdesc_t *b) HT_PROTOTYPE(microdesc_map, microdesc_t, node, microdesc_hash_, microdesc_eq_); -HT_GENERATE(microdesc_map, microdesc_t, node, +HT_GENERATE2(microdesc_map, microdesc_t, node, microdesc_hash_, microdesc_eq_, 0.6, - malloc, realloc, free); + tor_reallocarray_, tor_free_) /** Write the body of <b>md</b> into <b>f</b>, with appropriate annotations. * On success, return the total number of bytes written, and set @@ -576,6 +576,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) microdesc_wipe_body(md); } } + smartlist_free(wrote); return -1; } diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 890da0ad17..c7bed9b059 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -83,7 +83,11 @@ static consensus_waiting_for_certs_t * before the current consensus becomes invalid. */ static time_t time_to_download_next_consensus[N_CONSENSUS_FLAVORS]; /** Download status for the current consensus networkstatus. */ -static download_status_t consensus_dl_status[N_CONSENSUS_FLAVORS]; +static download_status_t consensus_dl_status[N_CONSENSUS_FLAVORS] = + { + { 0, 0, DL_SCHED_CONSENSUS }, + { 0, 0, DL_SCHED_CONSENSUS }, + }; /** True iff we have logged a warning about this OR's version being older than * listed by the authorities. */ @@ -754,6 +758,9 @@ update_consensus_networkstatus_downloads(time_t now) resource = networkstatus_get_flavor_name(i); + /* Let's make sure we remembered to update consensus_dl_status */ + tor_assert(consensus_dl_status[i].schedule == DL_SCHED_CONSENSUS); + if (!download_status_is_ready(&consensus_dl_status[i], now, options->TestingConsensusMaxDownloadTries)) continue; /* We failed downloading a consensus too recently. */ @@ -1055,7 +1062,6 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b) a->is_valid != b->is_valid || a->is_possible_guard != b->is_possible_guard || a->is_bad_exit != b->is_bad_exit || - a->is_bad_directory != b->is_bad_directory || a->is_hs_dir != b->is_hs_dir || a->version_known != b->version_known; } @@ -1655,7 +1661,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now) if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE) dirserv_set_router_is_running(ri, now); /* then generate and write out status lines for each of them */ - set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0, 0); + set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0); smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs)); } SMARTLIST_FOREACH_END(ri); diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 7b1f338bd4..f37fb49927 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -53,8 +53,8 @@ node_id_eq(const node_t *node1, const node_t *node2) } HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq); -HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq, - 0.6, malloc, realloc, free); +HT_GENERATE2(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq, + 0.6, tor_reallocarray_, tor_free_) /** The global nodelist. */ static nodelist_t *the_nodelist=NULL; @@ -241,7 +241,6 @@ nodelist_set_consensus(networkstatus_t *ns) node->is_stable = rs->is_stable; node->is_possible_guard = rs->is_possible_guard; node->is_exit = rs->is_exit; - node->is_bad_directory = rs->is_bad_directory; node->is_bad_exit = rs->is_bad_exit; node->is_hs_dir = rs->is_hs_dir; node->ipv6_preferred = 0; @@ -267,8 +266,7 @@ nodelist_set_consensus(networkstatus_t *ns) node->is_valid = node->is_running = node->is_hs_dir = node->is_fast = node->is_stable = node->is_possible_guard = node->is_exit = - node->is_bad_exit = node->is_bad_directory = - node->ipv6_preferred = 0; + node->is_bad_exit = node->ipv6_preferred = 0; } } } SMARTLIST_FOREACH_END(node); @@ -474,8 +472,8 @@ nodelist_assert_ok(void) /** Return a list of a node_t * for every node we know about. The caller * MUST NOT modify the list. (You can set and clear flags in the nodes if * you must, but you must not add or remove nodes.) */ -smartlist_t * -nodelist_get_list(void) +MOCK_IMPL(smartlist_t *, +nodelist_get_list,(void)) { init_nodelist(); return the_nodelist->nodes; @@ -517,8 +515,8 @@ node_get_by_hex_id(const char *hex_id) * the corresponding node_t, or NULL if none exists. Warn the user if * <b>warn_if_unnamed</b> is set, and they have specified a router by * nickname, but the Named flag isn't set for that router. */ -const node_t * -node_get_by_nickname(const char *nickname, int warn_if_unnamed) +MOCK_IMPL(const node_t *, +node_get_by_nickname,(const char *nickname, int warn_if_unnamed)) { const node_t *node; if (!the_nodelist) diff --git a/src/or/nodelist.h b/src/or/nodelist.h index 8e719e012d..cb54cecf1d 100644 --- a/src/or/nodelist.h +++ b/src/or/nodelist.h @@ -31,7 +31,8 @@ smartlist_t *nodelist_find_nodes_with_microdesc(const microdesc_t *md); void nodelist_free_all(void); void nodelist_assert_ok(void); -const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed); +MOCK_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unnamed)); void node_get_verbose_nickname(const node_t *node, char *verbose_name_out); void node_get_verbose_nickname_by_id(const char *id_digest, @@ -60,7 +61,7 @@ void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out); void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out); int node_has_curve25519_onion_key(const node_t *node); -smartlist_t *nodelist_get_list(void); +MOCK_DECL(smartlist_t *, nodelist_get_list, (void)); /* Temporary during transition to multiple addresses. */ void node_get_addr(const node_t *node, tor_addr_t *addr_out); diff --git a/src/or/ntmain.h b/src/or/ntmain.h index d3027936cd..d09a413aee 100644 --- a/src/or/ntmain.h +++ b/src/or/ntmain.h @@ -13,10 +13,8 @@ #define TOR_NTMAIN_H #ifdef _WIN32 -#if !defined (WINCE) #define NT_SERVICE #endif -#endif #ifdef NT_SERVICE int nt_service_parse_options(int argc, char **argv, int *should_exit); diff --git a/src/or/or.h b/src/or/or.h index 1609587717..54cee46ee3 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -14,7 +14,7 @@ #include "orconfig.h" -#ifdef __COVERITY__ +#if defined(__clang_analyzer__) || defined(__COVERITY__) /* If we're building for a static analysis, turn on all the off-by-default * features. */ #ifndef INSTRUMENT_DOWNLOADS @@ -2139,8 +2139,6 @@ typedef struct routerstatus_t { * choice as an entry guard. */ unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for * an exit node. */ - unsigned int is_bad_directory:1; /**< Do we think this directory is junky, - * underpowered, or otherwise useless? */ unsigned int is_hs_dir:1; /**< True iff this router is a v2-or-later hidden * service directory. */ /** True iff we know version info for this router. (i.e., a "v" entry was @@ -2151,9 +2149,6 @@ typedef struct routerstatus_t { /** True iff this router is a version that, if it caches directory info, * we can get microdescriptors from. */ unsigned int version_supports_microdesc_cache:1; - /** True iff this router is a version that allows DATA cells to arrive on - * a stream before it has sent a CONNECTED cell. */ - unsigned int version_supports_optimistic_data:1; /** True iff this router has a version that allows it to accept EXTEND2 * cells */ unsigned int version_supports_extend2_cells:1; @@ -2300,8 +2295,6 @@ typedef struct node_t { unsigned int is_exit:1; /**< Do we think this is an OK exit? */ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked, * or otherwise nasty? */ - unsigned int is_bad_directory:1; /**< Do we think this directory is junky, - * underpowered, or otherwise useless? */ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service * directory according to the authorities. */ @@ -2865,8 +2858,8 @@ typedef struct circuit_t { /** Unique ID for measuring tunneled network status requests. */ uint64_t dirreq_id; - /** Next circuit in linked list of all circuits (global_circuitlist). */ - TOR_LIST_ENTRY(circuit_t) head; + /** Index in smartlist of all circuits (global_circuitlist). */ + int global_circuitlist_idx; /** Next circuit in the doubly-linked ring of circuits waiting to add * cells to n_conn. NULL if we have no cells pending, or if we're not @@ -3403,6 +3396,8 @@ typedef struct { int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which * each log message occurs? */ + int TruncateLogFile; /**< Boolean: Should we truncate the log file + before we start writing? */ char *DebugLogFile; /**< Where to send verbose log messages. */ char *DataDirectory; /**< OR only: where to store long-term data. */ @@ -3531,8 +3526,6 @@ typedef struct { int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */ int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory * for version 3 directories? */ - int NamingAuthoritativeDir; /**< Boolean: is this an authoritative directory - * that's willing to bind names? */ int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative * directory that's willing to recommend * versions? */ @@ -3742,8 +3735,6 @@ typedef struct { config_line_t *NodeFamilies; /**< List of config lines for * node families */ smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */ - config_line_t *AuthDirBadDir; /**< Address policy for descriptors to - * mark as bad dir mirrors. */ config_line_t *AuthDirBadExit; /**< Address policy for descriptors to * mark as bad exits. */ config_line_t *AuthDirReject; /**< Address policy for descriptors to @@ -3752,23 +3743,18 @@ typedef struct { * never mark as valid. */ /** @name AuthDir...CC * - * Lists of country codes to mark as BadDir, BadExit, or Invalid, or to + * Lists of country codes to mark as BadExit, or Invalid, or to * reject entirely. * * @{ */ - smartlist_t *AuthDirBadDirCCs; smartlist_t *AuthDirBadExitCCs; smartlist_t *AuthDirInvalidCCs; smartlist_t *AuthDirRejectCCs; /**@}*/ - int AuthDirListBadDirs; /**< True iff we should list bad dirs, - * and vote for all other dir mirrors as good. */ int AuthDirListBadExits; /**< True iff we should list bad exits, * and vote for all other exits as good. */ - int AuthDirRejectUnlisted; /**< Boolean: do we reject all routers that - * aren't named in our fingerprint file? */ int AuthDirMaxServersPerAddr; /**< Do not permit more than this * number of servers per IP address. */ int AuthDirMaxServersPerAuthAddr; /**< Do not permit more than this @@ -3789,6 +3775,11 @@ typedef struct { uint64_t AccountingMax; /**< How many bytes do we allow per accounting * interval before hibernation? 0 for "never * hibernate." */ + /** How do we determine when our AccountingMax has been reached? + * "max" for when in or out reaches AccountingMax + * "sum for when in plus out reaches AccountingMax */ + char *AccountingRule_option; + enum { ACCT_MAX, ACCT_SUM } AccountingRule; /** Base64-encoded hash of accepted passwords for the control system. */ config_line_t *HashedControlPassword; @@ -3921,8 +3912,11 @@ typedef struct { * instead of a hostname. */ int WarnUnsafeSocks; - /** If true, the user wants us to collect statistics on clients + /** If true, we're configured to collect statistics on clients * requesting network statuses from us as directory. */ + int DirReqStatistics_option; + /** Internal variable to remember whether we're actually acting on + * DirReqStatistics_option -- yes if it's set and we're a server, else no. */ int DirReqStatistics; /** If true, the user wants us to collect statistics on port usage. */ diff --git a/src/or/policies.c b/src/or/policies.c index 8a91509a77..7090eda2c4 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -29,9 +29,6 @@ static smartlist_t *authdir_reject_policy = NULL; * to be marked as valid in our networkstatus. */ static smartlist_t *authdir_invalid_policy = NULL; /** Policy that addresses for incoming router descriptors must <b>not</b> - * match in order to not be marked as BadDirectory. */ -static smartlist_t *authdir_baddir_policy = NULL; -/** Policy that addresses for incoming router descriptors must <b>not</b> * match in order to not be marked as BadExit. */ static smartlist_t *authdir_badexit_policy = NULL; @@ -65,6 +62,13 @@ static const char *private_nets[] = { NULL }; +static int policies_parse_exit_policy_internal(config_line_t *cfg, + smartlist_t **dest, + int ipv6_exit, + int rejectprivate, + uint32_t local_address, + int add_default_policy); + /** Replace all "private" entries in *<b>policy</b> with their expanded * equivalents. */ void @@ -400,17 +404,6 @@ authdir_policy_valid_address(uint32_t addr, uint16_t port) return !addr_is_in_cc_list(addr, get_options()->AuthDirInvalidCCs); } -/** Return 1 if <b>addr</b>:<b>port</b> should be marked as a bad dir, - * based on <b>authdir_baddir_policy</b>. Else return 0. - */ -int -authdir_policy_baddir_address(uint32_t addr, uint16_t port) -{ - if (! addr_policy_permits_address(addr, port, authdir_baddir_policy)) - return 1; - return addr_is_in_cc_list(addr, get_options()->AuthDirBadDirCCs); -} - /** Return 1 if <b>addr</b>:<b>port</b> should be marked as a bad exit, * based on <b>authdir_badexit_policy</b>. Else return 0. */ @@ -437,11 +430,9 @@ validate_addr_policies(const or_options_t *options, char **msg) smartlist_t *addr_policy=NULL; *msg = NULL; - if (policies_parse_exit_policy(options->ExitPolicy, &addr_policy, - options->IPv6Exit, - options->ExitPolicyRejectPrivate, 0, - !options->BridgeRelay)) + if (policies_parse_exit_policy_from_options(options,0,&addr_policy)) { REJECT("Error in ExitPolicy entry."); + } /* The rest of these calls *append* to addr_policy. So don't actually * use the results for anything other than checking if they parse! */ @@ -455,9 +446,6 @@ validate_addr_policies(const or_options_t *options, char **msg) if (parse_addr_policy(options->AuthDirInvalid, &addr_policy, ADDR_POLICY_REJECT)) REJECT("Error in AuthDirInvalid entry."); - if (parse_addr_policy(options->AuthDirBadDir, &addr_policy, - ADDR_POLICY_REJECT)) - REJECT("Error in AuthDirBadDir entry."); if (parse_addr_policy(options->AuthDirBadExit, &addr_policy, ADDR_POLICY_REJECT)) REJECT("Error in AuthDirBadExit entry."); @@ -535,9 +523,6 @@ policies_parse_from_options(const or_options_t *options) if (load_policy_from_option(options->AuthDirInvalid, "AuthDirInvalid", &authdir_invalid_policy, ADDR_POLICY_REJECT) < 0) ret = -1; - if (load_policy_from_option(options->AuthDirBadDir, "AuthDirBadDir", - &authdir_baddir_policy, ADDR_POLICY_REJECT) < 0) - ret = -1; if (load_policy_from_option(options->AuthDirBadExit, "AuthDirBadExit", &authdir_badexit_policy, ADDR_POLICY_REJECT) < 0) ret = -1; @@ -629,8 +614,8 @@ policy_hash(const policy_map_ent_t *ent) HT_PROTOTYPE(policy_map, policy_map_ent_t, node, policy_hash, policy_eq) -HT_GENERATE(policy_map, policy_map_ent_t, node, policy_hash, - policy_eq, 0.6, malloc, realloc, free) +HT_GENERATE2(policy_map, policy_map_ent_t, node, policy_hash, + policy_eq, 0.6, tor_reallocarray_, tor_free_) /** Given a pointer to an addr_policy_t, return a copy of the pointer to the * "canonical" copy of that addr_policy_t; the canonical copy is a single @@ -769,9 +754,9 @@ compare_unknown_tor_addr_to_addr_policy(uint16_t port, * We could do better by assuming that some ranges never match typical * addresses (127.0.0.1, and so on). But we'll try this for now. */ -addr_policy_result_t -compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port, - const smartlist_t *policy) +MOCK_IMPL(addr_policy_result_t, +compare_tor_addr_to_addr_policy,(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy)) { if (!policy) { /* no policy? accept all. */ @@ -968,11 +953,12 @@ exit_policy_remove_redundancies(smartlist_t *dest) * the functions used to parse the exit policy from a router descriptor, * see router_add_exit_policy. */ -int -policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, - int ipv6_exit, - int rejectprivate, uint32_t local_address, - int add_default_policy) +static int +policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest, + int ipv6_exit, + int rejectprivate, + uint32_t local_address, + int add_default_policy) { if (!ipv6_exit) { append_exit_policy_string(dest, "reject *6:*"); @@ -998,6 +984,68 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, return 0; } +/** Parse exit policy in <b>cfg</b> into <b>dest</b> smartlist. + * + * Add entry that rejects all IPv6 destinations unless + * <b>EXIT_POLICY_IPV6_ENABLED</b> bit is set in <b>options</b> bitmask. + * + * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>, + * do add entry that rejects all destinations in private subnetwork + * Tor is running in. + * + * Respectively, if <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set, add + * default exit policy entries to <b>result</b> smartlist. + */ +int +policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, + exit_policy_parser_cfg_t options, + uint32_t local_address) +{ + int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0; + int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0; + int add_default = (options & EXIT_POLICY_ADD_DEFAULT) ? 1 : 0; + + return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled, + reject_private, + local_address, + add_default); +} + +/** Parse <b>ExitPolicy</b> member of <b>or_options</b> into <b>result</b> + * smartlist. + * If <b>or_options->IPv6Exit</b> is false, add an entry that + * rejects all IPv6 destinations. + * + * If <b>or_options->ExitPolicyRejectPrivate</b> is true, add entry that + * rejects all destinations in the private subnetwork of machine Tor + * instance is running in. + * + * If <b>or_options->BridgeRelay</b> is false, add entries of default + * Tor exit policy into <b>result</b> smartlist. + */ +int +policies_parse_exit_policy_from_options(const or_options_t *or_options, + uint32_t local_address, + smartlist_t **result) +{ + exit_policy_parser_cfg_t parser_cfg = 0; + + if (or_options->IPv6Exit) { + parser_cfg |= EXIT_POLICY_IPV6_ENABLED; + } + + if (or_options->ExitPolicyRejectPrivate) { + parser_cfg |= EXIT_POLICY_REJECT_PRIVATE; + } + + if (!or_options->BridgeRelay) { + parser_cfg |= EXIT_POLICY_ADD_DEFAULT; + } + + return policies_parse_exit_policy(or_options->ExitPolicy,result, + parser_cfg,local_address); +} + /** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating * *<b>dest</b> as needed. */ void @@ -1334,9 +1382,9 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) * The summary will either be an "accept" plus a comma-separated list of port * ranges or a "reject" plus port-ranges, depending on which is shorter. * - * If no exits are allowed at all then NULL is returned, if no ports - * are blocked instead of "reject " we return "accept 1-65535" (this - * is an exception to the shorter-representation-wins rule). + * If no exits are allowed at all then "reject 1-65535" is returned. If no + * ports are blocked instead of "reject " we return "accept 1-65535". (These + * are an exception to the shorter-representation-wins rule). */ char * policy_summarize(smartlist_t *policy, sa_family_t family) @@ -1766,8 +1814,6 @@ policies_free_all(void) authdir_reject_policy = NULL; addr_policy_list_free(authdir_invalid_policy); authdir_invalid_policy = NULL; - addr_policy_list_free(authdir_baddir_policy); - authdir_baddir_policy = NULL; addr_policy_list_free(authdir_badexit_policy); authdir_badexit_policy = NULL; diff --git a/src/or/policies.h b/src/or/policies.h index 91ac427492..0b47b761ec 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -18,6 +18,12 @@ */ #define POLICY_BUF_LEN 72 +#define EXIT_POLICY_IPV6_ENABLED (1 << 0) +#define EXIT_POLICY_REJECT_PRIVATE (1 << 1) +#define EXIT_POLICY_ADD_DEFAULT (1 << 2) + +typedef int exit_policy_parser_cfg_t; + int firewall_is_fascist_or(void); int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port); int fascist_firewall_allows_or(const routerinfo_t *ri); @@ -27,7 +33,6 @@ int dir_policy_permits_address(const tor_addr_t *addr); int socks_policy_permits_address(const tor_addr_t *addr); int authdir_policy_permits_address(uint32_t addr, uint16_t port); int authdir_policy_valid_address(uint32_t addr, uint16_t port); -int authdir_policy_baddir_address(uint32_t addr, uint16_t port); int authdir_policy_badexit_address(uint32_t addr, uint16_t port); int validate_addr_policies(const or_options_t *options, char **msg); @@ -37,16 +42,24 @@ int policies_parse_from_options(const or_options_t *options); addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent); int cmp_addr_policies(smartlist_t *a, smartlist_t *b); -addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr, - uint16_t port, const smartlist_t *policy); +MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, const node_t *node); +/* int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, int ipv6exit, int rejectprivate, uint32_t local_address, int add_default_policy); +*/ +int policies_parse_exit_policy_from_options(const or_options_t *or_options, + uint32_t local_address, + smartlist_t **result); +int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, + exit_policy_parser_cfg_t options, + uint32_t local_address); void policies_exit_policy_append_reject_star(smartlist_t **dest); void addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *addr); diff --git a/src/or/reasons.c b/src/or/reasons.c index 750e89bbe7..1a53a93d88 100644 --- a/src/or/reasons.c +++ b/src/or/reasons.c @@ -367,7 +367,7 @@ circuit_end_reason_to_control_string(int reason) } } -/** Return a string corresponding to a SOCKS4 reponse code. */ +/** Return a string corresponding to a SOCKS4 response code. */ const char * socks4_response_code_to_string(uint8_t code) { @@ -385,7 +385,7 @@ socks4_response_code_to_string(uint8_t code) } } -/** Return a string corresponding to a SOCKS5 reponse code. */ +/** Return a string corresponding to a SOCKS5 response code. */ const char * socks5_response_code_to_string(uint8_t code) { diff --git a/src/or/relay.c b/src/or/relay.c index 4d71157db8..d97c84fb07 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -2328,15 +2328,15 @@ packed_cell_free(packed_cell_t *cell) void dump_cell_pool_usage(int severity) { - circuit_t *c; int n_circs = 0; int n_cells = 0; - TOR_LIST_FOREACH(c, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) { n_cells += c->n_chan_cells.n; if (!CIRCUIT_IS_ORIGIN(c)) n_cells += TO_OR_CIRCUIT(c)->p_chan_cells.n; ++n_circs; } + SMARTLIST_FOREACH_END(c); tor_log(severity, LD_MM, "%d cells allocated on %d circuits. %d cells leaked.", n_cells, n_circs, (int)total_cells_allocated - n_cells); @@ -2439,6 +2439,7 @@ cell_queues_check_size(void) { size_t alloc = cell_queues_get_total_allocation(); alloc += buf_get_total_allocation(); + alloc += tor_zlib_get_total_allocation(); if (alloc >= get_options()->MaxMemInQueues) { circuits_handle_oom(alloc); return 1; diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 19a8cef1bf..bc34695bc0 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -376,9 +376,8 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ) static void rend_client_close_other_intros(const char *onion_address) { - circuit_t *c; /* abort parallel intro circs, if any */ - TOR_LIST_FOREACH(c, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) { if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) && !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { @@ -393,6 +392,7 @@ rend_client_close_other_intros(const char *onion_address) } } } + SMARTLIST_FOREACH_END(c); } /** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell. diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index a664b5d501..269cd65679 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -155,7 +155,7 @@ rend_compute_v2_desc_id(char *desc_id_out, const char *service_id, } /* Calculate current time-period. */ time_period = get_time_period(now, 0, service_id_binary); - /* Calculate secret-id-part = h(time-period + replica). */ + /* Calculate secret-id-part = h(time-period | replica). */ get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie, replica); /* Calculate descriptor ID. */ @@ -528,7 +528,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, return -1; } /* Base64-encode introduction points. */ - ipos_base64 = tor_malloc_zero(ipos_len * 2); + ipos_base64 = tor_calloc(ipos_len, 2); if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len)<0) { log_warn(LD_REND, "Could not encode introduction point string to " "base64. length=%d", (int)ipos_len); @@ -556,7 +556,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, char desc_digest[DIGEST_LEN]; rend_encoded_v2_service_descriptor_t *enc = tor_malloc_zero(sizeof(rend_encoded_v2_service_descriptor_t)); - /* Calculate secret-id-part = h(time-period + cookie + replica). */ + /* Calculate secret-id-part = h(time-period | cookie | replica). */ get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie, k); base32_encode(secret_id_part_base32, sizeof(secret_id_part_base32), diff --git a/src/or/rendmid.c b/src/or/rendmid.c index d89cdf6bed..1bcd17bc44 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -188,7 +188,7 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, "Unable to send INTRODUCE2 cell to Tor client."); goto err; } - /* And sent an ack down Alice's circuit. Empty body means succeeded. */ + /* And send an ack down Alice's circuit. Empty body means succeeded. */ if (relay_send_command_from_edge(0,TO_CIRCUIT(circ), RELAY_COMMAND_INTRODUCE_ACK, NULL,0,NULL)) { @@ -199,7 +199,7 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, return 0; err: - /* Send the client an NACK */ + /* Send the client a NACK */ nak_body[0] = 1; if (relay_send_command_from_edge(0,TO_CIRCUIT(circ), RELAY_COMMAND_INTRODUCE_ACK, diff --git a/src/or/rendservice.c b/src/or/rendservice.c index a7c1e32f15..31b612bb26 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -524,7 +524,6 @@ rend_config_services(const or_options_t *options, int validate_only) * other ones. */ if (old_service_list && !validate_only) { smartlist_t *surviving_services = smartlist_new(); - circuit_t *circ; /* Copy introduction points to new services. */ /* XXXX This is O(n^2), but it's only called on reconfigure, so it's @@ -544,7 +543,7 @@ rend_config_services(const or_options_t *options, int validate_only) /* XXXX it would be nicer if we had a nicer abstraction to use here, * so we could just iterate over the list of services to close, but * once again, this isn't critical-path code. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN && (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -569,6 +568,7 @@ rend_config_services(const or_options_t *options, int validate_only) /* XXXX Is there another reason we should use here? */ } } + SMARTLIST_FOREACH_END(circ); smartlist_free(surviving_services); SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr, rend_service_free(ptr)); @@ -1446,10 +1446,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, memwipe(hexcookie, 0, sizeof(hexcookie)); /* Free the parsed cell */ - if (parsed_req) { - rend_service_free_intro(parsed_req); - parsed_req = NULL; - } + rend_service_free_intro(parsed_req); /* Free rp if we must */ if (need_rp_free) extend_info_free(rp); @@ -1539,7 +1536,6 @@ void rend_service_free_intro(rend_intro_cell_t *request) { if (!request) { - log_info(LD_BUG, "rend_service_free_intro() called with NULL request!"); return; } @@ -1648,8 +1644,9 @@ rend_service_begin_parse_intro(const uint8_t *request, goto done; err: - if (rv) rend_service_free_intro(rv); + rend_service_free_intro(rv); rv = NULL; + if (err_msg_out && !err_msg) { tor_asprintf(&err_msg, "unknown INTRODUCE%d error", @@ -1757,7 +1754,7 @@ rend_service_parse_intro_for_v2( /* * We accept version 3 too so that the v3 parser can call this with - * and adjusted buffer for the latter part of a v3 cell, which is + * an adjusted buffer for the latter part of a v3 cell, which is * identical to a v2 cell. */ if (!(intro->version == 2 || @@ -1985,7 +1982,7 @@ rend_service_decrypt_intro( char service_id[REND_SERVICE_ID_LEN_BASE32+1]; ssize_t key_len; uint8_t buf[RELAY_PAYLOAD_SIZE]; - int result, status = 0; + int result, status = -1; if (!intro || !key) { if (err_msg_out) { @@ -2064,6 +2061,8 @@ rend_service_decrypt_intro( intro->plaintext = tor_malloc(intro->plaintext_len); memcpy(intro->plaintext, buf, intro->plaintext_len); + status = 0; + goto done; err: @@ -2072,7 +2071,6 @@ rend_service_decrypt_intro( "unknown INTRODUCE%d error decrypting encrypted part", intro ? (int)(intro->type) : -1); } - if (status >= 0) status = -1; done: if (err_msg_out) *err_msg_out = err_msg; @@ -2099,7 +2097,7 @@ rend_service_parse_intro_plaintext( char *err_msg = NULL; ssize_t ver_specific_len, ver_invariant_len; uint8_t version; - int status = 0; + int status = -1; if (!intro) { if (err_msg_out) { @@ -2158,6 +2156,7 @@ rend_service_parse_intro_plaintext( (int)(intro->type), (long)(intro->plaintext_len)); status = -6; + goto err; } else { memcpy(intro->rc, intro->plaintext + ver_specific_len, @@ -2170,6 +2169,7 @@ rend_service_parse_intro_plaintext( /* Flag it as being fully parsed */ intro->parsed = 1; + status = 0; goto done; err: @@ -2178,7 +2178,6 @@ rend_service_parse_intro_plaintext( "unknown INTRODUCE%d error parsing encrypted part", intro ? (int)(intro->type) : -1); } - if (status >= 0) status = -1; done: if (err_msg_out) *err_msg_out = err_msg; @@ -2384,8 +2383,7 @@ static int count_established_intro_points(const char *query) { int num_ipos = 0; - circuit_t *circ; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN && (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -2396,6 +2394,7 @@ count_established_intro_points(const char *query) num_ipos++; } } + SMARTLIST_FOREACH_END(circ); return num_ipos; } diff --git a/src/or/rephist.c b/src/or/rephist.c index 72de54c0c9..cd92b0adc5 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1998,12 +1998,9 @@ void rep_hist_exit_stats_init(time_t now) { start_of_exit_stats_interval = now; - exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS * - sizeof(uint64_t)); - exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS * - sizeof(uint64_t)); - exit_streams = tor_malloc_zero(EXIT_STATS_NUM_PORTS * - sizeof(uint32_t)); + exit_bytes_read = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t)); + exit_bytes_written = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t)); + exit_streams = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint32_t)); } /** Reset counters for exit port statistics. */ @@ -2474,7 +2471,6 @@ rep_hist_format_buffer_stats(time_t now) time_t rep_hist_buffer_stats_write(time_t now) { - circuit_t *circ; char *str = NULL; if (!start_of_buffer_stats_interval) @@ -2483,9 +2479,10 @@ rep_hist_buffer_stats_write(time_t now) goto done; /* Not ready to write */ /* Add open circuits to the history. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { rep_hist_buffer_stats_add_circ(circ, now); } + SMARTLIST_FOREACH_END(circ); /* Generate history string. */ str = rep_hist_format_buffer_stats(now); @@ -2572,7 +2569,7 @@ rep_hist_format_desc_stats(time_t now) size = digestmap_size(served_descs); if (size > 0) { - vals = tor_malloc(size * sizeof(int)); + vals = tor_calloc(size, sizeof(int)); for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); iter = digestmap_iter_next(served_descs, iter)) { @@ -2727,8 +2724,8 @@ bidi_map_ent_hash(const bidi_map_entry_t *entry) HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, bidi_map_ent_eq); -HT_GENERATE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, - bidi_map_ent_eq, 0.6, malloc, realloc, free); +HT_GENERATE2(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, + bidi_map_ent_eq, 0.6, tor_reallocarray_, tor_free_) /* DOCDOC bidi_map_free */ static void diff --git a/src/or/router.c b/src/or/router.c index 2cdbb0c8bb..dbe985ac78 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -911,9 +911,8 @@ init_keys(void) const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ - if (dirserv_add_own_fingerprint(options->Nickname, - get_server_identity_key())) { - log_err(LD_GENERAL,"Error adding own fingerprint to approved set"); + if (dirserv_add_own_fingerprint(get_server_identity_key())) { + log_err(LD_GENERAL,"Error adding own fingerprint to set of relays"); return -1; } if (mydesc) { @@ -1081,6 +1080,7 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) * they're confused or to get statistics. */ int interval_length = accounting_get_interval_length(); uint32_t effective_bw = get_effective_bwrate(options); + uint64_t acc_bytes; if (!interval_length) { log_warn(LD_BUG, "An accounting interval is not allowed to be zero " "seconds long. Raising to 1."); @@ -1091,8 +1091,12 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) "accounting interval length %d", effective_bw, U64_PRINTF_ARG(options->AccountingMax), interval_length); + + acc_bytes = options->AccountingMax; + if (get_options()->AccountingRule == ACCT_SUM) + acc_bytes /= 2; if (effective_bw >= - options->AccountingMax / interval_length) { + acc_bytes / interval_length) { new_choice = 0; reason = "AccountingMax enabled"; } @@ -1856,10 +1860,8 @@ router_rebuild_descriptor(int force) /* DNS is screwed up; don't claim to be an exit. */ policies_exit_policy_append_reject_star(&ri->exit_policy); } else { - policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy, - options->IPv6Exit, - options->ExitPolicyRejectPrivate, - ri->addr, !options->BridgeRelay); + policies_parse_exit_policy_from_options(options,ri->addr, + &ri->exit_policy); } ri->policy_is_reject_star = policy_is_reject_star(ri->exit_policy, AF_INET) && @@ -1879,7 +1881,7 @@ router_rebuild_descriptor(int force) family = smartlist_new(); ri->declared_family = smartlist_new(); smartlist_split_string(family, options->MyFamily, ",", - SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); SMARTLIST_FOREACH_BEGIN(family, char *, name) { const node_t *member; if (!strcasecmp(name, options->Nickname)) @@ -2063,7 +2065,8 @@ mark_my_descriptor_dirty(const char *reason) } /** How frequently will we republish our descriptor because of large (factor - * of 2) shifts in estimated bandwidth? */ + * of 2) shifts in estimated bandwidth? Note: We don't use this constant + * if our previous bandwidth estimate was exactly 0. */ #define MAX_BANDWIDTH_CHANGE_FREQ (20*60) /** Check whether bandwidth has changed a lot since the last time we announced @@ -2081,7 +2084,7 @@ check_descriptor_bandwidth_changed(time_t now) if ((prev != cur && (!prev || !cur)) || cur > prev*2 || cur < prev/2) { - if (last_changed+MAX_BANDWIDTH_CHANGE_FREQ < now) { + if (last_changed+MAX_BANDWIDTH_CHANGE_FREQ < now || !prev) { log_info(LD_GENERAL, "Measured bandwidth has changed; rebuilding descriptor."); mark_my_descriptor_dirty("bandwidth has changed"); @@ -2371,7 +2374,8 @@ router_dump_router_to_string(routerinfo_t *router, has_extra_info_digest ? "extra-info-digest " : "", has_extra_info_digest ? extra_info_digest : "", has_extra_info_digest ? "\n" : "", - options->DownloadExtraInfo ? "caches-extra-info\n" : "", + (options->DownloadExtraInfo || options->V3AuthoritativeDir) ? + "caches-extra-info\n" : "", onion_pkey, identity_pkey, family_line, we_are_hibernating() ? "hibernating 1\n" : "", diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 32cbe19379..22489a4476 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -448,9 +448,10 @@ trusted_dirs_flush_certs_to_disk(void) trusted_dir_servers_certs_changed = 0; } -/** Remove all v3 authority certificates that have been superseded for more - * than 48 hours. (If the most recent cert was published more than 48 hours - * ago, then we aren't going to get any consensuses signed with older +/** Remove all expired v3 authority certificates that have been superseded for + * more than 48 hours or, if not expired, that were published more than 7 days + * before being superseded. (If the most recent cert was published more than 48 + * hours ago, then we aren't going to get any consensuses signed with older * keys.) */ static void trusted_dirs_remove_old_certs(void) @@ -474,6 +475,8 @@ trusted_dirs_remove_old_certs(void) time_t cert_published; if (newest == cert) continue; + /* resolve spurious clang shallow analysis null pointer errors */ + tor_assert(cert); expired = now > cert->expires; cert_published = cert->cache_info.published_on; /* Store expired certs for 48 hours after a newer arrives; @@ -488,6 +491,7 @@ trusted_dirs_remove_old_certs(void) } SMARTLIST_FOREACH_END(cert); } } DIGESTMAP_FOREACH_END; +#undef DEAD_CERT_LIFETIME #undef OLD_CERT_LIFETIME trusted_dirs_flush_certs_to_disk(); @@ -1438,7 +1442,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) /* Find all the running dirservers we know about. */ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { - int is_trusted; + int is_trusted, is_trusted_extrainfo; int is_overloaded; tor_addr_t addr; const routerstatus_t *status = node->rs; @@ -1448,13 +1452,13 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) if (!node->is_running || !status->dir_port || !node->is_valid) continue; - if (node->is_bad_directory) - continue; if (requireother && router_digest_is_me(node->identity)) continue; is_trusted = router_digest_is_trusted_dir(node->identity); + is_trusted_extrainfo = router_digest_is_trusted_dir_type( + node->identity, EXTRAINFO_DIRINFO); if ((type & EXTRAINFO_DIRINFO) && - !router_supports_extrainfo(node->identity, 0)) + !router_supports_extrainfo(node->identity, is_trusted_extrainfo)) continue; if ((type & MICRODESC_DIRINFO) && !is_trusted && !node->rs->version_supports_microdesc_cache) @@ -1530,7 +1534,7 @@ dirserver_choose_by_weight(const smartlist_t *servers, double authority_weight) u64_dbl_t *weights; const dir_server_t *ds; - weights = tor_malloc(sizeof(u64_dbl_t) * n); + weights = tor_calloc(sizeof(u64_dbl_t), n); for (i = 0; i < n; ++i) { ds = smartlist_get(servers, i); weights[i].dbl = ds->weight; @@ -1802,15 +1806,16 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, uint64_t *total_out) { double total = 0.0; - double scale_factor; + double scale_factor = 0.0; int i; /* big, but far away from overflowing an int64_t */ -#define SCALE_TO_U64_MAX (INT64_MAX / 4) +#define SCALE_TO_U64_MAX ((int64_t) (INT64_MAX / 4)) for (i = 0; i < n_entries; ++i) total += entries[i].dbl; - scale_factor = SCALE_TO_U64_MAX / total; + if (total > 0.0) + scale_factor = SCALE_TO_U64_MAX / total; for (i = 0; i < n_entries; ++i) entries[i].u64 = tor_llround(entries[i].dbl * scale_factor); @@ -2038,7 +2043,7 @@ compute_weighted_bandwidths(const smartlist_t *sl, Web /= weight_scale; Wdb /= weight_scale; - bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl)); + bandwidths = tor_calloc(sizeof(u64_dbl_t), smartlist_len(sl)); // Cycle through smartlist and total the bandwidth. SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { @@ -2185,7 +2190,7 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl, /* First count the total bandwidth weight, and make a list * of each value. We use UINT64_MAX to indicate "unknown". */ - bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl)); + bandwidths = tor_calloc(sizeof(u64_dbl_t), smartlist_len(sl)); fast_bits = bitarray_init_zero(smartlist_len(sl)); exit_bits = bitarray_init_zero(smartlist_len(sl)); guard_bits = bitarray_init_zero(smartlist_len(sl)); @@ -3292,6 +3297,14 @@ routerlist_reset_warnings(void) networkstatus_reset_warnings(); } +/** Return 1 if the signed descriptor of this router is older than + * <b>seconds</b> seconds. Otherwise return 0. */ +MOCK_IMPL(int, +router_descriptor_is_older_than,(const routerinfo_t *router, int seconds)) +{ + return router->cache_info.published_on < time(NULL) - seconds; +} + /** Add <b>router</b> to the routerlist, if we don't already have it. Replace * older entries (if any) with the same key. Note: Callers should not hold * their pointers to <b>router</b> if this function fails; <b>router</b> @@ -3461,7 +3474,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, } if (!in_consensus && from_cache && - router->cache_info.published_on < time(NULL) - OLD_ROUTER_DESC_MAX_AGE) { + router_descriptor_is_older_than(router, OLD_ROUTER_DESC_MAX_AGE)) { *msg = "Router descriptor was really old."; routerinfo_free(router); return ROUTER_WAS_NOT_NEW; @@ -3569,9 +3582,9 @@ routerlist_remove_old_cached_routers_with_id(time_t now, n_extra = n - mdpr; } - lifespans = tor_malloc_zero(sizeof(struct duration_idx_t)*n); - rmv = tor_malloc_zero(sizeof(uint8_t)*n); - must_keep = tor_malloc_zero(sizeof(uint8_t)*n); + lifespans = tor_calloc(sizeof(struct duration_idx_t), n); + rmv = tor_calloc(sizeof(uint8_t), n); + must_keep = tor_calloc(sizeof(uint8_t), n); /* Set lifespans to contain the lifespan and index of each server. */ /* Set rmv[i-lo]=1 if we're going to remove a server for being too old. */ for (i = lo; i <= hi; ++i) { diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 6e2f2eaea0..52f2303c7c 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -212,6 +212,9 @@ STATIC int choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries); STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, uint64_t *total_out); + +MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router, + int seconds)); #endif #endif diff --git a/src/or/routerparse.c b/src/or/routerparse.c index f990cebd82..250d1cd062 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1900,8 +1900,6 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->is_possible_guard = 1; else if (!strcmp(tok->args[i], "BadExit")) rs->is_bad_exit = 1; - else if (!strcmp(tok->args[i], "BadDirectory")) - rs->is_bad_directory = 1; else if (!strcmp(tok->args[i], "Authority")) rs->is_authority = 1; else if (!strcmp(tok->args[i], "Unnamed") && @@ -1918,12 +1916,9 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->version_known = 1; if (strcmpstart(tok->args[0], "Tor ")) { rs->version_supports_microdesc_cache = 1; - rs->version_supports_optimistic_data = 1; } else { rs->version_supports_microdesc_cache = tor_version_supports_microdescriptors(tok->args[0]); - rs->version_supports_optimistic_data = - tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha"); rs->version_supports_extend2_cells = tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha"); } @@ -2048,6 +2043,7 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method) double Gtotal=0, Mtotal=0, Etotal=0; const char *casename = NULL; int valid = 1; + (void) consensus_method; weight_scale = networkstatus_get_weight_scale_param(ns); Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1); @@ -2127,12 +2123,8 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method) // Then, gather G, M, E, D, T to determine case SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { int is_exit = 0; - if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) { - /* Bug #2203: Don't count bad exits as exits for balancing */ - is_exit = rs->is_exit && !rs->is_bad_exit; - } else { - is_exit = rs->is_exit; - } + /* Bug #2203: Don't count bad exits as exits for balancing */ + is_exit = rs->is_exit && !rs->is_bad_exit; if (rs->has_bandwidth) { T += rs->bandwidth_kb; if (is_exit && rs->is_possible_guard) { @@ -3247,8 +3239,8 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair * of AF_INET and AF_INET6 items. */ -addr_policy_t * -router_parse_addr_policy_item_from_string(const char *s, int assume_action) +MOCK_IMPL(addr_policy_t *, +router_parse_addr_policy_item_from_string,(const char *s, int assume_action)) { directory_token_t *tok = NULL; const char *cp, *eos; diff --git a/src/or/routerparse.h b/src/or/routerparse.h index 5d5d9e59ef..fa275c8265 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -37,8 +37,8 @@ routerinfo_t *router_parse_entry_from_string(const char *s, const char *end, const char *prepend_annotations); extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end, int cache_copy, struct digest_ri_map_t *routermap); -addr_policy_t *router_parse_addr_policy_item_from_string(const char *s, - int assume_action); +MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string, + (const char *s, int assume_action)); version_status_t tor_version_is_obsolete(const char *myversion, const char *versionlist); int tor_version_supports_microdescriptors(const char *platform); diff --git a/src/or/routerset.c b/src/or/routerset.c index 7aee90d6db..e1b8e23742 100644 --- a/src/or/routerset.c +++ b/src/or/routerset.c @@ -4,6 +4,8 @@ * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#define ROUTERSET_PRIVATE + #include "or.h" #include "geoip.h" #include "nodelist.h" @@ -12,39 +14,6 @@ #include "routerparse.h" #include "routerset.h" -/** A routerset specifies constraints on a set of possible routerinfos, based - * on their names, identities, or addresses. It is optimized for determining - * whether a router is a member or not, in O(1+P) time, where P is the number - * of address policy constraints. */ -struct routerset_t { - /** A list of strings for the elements of the policy. Each string is either - * a nickname, a hexadecimal identity fingerprint, or an address policy. A - * router belongs to the set if its nickname OR its identity OR its address - * matches an entry here. */ - smartlist_t *list; - /** A map from lowercase nicknames of routers in the set to (void*)1 */ - strmap_t *names; - /** A map from identity digests routers in the set to (void*)1 */ - digestmap_t *digests; - /** An address policy for routers in the set. For implementation reasons, - * a router belongs to the set if it is _rejected_ by this policy. */ - smartlist_t *policies; - - /** A human-readable description of what this routerset is for. Used in - * log messages. */ - char *description; - - /** A list of the country codes in this set. */ - smartlist_t *country_names; - /** Total number of countries we knew about when we built <b>countries</b>.*/ - int n_countries; - /** Bit array mapping the return value of geoip_get_country() to 1 iff the - * country is a member of this routerset. Note that we MUST call - * routerset_refresh_countries() whenever the geoip country list is - * reloaded. */ - bitarray_t *countries; -}; - /** Return a new empty routerset. */ routerset_t * routerset_new(void) @@ -60,7 +29,7 @@ routerset_new(void) /** If <b>c</b> is a country code in the form {cc}, return a newly allocated * string holding the "cc" part. Else, return NULL. */ -static char * +STATIC char * routerset_get_countryname(const char *c) { char *country; @@ -200,7 +169,7 @@ routerset_is_empty(const routerset_t *set) * * (If country is -1, then we take the country * from addr.) */ -static int +STATIC int routerset_contains(const routerset_t *set, const tor_addr_t *addr, uint16_t orport, const char *nickname, const char *id_digest, diff --git a/src/or/routerset.h b/src/or/routerset.h index 8261c7fb09..eafd331b00 100644 --- a/src/or/routerset.h +++ b/src/or/routerset.h @@ -39,5 +39,45 @@ char *routerset_to_string(const routerset_t *routerset); int routerset_equal(const routerset_t *old, const routerset_t *new); void routerset_free(routerset_t *routerset); +#ifdef ROUTERSET_PRIVATE +STATIC char * routerset_get_countryname(const char *c); +STATIC int routerset_contains(const routerset_t *set, const tor_addr_t *addr, + uint16_t orport, + const char *nickname, const char *id_digest, + country_t country); + +/** A routerset specifies constraints on a set of possible routerinfos, based + * on their names, identities, or addresses. It is optimized for determining + * whether a router is a member or not, in O(1+P) time, where P is the number + * of address policy constraints. */ +struct routerset_t { + /** A list of strings for the elements of the policy. Each string is either + * a nickname, a hexadecimal identity fingerprint, or an address policy. A + * router belongs to the set if its nickname OR its identity OR its address + * matches an entry here. */ + smartlist_t *list; + /** A map from lowercase nicknames of routers in the set to (void*)1 */ + strmap_t *names; + /** A map from identity digests routers in the set to (void*)1 */ + digestmap_t *digests; + /** An address policy for routers in the set. For implementation reasons, + * a router belongs to the set if it is _rejected_ by this policy. */ + smartlist_t *policies; + + /** A human-readable description of what this routerset is for. Used in + * log messages. */ + char *description; + + /** A list of the country codes in this set. */ + smartlist_t *country_names; + /** Total number of countries we knew about when we built <b>countries</b>.*/ + int n_countries; + /** Bit array mapping the return value of geoip_get_country() to 1 iff the + * country is a member of this routerset. Note that we MUST call + * routerset_refresh_countries() whenever the geoip country list is + * reloaded. */ + bitarray_t *countries; +}; +#endif #endif diff --git a/src/or/status.c b/src/or/status.c index afaa9de840..daae1d71c6 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -28,13 +28,7 @@ static void log_accounting(const time_t now, const or_options_t *options); STATIC int count_circuits(void) { - circuit_t *circ; - int nr=0; - - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) - nr++; - - return nr; + return smartlist_len(circuit_get_global_list()); } /** Take seconds <b>secs</b> and return a newly allocated human-readable @@ -151,10 +145,14 @@ log_accounting(const time_t now, const or_options_t *options) or_state_t *state = get_or_state(); char *acc_rcvd = bytes_to_usage(state->AccountingBytesReadInInterval); char *acc_sent = bytes_to_usage(state->AccountingBytesWrittenInInterval); - char *acc_max = bytes_to_usage(options->AccountingMax); + uint64_t acc_bytes = options->AccountingMax; + char *acc_max; time_t interval_end = accounting_get_end_time(); char end_buf[ISO_TIME_LEN + 1]; char *remaining = NULL; + if (options->AccountingRule == ACCT_SUM) + acc_bytes *= 2; + acc_max = bytes_to_usage(acc_bytes); format_local_iso_time(end_buf, interval_end); remaining = secs_to_uptime(interval_end - now); diff --git a/src/or/transports.c b/src/or/transports.c index dc30754162..5c7c0b7130 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -124,6 +124,8 @@ static INLINE void free_execve_args(char **arg); #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR" #define PROTO_CMETHODS_DONE "CMETHODS DONE" #define PROTO_SMETHODS_DONE "SMETHODS DONE" +#define PROTO_PROXY_DONE "PROXY DONE" +#define PROTO_PROXY_ERROR "PROXY-ERROR" /** The first and only supported - at the moment - configuration protocol version. */ @@ -439,6 +441,17 @@ add_transport_to_proxy(const char *transport, managed_proxy_t *mp) static int proxy_needs_restart(const managed_proxy_t *mp) { + int ret = 1; + char* proxy_uri; + + /* If the PT proxy config has changed, then all existing pluggable transports + * should be restarted. + */ + + proxy_uri = get_pt_proxy_uri(); + if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0) + goto needs_restart; + /* mp->transport_to_launch is populated with the names of the transports that must be launched *after* the SIGHUP. mp->transports is populated with the transports that were @@ -459,10 +472,10 @@ proxy_needs_restart(const managed_proxy_t *mp) } SMARTLIST_FOREACH_END(t); - return 0; - + ret = 0; needs_restart: - return 1; + tor_free(proxy_uri); + return ret; } /** Managed proxy <b>mp</b> must be restarted. Do all the necessary @@ -493,6 +506,11 @@ proxy_prepare_for_restart(managed_proxy_t *mp) SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); smartlist_clear(mp->transports); + /* Reset the proxy's HTTPS/SOCKS proxy */ + tor_free(mp->proxy_uri); + mp->proxy_uri = get_pt_proxy_uri(); + mp->proxy_supported = 0; + /* flag it as an infant proxy so that it gets launched on next tick */ mp->conf_state = PT_PROTO_INFANT; unconfigured_proxies_n++; @@ -727,12 +745,54 @@ managed_proxy_destroy(managed_proxy_t *mp, /* free the argv */ free_execve_args(mp->argv); + /* free the outgoing proxy URI */ + tor_free(mp->proxy_uri); + tor_process_handle_destroy(mp->process_handle, also_terminate_process); mp->process_handle = NULL; tor_free(mp); } +/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. + * Return a newly allocated string containing the URI, or NULL if no + * proxy is set. */ +STATIC char * +get_pt_proxy_uri(void) +{ + const or_options_t *options = get_options(); + char *uri = NULL; + + if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) { + char addr[TOR_ADDR_BUF_LEN+1]; + + if (options->Socks4Proxy) { + tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1); + tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort); + } else if (options->Socks5Proxy) { + tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1); + if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) { + tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort); + } else { + tor_asprintf(&uri, "socks5://%s:%s@%s:%d", + options->Socks5ProxyUsername, + options->Socks5ProxyPassword, + addr, options->Socks5ProxyPort); + } + } else if (options->HTTPSProxy) { + tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1); + if (!options->HTTPSProxyAuthenticator) { + tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort); + } else { + tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator, + addr, options->HTTPSProxyPort); + } + } + } + + return uri; +} + /** Handle a configured or broken managed proxy <b>mp</b>. */ static void handle_finished_proxy(managed_proxy_t *mp) @@ -745,6 +805,13 @@ handle_finished_proxy(managed_proxy_t *mp) managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */ break; case PT_PROTO_CONFIGURED: /* if configured correctly: */ + if (mp->proxy_uri && !mp->proxy_supported) { + log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the " + "specified outgoing proxy and will be terminated.", + mp->argv[0]); + managed_proxy_destroy(mp, 1); /* annihilate it. */ + break; + } register_proxy(mp); /* register its transports */ mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */ break; @@ -862,6 +929,22 @@ handle_proxy_line(const char *line, managed_proxy_t *mp) goto err; return; + } else if (!strcmpstart(line, PROTO_PROXY_DONE)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + if (mp->proxy_uri) { + mp->proxy_supported = 1; + return; + } + + /* No proxy was configured, this should log */ + } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + parse_proxy_error(line); + goto err; } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) { /* managed proxy launch failed: parse error message to learn why. */ int retval, child_state, saved_errno; @@ -1128,6 +1211,21 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp) return r; } +/** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */ +STATIC void +parse_proxy_error(const char *line) +{ + /* (Length of the protocol string) plus (a space) and (the first char of + the error message) */ + if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2)) + log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error " + "message.", PROTO_PROXY_ERROR); + + log_warn(LD_CONFIG, "Managed proxy failed to configure the " + "pluggable transport's outgoing proxy. (%s)", + line+strlen(PROTO_PROXY_ERROR)+1); +} + /** Return a newly allocated string that tor should place in * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server * manged proxy in <b>mp</b>. Return NULL if no such options are found. */ @@ -1292,6 +1390,14 @@ create_managed_proxy_environment(const managed_proxy_t *mp) } else { smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT="); } + } else { + /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the + * TOR_PT_PROXY line. + */ + + if (mp->proxy_uri) { + smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri); + } } SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) { @@ -1324,6 +1430,7 @@ managed_proxy_create(const smartlist_t *transport_list, mp->is_server = is_server; mp->argv = proxy_argv; mp->transports = smartlist_new(); + mp->proxy_uri = get_pt_proxy_uri(); mp->transports_to_launch = smartlist_new(); SMARTLIST_FOREACH(transport_list, const char *, transport, diff --git a/src/or/transports.h b/src/or/transports.h index 1365ead006..25fe5a29a9 100644 --- a/src/or/transports.h +++ b/src/or/transports.h @@ -81,6 +81,9 @@ typedef struct { char **argv; /* the cli arguments of this proxy */ int conf_protocol; /* the configuration protocol version used */ + char *proxy_uri; /* the outgoing proxy in TOR_PT_PROXY URI format */ + unsigned int proxy_supported : 1; /* the proxy honors TOR_PT_PROXY */ + int is_server; /* is it a server proxy? */ /* A pointer to the process handle of this managed proxy. */ @@ -112,6 +115,7 @@ STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp); STATIC int parse_version(const char *line, managed_proxy_t *mp); STATIC void parse_env_error(const char *line); +STATIC void parse_proxy_error(const char *line); STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp); STATIC char *get_transport_options_for_server_proxy(const managed_proxy_t *mp); @@ -123,6 +127,8 @@ STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list, STATIC int configure_proxy(managed_proxy_t *mp); +STATIC char* get_pt_proxy_uri(void); + #endif #endif diff --git a/src/test/bench.c b/src/test/bench.c index f6c33626f2..1204854b36 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -30,6 +30,7 @@ const char tor_git_revision[] = ""; #include "crypto_curve25519.h" #include "onion_ntor.h" #endif +#include "crypto_ed25519.h" #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) static uint64_t nanostart; @@ -79,6 +80,9 @@ perftime(void) #define NANOCOUNT(start,end,iters) \ ( ((double)((end)-(start))) / (iters) ) +#define MICROCOUNT(start,end,iters) \ + ( NANOCOUNT((start), (end), (iters)) / 1000.0 ) + /** Run AES performance benchmarks. */ static void bench_aes(void) @@ -232,6 +236,63 @@ bench_onion_ntor(void) ntor_handshake_state_free(state); dimap_free(keymap, NULL); } + +static void +bench_ed25519(void) +{ + uint64_t start, end; + const int iters = 1<<12; + int i; + const uint8_t msg[] = "but leaving, could not tell what they had heard"; + ed25519_signature_t sig; + ed25519_keypair_t kp; + curve25519_keypair_t curve_kp; + ed25519_public_key_t pubkey_tmp; + + ed25519_secret_key_generate(&kp.seckey, 0); + start = perftime(); + for (i = 0; i < iters; ++i) { + ed25519_public_key_generate(&kp.pubkey, &kp.seckey); + } + end = perftime(); + printf("Generate public key: %.2f usec\n", + MICROCOUNT(start, end, iters)); + + start = perftime(); + for (i = 0; i < iters; ++i) { + ed25519_sign(&sig, msg, sizeof(msg), &kp); + } + end = perftime(); + printf("Sign a short message: %.2f usec\n", + MICROCOUNT(start, end, iters)); + + start = perftime(); + for (i = 0; i < iters; ++i) { + ed25519_checksig(&sig, msg, sizeof(msg), &kp.pubkey); + } + end = perftime(); + printf("Verify signature: %.2f usec\n", + MICROCOUNT(start, end, iters)); + + curve25519_keypair_generate(&curve_kp, 0); + start = perftime(); + for (i = 0; i < iters; ++i) { + ed25519_public_key_from_curve25519_public_key(&pubkey_tmp, + &curve_kp.pubkey, 1); + } + end = perftime(); + printf("Convert public point from curve25519: %.2f usec\n", + MICROCOUNT(start, end, iters)); + + curve25519_keypair_generate(&curve_kp, 0); + start = perftime(); + for (i = 0; i < iters; ++i) { + ed25519_public_blind(&pubkey_tmp, &kp.pubkey, msg); + } + end = perftime(); + printf("Blind a public key: %.2f usec\n", + MICROCOUNT(start, end, iters)); +} #endif static void @@ -514,6 +575,7 @@ static struct benchmark_t benchmarks[] = { ENT(onion_TAP), #ifdef CURVE25519_ENABLED ENT(onion_ntor), + ENT(ed25519), #endif ENT(cell_aes), ENT(cell_ops), diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py new file mode 100644 index 0000000000..93dc49ee93 --- /dev/null +++ b/src/test/ed25519_exts_ref.py @@ -0,0 +1,234 @@ +#!/usr/bin/python +# Copyright 2014, The Tor Project, Inc +# See LICENSE for licensing information + +""" + Reference implementations for the ed25519 tweaks that Tor uses. + + Includes self-tester and test vector generator. +""" + +import slow_ed25519 +from slow_ed25519 import * + +import os +import random +import slownacl_curve25519 +import unittest +import binascii +import textwrap + +#define a synonym that doesn't look like 1 +ell = l + +# This replaces expmod above and makes it go a lot faster. +slow_ed25519.expmod = pow + +def curve25519ToEd25519(c, sign): + u = decodeint(c) + y = ((u - 1) * inv(u + 1)) % q + x = xrecover(y) + if x & 1 != sign: x = q-x + return encodepoint([x,y]) + +def blindESK(esk, param): + h = H("Derive temporary signing key" + param) + mult = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + s = decodeint(esk[:32]) + s_prime = (s * mult) % ell + k = esk[32:] + assert(len(k) == 32) + k_prime = H("Derive temporary signing key hash input" + k)[:32] + return encodeint(s_prime) + k_prime + +def blindPK(pk, param): + h = H("Derive temporary signing key" + param) + mult = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + P = decodepoint(pk) + return encodepoint(scalarmult(P, mult)) + +def expandSK(sk): + h = H(sk) + a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + k = ''.join([h[i] for i in range(b/8,b/4)]) + assert len(k) == 32 + return encodeint(a)+k + +def publickeyFromESK(h): + a = decodeint(h[:32]) + A = scalarmult(B,a) + return encodepoint(A) + +def signatureWithESK(m,h,pk): + a = decodeint(h[:32]) + r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m) + R = scalarmult(B,r) + S = (r + Hint(encodepoint(R) + pk + m) * a) % l + return encodepoint(R) + encodeint(S) + +def newSK(): + return os.urandom(32) + +# ------------------------------------------------------------ + +MSG = "This is extremely silly. But it is also incredibly serious business!" + +class SelfTest(unittest.TestCase): + + def _testSignatures(self, esk, pk): + sig = signatureWithESK(MSG, esk, pk) + checkvalid(sig, MSG, pk) + bad = False + try: + checkvalid(sig, MSG*2, pk) + bad = True + except Exception: + pass + + self.failIf(bad) + + def testExpand(self): + sk = newSK() + pk = publickey(sk) + esk = expandSK(sk) + sig1 = signature(MSG, sk, pk) + sig2 = signatureWithESK(MSG, esk, pk) + self.assertEquals(sig1, sig2) + + def testSignatures(self): + sk = newSK() + esk = expandSK(sk) + pk = publickeyFromESK(esk) + pk2 = publickey(sk) + self.assertEquals(pk, pk2) + + self._testSignatures(esk, pk) + + def testDerivation(self): + priv = slownacl_curve25519.Private() + pub = priv.get_public() + + ed_pub0 = publickeyFromESK(priv.private) + sign = (ord(ed_pub0[31]) & 255) >> 7 + ed_pub1 = curve25519ToEd25519(pub.public, sign) + + self.assertEquals(ed_pub0, ed_pub1) + + def testBlinding(self): + sk = newSK() + esk = expandSK(sk) + pk = publickeyFromESK(esk) + param = os.urandom(32) + besk = blindESK(esk, param) + bpk = blindPK(pk, param) + bpk2 = publickeyFromESK(besk) + self.assertEquals(bpk, bpk2) + + self._testSignatures(besk, bpk) + +# ------------------------------------------------------------ + +# From pprint.pprint([ binascii.b2a_hex(os.urandom(32)) for _ in xrange(8) ]) +RAND_INPUTS = [ + '26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36', + 'fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128d', + '67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0e', + 'd51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a6', + '5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb433', + 'eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b86', + '4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533d', + 'c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290b'] + +# From pprint.pprint([ binascii.b2a_hex(os.urandom(32)) for _ in xrange(8) ]) +BLINDING_PARAMS = [ + '54a513898b471d1d448a2f3c55c1de2c0ef718c447b04497eeb999ed32027823', + '831e9b5325b5d31b7ae6197e9c7a7baf2ec361e08248bce055908971047a2347', + 'ac78a1d46faf3bfbbdc5af5f053dc6dc9023ed78236bec1760dadfd0b2603760', + 'f9c84dc0ac31571507993df94da1b3d28684a12ad14e67d0a068aba5c53019fc', + 'b1fe79d1dec9bc108df69f6612c72812755751f21ecc5af99663b30be8b9081f', + '81f1512b63ab5fb5c1711a4ec83d379c420574aedffa8c3368e1c3989a3a0084', + '97f45142597c473a4b0e9a12d64561133ad9e1155fe5a9807fe6af8a93557818', + '3f44f6a5a92cde816635dfc12ade70539871078d2ff097278be2a555c9859cd0'] + +PREFIX = "ED25519_" + +def writeArray(name, array): + print "static const char *{prefix}{name}[] = {{".format( + prefix=PREFIX,name=name) + for a in array: + h = binascii.b2a_hex(a) + if len(h) > 70: + h1 = h[:70] + h2 = h[70:] + print ' "{0}"\n "{1}",'.format(h1,h2) + else: + print ' "{0}",'.format(h) + print "};\n" + +def comment(text, initial="/**"): + print initial + print textwrap.fill(text,initial_indent=" * ",subsequent_indent=" * ") + print " */" + +def makeTestVectors(): + comment("""Test vectors for our ed25519 implementation and related + functions. These were automatically generated by the + ed25519_exts_ref.py script.""", initial="/*") + + + comment("""Secret key seeds used as inputs for the ed25519 test vectors. + Randomly generated. """) + secretKeys = [ binascii.a2b_hex(r) for r in RAND_INPUTS ] + writeArray("SECRET_KEYS", secretKeys) + + comment("""Secret ed25519 keys after expansion from seeds. This is how Tor + represents them internally.""") + expandedSecretKeys = [ expandSK(sk) for sk in secretKeys ] + writeArray("EXPANDED_SECRET_KEYS", expandedSecretKeys) + + comment("""Public keys derived from the above secret keys""") + publicKeys = [ publickey(sk) for sk in secretKeys ] + writeArray("PUBLIC_KEYS", publicKeys) + + comment("""The curve25519 public keys from which the ed25519 keys can be + derived. Used to test our 'derive ed25519 from curve25519' + code.""") + writeArray("CURVE25519_PUBLIC_KEYS", + (slownacl_curve25519.smult_curve25519_base(sk[:32]) + for sk in expandedSecretKeys)) + + comment("""Parameters used for key blinding tests. Randomly generated.""") + blindingParams = [ binascii.a2b_hex(r) for r in BLINDING_PARAMS ] + writeArray("BLINDING_PARAMS", blindingParams) + + comment("""Blinded secret keys for testing key blinding. The nth blinded + key corresponds to the nth secret key blidned with the nth + blinding parameter.""") + writeArray("BLINDED_SECRET_KEYS", + (blindESK(expandSK(sk), bp) + for sk,bp in zip(secretKeys,blindingParams))) + + comment("""Blinded public keys for testing key blinding. The nth blinded + key corresponds to the nth public key blidned with the nth + blinding parameter.""") + writeArray("BLINDED_PUBLIC_KEYS", + (blindPK(pk, bp) for pk,bp in zip(publicKeys,blindingParams))) + + comment("""Signatures of the public keys, made with their corresponding + secret keys.""") + writeArray("SELF_SIGNATURES", + (signature(pk, sk, pk) for pk,sk in zip(publicKeys,secretKeys))) + + + +if __name__ == '__main__': + import sys + if len(sys.argv) == 1 or sys.argv[1] not in ("SelfTest", "MakeVectors"): + print "You should specify one of 'SelfTest' or 'MakeVectors'" + sys.exit(1) + if sys.argv[1] == 'SelfTest': + unittest.main() + else: + makeTestVectors() + + diff --git a/src/test/ed25519_vectors.inc b/src/test/ed25519_vectors.inc new file mode 100644 index 0000000000..760bafb971 --- /dev/null +++ b/src/test/ed25519_vectors.inc @@ -0,0 +1,150 @@ +/* + * Test vectors for our ed25519 implementation and related + * functions. These were automatically generated by the + * ed25519_exts_ref.py script. + */ +/** + * Secret key seeds used as inputs for the ed25519 test vectors. + * Randomly generated. + */ +static const char *ED25519_SECRET_KEYS[] = { + "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36", + "fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128d", + "67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0e", + "d51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a6", + "5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb433", + "eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b86", + "4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533d", + "c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290b", +}; + +/** + * Secret ed25519 keys after expansion from seeds. This is how Tor + * represents them internally. + */ +static const char *ED25519_EXPANDED_SECRET_KEYS[] = { + "c0a4de23cc64392d85aa1da82b3defddbea946d13bb053bf8489fa9296281f495022f1" + "f7ec0dcf52f07d4c7965c4eaed121d5d88d0a8ff546b06116a20e97755", + "18a8a69a06790dac778e882f7e868baacfa12521a5c058f5194f3a729184514a2a656f" + "e7799c3e41f43d756da8d9cd47a061316cfe6147e23ea2f90d1ca45f30", + "58d84f8862d2ecfa30eb491a81c36d05b574310ea69dae18ecb57e992a896656b98218" + "7ee96c15bf4caeeab2d0b0ae4cd0b8d17470fc7efa98bb26428f4ef36d", + "50702d20b3550c6e16033db5ad4fba16436f1ecc7485be6af62b0732ceb5d173c47ccd" + "9d044b6ea99dd99256adcc9c62191be194e7cb1a5b58ddcec85d876a2b", + "7077464c864c2ed5ed21c9916dc3b3ba6256f8b742fec67658d8d233dadc8d5a7a82c3" + "71083cc86892c2c8782dda2a09b6baf016aec51b689183ae59ce932ff2", + "8883c1387a6c86fc0bd7b9f157b4e4cd83f6885bf55e2706d2235d4527a2f05311a359" + "5953282e436df0349e1bb313a19b3ddbf7a7b91ecce8a2c34abadb38b3", + "186791ac8d03a3ac8efed6ac360467edd5a3bed2d02b3be713ddd5be53b3287ee37436" + "e5fd7ac43794394507ad440ecfdf59c4c255f19b768a273109e06d7d8e", + "b003077c1e52a62308eef7950b2d532e1d4a7eea50ad22d8ac11b892851f1c40ffb9c9" + "ff8dcd0c6c233f665a2e176324d92416bfcfcd1f787424c0c667452d86", +}; + +/** + * Public keys derived from the above secret keys + */ +static const char *ED25519_PUBLIC_KEYS[] = { + "c2247870536a192d142d056abefca68d6193158e7c1a59c1654c954eccaff894", + "1519a3b15816a1aafab0b213892026ebf5c0dc232c58b21088d88cb90e9b940d", + "081faa81992e360ea22c06af1aba096e7a73f1c665bc8b3e4e531c46455fd1dd", + "73cfa1189a723aad7966137cbffa35140bb40d7e16eae4c40b79b5f0360dd65a", + "66c1a77104d86461b6f98f73acf3cd229c80624495d2d74d6fda1e940080a96b", + "d21c294db0e64cb2d8976625786ede1d9754186ae8197a64d72f68c792eecc19", + "c4d58b4cf85a348ff3d410dd936fa460c4f18da962c01b1963792b9dcc8a6ea6", + "95126f14d86494020665face03f2d42ee2b312a85bc729903eb17522954a1c4a", +}; + +/** + * The curve25519 public keys from which the ed25519 keys can be + * derived. Used to test our 'derive ed25519 from curve25519' + * code. + */ +static const char *ED25519_CURVE25519_PUBLIC_KEYS[] = { + "17ba77846e04c7ee5ca17cade774ac1884408f9701f439d4df32cbd8736c6a1f", + "022be2124bc1899a78ba2b4167d191af3b59cadf94f0382bc31ce183a117f161", + "bf4fd38ef22f718f03c0a12ba5127bd1e3afd494793753f519728b29cc577571", + "56c493e490261cef31633efd2461d2b896908e90459e4eecde950a895aef681d", + "089675a3e8ff2a7d8b2844a79269c95b7f97a4b8b5ea0cbeec669c6f2dea9b39", + "59e20dcb691c4a345fe86c8a79ac817e5b514d84bbf0512a842a08e43f7f087e", + "9e43b820b320eda35f66f122c155b2bf8e2192c468617b7115bf067d19e08369", + "861f33296cb57f8f01e4a5e8a7e5d5d7043a6247586ab36dea8a1a3c4403ee30", +}; + +/** + * Parameters used for key blinding tests. Randomly generated. + */ +static const char *ED25519_BLINDING_PARAMS[] = { + "54a513898b471d1d448a2f3c55c1de2c0ef718c447b04497eeb999ed32027823", + "831e9b5325b5d31b7ae6197e9c7a7baf2ec361e08248bce055908971047a2347", + "ac78a1d46faf3bfbbdc5af5f053dc6dc9023ed78236bec1760dadfd0b2603760", + "f9c84dc0ac31571507993df94da1b3d28684a12ad14e67d0a068aba5c53019fc", + "b1fe79d1dec9bc108df69f6612c72812755751f21ecc5af99663b30be8b9081f", + "81f1512b63ab5fb5c1711a4ec83d379c420574aedffa8c3368e1c3989a3a0084", + "97f45142597c473a4b0e9a12d64561133ad9e1155fe5a9807fe6af8a93557818", + "3f44f6a5a92cde816635dfc12ade70539871078d2ff097278be2a555c9859cd0", +}; + +/** + * Blinded secret keys for testing key blinding. The nth blinded + * key corresponds to the nth secret key blidned with the nth + * blinding parameter. + */ +static const char *ED25519_BLINDED_SECRET_KEYS[] = { + "014e83abadb2ca9a27e0ffe23920333d817729f48700e97656ec2823d694050e171d43" + "f24e3f53e70ec7ac280044ac77d4942dee5d6807118a59bdf3ee647e89", + "fad8cca0b4335847795288b1452508752b253e64e6c7c78d4a02dbbd7d46aa0eb8ceff" + "20dfcf53eb52b891fc078c934efbf0353af7242e7dc51bb32a093afa29", + "116eb0ae0a4a91763365bdf86db427b00862db448487808788cc339ac10e5e089217f5" + "2e92797462bd890fc274672e05c98f2c82970d640084781334aae0f940", + "bd1fbb0ee5acddc4adbcf5f33e95d9445f40326ce579fdd764a24483a9ccb20f509ece" + "e77082ce088f7c19d5a00e955eeef8df6fa41686abc1030c2d76807733", + "237f5345cefe8573ce9fa7e216381a1172796c9e3f70668ab503b1352952530fb57b95" + "a440570659a440a3e4771465022a8e67af86bdf2d0990c54e7bb87ff9a", + "ba8ff23bc4ad2b739e1ccffc9fbc7837053ea81cdfdb15073f56411cfbae1d0ec492fc" + "87d5ec2a1b185ca5a40541fdef0b1e128fd5c2380c888bfa924711bcab", + "0fa68f969de038c7a90a4a74ee6167c77582006f2dedecc1956501ba6b6fb10391b476" + "8f8e556d78f4bdcb9a13b6f6066fe81d3134ae965dc48cd0785b3af2b8", + "deaa3456d1c21944d5dcd361a646858c6cf9336b0a6851d925717eb1ae186902053d9c" + "00c81e1331c06ab50087be8cfc7dc11691b132614474f1aa9c2503cccd", +}; + +/** + * Blinded public keys for testing key blinding. The nth blinded + * key corresponds to the nth public key blidned with the nth + * blinding parameter. + */ +static const char *ED25519_BLINDED_PUBLIC_KEYS[] = { + "722d6da6348e618967ef782e71061e27163a8b35f21856475d9d2023f65b6495", + "1dffa0586da6cbfcff2024eedf4fc6c818242d9a82dbbe635d6da1b975a1160d", + "5ed81f98fed5a6acda4ea6da2c34fab0ab359d950c510c256473f1f33ff438b4", + "6e6f92a54fb282120c46d9603df41135f025bc1f58f283809d04be96aeb04040", + "cda236f28edc4c7e02d18007b8dab49d669265b0f7aefb1824d7cc8e73a2cd63", + "367b03b17b67ca7329b89a520bdab91782402a41cd67264e34b5541a4b3f875b", + "8d486b03ac4e3b486b7a1d563706c7fdac75aee789a7cf6f22789eedeff61a31", + "9f297ff0aa2ceda91c5ab1b6446f12533d145940de6d850dc323417afde0cb78", +}; + +/** + * Signatures of the public keys, made with their corresponding + * secret keys. + */ +static const char *ED25519_SELF_SIGNATURES[] = { + "d23188eac3773a316d46006fa59c095060be8b1a23582a0dd99002a82a0662bd246d84" + "49e172e04c5f46ac0d1404cebe4aabd8a75a1457aa06cae41f3334f104", + "3a785ac1201c97ee5f6f0d99323960d5f264c7825e61aa7cc81262f15bef75eb4fa572" + "3add9b9d45b12311b6d403eb3ac79ff8e4e631fc3cd51e4ad2185b200b", + "cf431fd0416bfbd20c9d95ef9b723e2acddffb33900edc72195dea95965d52d888d30b" + "7b8a677c0bd8ae1417b1e1a0ec6700deadd5d8b54b6689275e04a04509", + "2375380cd72d1a6c642aeddff862be8a5804b916acb72c02d9ed052c1561881aa658a5" + "af856fcd6d43113e42f698cd6687c99efeef7f2ce045824440d26c5d00", + "2385a472f599ca965bbe4d610e391cdeabeba9c336694b0d6249e551458280be122c24" + "41dd9746a81bbfb9cd619364bab0df37ff4ceb7aefd24469c39d3bc508", + "e500cd0b8cfff35442f88008d894f3a2fa26ef7d3a0ca5714ae0d3e2d40caae58ba7cd" + "f69dd126994dad6be536fcda846d89dd8138d1683cc144c8853dce7607", + "d187b9e334b0050154de10bf69b3e4208a584e1a65015ec28b14bcc252cf84b8baa9c9" + "4867daa60f2a82d09ba9652d41e8dde292b624afc8d2c26441b95e3c0e", + "815213640a643d198bd056e02bba74e1c8d2d931643e84497adf3347eb485079c9afe0" + "afce9284cdc084946b561abbb214f1304ca11228ff82702185cf28f60d", +}; + diff --git a/src/test/include.am b/src/test/include.am index fba439a616..4020ac4190 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -28,11 +28,13 @@ src_test_test_SOURCES = \ src/test/test_cell_queue.c \ src/test/test_data.c \ src/test/test_dir.c \ + src/test/test_entrynodes.c \ src/test/test_extorport.c \ src/test/test_introduce.c \ src/test/test_logging.c \ src/test/test_microdesc.c \ src/test/test_oom.c \ + src/test/test_accounting.c \ src/test/test_options.c \ src/test/test_pt.c \ src/test/test_relaycell.c \ @@ -45,6 +47,7 @@ src_test_test_SOURCES = \ src/test/test_nodelist.c \ src/test/test_policy.c \ src/test/test_status.c \ + src/test/test_routerset.c \ src/ext/tinytest.c src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) @@ -58,7 +61,7 @@ src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \ src/common/libor-crypto-testing.a $(LIBDONNA) \ - src/common/libor-event-testing.a \ + src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @@ -71,7 +74,9 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ noinst_HEADERS+= \ - src/test/test.h + src/test/test.h \ + src/test/test_descriptors.inc \ + src/test/ed25519_vectors.inc if CURVE25519_ENABLED noinst_PROGRAMS+= src/test/test-ntor-cl diff --git a/src/test/slow_ed25519.py b/src/test/slow_ed25519.py new file mode 100644 index 0000000000..f44708b200 --- /dev/null +++ b/src/test/slow_ed25519.py @@ -0,0 +1,115 @@ +# This is the ed25519 implementation from +# http://ed25519.cr.yp.to/python/ed25519.py . +# It is in the public domain. +# +# It isn't constant-time. Don't use it except for testing. Also, see +# warnings about how very slow it is. Only use this for generating +# test vectors, I'd suggest. +# +# Don't edit this file. Mess with ed25519_ref.py + +import hashlib + +b = 256 +q = 2**255 - 19 +l = 2**252 + 27742317777372353535851937790883648493 + +def H(m): + return hashlib.sha512(m).digest() + +def expmod(b,e,m): + if e == 0: return 1 + t = expmod(b,e/2,m)**2 % m + if e & 1: t = (t*b) % m + return t + +def inv(x): + return expmod(x,q-2,q) + +d = -121665 * inv(121666) +I = expmod(2,(q-1)/4,q) + +def xrecover(y): + xx = (y*y-1) * inv(d*y*y+1) + x = expmod(xx,(q+3)/8,q) + if (x*x - xx) % q != 0: x = (x*I) % q + if x % 2 != 0: x = q-x + return x + +By = 4 * inv(5) +Bx = xrecover(By) +B = [Bx % q,By % q] + +def edwards(P,Q): + x1 = P[0] + y1 = P[1] + x2 = Q[0] + y2 = Q[1] + x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2) + y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2) + return [x3 % q,y3 % q] + +def scalarmult(P,e): + if e == 0: return [0,1] + Q = scalarmult(P,e/2) + Q = edwards(Q,Q) + if e & 1: Q = edwards(Q,P) + return Q + +def encodeint(y): + bits = [(y >> i) & 1 for i in range(b)] + return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)]) + +def encodepoint(P): + x = P[0] + y = P[1] + bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1] + return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)]) + +def bit(h,i): + return (ord(h[i/8]) >> (i%8)) & 1 + +def publickey(sk): + h = H(sk) + a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + A = scalarmult(B,a) + return encodepoint(A) + +def Hint(m): + h = H(m) + return sum(2**i * bit(h,i) for i in range(2*b)) + +def signature(m,sk,pk): + h = H(sk) + a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m) + R = scalarmult(B,r) + S = (r + Hint(encodepoint(R) + pk + m) * a) % l + return encodepoint(R) + encodeint(S) + +def isoncurve(P): + x = P[0] + y = P[1] + return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0 + +def decodeint(s): + return sum(2**i * bit(s,i) for i in range(0,b)) + +def decodepoint(s): + y = sum(2**i * bit(s,i) for i in range(0,b-1)) + x = xrecover(y) + if x & 1 != bit(s,b-1): x = q-x + P = [x,y] + if not isoncurve(P): raise Exception("decoding point that is not on curve") + return P + +def checkvalid(s,m,pk): + if len(s) != b/4: raise Exception("signature length is wrong") + if len(pk) != b/8: raise Exception("public-key length is wrong") + R = decodepoint(s[0:b/8]) + A = decodepoint(pk) + S = decodeint(s[b/8:b/4]) + h = Hint(encodepoint(R) + pk + m) + if scalarmult(B,S) != edwards(R,scalarmult(A,h)): + raise Exception("signature does not pass verification") + diff --git a/src/test/test.c b/src/test/test.c index 8bce9c91f4..d2813ed42a 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -43,6 +43,7 @@ long int lround(double x); double fabs(double x); #include "or.h" +#include "backtrace.h" #include "buffers.h" #include "circuitlist.h" #include "circuitstats.h" @@ -106,11 +107,18 @@ setup_directory(void) { char buf[MAX_PATH]; const char *tmp = buf; + const char *extra_backslash = ""; /* If this fails, we're probably screwed anyway */ if (!GetTempPathA(sizeof(buf),buf)) - tmp = "c:\\windows\\temp"; + tmp = "c:\\windows\\temp\\"; + if (strcmpend(tmp, "\\")) { + /* According to MSDN, it should be impossible for GetTempPath to give us + * an answer that doesn't end with \. But let's make sure. */ + extra_backslash = "\\"; + } tor_snprintf(temp_dir, sizeof(temp_dir), - "%s\\tor_test_%d_%s", tmp, (int)getpid(), rnd32); + "%s%stor_test_%d_%s", tmp, extra_backslash, + (int)getpid(), rnd32); r = mkdir(temp_dir); } #else @@ -184,7 +192,7 @@ remove_directory(void) #undef CACHE_GENERATED_KEYS static crypto_pk_t *pregen_keys[5] = {NULL, NULL, NULL, NULL, NULL}; -#define N_PREGEN_KEYS ((int)(sizeof(pregen_keys)/sizeof(pregen_keys[0]))) +#define N_PREGEN_KEYS ARRAY_LENGTH(pregen_keys) /** Generate and return a new keypair for use in unit tests. If we're using * the key cache optimization, we might reuse keys: we only guarantee that @@ -224,7 +232,7 @@ free_pregenerated_keys(void) /** Run unit tests for the onion handshake code. */ static void -test_onion_handshake(void) +test_onion_handshake(void *arg) { /* client-side */ crypto_dh_t *c_dh = NULL; @@ -237,12 +245,13 @@ test_onion_handshake(void) /* shared */ crypto_pk_t *pk = NULL, *pk2 = NULL; + (void)arg; pk = pk_generate(0); pk2 = pk_generate(1); /* client handshake 1. */ memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); + tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); for (i = 1; i <= 3; ++i) { crypto_pk_t *k1, *k2; @@ -259,16 +268,16 @@ test_onion_handshake(void) memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN); memset(s_keys, 0, 40); - test_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2, + tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2, s_buf, s_keys, 40)); /* client handshake 2 */ memset(c_keys, 0, 40); - test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40)); + tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40)); - test_memeq(c_keys, s_keys, 40); + tt_mem_op(c_keys,==, s_keys, 40); memset(s_buf, 0, 40); - test_memneq(c_keys, s_buf, 40); + tt_mem_op(c_keys,!=, s_buf, 40); } done: crypto_dh_free(c_dh); @@ -315,7 +324,7 @@ test_bad_onion_handshake(void *arg) /* client handshake 1: do it straight. */ memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); + tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); /* Server: Case 3: we just don't have the right key. */ tt_int_op(-1, ==, @@ -343,7 +352,7 @@ test_bad_onion_handshake(void *arg) /* Let the client finish; make sure it can. */ tt_int_op(0, ==, onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40)); - test_memeq(s_keys, c_keys, 40); + tt_mem_op(s_keys,==, c_keys, 40); /* Client: Case 2: The server sent back a degenerate DH. */ memset(s_buf, 0, sizeof(s_buf)); @@ -400,9 +409,9 @@ test_ntor_handshake(void *arg) tt_int_op(0, ==, onion_skin_ntor_client_handshake(c_state, s_buf, c_keys, 400)); - test_memeq(c_keys, s_keys, 400); + tt_mem_op(c_keys,==, s_keys, 400); memset(s_buf, 0, 40); - test_memneq(c_keys, s_buf, 40); + tt_mem_op(c_keys,!=, s_buf, 40); done: ntor_handshake_state_free(c_state); @@ -412,7 +421,7 @@ test_ntor_handshake(void *arg) /** Run unit tests for the onion queues. */ static void -test_onion_queues(void) +test_onion_queues(void *arg) { uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0}; @@ -423,6 +432,7 @@ test_onion_queues(void) create_cell_t *onionskin = NULL, *create2_ptr; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); + (void)arg; create2_ptr = create2; /* remember, but do not free */ create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, @@ -430,24 +440,24 @@ test_onion_queues(void) create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf2); - test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - test_eq(0, onion_pending_add(circ1, create1)); + tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,==, onion_pending_add(circ1, create1)); create1 = NULL; - test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(1,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - test_eq(0, onion_pending_add(circ2, create2)); + tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_int_op(0,==, onion_pending_add(circ2, create2)); create2 = NULL; - test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_int_op(1,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - test_eq_ptr(circ2, onion_next_task(&onionskin)); - test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_ptr_op(circ2,==, onion_next_task(&onionskin)); + tt_int_op(1,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_ptr_op(onionskin, ==, create2_ptr); clear_pending_onions(); - test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); done: circuit_free(TO_CIRCUIT(circ1)); @@ -458,7 +468,7 @@ test_onion_queues(void) } static void -test_circuit_timeout(void) +test_circuit_timeout(void *arg) { /* Plan: * 1. Generate 1000 samples @@ -476,6 +486,7 @@ test_circuit_timeout(void) or_state_t *state=NULL; int i, runs; double close_ms; + (void)arg; circuit_build_times_init(&initial); circuit_build_times_init(&estimate); circuit_build_times_init(&final); @@ -510,11 +521,11 @@ test_circuit_timeout(void) } while (fabs(circuit_build_times_cdf(&initial, timeout0) - circuit_build_times_cdf(&initial, timeout1)) > 0.02); - test_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE); + tt_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE); circuit_build_times_update_state(&estimate, state); circuit_build_times_free_timeouts(&final); - test_assert(circuit_build_times_parse_state(&final, state) == 0); + tt_assert(circuit_build_times_parse_state(&final, state) == 0); circuit_build_times_update_alpha(&final); timeout2 = circuit_build_times_calculate_timeout(&final, @@ -524,7 +535,7 @@ test_circuit_timeout(void) log_notice(LD_CIRC, "Timeout2 is %f, Xm is %d", timeout2, final.Xm); /* 5% here because some accuracy is lost due to histogram conversion */ - test_assert(fabs(circuit_build_times_cdf(&initial, timeout0) - + tt_assert(fabs(circuit_build_times_cdf(&initial, timeout0) - circuit_build_times_cdf(&initial, timeout2)) < 0.05); for (runs = 0; runs < 50; runs++) { @@ -547,8 +558,8 @@ test_circuit_timeout(void) CBT_DEFAULT_QUANTILE_CUTOFF/100.0)); } - test_assert(!circuit_build_times_network_check_changed(&estimate)); - test_assert(!circuit_build_times_network_check_changed(&final)); + tt_assert(!circuit_build_times_network_check_changed(&estimate)); + tt_assert(!circuit_build_times_network_check_changed(&final)); /* Reset liveness to be non-live */ final.liveness.network_last_live = 0; @@ -557,27 +568,27 @@ test_circuit_timeout(void) build_times_idx = estimate.build_times_idx; total_build_times = estimate.total_build_times; - test_assert(circuit_build_times_network_check_live(&estimate)); - test_assert(circuit_build_times_network_check_live(&final)); + tt_assert(circuit_build_times_network_check_live(&estimate)); + tt_assert(circuit_build_times_network_check_live(&final)); circuit_build_times_count_close(&estimate, 0, (time_t)(approx_time()-estimate.close_ms/1000.0-1)); circuit_build_times_count_close(&final, 0, (time_t)(approx_time()-final.close_ms/1000.0-1)); - test_assert(!circuit_build_times_network_check_live(&estimate)); - test_assert(!circuit_build_times_network_check_live(&final)); + tt_assert(!circuit_build_times_network_check_live(&estimate)); + tt_assert(!circuit_build_times_network_check_live(&final)); log_info(LD_CIRC, "idx: %d %d, tot: %d %d", build_times_idx, estimate.build_times_idx, total_build_times, estimate.total_build_times); /* Check rollback index. Should match top of loop. */ - test_assert(build_times_idx == estimate.build_times_idx); + tt_assert(build_times_idx == estimate.build_times_idx); // This can fail if estimate.total_build_times == 1000, because // in that case, rewind actually causes us to lose timeouts if (total_build_times != CBT_NCIRCUITS_TO_OBSERVE) - test_assert(total_build_times == estimate.total_build_times); + tt_assert(total_build_times == estimate.total_build_times); /* Now simulate that the network has become live and we need * a change */ @@ -592,12 +603,12 @@ test_circuit_timeout(void) } } - test_assert(estimate.liveness.after_firsthop_idx == 0); - test_assert(final.liveness.after_firsthop_idx == + tt_assert(estimate.liveness.after_firsthop_idx == 0); + tt_assert(final.liveness.after_firsthop_idx == CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1); - test_assert(circuit_build_times_network_check_live(&estimate)); - test_assert(circuit_build_times_network_check_live(&final)); + tt_assert(circuit_build_times_network_check_live(&estimate)); + tt_assert(circuit_build_times_network_check_live(&final)); circuit_build_times_count_timeout(&final, 1); } @@ -611,7 +622,7 @@ test_circuit_timeout(void) /** Test encoding and parsing of rendezvous service descriptors. */ static void -test_rend_fns(void) +test_rend_fns(void *arg) { rend_service_descriptor_t *generated = NULL, *parsed = NULL; char service_id[DIGEST_LEN]; @@ -634,16 +645,17 @@ test_rend_fns(void) char address6[] = "foo.bar.abcdefghijklmnop.onion"; char address7[] = ".abcdefghijklmnop.onion"; - test_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); - test_assert(ONION_HOSTNAME == parse_extended_hostname(address2)); - test_streq(address2, "aaaaaaaaaaaaaaaa"); - test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); - test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); - test_assert(ONION_HOSTNAME == parse_extended_hostname(address5)); - test_streq(address5, "abcdefghijklmnop"); - test_assert(ONION_HOSTNAME == parse_extended_hostname(address6)); - test_streq(address6, "abcdefghijklmnop"); - test_assert(BAD_HOSTNAME == parse_extended_hostname(address7)); + (void)arg; + tt_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); + tt_assert(ONION_HOSTNAME == parse_extended_hostname(address2)); + tt_str_op(address2,==, "aaaaaaaaaaaaaaaa"); + tt_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); + tt_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); + tt_assert(ONION_HOSTNAME == parse_extended_hostname(address5)); + tt_str_op(address5,==, "abcdefghijklmnop"); + tt_assert(ONION_HOSTNAME == parse_extended_hostname(address6)); + tt_str_op(address6,==, "abcdefghijklmnop"); + tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7)); pk1 = pk_generate(0); pk2 = pk_generate(1); @@ -676,40 +688,41 @@ test_rend_fns(void) intro->intro_key = crypto_pk_dup_key(pk2); smartlist_add(generated->intro_nodes, intro); } - test_assert(rend_encode_v2_descriptors(descs, generated, now, 0, + tt_assert(rend_encode_v2_descriptors(descs, generated, now, 0, REND_NO_AUTH, NULL, NULL) > 0); - test_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32, + tt_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32, NULL, now, 0) == 0); - test_memeq(((rend_encoded_v2_service_descriptor_t *) - smartlist_get(descs, 0))->desc_id, computed_desc_id, DIGEST_LEN); - test_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id, + tt_mem_op(((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0))->desc_id, ==, + computed_desc_id, DIGEST_LEN); + tt_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id, &intro_points_encrypted, &intro_points_size, &encoded_size, &next_desc, ((rend_encoded_v2_service_descriptor_t *) smartlist_get(descs, 0))->desc_str) == 0); - test_assert(parsed); - test_memeq(((rend_encoded_v2_service_descriptor_t *) - smartlist_get(descs, 0))->desc_id, parsed_desc_id, DIGEST_LEN); - test_eq(rend_parse_introduction_points(parsed, intro_points_encrypted, - intro_points_size), 3); - test_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk)); - test_eq(parsed->timestamp, now); - test_eq(parsed->version, 2); - test_eq(parsed->protocols, 42); - test_eq(smartlist_len(parsed->intro_nodes), 3); + tt_assert(parsed); + tt_mem_op(((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0))->desc_id,==, parsed_desc_id, DIGEST_LEN); + tt_int_op(rend_parse_introduction_points(parsed, intro_points_encrypted, + intro_points_size),==, 3); + tt_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk)); + tt_int_op(parsed->timestamp,==, now); + tt_int_op(parsed->version,==, 2); + tt_int_op(parsed->protocols,==, 42); + tt_int_op(smartlist_len(parsed->intro_nodes),==, 3); for (i = 0; i < smartlist_len(parsed->intro_nodes); i++) { rend_intro_point_t *par_intro = smartlist_get(parsed->intro_nodes, i), *gen_intro = smartlist_get(generated->intro_nodes, i); extend_info_t *par_info = par_intro->extend_info; extend_info_t *gen_info = gen_intro->extend_info; - test_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key)); - test_memeq(gen_info->identity_digest, par_info->identity_digest, + tt_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key)); + tt_mem_op(gen_info->identity_digest,==, par_info->identity_digest, DIGEST_LEN); - test_streq(gen_info->nickname, par_info->nickname); - test_assert(tor_addr_eq(&gen_info->addr, &par_info->addr)); - test_eq(gen_info->port, par_info->port); + tt_str_op(gen_info->nickname,==, par_info->nickname); + tt_assert(tor_addr_eq(&gen_info->addr, &par_info->addr)); + tt_int_op(gen_info->port,==, par_info->port); } rend_service_descriptor_free(parsed); @@ -753,17 +766,17 @@ test_rend_fns(void) } while (0) #define CHECK_COUNTRY(country, val) do { \ /* test ipv4 country lookup */ \ - test_streq(country, \ + tt_str_op(country, ==, \ geoip_get_country_name(geoip_get_country_by_ipv4(val))); \ /* test ipv6 country lookup */ \ SET_TEST_IPV6(val); \ - test_streq(country, \ + tt_str_op(country, ==, \ geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \ } while (0) /** Run unit tests for GeoIP code. */ static void -test_geoip(void) +test_geoip(void *arg) { int i, j; time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ @@ -817,23 +830,24 @@ test_geoip(void) /* Populate the DB a bit. Add these in order, since we can't do the final * 'sort' step. These aren't very good IP addresses, but they're perfectly * fine uint32_t values. */ - test_eq(0, geoip_parse_entry("10,50,AB", AF_INET)); - test_eq(0, geoip_parse_entry("52,90,XY", AF_INET)); - test_eq(0, geoip_parse_entry("95,100,AB", AF_INET)); - test_eq(0, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET)); - test_eq(0, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET)); - test_eq(0, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET)); + (void)arg; + tt_int_op(0,==, geoip_parse_entry("10,50,AB", AF_INET)); + tt_int_op(0,==, geoip_parse_entry("52,90,XY", AF_INET)); + tt_int_op(0,==, geoip_parse_entry("95,100,AB", AF_INET)); + tt_int_op(0,==, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET)); + tt_int_op(0,==, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET)); + tt_int_op(0,==, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET)); /* Populate the IPv6 DB equivalently with fake IPs in the same range */ - test_eq(0, geoip_parse_entry("::a,::32,AB", AF_INET6)); - test_eq(0, geoip_parse_entry("::34,::5a,XY", AF_INET6)); - test_eq(0, geoip_parse_entry("::5f,::64,AB", AF_INET6)); - test_eq(0, geoip_parse_entry("::69,::8c,ZZ", AF_INET6)); - test_eq(0, geoip_parse_entry("::96,::be,XY", AF_INET6)); - test_eq(0, geoip_parse_entry("::c8,::fa,AB", AF_INET6)); + tt_int_op(0,==, geoip_parse_entry("::a,::32,AB", AF_INET6)); + tt_int_op(0,==, geoip_parse_entry("::34,::5a,XY", AF_INET6)); + tt_int_op(0,==, geoip_parse_entry("::5f,::64,AB", AF_INET6)); + tt_int_op(0,==, geoip_parse_entry("::69,::8c,ZZ", AF_INET6)); + tt_int_op(0,==, geoip_parse_entry("::96,::be,XY", AF_INET6)); + tt_int_op(0,==, geoip_parse_entry("::c8,::fa,AB", AF_INET6)); /* We should have 4 countries: ??, ab, xy, zz. */ - test_eq(4, geoip_get_n_countries()); + tt_int_op(4,==, geoip_get_n_countries()); memset(&in6, 0, sizeof(in6)); CHECK_COUNTRY("??", 3); @@ -844,9 +858,9 @@ test_geoip(void) CHECK_COUNTRY("xy", 190); CHECK_COUNTRY("??", 2000); - test_eq(0, geoip_get_country_by_ipv4(3)); + tt_int_op(0,==, geoip_get_country_by_ipv4(3)); SET_TEST_IPV6(3); - test_eq(0, geoip_get_country_by_ipv6(&in6)); + tt_int_op(0,==, geoip_get_country_by_ipv6(&in6)); get_options_mutable()->BridgeRelay = 1; get_options_mutable()->BridgeRecordUsageByCountry = 1; @@ -869,41 +883,41 @@ test_geoip(void) geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); } geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); - test_assert(s); - test_assert(v); - test_streq("zz=24,ab=16,xy=8", s); - test_streq("v4=16,v6=16", v); + tt_assert(s); + tt_assert(v); + tt_str_op("zz=24,ab=16,xy=8",==, s); + tt_str_op("v4=16,v6=16",==, v); tor_free(s); tor_free(v); /* Now clear out all the AB observations. */ geoip_remove_old_clients(now-6000); geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); - test_assert(s); - test_assert(v); - test_streq("zz=24,xy=8", s); - test_streq("v4=16,v6=16", v); + tt_assert(s); + tt_assert(v); + tt_str_op("zz=24,xy=8",==, s); + tt_str_op("v4=16,v6=16",==, v); tor_free(s); tor_free(v); /* Start testing bridge statistics by making sure that we don't output * bridge stats without initializing them. */ s = geoip_format_bridge_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Initialize stats and generate the bridge-stats history string out of * the connecting clients added above. */ geoip_bridge_stats_init(now); s = geoip_format_bridge_stats(now + 86400); - test_assert(s); - test_streq(bridge_stats_1, s); + tt_assert(s); + tt_str_op(bridge_stats_1,==, s); tor_free(s); /* Stop collecting bridge stats and make sure we don't write a history * string anymore. */ geoip_bridge_stats_term(); s = geoip_format_bridge_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Stop being a bridge and start being a directory mirror that gathers * directory request statistics. */ @@ -917,7 +931,7 @@ test_geoip(void) SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); s = geoip_format_dirreq_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Initialize stats, note one connecting client, and generate the * dirreq-stats history string. */ @@ -925,7 +939,7 @@ test_geoip(void) SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); s = geoip_format_dirreq_stats(now + 86400); - test_streq(dirreq_stats_1, s); + tt_str_op(dirreq_stats_1,==, s); tor_free(s); /* Stop collecting stats, add another connecting client, and ensure we @@ -934,7 +948,7 @@ test_geoip(void) SET_TEST_ADDRESS(101); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); s = geoip_format_dirreq_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Re-start stats, add a connecting client, reset stats, and make sure * that we get an all empty history string. */ @@ -943,20 +957,20 @@ test_geoip(void) geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); geoip_reset_dirreq_stats(now); s = geoip_format_dirreq_stats(now + 86400); - test_streq(dirreq_stats_2, s); + tt_str_op(dirreq_stats_2,==, s); tor_free(s); /* Note a successful network status response and make sure that it * appears in the history string. */ geoip_note_ns_response(GEOIP_SUCCESS); s = geoip_format_dirreq_stats(now + 86400); - test_streq(dirreq_stats_3, s); + tt_str_op(dirreq_stats_3,==, s); tor_free(s); /* Start a tunneled directory request. */ geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED); s = geoip_format_dirreq_stats(now + 86400); - test_streq(dirreq_stats_4, s); + tt_str_op(dirreq_stats_4,==, s); tor_free(s); /* Stop collecting directory request statistics and start gathering @@ -970,7 +984,7 @@ test_geoip(void) SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); s = geoip_format_entry_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Initialize stats, note one connecting client, and generate the * entry-stats history string. */ @@ -978,7 +992,7 @@ test_geoip(void) SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); s = geoip_format_entry_stats(now + 86400); - test_streq(entry_stats_1, s); + tt_str_op(entry_stats_1,==, s); tor_free(s); /* Stop collecting stats, add another connecting client, and ensure we @@ -987,7 +1001,7 @@ test_geoip(void) SET_TEST_ADDRESS(101); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); s = geoip_format_entry_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Re-start stats, add a connecting client, reset stats, and make sure * that we get an all empty history string. */ @@ -996,7 +1010,7 @@ test_geoip(void) geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); geoip_reset_entry_stats(now); s = geoip_format_entry_stats(now + 86400); - test_streq(entry_stats_2, s); + tt_str_op(entry_stats_2,==, s); tor_free(s); /* Stop collecting entry statistics. */ @@ -1009,7 +1023,7 @@ test_geoip(void) } static void -test_geoip_with_pt(void) +test_geoip_with_pt(void *arg) { time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ char *s = NULL; @@ -1017,6 +1031,7 @@ test_geoip_with_pt(void) tor_addr_t addr; struct in6_addr in6; + (void)arg; get_options_mutable()->BridgeRelay = 1; get_options_mutable()->BridgeRecordUsageByCountry = 1; @@ -1068,7 +1083,7 @@ test_geoip_with_pt(void) /* Test the transport history string. */ s = geoip_get_transport_history(); tor_assert(s); - test_streq(s, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136," + tt_str_op(s,==, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136," "entropy=8,fire=8,google=8"); /* Stop collecting entry statistics. */ @@ -1085,7 +1100,7 @@ test_geoip_with_pt(void) /** Run unit tests for stats code. */ static void -test_stats(void) +test_stats(void *arg) { time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ char *s = NULL; @@ -1093,10 +1108,11 @@ test_stats(void) /* Start with testing exit port statistics; we shouldn't collect exit * stats without initializing them. */ + (void)arg; rep_hist_note_exit_stream_opened(80); rep_hist_note_exit_bytes(80, 100, 10000); s = rep_hist_format_exit_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Initialize stats, note some streams and bytes, and generate history * string. */ @@ -1107,10 +1123,10 @@ test_stats(void) rep_hist_note_exit_bytes(443, 100, 10000); rep_hist_note_exit_bytes(443, 100, 10000); s = rep_hist_format_exit_stats(now + 86400); - test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" "exit-kibibytes-written 80=1,443=1,other=0\n" "exit-kibibytes-read 80=10,443=20,other=0\n" - "exit-streams-opened 80=4,443=4,other=0\n", s); + "exit-streams-opened 80=4,443=4,other=0\n",==, s); tor_free(s); /* Add a few bytes on 10 more ports and ensure that only the top 10 @@ -1120,13 +1136,13 @@ test_stats(void) rep_hist_note_exit_stream_opened(i); } s = rep_hist_format_exit_stats(now + 86400); - test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1," "59=1,80=1,443=1,other=1\n" "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1," "59=1,80=10,443=20,other=1\n" "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4," - "59=4,80=4,443=4,other=4\n", s); + "59=4,80=4,443=4,other=4\n",==, s); tor_free(s); /* Stop collecting stats, add some bytes, and ensure we don't generate @@ -1134,7 +1150,7 @@ test_stats(void) rep_hist_exit_stats_term(); rep_hist_note_exit_bytes(80, 100, 10000); s = rep_hist_format_exit_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Re-start stats, add some bytes, reset stats, and see what history we * get when observing no streams or bytes at all. */ @@ -1143,17 +1159,17 @@ test_stats(void) rep_hist_note_exit_bytes(80, 100, 10000); rep_hist_reset_exit_stats(now); s = rep_hist_format_exit_stats(now + 86400); - test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" "exit-kibibytes-written other=0\n" "exit-kibibytes-read other=0\n" - "exit-streams-opened other=0\n", s); + "exit-streams-opened other=0\n",==, s); tor_free(s); /* Continue with testing connection statistics; we shouldn't collect * conn stats without initializing them. */ rep_hist_note_or_conn_bytes(1, 20, 400, now); s = rep_hist_format_conn_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Initialize stats, note bytes, and generate history string. */ rep_hist_conn_stats_init(now); @@ -1162,7 +1178,7 @@ test_stats(void) rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); s = rep_hist_format_conn_stats(now + 86400); - test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n", s); + tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",==, s); tor_free(s); /* Stop collecting stats, add some bytes, and ensure we don't generate @@ -1170,7 +1186,7 @@ test_stats(void) rep_hist_conn_stats_term(); rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); s = rep_hist_format_conn_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Re-start stats, add some bytes, reset stats, and see what history we * get when observing no bytes at all. */ @@ -1181,26 +1197,26 @@ test_stats(void) rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); rep_hist_reset_conn_stats(now); s = rep_hist_format_conn_stats(now + 86400); - test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", s); + tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",==, s); tor_free(s); /* Continue with testing buffer statistics; we shouldn't collect buffer * stats without initializing them. */ rep_hist_add_buffer_stats(2.0, 2.0, 20); s = rep_hist_format_buffer_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Initialize stats, add statistics for a single circuit, and generate * the history string. */ rep_hist_buffer_stats_init(now); rep_hist_add_buffer_stats(2.0, 2.0, 20); s = rep_hist_format_buffer_stats(now + 86400); - test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n" "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," "0.00,0.00\n" "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n" - "cell-circuits-per-decile 1\n", s); + "cell-circuits-per-decile 1\n",==, s); tor_free(s); /* Add nineteen more circuit statistics to the one that's already in the @@ -1210,12 +1226,12 @@ test_stats(void) for (i = 20; i < 30; i++) rep_hist_add_buffer_stats(3.5, 3.5, i); s = rep_hist_format_buffer_stats(now + 86400); - test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n" "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75," "2.75,2.75\n" "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n" - "cell-circuits-per-decile 2\n", s); + "cell-circuits-per-decile 2\n",==, s); tor_free(s); /* Stop collecting stats, add statistics for one circuit, and ensure we @@ -1223,7 +1239,7 @@ test_stats(void) rep_hist_buffer_stats_term(); rep_hist_add_buffer_stats(2.0, 2.0, 20); s = rep_hist_format_buffer_stats(now + 86400); - test_assert(!s); + tt_assert(!s); /* Re-start stats, add statistics for one circuit, reset stats, and make * sure that the history has all zeros. */ @@ -1231,46 +1247,21 @@ test_stats(void) rep_hist_add_buffer_stats(2.0, 2.0, 20); rep_hist_reset_buffer_stats(now); s = rep_hist_format_buffer_stats(now + 86400); - test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n" "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," "0.00,0.00\n" "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n" - "cell-circuits-per-decile 0\n", s); + "cell-circuits-per-decile 0\n",==, s); done: tor_free(s); } -static void * -legacy_test_setup(const struct testcase_t *testcase) -{ - return testcase->setup_data; -} - -void -legacy_test_helper(void *data) -{ - void (*fn)(void) = data; - fn(); -} - -static int -legacy_test_cleanup(const struct testcase_t *testcase, void *ptr) -{ - (void)ptr; - (void)testcase; - return 1; -} - -const struct testcase_setup_t legacy_setup = { - legacy_test_setup, legacy_test_cleanup -}; - #define ENT(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_ ## name } + { #name, test_ ## name , 0, NULL, NULL } #define FORK(name) \ - { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name } + { #name, test_ ## name , TT_FORK, NULL, NULL } static struct testcase_t test_array[] = { ENT(onion_handshake), @@ -1306,6 +1297,7 @@ extern struct testcase_t circuitmux_tests[]; extern struct testcase_t cell_queue_tests[]; extern struct testcase_t options_tests[]; extern struct testcase_t socks_tests[]; +extern struct testcase_t entrynodes_tests[]; extern struct testcase_t extorport_tests[]; extern struct testcase_t controller_event_tests[]; extern struct testcase_t logging_tests[]; @@ -1313,8 +1305,10 @@ extern struct testcase_t hs_tests[]; extern struct testcase_t nodelist_tests[]; extern struct testcase_t routerkeys_tests[]; extern struct testcase_t oom_tests[]; +extern struct testcase_t accounting_tests[]; extern struct testcase_t policy_tests[]; extern struct testcase_t status_tests[]; +extern struct testcase_t routerset_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1337,14 +1331,17 @@ static struct testgroup_t testgroups[] = { { "circuitlist/", circuitlist_tests }, { "circuitmux/", circuitmux_tests }, { "options/", options_tests }, + { "entrynodes/", entrynodes_tests }, { "extorport/", extorport_tests }, { "control/", controller_event_tests }, { "hs/", hs_tests }, { "nodelist/", nodelist_tests }, { "routerkeys/", routerkeys_tests }, { "oom/", oom_tests }, + { "accounting/", accounting_tests }, { "policy/" , policy_tests }, { "status/" , status_tests }, + { "routerset/" , routerset_tests }, END_OF_GROUPS }; @@ -1370,6 +1367,7 @@ main(int c, const char **v) options = options_new(); tor_threads_init(); init_logging(); + configure_backtrace_handler(get_version()); for (i_out = i = 1; i < c; ++i) { if (!strcmp(v[i], "--warn")) { diff --git a/src/test/test.h b/src/test/test.h index b9e4d5bdb4..8eb2dfc016 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -22,25 +22,6 @@ #define PRETTY_FUNCTION "" #endif -#define test_fail_msg(msg) TT_DIE((msg)) - -#define test_fail() test_fail_msg("Assertion failed.") - -#define test_assert(expr) tt_assert(expr) - -#define test_eq(expr1, expr2) tt_int_op((expr1), ==, (expr2)) -#define test_eq_ptr(expr1, expr2) tt_ptr_op((expr1), ==, (expr2)) -#define test_neq(expr1, expr2) tt_int_op((expr1), !=, (expr2)) -#define test_neq_ptr(expr1, expr2) tt_ptr_op((expr1), !=, (expr2)) -#define test_streq(expr1, expr2) tt_str_op((expr1), ==, (expr2)) -#define test_strneq(expr1, expr2) tt_str_op((expr1), !=, (expr2)) - -#define test_mem_op(expr1, op, expr2, len) \ - tt_mem_op((expr1), op, (expr2), (len)) - -#define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len) -#define test_memneq(expr1, expr2, len) test_mem_op((expr1), !=, (expr2), len) - /* As test_mem_op, but decodes 'hex' before comparing. There must be a * local char* variable called mem_op_hex_tmp for this to work. */ #define test_mem_op_hex(expr1, op, hex) \ @@ -50,7 +31,7 @@ mem_op_hex_tmp = tor_malloc(length/2); \ tor_assert((length&1)==0); \ base16_decode(mem_op_hex_tmp, length/2, hex, length); \ - test_mem_op(expr1, op, mem_op_hex_tmp, length/2); \ + tt_mem_op(expr1, op, mem_op_hex_tmp, length/2); \ STMT_END #define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, ==, hex) @@ -85,9 +66,6 @@ const char *get_fname(const char *name); crypto_pk_t *pk_generate(int idx); -void legacy_test_helper(void *data); -extern const struct testcase_setup_t legacy_setup; - #define US2_CONCAT_2__(a, b) a ## __ ## b #define US_CONCAT_2__(a, b) a ## _ ## b #define US_CONCAT_3__(a, b, c) a ## _ ## b ## _ ## c diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c new file mode 100644 index 0000000000..25908e942c --- /dev/null +++ b/src/test/test_accounting.c @@ -0,0 +1,76 @@ +#include "or.h" +#include "test.h" +#define HIBERNATE_PRIVATE +#include "hibernate.h" +#include "config.h" +#define STATEFILE_PRIVATE +#include "statefile.h" + +#define NS_MODULE accounting + +#define NS_SUBMODULE limits + +/* + * Test to make sure accounting triggers hibernation + * correctly with both sum or max rules set + */ + +static or_state_t *or_state; +NS_DECL(or_state_t *, get_or_state, (void)); +static or_state_t * +NS(get_or_state)(void) +{ + return or_state; +} + +static void +test_accounting_limits(void *arg) +{ + or_options_t *options = get_options_mutable(); + time_t fake_time = time(NULL); + (void) arg; + + NS_MOCK(get_or_state); + or_state = or_state_new(); + + options->AccountingMax = 100; + options->AccountingRule = ACCT_MAX; + + tor_assert(accounting_is_enabled(options)); + configure_accounting(fake_time); + + accounting_add_bytes(10, 0, 1); + fake_time += 1; + consider_hibernation(fake_time); + tor_assert(we_are_hibernating() == 0); + + accounting_add_bytes(90, 0, 1); + fake_time += 1; + consider_hibernation(fake_time); + tor_assert(we_are_hibernating() == 1); + + options->AccountingMax = 200; + options->AccountingRule = ACCT_SUM; + + accounting_add_bytes(0, 10, 1); + fake_time += 1; + consider_hibernation(fake_time); + tor_assert(we_are_hibernating() == 0); + + accounting_add_bytes(0, 90, 1); + fake_time += 1; + consider_hibernation(fake_time); + tor_assert(we_are_hibernating() == 1); + goto done; + done: + NS_UNMOCK(get_or_state); + or_state_free(or_state); +} + +#undef NS_SUBMODULE + +struct testcase_t accounting_tests[] = { + { "bwlimits", test_accounting_limits, TT_FORK, NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 50011e606b..043c2a0d4a 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -10,49 +10,50 @@ #include "addressmap.h" static void -test_addr_basic(void) +test_addr_basic(void *arg) { uint32_t u32; uint16_t u16; char *cp; /* Test addr_port_lookup */ + (void)arg; cp = NULL; u32 = 3; u16 = 3; - test_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16)); - test_streq(cp, "1.2.3.4"); - test_eq(u32, 0x01020304u); - test_eq(u16, 0); + tt_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16)); + tt_str_op(cp,==, "1.2.3.4"); + tt_int_op(u32,==, 0x01020304u); + tt_int_op(u16,==, 0); tor_free(cp); - test_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16)); - test_streq(cp, "4.3.2.1"); - test_eq(u32, 0x04030201u); - test_eq(u16, 99); + tt_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16)); + tt_str_op(cp,==, "4.3.2.1"); + tt_int_op(u32,==, 0x04030201u); + tt_int_op(u16,==, 99); tor_free(cp); - test_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040", + tt_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040", &cp, NULL, &u16)); - test_streq(cp, "nonexistent.address"); - test_eq(u16, 4040); + tt_str_op(cp,==, "nonexistent.address"); + tt_int_op(u16,==, 4040); tor_free(cp); - test_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16)); - test_streq(cp, "localhost"); - test_eq(u32, 0x7f000001u); - test_eq(u16, 9999); + tt_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16)); + tt_str_op(cp,==, "localhost"); + tt_int_op(u32,==, 0x7f000001u); + tt_int_op(u16,==, 9999); tor_free(cp); u32 = 3; - test_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16)); - test_eq_ptr(cp, NULL); - test_eq(u32, 0x7f000001u); - test_eq(u16, 0); + tt_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16)); + tt_ptr_op(cp,==, NULL); + tt_int_op(u32,==, 0x7f000001u); + tt_int_op(u16,==, 0); tor_free(cp); - test_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL)); + tt_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL)); tor_free(cp); - test_eq(0, addr_mask_get_bits(0x0u)); - test_eq(32, addr_mask_get_bits(0xFFFFFFFFu)); - test_eq(16, addr_mask_get_bits(0xFFFF0000u)); - test_eq(31, addr_mask_get_bits(0xFFFFFFFEu)); - test_eq(1, addr_mask_get_bits(0x80000000u)); + tt_int_op(0,==, addr_mask_get_bits(0x0u)); + tt_int_op(32,==, addr_mask_get_bits(0xFFFFFFFFu)); + tt_int_op(16,==, addr_mask_get_bits(0xFFFF0000u)); + tt_int_op(31,==, addr_mask_get_bits(0xFFFFFFFEu)); + tt_int_op(1,==, addr_mask_get_bits(0x80000000u)); /* Test inet_ntop */ { @@ -61,15 +62,15 @@ test_addr_basic(void) struct in_addr in; /* good round trip */ - test_eq(tor_inet_pton(AF_INET, ip, &in), 1); - test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)), &tmpbuf); - test_streq(tmpbuf, ip); + tt_int_op(tor_inet_pton(AF_INET, ip, &in),==, 1); + tt_ptr_op(tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)),==, &tmpbuf); + tt_str_op(tmpbuf,==, ip); /* just enough buffer length */ - test_streq(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip) + 1), ip); + tt_str_op(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip) + 1),==, ip); /* too short buffer */ - test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip)), NULL); + tt_ptr_op(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip)),==, NULL); } done: @@ -96,67 +97,68 @@ test_addr_basic(void) /** Helper: Assert that two strings both decode as IPv6 addresses with * tor_inet_pton(), and both decode to the same address. */ -#define test_pton6_same(a,b) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \ - test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \ - test_op_ip6_(&a1,==,&a2,#a,#b); \ +#define test_pton6_same(a,b) STMT_BEGIN \ + tt_int_op(tor_inet_pton(AF_INET6, a, &a1), ==, 1); \ + tt_int_op(tor_inet_pton(AF_INET6, b, &a2), ==, 1); \ + test_op_ip6_(&a1,==,&a2,#a,#b); \ STMT_END /** Helper: Assert that <b>a</b> is recognized as a bad IPv6 address by * tor_inet_pton(). */ #define test_pton6_bad(a) \ - test_eq(0, tor_inet_pton(AF_INET6, a, &a1)) + tt_int_op(0, ==, tor_inet_pton(AF_INET6, a, &a1)) /** Helper: assert that <b>a</b>, when parsed by tor_inet_pton() and displayed * with tor_inet_ntop(), yields <b>b</b>. Also assert that <b>b</b> parses to * the same value as <b>a</b>. */ -#define test_ntop6_reduces(a,b) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \ - test_streq(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), b); \ - test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \ - test_op_ip6_(&a1, ==, &a2, a, b); \ +#define test_ntop6_reduces(a,b) STMT_BEGIN \ + tt_int_op(tor_inet_pton(AF_INET6, a, &a1), ==, 1); \ + tt_str_op(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), ==, b); \ + tt_int_op(tor_inet_pton(AF_INET6, b, &a2), ==, 1); \ + test_op_ip6_(&a1, ==, &a2, a, b); \ STMT_END /** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that * passes tor_addr_is_internal() with <b>for_listening</b>. */ #define test_internal_ip(a,for_listening) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ + tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \ t1.family = AF_INET6; \ if (!tor_addr_is_internal(&t1, for_listening)) \ - test_fail_msg( a "was not internal."); \ + TT_DIE(("%s was not internal", a)); \ STMT_END /** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that * does not pass tor_addr_is_internal() with <b>for_listening</b>. */ #define test_external_ip(a,for_listening) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ + tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \ t1.family = AF_INET6; \ if (tor_addr_is_internal(&t1, for_listening)) \ - test_fail_msg(a "was not external."); \ + TT_DIE(("%s was not internal", a)); \ STMT_END /** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by * tor_inet_pton(), give addresses that compare in the order defined by * <b>op</b> with tor_addr_compare(). */ #define test_addr_compare(a, op, b) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ - test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \ + tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \ + tt_int_op(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), ==, 1); \ t1.family = t2.family = AF_INET6; \ r = tor_addr_compare(&t1,&t2,CMP_SEMANTIC); \ if (!(r op 0)) \ - test_fail_msg("failed: tor_addr_compare("a","b") "#op" 0"); \ + TT_DIE(("Failed: tor_addr_compare(%s,%s) %s 0", a, b, #op));\ STMT_END /** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by * tor_inet_pton(), give addresses that compare in the order defined by * <b>op</b> with tor_addr_compare_masked() with <b>m</b> masked. */ #define test_addr_compare_masked(a, op, b, m) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ - test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \ + tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \ + tt_int_op(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), ==, 1); \ t1.family = t2.family = AF_INET6; \ r = tor_addr_compare_masked(&t1,&t2,m,CMP_SEMANTIC); \ if (!(r op 0)) \ - test_fail_msg("failed: tor_addr_compare_masked("a","b","#m") "#op" 0"); \ + TT_DIE(("Failed: tor_addr_compare_masked(%s,%s,%d) %s 0", \ + a, b, m, #op)); \ STMT_END /** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with @@ -165,21 +167,21 @@ test_addr_basic(void) * as <b>pt1..pt2</b>. */ #define test_addr_mask_ports_parse(xx, f, ip1, ip2, ip3, ip4, mm, pt1, pt2) \ STMT_BEGIN \ - test_eq(tor_addr_parse_mask_ports(xx, 0, &t1, &mask, &port1, &port2), \ - f); \ + tt_int_op(tor_addr_parse_mask_ports(xx, 0, &t1, &mask, &port1, &port2), \ + ==, f); \ p1=tor_inet_ntop(AF_INET6, &t1.addr.in6_addr, bug, sizeof(bug)); \ - test_eq(htonl(ip1), tor_addr_to_in6_addr32(&t1)[0]); \ - test_eq(htonl(ip2), tor_addr_to_in6_addr32(&t1)[1]); \ - test_eq(htonl(ip3), tor_addr_to_in6_addr32(&t1)[2]); \ - test_eq(htonl(ip4), tor_addr_to_in6_addr32(&t1)[3]); \ - test_eq(mask, mm); \ - test_eq(port1, pt1); \ - test_eq(port2, pt2); \ + tt_int_op(htonl(ip1), ==, tor_addr_to_in6_addr32(&t1)[0]); \ + tt_int_op(htonl(ip2), ==, tor_addr_to_in6_addr32(&t1)[1]); \ + tt_int_op(htonl(ip3), ==, tor_addr_to_in6_addr32(&t1)[2]); \ + tt_int_op(htonl(ip4), ==, tor_addr_to_in6_addr32(&t1)[3]); \ + tt_int_op(mask, ==, mm); \ + tt_uint_op(port1, ==, pt1); \ + tt_uint_op(port2, ==, pt2); \ STMT_END /** Run unit tests for IPv6 encoding/decoding/manipulation functions. */ static void -test_addr_ip6_helpers(void) +test_addr_ip6_helpers(void *arg) { char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN]; char rbuf[REVERSE_LOOKUP_NAME_BUF_LEN]; @@ -194,28 +196,29 @@ test_addr_ip6_helpers(void) struct sockaddr_in6 *sin6; /* Test tor_inet_ntop and tor_inet_pton: IPv6 */ + (void)arg; { const char *ip = "2001::1234"; const char *ip_ffff = "::ffff:192.168.1.2"; /* good round trip */ - test_eq(tor_inet_pton(AF_INET6, ip, &a1), 1); - test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), &buf); - test_streq(buf, ip); + tt_int_op(tor_inet_pton(AF_INET6, ip, &a1),==, 1); + tt_ptr_op(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)),==, &buf); + tt_str_op(buf,==, ip); /* good round trip - ::ffff:0:0 style */ - test_eq(tor_inet_pton(AF_INET6, ip_ffff, &a2), 1); - test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)), &buf); - test_streq(buf, ip_ffff); + tt_int_op(tor_inet_pton(AF_INET6, ip_ffff, &a2),==, 1); + tt_ptr_op(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)),==, &buf); + tt_str_op(buf,==, ip_ffff); /* just long enough buffer (remember \0) */ - test_streq(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1), ip); - test_streq(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1), + tt_str_op(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1),==, ip); + tt_str_op(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1),==, ip_ffff); /* too short buffer (remember \0) */ - test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)), NULL); - test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)), NULL); + tt_ptr_op(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)),==, NULL); + tt_ptr_op(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)),==, NULL); } /* ==== Converting to and from sockaddr_t. */ @@ -224,16 +227,16 @@ test_addr_ip6_helpers(void) sin->sin_port = htons(9090); sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/ tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, &port1); - test_eq(tor_addr_family(&t1), AF_INET); - test_eq(tor_addr_to_ipv4h(&t1), 0x7f7f0102); + tt_int_op(tor_addr_family(&t1),==, AF_INET); + tt_int_op(tor_addr_to_ipv4h(&t1),==, 0x7f7f0102); tt_int_op(port1, ==, 9090); memset(&sa_storage, 0, sizeof(sa_storage)); - test_eq(sizeof(struct sockaddr_in), + tt_int_op(sizeof(struct sockaddr_in),==, tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage, sizeof(sa_storage))); - test_eq(1234, ntohs(sin->sin_port)); - test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr)); + tt_int_op(1234,==, ntohs(sin->sin_port)); + tt_int_op(0x7f7f0102,==, ntohl(sin->sin_addr.s_addr)); memset(&sa_storage, 0, sizeof(sa_storage)); sin6 = (struct sockaddr_in6 *)&sa_storage; @@ -241,37 +244,37 @@ test_addr_ip6_helpers(void) sin6->sin6_port = htons(7070); sin6->sin6_addr.s6_addr[0] = 128; tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, &port1); - test_eq(tor_addr_family(&t1), AF_INET6); + tt_int_op(tor_addr_family(&t1),==, AF_INET6); tt_int_op(port1, ==, 7070); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); - test_streq(p1, "8000::"); + tt_str_op(p1,==, "8000::"); memset(&sa_storage, 0, sizeof(sa_storage)); - test_eq(sizeof(struct sockaddr_in6), + tt_int_op(sizeof(struct sockaddr_in6),==, tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage, sizeof(sa_storage))); - test_eq(AF_INET6, sin6->sin6_family); - test_eq(9999, ntohs(sin6->sin6_port)); - test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0])); + tt_int_op(AF_INET6,==, sin6->sin6_family); + tt_int_op(9999,==, ntohs(sin6->sin6_port)); + tt_int_op(0x80000000,==, ntohl(S6_ADDR32(sin6->sin6_addr)[0])); /* ==== tor_addr_lookup: static cases. (Can't test dns without knowing we * have a good resolver. */ - test_eq(0, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1)); - test_eq(AF_INET, tor_addr_family(&t1)); - test_eq(tor_addr_to_ipv4h(&t1), 0x7f808182); + tt_int_op(0,==, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1)); + tt_int_op(AF_INET,==, tor_addr_family(&t1)); + tt_int_op(tor_addr_to_ipv4h(&t1),==, 0x7f808182); - test_eq(0, tor_addr_lookup("9000::5", AF_UNSPEC, &t1)); - test_eq(AF_INET6, tor_addr_family(&t1)); - test_eq(0x90, tor_addr_to_in6_addr8(&t1)[0]); - test_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14)); - test_eq(0x05, tor_addr_to_in6_addr8(&t1)[15]); + tt_int_op(0,==, tor_addr_lookup("9000::5", AF_UNSPEC, &t1)); + tt_int_op(AF_INET6,==, tor_addr_family(&t1)); + tt_int_op(0x90,==, tor_addr_to_in6_addr8(&t1)[0]); + tt_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14)); + tt_int_op(0x05,==, tor_addr_to_in6_addr8(&t1)[15]); /* === Test pton: valid af_inet6 */ /* Simple, valid parsing. */ r = tor_inet_pton(AF_INET6, "0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1); - test_assert(r==1); - for (i=0;i<16;++i) { test_eq(i+1, (int)a1.s6_addr[i]); } + tt_int_op(r, ==, 1); + for (i=0;i<16;++i) { tt_int_op(i+1,==, (int)a1.s6_addr[i]); } /* ipv4 ending. */ test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10", "0102:0304:0506:0708:090A:0B0C:13.14.15.16"); @@ -311,7 +314,7 @@ test_addr_ip6_helpers(void) "1000:1:0:7::"); /* Bad af param */ - test_eq(tor_inet_pton(AF_UNSPEC, 0, 0), -1); + tt_int_op(tor_inet_pton(AF_UNSPEC, 0, 0),==, -1); /* === Test pton: invalid in6. */ test_pton6_bad("foobar."); @@ -414,10 +417,10 @@ test_addr_ip6_helpers(void) test_addr_compare("0::ffff:5.2.2.1", <, "::ffff:6.0.0.0"); /* XXXX wrong. */ tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", 0, &t1, NULL, NULL, NULL); tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL); - test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0); + tt_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0); tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", 0, &t1, NULL, NULL, NULL); tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL); - test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0); + tt_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0); /* test compare_masked */ test_addr_compare_masked("ffff::", ==, "ffff::0", 128); @@ -426,113 +429,113 @@ test_addr_ip6_helpers(void) test_addr_compare_masked("0::2:2:1", ==, "0::8000:2:1", 80); /* Test undecorated tor_addr_to_str */ - test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]")); + tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "[123:45:6789::5005:11]")); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); - test_streq(p1, "123:45:6789::5005:11"); - test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1")); + tt_str_op(p1,==, "123:45:6789::5005:11"); + tt_int_op(AF_INET,==, tor_addr_parse(&t1, "18.0.0.1")); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); - test_streq(p1, "18.0.0.1"); + tt_str_op(p1,==, "18.0.0.1"); /* Test decorated tor_addr_to_str */ - test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]")); + tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "[123:45:6789::5005:11]")); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); - test_streq(p1, "[123:45:6789::5005:11]"); - test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1")); + tt_str_op(p1,==, "[123:45:6789::5005:11]"); + tt_int_op(AF_INET,==, tor_addr_parse(&t1, "18.0.0.1")); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); - test_streq(p1, "18.0.0.1"); + tt_str_op(p1,==, "18.0.0.1"); /* Test buffer bounds checking of tor_addr_to_str */ - test_eq(AF_INET6, tor_addr_parse(&t1, "::")); /* 2 + \0 */ - test_eq_ptr(tor_addr_to_str(buf, &t1, 2, 0), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 3, 0), "::"); - test_eq_ptr(tor_addr_to_str(buf, &t1, 4, 1), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 5, 1), "[::]"); - - test_eq(AF_INET6, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */ - test_eq_ptr(tor_addr_to_str(buf, &t1, 10, 0), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 11, 0), "2000::1337"); - test_eq_ptr(tor_addr_to_str(buf, &t1, 12, 1), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 13, 1), "[2000::1337]"); - - test_eq(AF_INET, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */ - test_eq_ptr(tor_addr_to_str(buf, &t1, 7, 0), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 8, 0), "1.2.3.4"); - - test_eq(AF_INET, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */ - test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 0), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 16, 0), "255.255.255.255"); - test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 1), NULL); /* too short buf */ - test_streq(tor_addr_to_str(buf, &t1, 16, 1), "255.255.255.255"); + tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "::")); /* 2 + \0 */ + tt_ptr_op(tor_addr_to_str(buf, &t1, 2, 0),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 3, 0),==, "::"); + tt_ptr_op(tor_addr_to_str(buf, &t1, 4, 1),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 5, 1),==, "[::]"); + + tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */ + tt_ptr_op(tor_addr_to_str(buf, &t1, 10, 0),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 11, 0),==, "2000::1337"); + tt_ptr_op(tor_addr_to_str(buf, &t1, 12, 1),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 13, 1),==, "[2000::1337]"); + + tt_int_op(AF_INET,==, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */ + tt_ptr_op(tor_addr_to_str(buf, &t1, 7, 0),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 8, 0),==, "1.2.3.4"); + + tt_int_op(AF_INET,==, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */ + tt_ptr_op(tor_addr_to_str(buf, &t1, 15, 0),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 16, 0),==, "255.255.255.255"); + tt_ptr_op(tor_addr_to_str(buf, &t1, 15, 1),==, NULL); /* too short buf */ + tt_str_op(tor_addr_to_str(buf, &t1, 16, 1),==, "255.255.255.255"); t1.family = AF_UNSPEC; - test_eq_ptr(tor_addr_to_str(buf, &t1, sizeof(buf), 0), NULL); + tt_ptr_op(tor_addr_to_str(buf, &t1, sizeof(buf), 0),==, NULL); /* Test tor_addr_parse_PTR_name */ i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 0); - test_eq(0, i); + tt_int_op(0,==, i); i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 1); - test_eq(0, i); + tt_int_op(0,==, i); i = tor_addr_parse_PTR_name(&t1, "9999999999999999999999999999.in-addr.arpa", AF_UNSPEC, 1); - test_eq(-1, i); + tt_int_op(-1,==, i); i = tor_addr_parse_PTR_name(&t1, "1.0.168.192.in-addr.arpa", AF_UNSPEC, 1); - test_eq(1, i); - test_eq(tor_addr_family(&t1), AF_INET); + tt_int_op(1,==, i); + tt_int_op(tor_addr_family(&t1),==, AF_INET); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); - test_streq(p1, "192.168.0.1"); + tt_str_op(p1,==, "192.168.0.1"); i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 0); - test_eq(0, i); + tt_int_op(0,==, i); i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 1); - test_eq(1, i); + tt_int_op(1,==, i); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); - test_streq(p1, "192.168.0.99"); + tt_str_op(p1,==, "192.168.0.99"); memset(&t1, 0, sizeof(t1)); i = tor_addr_parse_PTR_name(&t1, "0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); - test_eq(1, i); + tt_int_op(1,==, i); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); - test_streq(p1, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]"); + tt_str_op(p1,==, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]"); /* Failing cases. */ i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.f.0." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f.X.0.0.0.0.9." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, "32.1.1.in-addr.arpa", AF_UNSPEC, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, ".in-addr.arpa", AF_UNSPEC, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa", AF_UNSPEC, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa", AF_INET6, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.0." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_INET, 0); - test_eq(i, -1); + tt_int_op(i,==, -1); /* === Test tor_addr_to_PTR_name */ @@ -544,19 +547,19 @@ test_addr_ip6_helpers(void) tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL); /* Check IPv4 PTR - too short buffer */ - test_eq(tor_addr_to_PTR_name(rbuf, 1, &t1), -1); - test_eq(tor_addr_to_PTR_name(rbuf, + tt_int_op(tor_addr_to_PTR_name(rbuf, 1, &t1),==, -1); + tt_int_op(tor_addr_to_PTR_name(rbuf, strlen("3.2.1.127.in-addr.arpa") - 1, - &t1), -1); + &t1),==, -1); /* Check IPv4 PTR - valid addr */ - test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), + tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),==, strlen("3.2.1.127.in-addr.arpa")); - test_streq(rbuf, "3.2.1.127.in-addr.arpa"); + tt_str_op(rbuf,==, "3.2.1.127.in-addr.arpa"); /* Invalid addr family */ t1.family = AF_UNSPEC; - test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), -1); + tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),==, -1); /* Stage IPv6 addr */ memset(&sa_storage, 0, sizeof(sa_storage)); @@ -573,114 +576,114 @@ test_addr_ip6_helpers(void) "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.ip6.arpa"; /* Check IPv6 PTR - too short buffer */ - test_eq(tor_addr_to_PTR_name(rbuf, 0, &t1), -1); - test_eq(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1), -1); + tt_int_op(tor_addr_to_PTR_name(rbuf, 0, &t1),==, -1); + tt_int_op(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1),==, -1); /* Check IPv6 PTR - valid addr */ - test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), + tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),==, strlen(addr_PTR)); - test_streq(rbuf, addr_PTR); + tt_str_op(rbuf,==, addr_PTR); } /* XXXX turn this into a separate function; it's not all IPv6. */ /* test tor_addr_parse_mask_ports */ test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6, 0, 0, 0, 0x0000000f, 17, 47, 95); - test_streq(p1, "::f"); + tt_str_op(p1,==, "::f"); //test_addr_parse("[::fefe:4.1.1.7/120]:999-1000"); //test_addr_parse_check("::fefe:401:107", 120, 999, 1000); test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6, 0, 0, 0x0000ffff, 0x04010107, 120, 443, 443); - test_streq(p1, "::ffff:4.1.1.7"); + tt_str_op(p1,==, "::ffff:4.1.1.7"); test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6, 0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000); - test_streq(p1, "abcd:2::44a:0"); + tt_str_op(p1,==, "abcd:2::44a:0"); /* Try some long addresses. */ r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111]", 0, &t1, NULL, NULL, NULL); - test_assert(r == AF_INET6); + tt_assert(r == AF_INET6); r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:11111]", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111:1]", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports( "[ffff:1111:1111:1111:1111:1111:1111:ffff:" "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:" "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:" "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Try some failing cases. */ r=tor_addr_parse_mask_ports("[fefef::]/112", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[fefe::/112", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[fefe::", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[fefe::X]", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("efef::/112", 0, &t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]",0,&t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/fred",0,&t1,&mask, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/255.255.0.0", 0,&t1, NULL, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* This one will get rejected because it isn't a pure prefix. */ r=tor_addr_parse_mask_ports("1.1.2.3/255.255.64.0",0,&t1, &mask,NULL,NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Test for V4-mapped address with mask < 96. (arguably not valid) */ r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]",0,&t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("1.1.2.2/33",0,&t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Try extended wildcard addresses with out TAPMP_EXTENDED_STAR*/ r=tor_addr_parse_mask_ports("*4",0,&t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); r=tor_addr_parse_mask_ports("*6",0,&t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_int_op(r, ==, -1); #if 0 /* Try a mask with a wildcard. */ r=tor_addr_parse_mask_ports("*/16",0,&t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_assert(r == -1); r=tor_addr_parse_mask_ports("*4/16",TAPMP_EXTENDED_STAR, &t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_assert(r == -1); r=tor_addr_parse_mask_ports("*6/30",TAPMP_EXTENDED_STAR, &t1, &mask, NULL, NULL); - test_assert(r == -1); + tt_assert(r == -1); #endif /* Basic mask tests*/ r=tor_addr_parse_mask_ports("1.1.2.2/31",0,&t1, &mask, NULL, NULL); - test_assert(r == AF_INET); + tt_assert(r == AF_INET); tt_int_op(mask,==,31); tt_int_op(tor_addr_family(&t1),==,AF_INET); tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010202); r=tor_addr_parse_mask_ports("3.4.16.032:1-2",0,&t1, &mask, &port1, &port2); - test_assert(r == AF_INET); + tt_assert(r == AF_INET); tt_int_op(mask,==,32); tt_int_op(tor_addr_family(&t1),==,AF_INET); tt_int_op(tor_addr_to_ipv4h(&t1),==,0x03041020); - test_assert(port1 == 1); - test_assert(port2 == 2); + tt_assert(port1 == 1); + tt_assert(port2 == 2); r=tor_addr_parse_mask_ports("1.1.2.3/255.255.128.0",0,&t1, &mask,NULL,NULL); - test_assert(r == AF_INET); + tt_assert(r == AF_INET); tt_int_op(mask,==,17); tt_int_op(tor_addr_family(&t1),==,AF_INET); tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010203); r=tor_addr_parse_mask_ports("[efef::]/112",0,&t1, &mask, &port1, &port2); - test_assert(r == AF_INET6); - test_assert(port1 == 1); - test_assert(port2 == 65535); + tt_assert(r == AF_INET6); + tt_assert(port1 == 1); + tt_assert(port2 == 65535); /* Try regular wildcard behavior without TAPMP_EXTENDED_STAR */ r=tor_addr_parse_mask_ports("*:80-443",0,&t1,&mask,&port1,&port2); tt_int_op(r,==,AF_INET); /* Old users of this always get inet */ @@ -715,11 +718,11 @@ test_addr_ip6_helpers(void) tt_int_op(port2,==,65535); /* make sure inet address lengths >= max */ - test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255")); - test_assert(TOR_ADDR_BUF_LEN >= + tt_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255")); + tt_assert(TOR_ADDR_BUF_LEN >= sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")); - test_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr)); + tt_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr)); /* get interface addresses */ r = get_interface_address6(LOG_DEBUG, AF_INET, &t1); @@ -736,7 +739,7 @@ test_addr_ip6_helpers(void) /** Test tor_addr_port_parse(). */ static void -test_addr_parse(void) +test_addr_parse(void *arg) { int r; tor_addr_t addr; @@ -744,89 +747,90 @@ test_addr_parse(void) uint16_t port = 0; /* Correct call. */ + (void)arg; r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.1:1234", &addr, &port, -1); - test_assert(r == 0); + tt_int_op(r, ==, 0); tor_addr_to_str(buf, &addr, sizeof(buf), 0); - test_streq(buf, "192.0.2.1"); - test_eq(port, 1234); + tt_str_op(buf,==, "192.0.2.1"); + tt_int_op(port,==, 1234); r= tor_addr_port_parse(LOG_DEBUG, "[::1]:1234", &addr, &port, -1); - test_assert(r == 0); + tt_int_op(r, ==, 0); tor_addr_to_str(buf, &addr, sizeof(buf), 0); - test_streq(buf, "::1"); - test_eq(port, 1234); + tt_str_op(buf,==, "::1"); + tt_int_op(port,==, 1234); /* Domain name. */ r= tor_addr_port_parse(LOG_DEBUG, "torproject.org:1234", &addr, &port, -1); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Only IP. */ r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.2", &addr, &port, -1); - test_assert(r == -1); + tt_int_op(r, ==, -1); r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.2", &addr, &port, 200); - test_assert(r == 0); + tt_int_op(r, ==, 0); tt_int_op(port,==,200); r= tor_addr_port_parse(LOG_DEBUG, "[::1]", &addr, &port, -1); - test_assert(r == -1); + tt_int_op(r, ==, -1); r= tor_addr_port_parse(LOG_DEBUG, "[::1]", &addr, &port, 400); - test_assert(r == 0); + tt_int_op(r, ==, 0); tt_int_op(port,==,400); /* Bad port. */ r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.2:66666", &addr, &port, -1); - test_assert(r == -1); + tt_int_op(r, ==, -1); r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.2:66666", &addr, &port, 200); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Only domain name */ r= tor_addr_port_parse(LOG_DEBUG, "torproject.org", &addr, &port, -1); - test_assert(r == -1); + tt_int_op(r, ==, -1); r= tor_addr_port_parse(LOG_DEBUG, "torproject.org", &addr, &port, 200); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Bad IP address */ r= tor_addr_port_parse(LOG_DEBUG, "192.0.2:1234", &addr, &port, -1); - test_assert(r == -1); + tt_int_op(r, ==, -1); /* Make sure that the default port has lower priority than the real one */ r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.2:1337", &addr, &port, 200); - test_assert(r == 0); + tt_int_op(r, ==, 0); tt_int_op(port,==,1337); r= tor_addr_port_parse(LOG_DEBUG, "[::1]:1369", &addr, &port, 200); - test_assert(r == 0); + tt_int_op(r, ==, 0); tt_int_op(port,==,1369); done: @@ -1047,7 +1051,7 @@ test_addr_make_null(void *data) } #define ADDR_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_addr_ ## name } + { #name, test_addr_ ## name , 0, NULL, NULL } struct testcase_t addr_tests[] = { ADDR_LEGACY(basic), diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c index 45ae82fb85..720ccd4627 100644 --- a/src/test/test_bt_cl.c +++ b/src/test/test_bt_cl.c @@ -30,7 +30,12 @@ int crash(int x) { if (crashtype == 0) { +#if defined(__clang_analyzer__) || defined(__COVERITY__) + tor_assert(1 == 0); /* Avert your eyes, clangalyzer and coverity! You + * don't need to see us dereference NULL. */ +#else *(volatile int *)0 = 0; +#endif } else if (crashtype == 1) { tor_assert(1 == 0); } else if (crashtype == -1) { diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index f24b80f0b0..3ab3d8d8c0 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -27,10 +27,10 @@ test_buffers_basic(void *arg) * buf_new ****/ if (!(buf = buf_new())) - test_fail(); + TT_DIE(("Assertion failed.")); //test_eq(buf_capacity(buf), 4096); - test_eq(buf_datalen(buf), 0); + tt_int_op(buf_datalen(buf),==, 0); /**** * General pointer frobbing @@ -40,16 +40,16 @@ test_buffers_basic(void *arg) } write_to_buf(str, 256, buf); write_to_buf(str, 256, buf); - test_eq(buf_datalen(buf), 512); + tt_int_op(buf_datalen(buf),==, 512); fetch_from_buf(str2, 200, buf); - test_memeq(str, str2, 200); - test_eq(buf_datalen(buf), 312); + tt_mem_op(str,==, str2, 200); + tt_int_op(buf_datalen(buf),==, 312); memset(str2, 0, sizeof(str2)); fetch_from_buf(str2, 256, buf); - test_memeq(str+200, str2, 56); - test_memeq(str, str2+56, 200); - test_eq(buf_datalen(buf), 56); + tt_mem_op(str+200,==, str2, 56); + tt_mem_op(str,==, str2+56, 200); + tt_int_op(buf_datalen(buf),==, 56); memset(str2, 0, sizeof(str2)); /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add * another 3584 bytes, we hit the end. */ @@ -57,16 +57,16 @@ test_buffers_basic(void *arg) write_to_buf(str, 256, buf); } assert_buf_ok(buf); - test_eq(buf_datalen(buf), 3896); + tt_int_op(buf_datalen(buf),==, 3896); fetch_from_buf(str2, 56, buf); - test_eq(buf_datalen(buf), 3840); - test_memeq(str+200, str2, 56); + tt_int_op(buf_datalen(buf),==, 3840); + tt_mem_op(str+200,==, str2, 56); for (j=0;j<15;++j) { memset(str2, 0, sizeof(str2)); fetch_from_buf(str2, 256, buf); - test_memeq(str, str2, 256); + tt_mem_op(str,==, str2, 256); } - test_eq(buf_datalen(buf), 0); + tt_int_op(buf_datalen(buf),==, 0); buf_free(buf); buf = NULL; @@ -76,7 +76,7 @@ test_buffers_basic(void *arg) write_to_buf(str+1, 255, buf); //test_eq(buf_capacity(buf), 256); fetch_from_buf(str2, 254, buf); - test_memeq(str+1, str2, 254); + tt_mem_op(str+1,==, str2, 254); //test_eq(buf_capacity(buf), 256); assert_buf_ok(buf); write_to_buf(str, 32, buf); @@ -85,15 +85,15 @@ test_buffers_basic(void *arg) write_to_buf(str, 256, buf); assert_buf_ok(buf); //test_eq(buf_capacity(buf), 512); - test_eq(buf_datalen(buf), 33+256); + tt_int_op(buf_datalen(buf),==, 33+256); fetch_from_buf(str2, 33, buf); - test_eq(*str2, str[255]); + tt_int_op(*str2,==, str[255]); - test_memeq(str2+1, str, 32); + tt_mem_op(str2+1,==, str, 32); //test_eq(buf_capacity(buf), 512); - test_eq(buf_datalen(buf), 256); + tt_int_op(buf_datalen(buf),==, 256); fetch_from_buf(str2, 256, buf); - test_memeq(str, str2, 256); + tt_mem_op(str,==, str2, 256); /* now try shrinking: case 1. */ buf_free(buf); @@ -102,10 +102,10 @@ test_buffers_basic(void *arg) write_to_buf(str,255, buf); } //test_eq(buf_capacity(buf), 33668); - test_eq(buf_datalen(buf), 17085); + tt_int_op(buf_datalen(buf),==, 17085); for (j=0; j < 40; ++j) { fetch_from_buf(str2, 255,buf); - test_memeq(str2, str, 255); + tt_mem_op(str2,==, str, 255); } /* now try shrinking: case 2. */ @@ -116,7 +116,7 @@ test_buffers_basic(void *arg) } for (j=0; j < 20; ++j) { fetch_from_buf(str2, 255,buf); - test_memeq(str2, str, 255); + tt_mem_op(str2,==, str, 255); } for (j=0;j<80;++j) { write_to_buf(str,255, buf); @@ -124,7 +124,7 @@ test_buffers_basic(void *arg) //test_eq(buf_capacity(buf),33668); for (j=0; j < 120; ++j) { fetch_from_buf(str2, 255,buf); - test_memeq(str2, str, 255); + tt_mem_op(str2,==, str, 255); } /* Move from buf to buf. */ @@ -133,27 +133,27 @@ test_buffers_basic(void *arg) buf2 = buf_new_with_capacity(4096); for (j=0;j<100;++j) write_to_buf(str, 255, buf); - test_eq(buf_datalen(buf), 25500); + tt_int_op(buf_datalen(buf),==, 25500); for (j=0;j<100;++j) { r = 10; move_buf_to_buf(buf2, buf, &r); - test_eq(r, 0); + tt_int_op(r,==, 0); } - test_eq(buf_datalen(buf), 24500); - test_eq(buf_datalen(buf2), 1000); + tt_int_op(buf_datalen(buf),==, 24500); + tt_int_op(buf_datalen(buf2),==, 1000); for (j=0;j<3;++j) { fetch_from_buf(str2, 255, buf2); - test_memeq(str2, str, 255); + tt_mem_op(str2,==, str, 255); } r = 8192; /*big move*/ move_buf_to_buf(buf2, buf, &r); - test_eq(r, 0); + tt_int_op(r,==, 0); r = 30000; /* incomplete move */ move_buf_to_buf(buf2, buf, &r); - test_eq(r, 13692); + tt_int_op(r,==, 13692); for (j=0;j<97;++j) { fetch_from_buf(str2, 255, buf2); - test_memeq(str2, str, 255); + tt_mem_op(str2,==, str, 255); } buf_free(buf); buf_free(buf2); @@ -163,16 +163,16 @@ test_buffers_basic(void *arg) cp = "Testing. This is a moderately long Testing string."; for (j = 0; cp[j]; j++) write_to_buf(cp+j, 1, buf); - test_eq(0, buf_find_string_offset(buf, "Testing", 7)); - test_eq(1, buf_find_string_offset(buf, "esting", 6)); - test_eq(1, buf_find_string_offset(buf, "est", 3)); - test_eq(39, buf_find_string_offset(buf, "ing str", 7)); - test_eq(35, buf_find_string_offset(buf, "Testing str", 11)); - test_eq(32, buf_find_string_offset(buf, "ng ", 3)); - test_eq(43, buf_find_string_offset(buf, "string.", 7)); - test_eq(-1, buf_find_string_offset(buf, "shrdlu", 6)); - test_eq(-1, buf_find_string_offset(buf, "Testing thing", 13)); - test_eq(-1, buf_find_string_offset(buf, "ngx", 3)); + tt_int_op(0,==, buf_find_string_offset(buf, "Testing", 7)); + tt_int_op(1,==, buf_find_string_offset(buf, "esting", 6)); + tt_int_op(1,==, buf_find_string_offset(buf, "est", 3)); + tt_int_op(39,==, buf_find_string_offset(buf, "ing str", 7)); + tt_int_op(35,==, buf_find_string_offset(buf, "Testing str", 11)); + tt_int_op(32,==, buf_find_string_offset(buf, "ng ", 3)); + tt_int_op(43,==, buf_find_string_offset(buf, "string.", 7)); + tt_int_op(-1,==, buf_find_string_offset(buf, "shrdlu", 6)); + tt_int_op(-1,==, buf_find_string_offset(buf, "Testing thing", 13)); + tt_int_op(-1,==, buf_find_string_offset(buf, "ngx", 3)); buf_free(buf); buf = NULL; @@ -240,16 +240,16 @@ test_buffer_pullup(void *arg) /* Make room for 3000 bytes in the first chunk, so that the pullup-move code * can get tested. */ tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 3000); - test_memeq(tmp, stuff, 3000); + tt_mem_op(tmp,==, stuff, 3000); buf_pullup(buf, 2048, 0); assert_buf_ok(buf); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, !=, NULL); tt_int_op(sz, >=, 2048); - test_memeq(cp, stuff+3000, 2048); + tt_mem_op(cp,==, stuff+3000, 2048); tt_int_op(3000, ==, buf_datalen(buf)); tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 0); - test_memeq(tmp, stuff+3000, 2048); + tt_mem_op(tmp,==, stuff+3000, 2048); buf_free(buf); @@ -269,16 +269,16 @@ test_buffer_pullup(void *arg) buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, !=, NULL); tt_int_op(sz, >=, 12500); - test_memeq(cp, stuff, 12500); + tt_mem_op(cp,==, stuff, 12500); tt_int_op(buf_datalen(buf), ==, 16000); fetch_from_buf(tmp, 12400, buf); - test_memeq(tmp, stuff, 12400); + tt_mem_op(tmp,==, stuff, 12400); tt_int_op(buf_datalen(buf), ==, 3600); fetch_from_buf(tmp, 3500, buf); - test_memeq(tmp, stuff+12400, 3500); + tt_mem_op(tmp,==, stuff+12400, 3500); fetch_from_buf(tmp, 100, buf); - test_memeq(tmp, stuff+15900, 10); + tt_mem_op(tmp,==, stuff+15900, 10); buf_free(buf); @@ -292,7 +292,7 @@ test_buffer_pullup(void *arg) buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, !=, NULL); tt_int_op(sz, ==, 7900); - test_memeq(cp, stuff+100, 7900); + tt_mem_op(cp,==, stuff+100, 7900); buf_free(buf); buf = NULL; @@ -335,14 +335,14 @@ test_buffer_copy(void *arg) tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf)); tt_int_op(len, ==, generic_buffer_len(buf2)); generic_buffer_get(buf2, b, len); - test_mem_op(b, ==, s, len); + tt_mem_op(b, ==, s, len); /* Now free buf2 and retry so we can test allocating */ generic_buffer_free(buf2); buf2 = NULL; tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf)); tt_int_op(len, ==, generic_buffer_len(buf2)); generic_buffer_get(buf2, b, len); - test_mem_op(b, ==, s, len); + tt_mem_op(b, ==, s, len); /* Clear buf for next test */ generic_buffer_get(buf, b, len); tt_int_op(generic_buffer_len(buf),==,0); @@ -362,7 +362,7 @@ test_buffer_copy(void *arg) for (i = 0; i < 256; ++i) { generic_buffer_get(buf2, b, len+1); tt_int_op((unsigned char)b[0],==,i); - test_mem_op(b+1, ==, s, len); + tt_mem_op(b+1, ==, s, len); } done: @@ -410,7 +410,7 @@ test_buffer_ext_or_cmd(void *arg) tt_ptr_op(NULL, !=, cmd); tt_int_op(0x1021, ==, cmd->cmd); tt_int_op(6, ==, cmd->len); - test_mem_op("abcdef", ==, cmd->body, 6); + tt_mem_op("abcdef", ==, cmd->body, 6); tt_int_op(0, ==, generic_buffer_len(buf)); ext_or_cmd_free(cmd); cmd = NULL; @@ -422,7 +422,7 @@ test_buffer_ext_or_cmd(void *arg) tt_ptr_op(NULL, !=, cmd); tt_int_op(0xffff, ==, cmd->cmd); tt_int_op(10, ==, cmd->len); - test_mem_op("loremipsum", ==, cmd->body, 10); + tt_mem_op("loremipsum", ==, cmd->body, 10); tt_int_op(4, ==, generic_buffer_len(buf)); ext_or_cmd_free(cmd); cmd = NULL; @@ -436,7 +436,7 @@ test_buffer_ext_or_cmd(void *arg) tt_ptr_op(NULL, !=, cmd); tt_int_op(0x1000, ==, cmd->cmd); tt_int_op(0xffff, ==, cmd->len); - test_mem_op(tmp, ==, cmd->body, 65535); + tt_mem_op(tmp, ==, cmd->body, 65535); tt_int_op(0, ==, generic_buffer_len(buf)); ext_or_cmd_free(cmd); cmd = NULL; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index d7f60680c2..995e519163 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -35,11 +35,11 @@ test_cfmt_relay_header(void *arg) tt_int_op(rh.command, ==, 3); tt_int_op(rh.recognized, ==, 0); tt_int_op(rh.stream_id, ==, 0x2122); - test_mem_op(rh.integrity, ==, "ABCD", 4); + tt_mem_op(rh.integrity, ==, "ABCD", 4); tt_int_op(rh.length, ==, 0x103); relay_header_pack(hdr_out, &rh); - test_mem_op(hdr_out, ==, hdr_1, RELAY_HEADER_SIZE); + tt_mem_op(hdr_out, ==, hdr_1, RELAY_HEADER_SIZE); done: ; @@ -402,10 +402,10 @@ test_cfmt_create_cells(void *arg) tt_int_op(CELL_CREATE, ==, cc.cell_type); tt_int_op(ONION_HANDSHAKE_TYPE_TAP, ==, cc.handshake_type); tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, ==, cc.handshake_len); - test_memeq(cc.onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); + tt_mem_op(cc.onionskin,==, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); tt_int_op(0, ==, create_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* A valid create_fast cell. */ memset(&cell, 0, sizeof(cell)); @@ -417,10 +417,10 @@ test_cfmt_create_cells(void *arg) tt_int_op(CELL_CREATE_FAST, ==, cc.cell_type); tt_int_op(ONION_HANDSHAKE_TYPE_FAST, ==, cc.handshake_type); tt_int_op(CREATE_FAST_LEN, ==, cc.handshake_len); - test_memeq(cc.onionskin, b, CREATE_FAST_LEN + 10); + tt_mem_op(cc.onionskin,==, b, CREATE_FAST_LEN + 10); tt_int_op(0, ==, create_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* A valid create2 cell with a TAP payload */ memset(&cell, 0, sizeof(cell)); @@ -433,10 +433,10 @@ test_cfmt_create_cells(void *arg) tt_int_op(CELL_CREATE2, ==, cc.cell_type); tt_int_op(ONION_HANDSHAKE_TYPE_TAP, ==, cc.handshake_type); tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, ==, cc.handshake_len); - test_memeq(cc.onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); + tt_mem_op(cc.onionskin,==, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); tt_int_op(0, ==, create_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* A valid create2 cell with an ntor payload */ memset(&cell, 0, sizeof(cell)); @@ -450,10 +450,10 @@ test_cfmt_create_cells(void *arg) tt_int_op(CELL_CREATE2, ==, cc.cell_type); tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, ==, cc.handshake_type); tt_int_op(NTOR_ONIONSKIN_LEN, ==, cc.handshake_len); - test_memeq(cc.onionskin, b, NTOR_ONIONSKIN_LEN + 10); + tt_mem_op(cc.onionskin,==, b, NTOR_ONIONSKIN_LEN + 10); tt_int_op(0, ==, create_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); #else tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); #endif @@ -470,10 +470,10 @@ test_cfmt_create_cells(void *arg) tt_int_op(CELL_CREATE, ==, cc.cell_type); tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, ==, cc.handshake_type); tt_int_op(NTOR_ONIONSKIN_LEN, ==, cc.handshake_len); - test_memeq(cc.onionskin, b, NTOR_ONIONSKIN_LEN + 10); + tt_mem_op(cc.onionskin,==, b, NTOR_ONIONSKIN_LEN + 10); tt_int_op(0, ==, create_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); #else tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); #endif @@ -527,10 +527,10 @@ test_cfmt_created_cells(void *arg) tt_int_op(0, ==, created_cell_parse(&cc, &cell)); tt_int_op(CELL_CREATED, ==, cc.cell_type); tt_int_op(TAP_ONIONSKIN_REPLY_LEN, ==, cc.handshake_len); - test_memeq(cc.reply, b, TAP_ONIONSKIN_REPLY_LEN + 10); + tt_mem_op(cc.reply,==, b, TAP_ONIONSKIN_REPLY_LEN + 10); tt_int_op(0, ==, created_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* A good CREATED_FAST cell */ memset(&cell, 0, sizeof(cell)); @@ -541,10 +541,10 @@ test_cfmt_created_cells(void *arg) tt_int_op(0, ==, created_cell_parse(&cc, &cell)); tt_int_op(CELL_CREATED_FAST, ==, cc.cell_type); tt_int_op(CREATED_FAST_LEN, ==, cc.handshake_len); - test_memeq(cc.reply, b, CREATED_FAST_LEN + 10); + tt_mem_op(cc.reply,==, b, CREATED_FAST_LEN + 10); tt_int_op(0, ==, created_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* A good CREATED2 cell with short reply */ memset(&cell, 0, sizeof(cell)); @@ -556,10 +556,10 @@ test_cfmt_created_cells(void *arg) tt_int_op(0, ==, created_cell_parse(&cc, &cell)); tt_int_op(CELL_CREATED2, ==, cc.cell_type); tt_int_op(64, ==, cc.handshake_len); - test_memeq(cc.reply, b, 80); + tt_mem_op(cc.reply,==, b, 80); tt_int_op(0, ==, created_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* A good CREATED2 cell with maximal reply */ memset(&cell, 0, sizeof(cell)); @@ -571,10 +571,10 @@ test_cfmt_created_cells(void *arg) tt_int_op(0, ==, created_cell_parse(&cc, &cell)); tt_int_op(CELL_CREATED2, ==, cc.cell_type); tt_int_op(496, ==, cc.handshake_len); - test_memeq(cc.reply, b, 496); + tt_mem_op(cc.reply,==, b, 496); tt_int_op(0, ==, created_cell_format(&cell2, &cc)); tt_int_op(cell.command, ==, cell2.command); - test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE); /* Bogus CREATED2 cell: too long! */ memset(&cell, 0, sizeof(cell)); @@ -620,15 +620,15 @@ test_cfmt_extend_cells(void *arg) tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); tt_int_op(258, ==, ec.orport_ipv4.port); tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr)); - test_memeq(ec.node_id, "electroencephalogram", 20); + tt_mem_op(ec.node_id,==, "electroencephalogram", 20); tt_int_op(cc->cell_type, ==, CELL_CREATE); tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_TAP); tt_int_op(cc->handshake_len, ==, TAP_ONIONSKIN_CHALLENGE_LEN); - test_memeq(cc->onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN+20); + tt_mem_op(cc->onionskin,==, b, TAP_ONIONSKIN_CHALLENGE_LEN+20); tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND); tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN); - test_memeq(p2, p, RELAY_PAYLOAD_SIZE); + tt_mem_op(p2,==, p, RELAY_PAYLOAD_SIZE); /* Let's do an ntor stuffed in a legacy EXTEND cell */ memset(p, 0, sizeof(p)); @@ -644,15 +644,15 @@ test_cfmt_extend_cells(void *arg) tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); tt_int_op(258, ==, ec.orport_ipv4.port); tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr)); - test_memeq(ec.node_id, "electroencephalogram", 20); + tt_mem_op(ec.node_id,==, "electroencephalogram", 20); tt_int_op(cc->cell_type, ==, CELL_CREATE2); tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_NTOR); tt_int_op(cc->handshake_len, ==, NTOR_ONIONSKIN_LEN); - test_memeq(cc->onionskin, b, NTOR_ONIONSKIN_LEN+20); + tt_mem_op(cc->onionskin,==, b, NTOR_ONIONSKIN_LEN+20); tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND); tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN); - test_memeq(p2, p, RELAY_PAYLOAD_SIZE); + tt_mem_op(p2,==, p, RELAY_PAYLOAD_SIZE); tt_int_op(0, ==, create_cell_format_relayed(&cell, cc)); /* Now let's do a minimal ntor EXTEND2 cell. */ @@ -673,15 +673,15 @@ test_cfmt_extend_cells(void *arg) tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); tt_int_op(61681, ==, ec.orport_ipv4.port); tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr)); - test_memeq(ec.node_id, "anarchoindividualist", 20); + tt_mem_op(ec.node_id,==, "anarchoindividualist", 20); tt_int_op(cc->cell_type, ==, CELL_CREATE2); tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_NTOR); tt_int_op(cc->handshake_len, ==, NTOR_ONIONSKIN_LEN); - test_memeq(cc->onionskin, b, NTOR_ONIONSKIN_LEN+20); + tt_mem_op(cc->onionskin,==, b, NTOR_ONIONSKIN_LEN+20); tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND2); tt_int_op(p2_len, ==, 35+NTOR_ONIONSKIN_LEN); - test_memeq(p2, p, RELAY_PAYLOAD_SIZE); + tt_mem_op(p2,==, p, RELAY_PAYLOAD_SIZE); /* Now let's do a fanciful EXTEND2 cell. */ memset(&ec, 0xff, sizeof(ec)); @@ -706,11 +706,11 @@ test_cfmt_extend_cells(void *arg) tt_int_op(61681, ==, ec.orport_ipv4.port); tt_str_op("2002::f0:c51e", ==, fmt_addr(&ec.orport_ipv6.addr)); tt_int_op(4370, ==, ec.orport_ipv6.port); - test_memeq(ec.node_id, "anthropomorphization", 20); + tt_mem_op(ec.node_id,==, "anthropomorphization", 20); tt_int_op(cc->cell_type, ==, CELL_CREATE2); tt_int_op(cc->handshake_type, ==, 0x105); tt_int_op(cc->handshake_len, ==, 99); - test_memeq(cc->onionskin, b, 99+20); + tt_mem_op(cc->onionskin,==, b, 99+20); tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND2); /* We'll generate it minus the IPv6 address and minus the konami code */ @@ -722,7 +722,7 @@ test_cfmt_extend_cells(void *arg) "0214616e7468726f706f6d6f727068697a6174696f6e" /* Now the handshake prologue */ "01050063"); - test_memeq(p2+1+8+22+4, b, 99+20); + tt_mem_op(p2+1+8+22+4,==, b, 99+20); tt_int_op(0, ==, create_cell_format_relayed(&cell, cc)); /* == Now try parsing some junk */ @@ -836,11 +836,11 @@ test_cfmt_extended_cells(void *arg) tt_int_op(RELAY_COMMAND_EXTENDED, ==, ec.cell_type); tt_int_op(cc->cell_type, ==, CELL_CREATED); tt_int_op(cc->handshake_len, ==, TAP_ONIONSKIN_REPLY_LEN); - test_memeq(cc->reply, b, TAP_ONIONSKIN_REPLY_LEN); + tt_mem_op(cc->reply,==, b, TAP_ONIONSKIN_REPLY_LEN); tt_int_op(0, ==, extended_cell_format(&p2_cmd, &p2_len, p2, &ec)); tt_int_op(RELAY_COMMAND_EXTENDED, ==, p2_cmd); tt_int_op(TAP_ONIONSKIN_REPLY_LEN, ==, p2_len); - test_memeq(p2, p, sizeof(p2)); + tt_mem_op(p2,==, p, sizeof(p2)); /* Try an EXTENDED2 cell */ memset(&ec, 0xff, sizeof(ec)); @@ -853,11 +853,11 @@ test_cfmt_extended_cells(void *arg) tt_int_op(RELAY_COMMAND_EXTENDED2, ==, ec.cell_type); tt_int_op(cc->cell_type, ==, CELL_CREATED2); tt_int_op(cc->handshake_len, ==, 42); - test_memeq(cc->reply, b, 42+10); + tt_mem_op(cc->reply,==, b, 42+10); tt_int_op(0, ==, extended_cell_format(&p2_cmd, &p2_len, p2, &ec)); tt_int_op(RELAY_COMMAND_EXTENDED2, ==, p2_cmd); tt_int_op(2+42, ==, p2_len); - test_memeq(p2, p, sizeof(p2)); + tt_mem_op(p2,==, p, sizeof(p2)); /* Try an almost-too-long EXTENDED2 cell */ memcpy(p, "\x01\xf0", 2); diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c index 92629823ec..3226f7b973 100644 --- a/src/test/test_cell_queue.c +++ b/src/test/test_cell_queue.c @@ -69,15 +69,15 @@ test_cq_manip(void *arg) pc_tmp = cell_queue_pop(&cq); tt_int_op(cq.n, ==, 1); tt_ptr_op(pc_tmp, !=, NULL); - test_mem_op(pc_tmp->body, ==, "\x12\x34\x56\x78\x0a", 5); - test_mem_op(pc_tmp->body+5, ==, cell.payload, sizeof(cell.payload)); + tt_mem_op(pc_tmp->body, ==, "\x12\x34\x56\x78\x0a", 5); + tt_mem_op(pc_tmp->body+5, ==, cell.payload, sizeof(cell.payload)); packed_cell_free(pc_tmp); pc_tmp = cell_queue_pop(&cq); tt_int_op(cq.n, ==, 0); tt_ptr_op(pc_tmp, !=, NULL); - test_mem_op(pc_tmp->body, ==, "\x20\x13\x0a", 3); - test_mem_op(pc_tmp->body+3, ==, cell.payload, sizeof(cell.payload)); + tt_mem_op(pc_tmp->body, ==, "\x20\x13\x0a", 3); + tt_mem_op(pc_tmp->body+3, ==, cell.payload, sizeof(cell.payload)); packed_cell_free(pc_tmp); pc_tmp = NULL; diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index b19edd1fd4..e752eaf62a 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -79,9 +79,13 @@ test_clist_maps(void *arg) memset(&cam, 0, sizeof(cam)); memset(&cdm, 0, sizeof(cdm)); - ch1->cmux = (void*)0x1001; - ch2->cmux = (void*)0x1002; - ch3->cmux = (void*)0x1003; + tt_assert(ch1); + tt_assert(ch2); + tt_assert(ch3); + + ch1->cmux = tor_malloc(1); + ch2->cmux = tor_malloc(1); + ch3->cmux = tor_malloc(1); or_c1 = or_circuit_new(100, ch2); tt_assert(or_c1); @@ -156,6 +160,12 @@ test_clist_maps(void *arg) circuit_free(TO_CIRCUIT(or_c1)); if (or_c2) circuit_free(TO_CIRCUIT(or_c2)); + if (ch1) + tor_free(ch1->cmux); + if (ch2) + tor_free(ch2->cmux); + if (ch3) + tor_free(ch3->cmux); tor_free(ch1); tor_free(ch2); tor_free(ch3); @@ -241,7 +251,7 @@ test_rend_token_maps(void *arg) tt_ptr_op(c3->rendinfo, ==, NULL); tt_ptr_op(c4->rendinfo, !=, NULL); - test_mem_op(c4->rendinfo, ==, tok3, REND_TOKEN_LEN); + tt_mem_op(c4->rendinfo, ==, tok3, REND_TOKEN_LEN); /* Now clear c4's cookie. */ circuit_set_intro_point_digest(c4, NULL); diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index b9c0436ebf..a3cacc4cc7 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -65,7 +65,7 @@ test_cmux_destroy_cell_queue(void *arg) pc = cell_queue_pop(cq); tt_assert(pc); - test_mem_op(pc->body, ==, "\x00\x00\x00\x64\x04\x0a\x00\x00\x00", 9); + tt_mem_op(pc->body, ==, "\x00\x00\x00\x64\x04\x0a\x00\x00\x00", 9); packed_cell_free(pc); pc = NULL; diff --git a/src/test/test_config.c b/src/test/test_config.c index 94ac4dca13..6a91453e8c 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -53,57 +53,57 @@ test_config_addressmap(void *arg) /* MapAddress .invalidwildcard.com .torserver.exit - no match */ strlcpy(address, "www.invalidwildcard.com", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* MapAddress *invalidasterisk.com .torserver.exit - no match */ strlcpy(address, "www.invalidasterisk.com", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Where no mapping for FQDN match on top-level domain */ /* MapAddress .google.com .torserver.exit */ strlcpy(address, "reader.google.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "reader.torserver.exit"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "reader.torserver.exit"); /* MapAddress *.yahoo.com *.google.com.torserver.exit */ strlcpy(address, "reader.yahoo.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "reader.google.com.torserver.exit"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "reader.google.com.torserver.exit"); /*MapAddress *.cnn.com www.cnn.com */ strlcpy(address, "cnn.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "www.cnn.com"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "www.cnn.com"); /* MapAddress .cn.com www.cnn.com */ strlcpy(address, "www.cn.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "www.cnn.com"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "www.cnn.com"); /* MapAddress ex.com www.cnn.com - no match */ strlcpy(address, "www.ex.com", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* MapAddress ey.com *.cnn.com - invalid expression */ strlcpy(address, "ey.com", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Where mapping for FQDN match on FQDN */ strlcpy(address, "www.google.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "3.3.3.3"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "3.3.3.3"); strlcpy(address, "www.torproject.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "1.1.1.1"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "1.1.1.1"); strlcpy(address, "other.torproject.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "this.torproject.org.otherserver.exit"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "this.torproject.org.otherserver.exit"); strlcpy(address, "test.torproject.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "2.2.2.2"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "2.2.2.2"); /* Test a chain of address mappings and the order in which they were added: "MapAddress www.example.org 4.4.4.4" @@ -111,17 +111,17 @@ test_config_addressmap(void *arg) "MapAddress 4.4.4.4 5.5.5.5" */ strlcpy(address, "www.example.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "5.5.5.5"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "5.5.5.5"); /* Test infinite address mapping results in no change */ strlcpy(address, "www.infiniteloop.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "www.infiniteloop.org"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "www.infiniteloop.org"); /* Test we don't find false positives */ strlcpy(address, "www.example.com", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Test top-level-domain matching a bit harder */ config_free_lines(get_options_mutable()->AddressMap); @@ -134,24 +134,24 @@ test_config_addressmap(void *arg) config_register_addressmaps(get_options()); strlcpy(address, "www.abc.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "www.abc.torserver.exit"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "www.abc.torserver.exit"); strlcpy(address, "www.def.com", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "www.def.torserver.exit"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "www.def.torserver.exit"); strlcpy(address, "www.torproject.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "1.1.1.1"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "1.1.1.1"); strlcpy(address, "test.torproject.org", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "1.1.1.1"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "1.1.1.1"); strlcpy(address, "torproject.net", sizeof(address)); - test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); - test_streq(address, "2.2.2.2"); + tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_str_op(address,==, "2.2.2.2"); /* We don't support '*' as a mapping directive */ config_free_lines(get_options_mutable()->AddressMap); @@ -161,13 +161,13 @@ test_config_addressmap(void *arg) config_register_addressmaps(get_options()); strlcpy(address, "www.abc.com", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); strlcpy(address, "www.def.net", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); strlcpy(address, "www.torproject.org", sizeof(address)); - test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); + tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); #undef addressmap_rewrite @@ -184,7 +184,7 @@ is_private_dir(const char* path) if (r) { return 0; } -#if !defined (_WIN32) || defined (WINCE) +#if !defined (_WIN32) if ((st.st_mode & (S_IFDIR | 0777)) != (S_IFDIR | 0700)) { return 0; } @@ -201,7 +201,7 @@ test_config_check_or_create_data_subdir(void *arg) char *subpath; struct stat st; int r; -#if !defined (_WIN32) || defined (WINCE) +#if !defined (_WIN32) unsigned group_permission; #endif (void)arg; @@ -210,7 +210,7 @@ test_config_check_or_create_data_subdir(void *arg) datadir = options->DataDirectory = tor_strdup(get_fname("datadir-0")); subpath = get_datadir_fname(subdir); -#if defined (_WIN32) && !defined (WINCE) +#if defined (_WIN32) tt_int_op(mkdir(options->DataDirectory), ==, 0); #else tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0); @@ -220,20 +220,20 @@ test_config_check_or_create_data_subdir(void *arg) // The subdirectory shouldn't exist yet, // but should be created by the call to check_or_create_data_subdir. - test_assert(r && (errno == ENOENT)); - test_assert(!check_or_create_data_subdir(subdir)); - test_assert(is_private_dir(subpath)); + tt_assert(r && (errno == ENOENT)); + tt_assert(!check_or_create_data_subdir(subdir)); + tt_assert(is_private_dir(subpath)); // The check should return 0, if the directory already exists // and is private to the user. - test_assert(!check_or_create_data_subdir(subdir)); + tt_assert(!check_or_create_data_subdir(subdir)); r = stat(subpath, &st); if (r) { tt_abort_perror("stat"); } -#if !defined (_WIN32) || defined (WINCE) +#if !defined (_WIN32) group_permission = st.st_mode | 0070; r = chmod(subpath, group_permission); @@ -243,9 +243,9 @@ test_config_check_or_create_data_subdir(void *arg) // If the directory exists, but its mode is too permissive // a call to check_or_create_data_subdir should reset the mode. - test_assert(!is_private_dir(subpath)); - test_assert(!check_or_create_data_subdir(subdir)); - test_assert(is_private_dir(subpath)); + tt_assert(!is_private_dir(subpath)); + tt_assert(!check_or_create_data_subdir(subdir)); + tt_assert(is_private_dir(subpath)); #endif done: @@ -284,27 +284,27 @@ test_config_write_to_data_subdir(void *arg) datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1")); filepath = get_datadir_fname2(subdir, fname); -#if defined (_WIN32) && !defined (WINCE) +#if defined (_WIN32) tt_int_op(mkdir(options->DataDirectory), ==, 0); #else tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0); #endif // Write attempt shoudl fail, if subdirectory doesn't exist. - test_assert(write_to_data_subdir(subdir, fname, str, NULL)); - test_assert(! check_or_create_data_subdir(subdir)); + tt_assert(write_to_data_subdir(subdir, fname, str, NULL)); + tt_assert(! check_or_create_data_subdir(subdir)); // Content of file after write attempt should be // equal to the original string. - test_assert(!write_to_data_subdir(subdir, fname, str, NULL)); + tt_assert(!write_to_data_subdir(subdir, fname, str, NULL)); cp = read_file_to_str(filepath, 0, NULL); - test_streq(cp, str); + tt_str_op(cp,==, str); tor_free(cp); // A second write operation should overwrite the old content. - test_assert(!write_to_data_subdir(subdir, fname, str, NULL)); + tt_assert(!write_to_data_subdir(subdir, fname, str, NULL)); cp = read_file_to_str(filepath, 0, NULL); - test_streq(cp, str); + tt_str_op(cp,==, str); tor_free(cp); done: @@ -325,48 +325,48 @@ good_bridge_line_test(const char *string, const char *test_addrport, { char *tmp = NULL; bridge_line_t *bridge_line = parse_bridge_line(string); - test_assert(bridge_line); + tt_assert(bridge_line); /* test addrport */ tmp = tor_strdup(fmt_addrport(&bridge_line->addr, bridge_line->port)); - test_streq(test_addrport, tmp); + tt_str_op(test_addrport,==, tmp); tor_free(tmp); /* If we were asked to validate a digest, but we did not get a digest after parsing, we failed. */ if (test_digest && tor_digest_is_zero(bridge_line->digest)) - test_assert(0); + tt_assert(0); /* If we were not asked to validate a digest, and we got a digest after parsing, we failed again. */ if (!test_digest && !tor_digest_is_zero(bridge_line->digest)) - test_assert(0); + tt_assert(0); /* If we were asked to validate a digest, and we got a digest after parsing, make sure it's correct. */ if (test_digest) { tmp = tor_strdup(hex_str(bridge_line->digest, DIGEST_LEN)); tor_strlower(tmp); - test_streq(test_digest, tmp); + tt_str_op(test_digest,==, tmp); tor_free(tmp); } /* If we were asked to validate a transport name, make sure tha it matches with the transport name that was parsed. */ if (test_transport && !bridge_line->transport_name) - test_assert(0); + tt_assert(0); if (!test_transport && bridge_line->transport_name) - test_assert(0); + tt_assert(0); if (test_transport) - test_streq(test_transport, bridge_line->transport_name); + tt_str_op(test_transport,==, bridge_line->transport_name); /* Validate the SOCKS argument smartlist. */ if (test_socks_args && !bridge_line->socks_args) - test_assert(0); + tt_assert(0); if (!test_socks_args && bridge_line->socks_args) - test_assert(0); + tt_assert(0); if (test_socks_args) - test_assert(smartlist_strings_eq(test_socks_args, + tt_assert(smartlist_strings_eq(test_socks_args, bridge_line->socks_args)); done: @@ -382,7 +382,7 @@ bad_bridge_line_test(const char *string) bridge_line_t *bridge_line = parse_bridge_line(string); if (bridge_line) TT_FAIL(("%s was supposed to fail, but it didn't.", string)); - test_assert(!bridge_line); + tt_assert(!bridge_line); done: bridge_line_free(bridge_line); @@ -490,18 +490,18 @@ test_config_parse_transport_options_line(void *arg) { /* too small line */ options_sl = get_options_from_transport_options_line("valley", NULL); - test_assert(!options_sl); + tt_assert(!options_sl); } { /* no k=v values */ options_sl = get_options_from_transport_options_line("hit it!", NULL); - test_assert(!options_sl); + tt_assert(!options_sl); } { /* correct line, but wrong transport specified */ options_sl = get_options_from_transport_options_line("trebuchet k=v", "rook"); - test_assert(!options_sl); + tt_assert(!options_sl); } { /* correct -- no transport specified */ @@ -512,8 +512,8 @@ test_config_parse_transport_options_line(void *arg) options_sl = get_options_from_transport_options_line("rook ladi=dadi weliketo=party", NULL); - test_assert(options_sl); - test_assert(smartlist_strings_eq(options_sl, sl_tmp)); + tt_assert(options_sl); + tt_assert(smartlist_strings_eq(options_sl, sl_tmp)); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); @@ -531,8 +531,8 @@ test_config_parse_transport_options_line(void *arg) options_sl = get_options_from_transport_options_line("rook ladi=dadi weliketo=party", "rook"); - test_assert(options_sl); - test_assert(smartlist_strings_eq(options_sl, sl_tmp)); + tt_assert(options_sl); + tt_assert(smartlist_strings_eq(options_sl, sl_tmp)); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); sl_tmp = NULL; @@ -576,7 +576,7 @@ test_config_fix_my_family(void *arg) TT_FAIL(("options_validate failed: %s", err)); } - test_streq(options->MyFamily, "$1111111111111111111111111111111111111111, " + tt_str_op(options->MyFamily,==, "$1111111111111111111111111111111111111111, " "$1111111111111111111111111111111111111112, " "$1111111111111111111111111111111111111113"); diff --git a/src/test/test_containers.c b/src/test/test_containers.c index 067c4c1907..24211dd580 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -29,7 +29,7 @@ compare_strs_for_bsearch_(const void *a, const void **b) /** Helper: return a tristate based on comparing the strings in *<b>a</b> and * *<b>b</b>, excluding a's first character, and ignoring case. */ static int -compare_without_first_ch_(const void *a, const void **b) +cmp_without_first_(const void *a, const void **b) { const char *s1 = a, *s2 = *b; return strcasecmp(s1+1, s2); @@ -37,237 +37,256 @@ compare_without_first_ch_(const void *a, const void **b) /** Run unit tests for basic dynamic-sized array functionality. */ static void -test_container_smartlist_basic(void) +test_container_smartlist_basic(void *arg) { smartlist_t *sl; + char *v0 = tor_strdup("v0"); + char *v1 = tor_strdup("v1"); + char *v2 = tor_strdup("v2"); + char *v3 = tor_strdup("v3"); + char *v4 = tor_strdup("v4"); + char *v22 = tor_strdup("v22"); + char *v99 = tor_strdup("v99"); + char *v555 = tor_strdup("v555"); /* XXXX test sort_digests, uniq_strings, uniq_digests */ /* Test smartlist add, del_keeporder, insert, get. */ + (void)arg; sl = smartlist_new(); - smartlist_add(sl, (void*)1); - smartlist_add(sl, (void*)2); - smartlist_add(sl, (void*)3); - smartlist_add(sl, (void*)4); + smartlist_add(sl, v1); + smartlist_add(sl, v2); + smartlist_add(sl, v3); + smartlist_add(sl, v4); smartlist_del_keeporder(sl, 1); - smartlist_insert(sl, 1, (void*)22); - smartlist_insert(sl, 0, (void*)0); - smartlist_insert(sl, 5, (void*)555); - test_eq_ptr((void*)0, smartlist_get(sl,0)); - test_eq_ptr((void*)1, smartlist_get(sl,1)); - test_eq_ptr((void*)22, smartlist_get(sl,2)); - test_eq_ptr((void*)3, smartlist_get(sl,3)); - test_eq_ptr((void*)4, smartlist_get(sl,4)); - test_eq_ptr((void*)555, smartlist_get(sl,5)); + smartlist_insert(sl, 1, v22); + smartlist_insert(sl, 0, v0); + smartlist_insert(sl, 5, v555); + tt_ptr_op(v0,==, smartlist_get(sl,0)); + tt_ptr_op(v1,==, smartlist_get(sl,1)); + tt_ptr_op(v22,==, smartlist_get(sl,2)); + tt_ptr_op(v3,==, smartlist_get(sl,3)); + tt_ptr_op(v4,==, smartlist_get(sl,4)); + tt_ptr_op(v555,==, smartlist_get(sl,5)); /* Try deleting in the middle. */ smartlist_del(sl, 1); - test_eq_ptr((void*)555, smartlist_get(sl, 1)); + tt_ptr_op(v555,==, smartlist_get(sl, 1)); /* Try deleting at the end. */ smartlist_del(sl, 4); - test_eq(4, smartlist_len(sl)); + tt_int_op(4,==, smartlist_len(sl)); /* test isin. */ - test_assert(smartlist_contains(sl, (void*)3)); - test_assert(!smartlist_contains(sl, (void*)99)); + tt_assert(smartlist_contains(sl, v3)); + tt_assert(!smartlist_contains(sl, v99)); done: smartlist_free(sl); + tor_free(v0); + tor_free(v1); + tor_free(v2); + tor_free(v3); + tor_free(v4); + tor_free(v22); + tor_free(v99); + tor_free(v555); } /** Run unit tests for smartlist-of-strings functionality. */ static void -test_container_smartlist_strings(void) +test_container_smartlist_strings(void *arg) { smartlist_t *sl = smartlist_new(); char *cp=NULL, *cp_alloc=NULL; size_t sz; /* Test split and join */ - test_eq(0, smartlist_len(sl)); + (void)arg; + tt_int_op(0,==, smartlist_len(sl)); smartlist_split_string(sl, "abc", ":", 0, 0); - test_eq(1, smartlist_len(sl)); - test_streq("abc", smartlist_get(sl, 0)); + tt_int_op(1,==, smartlist_len(sl)); + tt_str_op("abc",==, smartlist_get(sl, 0)); smartlist_split_string(sl, "a::bc::", "::", 0, 0); - test_eq(4, smartlist_len(sl)); - test_streq("a", smartlist_get(sl, 1)); - test_streq("bc", smartlist_get(sl, 2)); - test_streq("", smartlist_get(sl, 3)); + tt_int_op(4,==, smartlist_len(sl)); + tt_str_op("a",==, smartlist_get(sl, 1)); + tt_str_op("bc",==, smartlist_get(sl, 2)); + tt_str_op("",==, smartlist_get(sl, 3)); cp_alloc = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp_alloc, "abcabc"); + tt_str_op(cp_alloc,==, "abcabc"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); - test_streq(cp_alloc, "abc!a!bc!"); + tt_str_op(cp_alloc,==, "abc!a!bc!"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); - test_streq(cp_alloc, "abcXYaXYbcXY"); + tt_str_op(cp_alloc,==, "abcXYaXYbcXY"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); - test_streq(cp_alloc, "abcXYaXYbcXYXY"); + tt_str_op(cp_alloc,==, "abcXYaXYbcXYXY"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "", 1, NULL); - test_streq(cp_alloc, "abcabc"); + tt_str_op(cp_alloc,==, "abcabc"); tor_free(cp_alloc); smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); - test_eq(8, smartlist_len(sl)); - test_streq("", smartlist_get(sl, 4)); - test_streq("def", smartlist_get(sl, 5)); - test_streq(" ", smartlist_get(sl, 6)); - test_streq("ghijk", smartlist_get(sl, 7)); + tt_int_op(8,==, smartlist_len(sl)); + tt_str_op("",==, smartlist_get(sl, 4)); + tt_str_op("def",==, smartlist_get(sl, 5)); + tt_str_op(" ",==, smartlist_get(sl, 6)); + tt_str_op("ghijk",==, smartlist_get(sl, 7)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); - test_eq(3, smartlist_len(sl)); - test_streq("a", smartlist_get(sl,0)); - test_streq("bbd", smartlist_get(sl,1)); - test_streq("cdef", smartlist_get(sl,2)); + tt_int_op(3,==, smartlist_len(sl)); + tt_str_op("a",==, smartlist_get(sl,0)); + tt_str_op("bbd",==, smartlist_get(sl,1)); + tt_str_op("cdef",==, smartlist_get(sl,2)); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE, 0); - test_eq(8, smartlist_len(sl)); - test_streq("z", smartlist_get(sl,3)); - test_streq("zhasd", smartlist_get(sl,4)); - test_streq("", smartlist_get(sl,5)); - test_streq("bnud", smartlist_get(sl,6)); - test_streq("", smartlist_get(sl,7)); + tt_int_op(8,==, smartlist_len(sl)); + tt_str_op("z",==, smartlist_get(sl,3)); + tt_str_op("zhasd",==, smartlist_get(sl,4)); + tt_str_op("",==, smartlist_get(sl,5)); + tt_str_op("bnud",==, smartlist_get(sl,6)); + tt_str_op("",==, smartlist_get(sl,7)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); smartlist_split_string(sl, " ab\tc \td ef ", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(4, smartlist_len(sl)); - test_streq("ab", smartlist_get(sl,0)); - test_streq("c", smartlist_get(sl,1)); - test_streq("d", smartlist_get(sl,2)); - test_streq("ef", smartlist_get(sl,3)); + tt_int_op(4,==, smartlist_len(sl)); + tt_str_op("ab",==, smartlist_get(sl,0)); + tt_str_op("c",==, smartlist_get(sl,1)); + tt_str_op("d",==, smartlist_get(sl,2)); + tt_str_op("ef",==, smartlist_get(sl,3)); smartlist_split_string(sl, "ghi\tj", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(6, smartlist_len(sl)); - test_streq("ghi", smartlist_get(sl,4)); - test_streq("j", smartlist_get(sl,5)); + tt_int_op(6,==, smartlist_len(sl)); + tt_str_op("ghi",==, smartlist_get(sl,4)); + tt_str_op("j",==, smartlist_get(sl,5)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); - test_streq(cp_alloc, ""); + tt_str_op(cp_alloc,==, ""); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); - test_streq(cp_alloc, "XY"); + tt_str_op(cp_alloc,==, "XY"); tor_free(cp_alloc); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(3, smartlist_len(sl)); - test_streq("z", smartlist_get(sl, 0)); - test_streq("zhasd", smartlist_get(sl, 1)); - test_streq("bnud", smartlist_get(sl, 2)); + tt_int_op(3,==, smartlist_len(sl)); + tt_str_op("z",==, smartlist_get(sl, 0)); + tt_str_op("zhasd",==, smartlist_get(sl, 1)); + tt_str_op("bnud",==, smartlist_get(sl, 2)); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); - test_eq(5, smartlist_len(sl)); - test_streq("z", smartlist_get(sl, 3)); - test_streq("zhasd <> <> bnud<>", smartlist_get(sl, 4)); + tt_int_op(5,==, smartlist_len(sl)); + tt_str_op("z",==, smartlist_get(sl, 3)); + tt_str_op("zhasd <> <> bnud<>",==, smartlist_get(sl, 4)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "abcd\n", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(1, smartlist_len(sl)); - test_streq("abcd", smartlist_get(sl, 0)); + tt_int_op(1,==, smartlist_len(sl)); + tt_str_op("abcd",==, smartlist_get(sl, 0)); smartlist_split_string(sl, "efgh", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(2, smartlist_len(sl)); - test_streq("efgh", smartlist_get(sl, 1)); + tt_int_op(2,==, smartlist_len(sl)); + tt_str_op("efgh",==, smartlist_get(sl, 1)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); /* Test swapping, shuffling, and sorting. */ smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); - test_eq(7, smartlist_len(sl)); + tt_int_op(7,==, smartlist_len(sl)); smartlist_sort(sl, compare_strs_); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the"); + tt_str_op(cp_alloc,==, "and,arma,by,nickm,onion,router,the"); tor_free(cp_alloc); smartlist_swap(sl, 1, 5); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc,"and,router,by,nickm,onion,arma,the"); + tt_str_op(cp_alloc,==, "and,router,by,nickm,onion,arma,the"); tor_free(cp_alloc); smartlist_shuffle(sl); - test_eq(7, smartlist_len(sl)); - test_assert(smartlist_contains_string(sl, "and")); - test_assert(smartlist_contains_string(sl, "router")); - test_assert(smartlist_contains_string(sl, "by")); - test_assert(smartlist_contains_string(sl, "nickm")); - test_assert(smartlist_contains_string(sl, "onion")); - test_assert(smartlist_contains_string(sl, "arma")); - test_assert(smartlist_contains_string(sl, "the")); + tt_int_op(7,==, smartlist_len(sl)); + tt_assert(smartlist_contains_string(sl, "and")); + tt_assert(smartlist_contains_string(sl, "router")); + tt_assert(smartlist_contains_string(sl, "by")); + tt_assert(smartlist_contains_string(sl, "nickm")); + tt_assert(smartlist_contains_string(sl, "onion")); + tt_assert(smartlist_contains_string(sl, "arma")); + tt_assert(smartlist_contains_string(sl, "the")); /* Test bsearch. */ smartlist_sort(sl, compare_strs_); - test_streq("nickm", smartlist_bsearch(sl, "zNicKM", - compare_without_first_ch_)); - test_streq("and", smartlist_bsearch(sl, " AND", compare_without_first_ch_)); - test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", compare_without_first_ch_)); + tt_str_op("nickm",==, smartlist_bsearch(sl, "zNicKM", + cmp_without_first_)); + tt_str_op("and",==, + smartlist_bsearch(sl, " AND", cmp_without_first_)); + tt_ptr_op(NULL,==, smartlist_bsearch(sl, " ANz", cmp_without_first_)); /* Test bsearch_idx */ { int f; smartlist_t *tmp = NULL; - test_eq(0, smartlist_bsearch_idx(sl," aaa",compare_without_first_ch_,&f)); - test_eq(f, 0); - test_eq(0, smartlist_bsearch_idx(sl," and",compare_without_first_ch_,&f)); - test_eq(f, 1); - test_eq(1, smartlist_bsearch_idx(sl," arm",compare_without_first_ch_,&f)); - test_eq(f, 0); - test_eq(1, smartlist_bsearch_idx(sl," arma",compare_without_first_ch_,&f)); - test_eq(f, 1); - test_eq(2, smartlist_bsearch_idx(sl," armb",compare_without_first_ch_,&f)); - test_eq(f, 0); - test_eq(7, smartlist_bsearch_idx(sl," zzzz",compare_without_first_ch_,&f)); - test_eq(f, 0); + tt_int_op(0,==,smartlist_bsearch_idx(sl," aaa",cmp_without_first_,&f)); + tt_int_op(f,==, 0); + tt_int_op(0,==, smartlist_bsearch_idx(sl," and",cmp_without_first_,&f)); + tt_int_op(f,==, 1); + tt_int_op(1,==, smartlist_bsearch_idx(sl," arm",cmp_without_first_,&f)); + tt_int_op(f,==, 0); + tt_int_op(1,==, smartlist_bsearch_idx(sl," arma",cmp_without_first_,&f)); + tt_int_op(f,==, 1); + tt_int_op(2,==, smartlist_bsearch_idx(sl," armb",cmp_without_first_,&f)); + tt_int_op(f,==, 0); + tt_int_op(7,==, smartlist_bsearch_idx(sl," zzzz",cmp_without_first_,&f)); + tt_int_op(f,==, 0); /* Test trivial cases for list of length 0 or 1 */ tmp = smartlist_new(); - test_eq(0, smartlist_bsearch_idx(tmp, "foo", + tt_int_op(0,==, smartlist_bsearch_idx(tmp, "foo", compare_strs_for_bsearch_, &f)); - test_eq(f, 0); + tt_int_op(f,==, 0); smartlist_insert(tmp, 0, (void *)("bar")); - test_eq(1, smartlist_bsearch_idx(tmp, "foo", + tt_int_op(1,==, smartlist_bsearch_idx(tmp, "foo", compare_strs_for_bsearch_, &f)); - test_eq(f, 0); - test_eq(0, smartlist_bsearch_idx(tmp, "aaa", + tt_int_op(f,==, 0); + tt_int_op(0,==, smartlist_bsearch_idx(tmp, "aaa", compare_strs_for_bsearch_, &f)); - test_eq(f, 0); - test_eq(0, smartlist_bsearch_idx(tmp, "bar", + tt_int_op(f,==, 0); + tt_int_op(0,==, smartlist_bsearch_idx(tmp, "bar", compare_strs_for_bsearch_, &f)); - test_eq(f, 1); + tt_int_op(f,==, 1); /* ... and one for length 2 */ smartlist_insert(tmp, 1, (void *)("foo")); - test_eq(1, smartlist_bsearch_idx(tmp, "foo", + tt_int_op(1,==, smartlist_bsearch_idx(tmp, "foo", compare_strs_for_bsearch_, &f)); - test_eq(f, 1); - test_eq(2, smartlist_bsearch_idx(tmp, "goo", + tt_int_op(f,==, 1); + tt_int_op(2,==, smartlist_bsearch_idx(tmp, "goo", compare_strs_for_bsearch_, &f)); - test_eq(f, 0); + tt_int_op(f,==, 0); smartlist_free(tmp); } /* Test reverse() and pop_last() */ smartlist_reverse(sl); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc,"the,router,onion,nickm,by,arma,and"); + tt_str_op(cp_alloc,==, "the,router,onion,nickm,by,arma,and"); tor_free(cp_alloc); cp_alloc = smartlist_pop_last(sl); - test_streq(cp_alloc, "and"); + tt_str_op(cp_alloc,==, "and"); tor_free(cp_alloc); - test_eq(smartlist_len(sl), 6); + tt_int_op(smartlist_len(sl),==, 6); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); cp_alloc = smartlist_pop_last(sl); - test_eq_ptr(cp_alloc, NULL); + tt_ptr_op(cp_alloc,==, NULL); /* Test uniq() */ smartlist_split_string(sl, @@ -276,16 +295,16 @@ test_container_smartlist_strings(void) smartlist_sort(sl, compare_strs_); smartlist_uniq(sl, compare_strs_, tor_free_); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar"); + tt_str_op(cp_alloc,==, "50,a,canal,man,noon,panama,plan,radar"); tor_free(cp_alloc); /* Test contains_string, contains_string_case and contains_int_as_string */ - test_assert(smartlist_contains_string(sl, "noon")); - test_assert(!smartlist_contains_string(sl, "noonoon")); - test_assert(smartlist_contains_string_case(sl, "nOOn")); - test_assert(!smartlist_contains_string_case(sl, "nooNooN")); - test_assert(smartlist_contains_int_as_string(sl, 50)); - test_assert(!smartlist_contains_int_as_string(sl, 60)); + tt_assert(smartlist_contains_string(sl, "noon")); + tt_assert(!smartlist_contains_string(sl, "noonoon")); + tt_assert(smartlist_contains_string_case(sl, "nOOn")); + tt_assert(!smartlist_contains_string_case(sl, "nooNooN")); + tt_assert(smartlist_contains_int_as_string(sl, 50)); + tt_assert(!smartlist_contains_int_as_string(sl, 60)); /* Test smartlist_choose */ { @@ -293,7 +312,7 @@ test_container_smartlist_strings(void) int allsame = 1; int allin = 1; void *first = smartlist_choose(sl); - test_assert(smartlist_contains(sl, first)); + tt_assert(smartlist_contains(sl, first)); for (i = 0; i < 100; ++i) { void *second = smartlist_choose(sl); if (second != first) @@ -301,8 +320,8 @@ test_container_smartlist_strings(void) if (!smartlist_contains(sl, second)) allin = 0; } - test_assert(!allsame); - test_assert(allin); + tt_assert(!allsame); + tt_assert(allin); } SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); @@ -312,17 +331,17 @@ test_container_smartlist_strings(void) "Some say the Earth will end in ice and some in fire", " ", 0, 0); cp = smartlist_get(sl, 4); - test_streq(cp, "will"); + tt_str_op(cp,==, "will"); smartlist_add(sl, cp); smartlist_remove(sl, cp); tor_free(cp); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); + tt_str_op(cp_alloc,==, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); tor_free(cp_alloc); smartlist_string_remove(sl, "in"); cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); - test_streq(cp_alloc, "Some+say+the+Earth+fire+end+some+ice+and"); - test_eq((int)sz, 40); + tt_str_op(cp_alloc,==, "Some+say+the+Earth+fire+end+some+ice+and"); + tt_int_op((int)sz,==, 40); done: @@ -333,7 +352,7 @@ test_container_smartlist_strings(void) /** Run unit tests for smartlist set manipulation functions. */ static void -test_container_smartlist_overlap(void) +test_container_smartlist_overlap(void *arg) { smartlist_t *sl = smartlist_new(); smartlist_t *ints = smartlist_new(); @@ -341,6 +360,7 @@ test_container_smartlist_overlap(void) smartlist_t *evens = smartlist_new(); smartlist_t *primes = smartlist_new(); int i; + (void)arg; for (i=1; i < 10; i += 2) smartlist_add(odds, (void*)(uintptr_t)i); for (i=0; i < 10; i += 2) @@ -349,7 +369,7 @@ test_container_smartlist_overlap(void) /* add_all */ smartlist_add_all(ints, odds); smartlist_add_all(ints, evens); - test_eq(smartlist_len(ints), 10); + tt_int_op(smartlist_len(ints),==, 10); smartlist_add(primes, (void*)2); smartlist_add(primes, (void*)3); @@ -357,24 +377,24 @@ test_container_smartlist_overlap(void) smartlist_add(primes, (void*)7); /* overlap */ - test_assert(smartlist_overlap(ints, odds)); - test_assert(smartlist_overlap(odds, primes)); - test_assert(smartlist_overlap(evens, primes)); - test_assert(!smartlist_overlap(odds, evens)); + tt_assert(smartlist_overlap(ints, odds)); + tt_assert(smartlist_overlap(odds, primes)); + tt_assert(smartlist_overlap(evens, primes)); + tt_assert(!smartlist_overlap(odds, evens)); /* intersect */ smartlist_add_all(sl, odds); smartlist_intersect(sl, primes); - test_eq(smartlist_len(sl), 3); - test_assert(smartlist_contains(sl, (void*)3)); - test_assert(smartlist_contains(sl, (void*)5)); - test_assert(smartlist_contains(sl, (void*)7)); + tt_int_op(smartlist_len(sl),==, 3); + tt_assert(smartlist_contains(sl, (void*)3)); + tt_assert(smartlist_contains(sl, (void*)5)); + tt_assert(smartlist_contains(sl, (void*)7)); /* subtract */ smartlist_add_all(sl, primes); smartlist_subtract(sl, odds); - test_eq(smartlist_len(sl), 1); - test_assert(smartlist_contains(sl, (void*)2)); + tt_int_op(smartlist_len(sl),==, 1); + tt_assert(smartlist_contains(sl, (void*)2)); done: smartlist_free(odds); @@ -386,31 +406,32 @@ test_container_smartlist_overlap(void) /** Run unit tests for smartlist-of-digests functions. */ static void -test_container_smartlist_digests(void) +test_container_smartlist_digests(void *arg) { smartlist_t *sl = smartlist_new(); /* contains_digest */ + (void)arg; smartlist_add(sl, tor_memdup("AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN)); smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); - test_eq(0, smartlist_contains_digest(NULL, "AAAAAAAAAAAAAAAAAAAA")); - test_assert(smartlist_contains_digest(sl, "AAAAAAAAAAAAAAAAAAAA")); - test_assert(smartlist_contains_digest(sl, "\00090AAB2AAAAaasdAAAAA")); - test_eq(0, smartlist_contains_digest(sl, "\00090AAB2AAABaasdAAAAA")); + tt_int_op(0,==, smartlist_contains_digest(NULL, "AAAAAAAAAAAAAAAAAAAA")); + tt_assert(smartlist_contains_digest(sl, "AAAAAAAAAAAAAAAAAAAA")); + tt_assert(smartlist_contains_digest(sl, "\00090AAB2AAAAaasdAAAAA")); + tt_int_op(0,==, smartlist_contains_digest(sl, "\00090AAB2AAABaasdAAAAA")); /* sort digests */ smartlist_sort_digests(sl); - test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); - test_memeq(smartlist_get(sl, 1), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); - test_memeq(smartlist_get(sl, 2), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); - test_eq(3, smartlist_len(sl)); + tt_mem_op(smartlist_get(sl, 0),==, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); + tt_mem_op(smartlist_get(sl, 1),==, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); + tt_mem_op(smartlist_get(sl, 2),==, "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); + tt_int_op(3,==, smartlist_len(sl)); /* uniq_digests */ smartlist_uniq_digests(sl); - test_eq(2, smartlist_len(sl)); - test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); - test_memeq(smartlist_get(sl, 1), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); + tt_int_op(2,==, smartlist_len(sl)); + tt_mem_op(smartlist_get(sl, 0),==, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); + tt_mem_op(smartlist_get(sl, 1),==, "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); done: SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); @@ -419,13 +440,14 @@ test_container_smartlist_digests(void) /** Run unit tests for concatenate-a-smartlist-of-strings functions. */ static void -test_container_smartlist_join(void) +test_container_smartlist_join(void *arg) { smartlist_t *sl = smartlist_new(); smartlist_t *sl2 = smartlist_new(), *sl3 = smartlist_new(), *sl4 = smartlist_new(); char *joined=NULL; /* unique, sorted. */ + (void)arg; smartlist_split_string(sl, "Abashments Ambush Anchorman Bacon Banks Borscht " "Bunks Inhumane Insurance Knish Know Manners " @@ -441,21 +463,21 @@ test_container_smartlist_join(void) sl2, char *, cp2, strcmp(cp1,cp2), smartlist_add(sl3, cp2)) { - test_streq(cp1, cp2); + tt_str_op(cp1,==, cp2); smartlist_add(sl4, cp1); } SMARTLIST_FOREACH_JOIN_END(cp1, cp2); SMARTLIST_FOREACH(sl3, const char *, cp, - test_assert(smartlist_contains(sl2, cp) && + tt_assert(smartlist_contains(sl2, cp) && !smartlist_contains_string(sl, cp))); SMARTLIST_FOREACH(sl4, const char *, cp, - test_assert(smartlist_contains(sl, cp) && + tt_assert(smartlist_contains(sl, cp) && smartlist_contains_string(sl2, cp))); joined = smartlist_join_strings(sl3, ",", 0, NULL); - test_streq(joined, "Anemias,Anemias,Crossbowmen,Work"); + tt_str_op(joined,==, "Anemias,Anemias,Crossbowmen,Work"); tor_free(joined); joined = smartlist_join_strings(sl4, ",", 0, NULL); - test_streq(joined, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance," + tt_str_op(joined,==, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance," "Knish,Know,Manners,Manners,Maraschinos,Wombats,Wombats"); tor_free(joined); @@ -516,18 +538,19 @@ test_container_smartlist_ints_eq(void *arg) /** Run unit tests for bitarray code */ static void -test_container_bitarray(void) +test_container_bitarray(void *arg) { bitarray_t *ba = NULL; int i, j, ok=1; + (void)arg; ba = bitarray_init_zero(1); - test_assert(ba); - test_assert(! bitarray_is_set(ba, 0)); + tt_assert(ba); + tt_assert(! bitarray_is_set(ba, 0)); bitarray_set(ba, 0); - test_assert(bitarray_is_set(ba, 0)); + tt_assert(bitarray_is_set(ba, 0)); bitarray_clear(ba, 0); - test_assert(! bitarray_is_set(ba, 0)); + tt_assert(! bitarray_is_set(ba, 0)); bitarray_free(ba); ba = bitarray_init_zero(1023); @@ -542,7 +565,7 @@ test_container_bitarray(void) if (!bool_eq(bitarray_is_set(ba, j), j%i)) ok = 0; } - test_assert(ok); + tt_assert(ok); if (i < 7) ++i; else if (i == 28) @@ -559,7 +582,7 @@ test_container_bitarray(void) /** Run unit tests for digest set code (implemented as a hashtable or as a * bloom filter) */ static void -test_container_digestset(void) +test_container_digestset(void *arg) { smartlist_t *included = smartlist_new(); char d[DIGEST_LEN]; @@ -568,6 +591,7 @@ test_container_digestset(void) int false_positives = 0; digestset_t *set = NULL; + (void)arg; for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); smartlist_add(included, tor_memdup(d, DIGEST_LEN)); @@ -576,19 +600,19 @@ test_container_digestset(void) SMARTLIST_FOREACH(included, const char *, cp, if (digestset_contains(set, cp)) ok = 0); - test_assert(ok); + tt_assert(ok); SMARTLIST_FOREACH(included, const char *, cp, digestset_add(set, cp)); SMARTLIST_FOREACH(included, const char *, cp, if (!digestset_contains(set, cp)) ok = 0); - test_assert(ok); + tt_assert(ok); for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); if (digestset_contains(set, d)) ++false_positives; } - test_assert(false_positives < 50); /* Should be far lower. */ + tt_int_op(50, >, false_positives); /* Should be far lower. */ done: if (set) @@ -612,7 +636,7 @@ compare_strings_for_pqueue_(const void *p1, const void *p2) /** Run unit tests for heap-based priority queue functions. */ static void -test_container_pqueue(void) +test_container_pqueue(void *arg) { smartlist_t *sl = smartlist_new(); int (*cmp)(const void *, const void*); @@ -634,6 +658,8 @@ test_container_pqueue(void) #define OK() smartlist_pqueue_assert_ok(sl, cmp, offset) + (void)arg; + cmp = compare_strings_for_pqueue_; smartlist_pqueue_add(sl, cmp, offset, &cows); smartlist_pqueue_add(sl, cmp, offset, &zebras); @@ -649,31 +675,31 @@ test_container_pqueue(void) OK(); - test_eq(smartlist_len(sl), 11); - test_eq_ptr(smartlist_get(sl, 0), &apples); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &apples); - test_eq(smartlist_len(sl), 10); + tt_int_op(smartlist_len(sl),==, 11); + tt_ptr_op(smartlist_get(sl, 0),==, &apples); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &apples); + tt_int_op(smartlist_len(sl),==, 10); OK(); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &cows); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &daschunds); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &cows); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &daschunds); smartlist_pqueue_add(sl, cmp, offset, &chinchillas); OK(); smartlist_pqueue_add(sl, cmp, offset, &fireflies); OK(); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &chinchillas); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &eggplants); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fireflies); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &chinchillas); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &eggplants); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &fireflies); OK(); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fish); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &frogs); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &lobsters); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &roquefort); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &fish); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &frogs); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &lobsters); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &roquefort); OK(); - test_eq(smartlist_len(sl), 3); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &squid); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &weissbier); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &zebras); - test_eq(smartlist_len(sl), 0); + tt_int_op(smartlist_len(sl),==, 3); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &squid); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &weissbier); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &zebras); + tt_int_op(smartlist_len(sl),==, 0); OK(); /* Now test remove. */ @@ -683,21 +709,21 @@ test_container_pqueue(void) smartlist_pqueue_add(sl, cmp, offset, &apples); smartlist_pqueue_add(sl, cmp, offset, &squid); smartlist_pqueue_add(sl, cmp, offset, &zebras); - test_eq(smartlist_len(sl), 6); + tt_int_op(smartlist_len(sl),==, 6); OK(); smartlist_pqueue_remove(sl, cmp, offset, &zebras); - test_eq(smartlist_len(sl), 5); + tt_int_op(smartlist_len(sl),==, 5); OK(); smartlist_pqueue_remove(sl, cmp, offset, &cows); - test_eq(smartlist_len(sl), 4); + tt_int_op(smartlist_len(sl),==, 4); OK(); smartlist_pqueue_remove(sl, cmp, offset, &apples); - test_eq(smartlist_len(sl), 3); + tt_int_op(smartlist_len(sl),==, 3); OK(); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fish); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &frogs); - test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &squid); - test_eq(smartlist_len(sl), 0); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &fish); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &frogs); + tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &squid); + tt_int_op(smartlist_len(sl),==, 0); OK(); #undef OK @@ -709,7 +735,7 @@ test_container_pqueue(void) /** Run unit tests for string-to-void* map functions */ static void -test_container_strmap(void) +test_container_strmap(void *arg) { strmap_t *map; strmap_iter_t *iter; @@ -717,36 +743,45 @@ test_container_strmap(void) void *v; char *visited = NULL; smartlist_t *found_keys = NULL; + char *v1 = tor_strdup("v1"); + char *v99 = tor_strdup("v99"); + char *v100 = tor_strdup("v100"); + char *v101 = tor_strdup("v101"); + char *v102 = tor_strdup("v102"); + char *v103 = tor_strdup("v103"); + char *v104 = tor_strdup("v104"); + char *v105 = tor_strdup("v105"); + (void)arg; map = strmap_new(); - test_assert(map); - test_eq(strmap_size(map), 0); - test_assert(strmap_isempty(map)); - v = strmap_set(map, "K1", (void*)99); - test_eq_ptr(v, NULL); - test_assert(!strmap_isempty(map)); - v = strmap_set(map, "K2", (void*)101); - test_eq_ptr(v, NULL); - v = strmap_set(map, "K1", (void*)100); - test_eq_ptr(v, (void*)99); - test_eq_ptr(strmap_get(map,"K1"), (void*)100); - test_eq_ptr(strmap_get(map,"K2"), (void*)101); - test_eq_ptr(strmap_get(map,"K-not-there"), NULL); + tt_assert(map); + tt_int_op(strmap_size(map),==, 0); + tt_assert(strmap_isempty(map)); + v = strmap_set(map, "K1", v99); + tt_ptr_op(v,==, NULL); + tt_assert(!strmap_isempty(map)); + v = strmap_set(map, "K2", v101); + tt_ptr_op(v,==, NULL); + v = strmap_set(map, "K1", v100); + tt_ptr_op(v,==, v99); + tt_ptr_op(strmap_get(map,"K1"),==, v100); + tt_ptr_op(strmap_get(map,"K2"),==, v101); + tt_ptr_op(strmap_get(map,"K-not-there"),==, NULL); strmap_assert_ok(map); v = strmap_remove(map,"K2"); strmap_assert_ok(map); - test_eq_ptr(v, (void*)101); - test_eq_ptr(strmap_get(map,"K2"), NULL); - test_eq_ptr(strmap_remove(map,"K2"), NULL); - - strmap_set(map, "K2", (void*)101); - strmap_set(map, "K3", (void*)102); - strmap_set(map, "K4", (void*)103); - test_eq(strmap_size(map), 4); + tt_ptr_op(v,==, v101); + tt_ptr_op(strmap_get(map,"K2"),==, NULL); + tt_ptr_op(strmap_remove(map,"K2"),==, NULL); + + strmap_set(map, "K2", v101); + strmap_set(map, "K3", v102); + strmap_set(map, "K4", v103); + tt_int_op(strmap_size(map),==, 4); strmap_assert_ok(map); - strmap_set(map, "K5", (void*)104); - strmap_set(map, "K6", (void*)105); + strmap_set(map, "K5", v104); + strmap_set(map, "K6", v105); strmap_assert_ok(map); /* Test iterator. */ @@ -755,7 +790,7 @@ test_container_strmap(void) while (!strmap_iter_done(iter)) { strmap_iter_get(iter,&k,&v); smartlist_add(found_keys, tor_strdup(k)); - test_eq_ptr(v, strmap_get(map, k)); + tt_ptr_op(v,==, strmap_get(map, k)); if (!strcmp(k, "K2")) { iter = strmap_iter_next_rmv(map,iter); @@ -765,12 +800,12 @@ test_container_strmap(void) } /* Make sure we removed K2, but not the others. */ - test_eq_ptr(strmap_get(map, "K2"), NULL); - test_eq_ptr(strmap_get(map, "K5"), (void*)104); + tt_ptr_op(strmap_get(map, "K2"),==, NULL); + tt_ptr_op(strmap_get(map, "K5"),==, v104); /* Make sure we visited everyone once */ smartlist_sort_strings(found_keys); visited = smartlist_join_strings(found_keys, ":", 0, NULL); - test_streq(visited, "K1:K2:K3:K4:K5:K6"); + tt_str_op(visited,==, "K1:K2:K3:K4:K5:K6"); strmap_assert_ok(map); /* Clean up after ourselves. */ @@ -779,14 +814,14 @@ test_container_strmap(void) /* Now try some lc functions. */ map = strmap_new(); - strmap_set_lc(map,"Ab.C", (void*)1); - test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); + strmap_set_lc(map,"Ab.C", v1); + tt_ptr_op(strmap_get(map,"ab.c"),==, v1); strmap_assert_ok(map); - test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); - test_eq_ptr(strmap_get(map,"AB.C"), NULL); - test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); + tt_ptr_op(strmap_get_lc(map,"AB.C"),==, v1); + tt_ptr_op(strmap_get(map,"AB.C"),==, NULL); + tt_ptr_op(strmap_remove_lc(map,"aB.C"),==, v1); strmap_assert_ok(map); - test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); + tt_ptr_op(strmap_get_lc(map,"AB.C"),==, NULL); done: if (map) @@ -796,34 +831,66 @@ test_container_strmap(void) smartlist_free(found_keys); } tor_free(visited); + tor_free(v1); + tor_free(v99); + tor_free(v100); + tor_free(v101); + tor_free(v102); + tor_free(v103); + tor_free(v104); + tor_free(v105); } /** Run unit tests for getting the median of a list. */ static void -test_container_order_functions(void) +test_container_order_functions(void *arg) { int lst[25], n = 0; + unsigned int lst2[25]; // int a=12,b=24,c=25,d=60,e=77; #define median() median_int(lst, n) + (void)arg; lst[n++] = 12; - test_eq(12, median()); /* 12 */ + tt_int_op(12,==, median()); /* 12 */ lst[n++] = 77; //smartlist_shuffle(sl); - test_eq(12, median()); /* 12, 77 */ + tt_int_op(12,==, median()); /* 12, 77 */ lst[n++] = 77; //smartlist_shuffle(sl); - test_eq(77, median()); /* 12, 77, 77 */ + tt_int_op(77,==, median()); /* 12, 77, 77 */ lst[n++] = 24; - test_eq(24, median()); /* 12,24,77,77 */ + tt_int_op(24,==, median()); /* 12,24,77,77 */ lst[n++] = 60; lst[n++] = 12; lst[n++] = 25; //smartlist_shuffle(sl); - test_eq(25, median()); /* 12,12,24,25,60,77,77 */ + tt_int_op(25,==, median()); /* 12,12,24,25,60,77,77 */ #undef median +#define third_quartile() third_quartile_uint32(lst2, n) + + n = 0; + lst2[n++] = 1; + tt_int_op(1,==, third_quartile()); /* ~1~ */ + lst2[n++] = 2; + tt_int_op(2,==, third_quartile()); /* 1, ~2~ */ + lst2[n++] = 3; + lst2[n++] = 4; + lst2[n++] = 5; + tt_int_op(4,==, third_quartile()); /* 1, 2, 3, ~4~, 5 */ + lst2[n++] = 6; + lst2[n++] = 7; + lst2[n++] = 8; + lst2[n++] = 9; + tt_int_op(7,==, third_quartile()); /* 1, 2, 3, 4, 5, 6, ~7~, 8, 9 */ + lst2[n++] = 10; + lst2[n++] = 11; + tt_int_op(9,==, third_quartile()); /* 1, 2, 3, 4, 5, 6, 7, 8, ~9~, 10, 11 */ + +#undef third_quartile + done: ; } @@ -874,18 +941,26 @@ test_container_di_map(void *arg) /** Run unit tests for fp_pair-to-void* map functions */ static void -test_container_fp_pair_map(void) +test_container_fp_pair_map(void *arg) { fp_pair_map_t *map; fp_pair_t fp1, fp2, fp3, fp4, fp5, fp6; void *v; fp_pair_map_iter_t *iter; fp_pair_t k; + char *v99 = tor_strdup("99"); + char *v100 = tor_strdup("v100"); + char *v101 = tor_strdup("v101"); + char *v102 = tor_strdup("v102"); + char *v103 = tor_strdup("v103"); + char *v104 = tor_strdup("v104"); + char *v105 = tor_strdup("v105"); + (void)arg; map = fp_pair_map_new(); - test_assert(map); - test_eq(fp_pair_map_size(map), 0); - test_assert(fp_pair_map_isempty(map)); + tt_assert(map); + tt_int_op(fp_pair_map_size(map),==, 0); + tt_assert(fp_pair_map_isempty(map)); memset(fp1.first, 0x11, DIGEST_LEN); memset(fp1.second, 0x12, DIGEST_LEN); @@ -900,38 +975,38 @@ test_container_fp_pair_map(void) memset(fp6.first, 0x61, DIGEST_LEN); memset(fp6.second, 0x62, DIGEST_LEN); - v = fp_pair_map_set(map, &fp1, (void*)99); + v = fp_pair_map_set(map, &fp1, v99); tt_ptr_op(v, ==, NULL); - test_assert(!fp_pair_map_isempty(map)); - v = fp_pair_map_set(map, &fp2, (void*)101); + tt_assert(!fp_pair_map_isempty(map)); + v = fp_pair_map_set(map, &fp2, v101); tt_ptr_op(v, ==, NULL); - v = fp_pair_map_set(map, &fp1, (void*)100); - tt_ptr_op(v, ==, (void*)99); - test_eq_ptr(fp_pair_map_get(map, &fp1), (void*)100); - test_eq_ptr(fp_pair_map_get(map, &fp2), (void*)101); - test_eq_ptr(fp_pair_map_get(map, &fp3), NULL); + v = fp_pair_map_set(map, &fp1, v100); + tt_ptr_op(v, ==, v99); + tt_ptr_op(fp_pair_map_get(map, &fp1),==, v100); + tt_ptr_op(fp_pair_map_get(map, &fp2),==, v101); + tt_ptr_op(fp_pair_map_get(map, &fp3),==, NULL); fp_pair_map_assert_ok(map); v = fp_pair_map_remove(map, &fp2); fp_pair_map_assert_ok(map); - test_eq_ptr(v, (void*)101); - test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); - test_eq_ptr(fp_pair_map_remove(map, &fp2), NULL); - - fp_pair_map_set(map, &fp2, (void*)101); - fp_pair_map_set(map, &fp3, (void*)102); - fp_pair_map_set(map, &fp4, (void*)103); - test_eq(fp_pair_map_size(map), 4); + tt_ptr_op(v,==, v101); + tt_ptr_op(fp_pair_map_get(map, &fp2),==, NULL); + tt_ptr_op(fp_pair_map_remove(map, &fp2),==, NULL); + + fp_pair_map_set(map, &fp2, v101); + fp_pair_map_set(map, &fp3, v102); + fp_pair_map_set(map, &fp4, v103); + tt_int_op(fp_pair_map_size(map),==, 4); fp_pair_map_assert_ok(map); - fp_pair_map_set(map, &fp5, (void*)104); - fp_pair_map_set(map, &fp6, (void*)105); + fp_pair_map_set(map, &fp5, v104); + fp_pair_map_set(map, &fp6, v105); fp_pair_map_assert_ok(map); /* Test iterator. */ iter = fp_pair_map_iter_init(map); while (!fp_pair_map_iter_done(iter)) { fp_pair_map_iter_get(iter, &k, &v); - test_eq_ptr(v, fp_pair_map_get(map, &k)); + tt_ptr_op(v,==, fp_pair_map_get(map, &k)); if (tor_memeq(&fp2, &k, sizeof(fp2))) { iter = fp_pair_map_iter_next_rmv(map, iter); @@ -941,8 +1016,8 @@ test_container_fp_pair_map(void) } /* Make sure we removed fp2, but not the others. */ - test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); - test_eq_ptr(fp_pair_map_get(map, &fp5), (void*)104); + tt_ptr_op(fp_pair_map_get(map, &fp2),==, NULL); + tt_ptr_op(fp_pair_map_get(map, &fp5),==, v104); fp_pair_map_assert_ok(map); /* Clean up after ourselves. */ @@ -952,10 +1027,17 @@ test_container_fp_pair_map(void) done: if (map) fp_pair_map_free(map, NULL); + tor_free(v99); + tor_free(v100); + tor_free(v101); + tor_free(v102); + tor_free(v103); + tor_free(v104); + tor_free(v105); } #define CONTAINER_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_container_ ## name } + { #name, test_container_ ## name , 0, NULL, NULL } #define CONTAINER(name, flags) \ { #name, test_container_ ## name, (flags), NULL, NULL } diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 5d8edb6550..795c603fd4 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -5,6 +5,7 @@ #include "orconfig.h" #define CRYPTO_CURVE25519_PRIVATE +#define CRYPTO_S2K_PRIVATE #include "or.h" #include "test.h" #include "aes.h" @@ -13,6 +14,10 @@ #ifdef CURVE25519_ENABLED #include "crypto_curve25519.h" #endif +#include "crypto_ed25519.h" +#include "ed25519_vectors.inc" +#include "crypto_s2k.h" +#include "crypto_pwbox.h" extern const char AUTHORITY_SIGNKEY_3[]; extern const char AUTHORITY_SIGNKEY_A_DIGEST[]; @@ -20,7 +25,7 @@ extern const char AUTHORITY_SIGNKEY_A_DIGEST256[]; /** Run unit tests for Diffie-Hellman functionality. */ static void -test_crypto_dh(void) +test_crypto_dh(void *arg) { crypto_dh_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT); crypto_dh_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT); @@ -30,24 +35,25 @@ test_crypto_dh(void) char s2[DH_BYTES]; ssize_t s1len, s2len; - test_eq(crypto_dh_get_bytes(dh1), DH_BYTES); - test_eq(crypto_dh_get_bytes(dh2), DH_BYTES); + (void)arg; + tt_int_op(crypto_dh_get_bytes(dh1),==, DH_BYTES); + tt_int_op(crypto_dh_get_bytes(dh2),==, DH_BYTES); memset(p1, 0, DH_BYTES); memset(p2, 0, DH_BYTES); - test_memeq(p1, p2, DH_BYTES); - test_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); - test_memneq(p1, p2, DH_BYTES); - test_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES)); - test_memneq(p1, p2, DH_BYTES); + tt_mem_op(p1,==, p2, DH_BYTES); + tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); + tt_mem_op(p1,!=, p2, DH_BYTES); + tt_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES)); + tt_mem_op(p1,!=, p2, DH_BYTES); memset(s1, 0, DH_BYTES); memset(s2, 0xFF, DH_BYTES); s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH_BYTES, s1, 50); s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH_BYTES, s2, 50); - test_assert(s1len > 0); - test_eq(s1len, s2len); - test_memeq(s1, s2, s1len); + tt_assert(s1len > 0); + tt_int_op(s1len,==, s2len); + tt_mem_op(s1,==, s2, s1len); { /* XXXX Now fabricate some bad values and make sure they get caught, @@ -63,17 +69,18 @@ test_crypto_dh(void) /** Run unit tests for our random number generation function and its wrappers. */ static void -test_crypto_rng(void) +test_crypto_rng(void *arg) { int i, j, allok; char data1[100], data2[100]; double d; /* Try out RNG. */ - test_assert(! crypto_seed_rng(0)); + (void)arg; + tt_assert(! crypto_seed_rng(0)); crypto_rand(data1, 100); crypto_rand(data2, 100); - test_memneq(data1,data2,100); + tt_mem_op(data1,!=, data2,100); allok = 1; for (i = 0; i < 100; ++i) { uint64_t big; @@ -88,8 +95,8 @@ test_crypto_rng(void) if (big >= 5) allok = 0; d = crypto_rand_double(); - test_assert(d >= 0); - test_assert(d < 1.0); + tt_assert(d >= 0); + tt_assert(d < 1.0); host = crypto_random_hostname(3,8,"www.",".onion"); if (strcmpstart(host,"www.") || strcmpend(host,".onion") || @@ -98,7 +105,7 @@ test_crypto_rng(void) allok = 0; tor_free(host); } - test_assert(allok); + tt_assert(allok); done: ; } @@ -128,15 +135,15 @@ test_crypto_aes(void *arg) memset(data2, 0, 1024); memset(data3, 0, 1024); env1 = crypto_cipher_new(NULL); - test_neq_ptr(env1, 0); + tt_ptr_op(env1, !=, NULL); env2 = crypto_cipher_new(crypto_cipher_get_key(env1)); - test_neq_ptr(env2, 0); + tt_ptr_op(env2, !=, NULL); /* Try encrypting 512 chars. */ crypto_cipher_encrypt(env1, data2, data1, 512); crypto_cipher_decrypt(env2, data3, data2, 512); - test_memeq(data1, data3, 512); - test_memneq(data1, data2, 512); + tt_mem_op(data1,==, data3, 512); + tt_mem_op(data1,!=, data2, 512); /* Now encrypt 1 at a time, and get 1 at a time. */ for (j = 512; j < 560; ++j) { @@ -145,7 +152,7 @@ test_crypto_aes(void *arg) for (j = 512; j < 560; ++j) { crypto_cipher_decrypt(env2, data3+j, data2+j, 1); } - test_memeq(data1, data3, 560); + tt_mem_op(data1,==, data3, 560); /* Now encrypt 3 at a time, and get 5 at a time. */ for (j = 560; j < 1024-5; j += 3) { crypto_cipher_encrypt(env1, data2+j, data1+j, 3); @@ -153,7 +160,7 @@ test_crypto_aes(void *arg) for (j = 560; j < 1024-5; j += 5) { crypto_cipher_decrypt(env2, data3+j, data2+j, 5); } - test_memeq(data1, data3, 1024-5); + tt_mem_op(data1,==, data3, 1024-5); /* Now make sure that when we encrypt with different chunk sizes, we get the same results. */ crypto_cipher_free(env2); @@ -161,7 +168,7 @@ test_crypto_aes(void *arg) memset(data3, 0, 1024); env2 = crypto_cipher_new(crypto_cipher_get_key(env1)); - test_neq_ptr(env2, NULL); + tt_ptr_op(env2, !=, NULL); for (j = 0; j < 1024-16; j += 17) { crypto_cipher_encrypt(env2, data3+j, data1+j, 17); } @@ -170,7 +177,7 @@ test_crypto_aes(void *arg) printf("%d: %d\t%d\n", j, (int) data2[j], (int) data3[j]); } } - test_memeq(data2, data3, 1024-16); + tt_mem_op(data2,==, data3, 1024-16); crypto_cipher_free(env1); env1 = NULL; crypto_cipher_free(env2); @@ -237,7 +244,7 @@ test_crypto_aes(void *arg) "\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff"); crypto_cipher_crypt_inplace(env1, data2, 64); - test_assert(tor_mem_is_zero(data2, 64)); + tt_assert(tor_mem_is_zero(data2, 64)); done: tor_free(mem_op_hex_tmp); @@ -252,7 +259,7 @@ test_crypto_aes(void *arg) /** Run unit tests for our SHA-1 functionality */ static void -test_crypto_sha(void) +test_crypto_sha(void *arg) { crypto_digest_t *d1 = NULL, *d2 = NULL; int i; @@ -263,6 +270,7 @@ test_crypto_sha(void) char *mem_op_hex_tmp=NULL; /* Test SHA-1 with a test vector from the specification. */ + (void)arg; i = crypto_digest(data, "abc", 3); test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D"); tt_int_op(i, ==, 0); @@ -277,13 +285,13 @@ test_crypto_sha(void) /* Case empty (wikipedia) */ crypto_hmac_sha256(digest, "", 0, "", 0); - test_streq(hex_str(digest, 32), + tt_str_op(hex_str(digest, 32),==, "B613679A0814D9EC772F95D778C35FC5FF1697C493715653C6C712144292C5AD"); /* Case quick-brown (wikipedia) */ crypto_hmac_sha256(digest, "key", 3, "The quick brown fox jumps over the lazy dog", 43); - test_streq(hex_str(digest, 32), + tt_str_op(hex_str(digest, 32),==, "F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8"); /* "Test Case 1" from RFC 4231 */ @@ -344,43 +352,43 @@ test_crypto_sha(void) /* Incremental digest code. */ d1 = crypto_digest_new(); - test_assert(d1); + tt_assert(d1); crypto_digest_add_bytes(d1, "abcdef", 6); d2 = crypto_digest_dup(d1); - test_assert(d2); + tt_assert(d2); crypto_digest_add_bytes(d2, "ghijkl", 6); crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); crypto_digest(d_out2, "abcdefghijkl", 12); - test_memeq(d_out1, d_out2, DIGEST_LEN); + tt_mem_op(d_out1,==, d_out2, DIGEST_LEN); crypto_digest_assign(d2, d1); crypto_digest_add_bytes(d2, "mno", 3); crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); crypto_digest(d_out2, "abcdefmno", 9); - test_memeq(d_out1, d_out2, DIGEST_LEN); + tt_mem_op(d_out1,==, d_out2, DIGEST_LEN); crypto_digest_get_digest(d1, d_out1, sizeof(d_out1)); crypto_digest(d_out2, "abcdef", 6); - test_memeq(d_out1, d_out2, DIGEST_LEN); + tt_mem_op(d_out1,==, d_out2, DIGEST_LEN); crypto_digest_free(d1); crypto_digest_free(d2); /* Incremental digest code with sha256 */ d1 = crypto_digest256_new(DIGEST_SHA256); - test_assert(d1); + tt_assert(d1); crypto_digest_add_bytes(d1, "abcdef", 6); d2 = crypto_digest_dup(d1); - test_assert(d2); + tt_assert(d2); crypto_digest_add_bytes(d2, "ghijkl", 6); crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); crypto_digest256(d_out2, "abcdefghijkl", 12, DIGEST_SHA256); - test_memeq(d_out1, d_out2, DIGEST_LEN); + tt_mem_op(d_out1,==, d_out2, DIGEST_LEN); crypto_digest_assign(d2, d1); crypto_digest_add_bytes(d2, "mno", 3); crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); crypto_digest256(d_out2, "abcdefmno", 9, DIGEST_SHA256); - test_memeq(d_out1, d_out2, DIGEST_LEN); + tt_mem_op(d_out1,==, d_out2, DIGEST_LEN); crypto_digest_get_digest(d1, d_out1, sizeof(d_out1)); crypto_digest256(d_out2, "abcdef", 6, DIGEST_SHA256); - test_memeq(d_out1, d_out2, DIGEST_LEN); + tt_mem_op(d_out1,==, d_out2, DIGEST_LEN); done: if (d1) @@ -392,7 +400,7 @@ test_crypto_sha(void) /** Run unit tests for our public key crypto functions */ static void -test_crypto_pk(void) +test_crypto_pk(void *arg) { crypto_pk_t *pk1 = NULL, *pk2 = NULL; char *encoded = NULL; @@ -401,74 +409,83 @@ test_crypto_pk(void) int i, len; /* Public-key ciphers */ + (void)arg; pk1 = pk_generate(0); pk2 = crypto_pk_new(); - test_assert(pk1 && pk2); - test_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size)); - test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size)); - test_eq(0, crypto_pk_cmp_keys(pk1, pk2)); + tt_assert(pk1 && pk2); + tt_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size)); + tt_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size)); + tt_int_op(0,==, crypto_pk_cmp_keys(pk1, pk2)); /* comparison between keys and NULL */ tt_int_op(crypto_pk_cmp_keys(NULL, pk1), <, 0); tt_int_op(crypto_pk_cmp_keys(NULL, NULL), ==, 0); tt_int_op(crypto_pk_cmp_keys(pk1, NULL), >, 0); - test_eq(128, crypto_pk_keysize(pk1)); - test_eq(1024, crypto_pk_num_bits(pk1)); - test_eq(128, crypto_pk_keysize(pk2)); - test_eq(1024, crypto_pk_num_bits(pk2)); + tt_int_op(128,==, crypto_pk_keysize(pk1)); + tt_int_op(1024,==, crypto_pk_num_bits(pk1)); + tt_int_op(128,==, crypto_pk_keysize(pk2)); + tt_int_op(1024,==, crypto_pk_num_bits(pk2)); - test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1), + tt_int_op(128,==, crypto_pk_public_encrypt(pk2, data1, sizeof(data1), "Hello whirled.", 15, PK_PKCS1_OAEP_PADDING)); - test_eq(128, crypto_pk_public_encrypt(pk1, data2, sizeof(data1), + tt_int_op(128,==, crypto_pk_public_encrypt(pk1, data2, sizeof(data1), "Hello whirled.", 15, PK_PKCS1_OAEP_PADDING)); /* oaep padding should make encryption not match */ - test_memneq(data1, data2, 128); - test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data1, 128, + tt_mem_op(data1,!=, data2, 128); + tt_int_op(15,==, + crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data1, 128, PK_PKCS1_OAEP_PADDING,1)); - test_streq(data3, "Hello whirled."); + tt_str_op(data3,==, "Hello whirled."); memset(data3, 0, 1024); - test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128, + tt_int_op(15,==, + crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128, PK_PKCS1_OAEP_PADDING,1)); - test_streq(data3, "Hello whirled."); + tt_str_op(data3,==, "Hello whirled."); /* Can't decrypt with public key. */ - test_eq(-1, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data2, 128, + tt_int_op(-1,==, + crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data2, 128, PK_PKCS1_OAEP_PADDING,1)); /* Try again with bad padding */ memcpy(data2+1, "XYZZY", 5); /* This has fails ~ once-in-2^40 */ - test_eq(-1, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128, + tt_int_op(-1,==, + crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128, PK_PKCS1_OAEP_PADDING,1)); /* File operations: save and load private key */ - test_assert(! crypto_pk_write_private_key_to_filename(pk1, + tt_assert(! crypto_pk_write_private_key_to_filename(pk1, get_fname("pkey1"))); /* failing case for read: can't read. */ - test_assert(crypto_pk_read_private_key_from_filename(pk2, + tt_assert(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")) < 0); write_str_to_file(get_fname("xyzzy"), "foobar", 6); /* Failing case for read: no key. */ - test_assert(crypto_pk_read_private_key_from_filename(pk2, + tt_assert(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")) < 0); - test_assert(! crypto_pk_read_private_key_from_filename(pk2, + tt_assert(! crypto_pk_read_private_key_from_filename(pk2, get_fname("pkey1"))); - test_eq(15, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data1, 128, + tt_int_op(15,==, + crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data1, 128, PK_PKCS1_OAEP_PADDING,1)); /* Now try signing. */ strlcpy(data1, "Ossifrage", 1024); - test_eq(128, crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10)); - test_eq(10, + tt_int_op(128,==, + crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10)); + tt_int_op(10,==, crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); - test_streq(data3, "Ossifrage"); + tt_str_op(data3,==, "Ossifrage"); /* Try signing digests. */ - test_eq(128, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2), + tt_int_op(128,==, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2), data1, 10)); - test_eq(20, + tt_int_op(20,==, crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); - test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128)); - test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128)); + tt_int_op(0,==, + crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128)); + tt_int_op(-1,==, + crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128)); /*XXXX test failed signing*/ @@ -476,9 +493,9 @@ test_crypto_pk(void) crypto_pk_free(pk2); pk2 = NULL; i = crypto_pk_asn1_encode(pk1, data1, 1024); - test_assert(i>0); + tt_int_op(i, >, 0); pk2 = crypto_pk_asn1_decode(data1, i); - test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); /* Try with hybrid encryption wrappers. */ crypto_rand(data1, 1024); @@ -487,19 +504,19 @@ test_crypto_pk(void) memset(data3,0,1024); len = crypto_pk_public_hybrid_encrypt(pk1,data2,sizeof(data2), data1,i,PK_PKCS1_OAEP_PADDING,0); - test_assert(len>=0); + tt_int_op(len, >=, 0); len = crypto_pk_private_hybrid_decrypt(pk1,data3,sizeof(data3), data2,len,PK_PKCS1_OAEP_PADDING,1); - test_eq(len,i); - test_memeq(data1,data3,i); + tt_int_op(len,==, i); + tt_mem_op(data1,==, data3,i); } /* Try copy_full */ crypto_pk_free(pk2); pk2 = crypto_pk_copy_full(pk1); - test_assert(pk2 != NULL); - test_neq_ptr(pk1, pk2); - test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + tt_assert(pk2 != NULL); + tt_ptr_op(pk1, !=, pk2); + tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); done: if (pk1) @@ -532,7 +549,7 @@ test_crypto_pk_fingerprints(void *arg) /* Is digest as expected? */ crypto_digest(d, encoded, n); tt_int_op(0, ==, crypto_pk_get_digest(pk, d2)); - test_memeq(d, d2, DIGEST_LEN); + tt_mem_op(d,==, d2, DIGEST_LEN); /* Is fingerprint right? */ tt_int_op(0, ==, crypto_pk_get_fingerprint(pk, fingerprint, 0)); @@ -561,28 +578,29 @@ test_crypto_pk_fingerprints(void *arg) /** Sanity check for crypto pk digests */ static void -test_crypto_digests(void) +test_crypto_digests(void *arg) { crypto_pk_t *k = NULL; ssize_t r; digests_t pkey_digests; char digest[DIGEST_LEN]; + (void)arg; k = crypto_pk_new(); - test_assert(k); + tt_assert(k); r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_3, -1); - test_assert(!r); + tt_assert(!r); r = crypto_pk_get_digest(k, digest); - test_assert(r == 0); - test_memeq(hex_str(digest, DIGEST_LEN), + tt_assert(r == 0); + tt_mem_op(hex_str(digest, DIGEST_LEN),==, AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN); r = crypto_pk_get_all_digests(k, &pkey_digests); - test_memeq(hex_str(pkey_digests.d[DIGEST_SHA1], DIGEST_LEN), + tt_mem_op(hex_str(pkey_digests.d[DIGEST_SHA1], DIGEST_LEN),==, AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN); - test_memeq(hex_str(pkey_digests.d[DIGEST_SHA256], DIGEST256_LEN), + tt_mem_op(hex_str(pkey_digests.d[DIGEST_SHA256], DIGEST256_LEN),==, AUTHORITY_SIGNKEY_A_DIGEST256, HEX_DIGEST256_LEN); done: crypto_pk_free(k); @@ -591,58 +609,59 @@ test_crypto_digests(void) /** Run unit tests for misc crypto formatting functionality (base64, base32, * fingerprints, etc) */ static void -test_crypto_formats(void) +test_crypto_formats(void *arg) { char *data1 = NULL, *data2 = NULL, *data3 = NULL; int i, j, idx; + (void)arg; data1 = tor_malloc(1024); data2 = tor_malloc(1024); data3 = tor_malloc(1024); - test_assert(data1 && data2 && data3); + tt_assert(data1 && data2 && data3); /* Base64 tests */ memset(data1, 6, 1024); for (idx = 0; idx < 10; ++idx) { i = base64_encode(data2, 1024, data1, idx); - test_assert(i >= 0); + tt_int_op(i, >=, 0); j = base64_decode(data3, 1024, data2, i); - test_eq(j,idx); - test_memeq(data3, data1, idx); + tt_int_op(j,==, idx); + tt_mem_op(data3,==, data1, idx); } strlcpy(data1, "Test string that contains 35 chars.", 1024); strlcat(data1, " 2nd string that contains 35 chars.", 1024); i = base64_encode(data2, 1024, data1, 71); - test_assert(i >= 0); + tt_int_op(i, >=, 0); j = base64_decode(data3, 1024, data2, i); - test_eq(j, 71); - test_streq(data3, data1); - test_assert(data2[i] == '\0'); + tt_int_op(j,==, 71); + tt_str_op(data3,==, data1); + tt_int_op(data2[i], ==, '\0'); crypto_rand(data1, DIGEST_LEN); memset(data2, 100, 1024); digest_to_base64(data2, data1); - test_eq(BASE64_DIGEST_LEN, strlen(data2)); - test_eq(100, data2[BASE64_DIGEST_LEN+2]); + tt_int_op(BASE64_DIGEST_LEN,==, strlen(data2)); + tt_int_op(100,==, data2[BASE64_DIGEST_LEN+2]); memset(data3, 99, 1024); - test_eq(digest_from_base64(data3, data2), 0); - test_memeq(data1, data3, DIGEST_LEN); - test_eq(99, data3[DIGEST_LEN+1]); + tt_int_op(digest_from_base64(data3, data2),==, 0); + tt_mem_op(data1,==, data3, DIGEST_LEN); + tt_int_op(99,==, data3[DIGEST_LEN+1]); - test_assert(digest_from_base64(data3, "###") < 0); + tt_assert(digest_from_base64(data3, "###") < 0); /* Encoding SHA256 */ crypto_rand(data2, DIGEST256_LEN); memset(data2, 100, 1024); digest256_to_base64(data2, data1); - test_eq(BASE64_DIGEST256_LEN, strlen(data2)); - test_eq(100, data2[BASE64_DIGEST256_LEN+2]); + tt_int_op(BASE64_DIGEST256_LEN,==, strlen(data2)); + tt_int_op(100,==, data2[BASE64_DIGEST256_LEN+2]); memset(data3, 99, 1024); - test_eq(digest256_from_base64(data3, data2), 0); - test_memeq(data1, data3, DIGEST256_LEN); - test_eq(99, data3[DIGEST256_LEN+1]); + tt_int_op(digest256_from_base64(data3, data2),==, 0); + tt_mem_op(data1,==, data3, DIGEST256_LEN); + tt_int_op(99,==, data3[DIGEST256_LEN+1]); /* Base32 tests */ strlcpy(data1, "5chrs", 1024); @@ -651,27 +670,27 @@ test_crypto_formats(void) * By 5s: [00110 10101 10001 10110 10000 11100 10011 10011] */ base32_encode(data2, 9, data1, 5); - test_streq(data2, "gvrwq4tt"); + tt_str_op(data2,==, "gvrwq4tt"); strlcpy(data1, "\xFF\xF5\x6D\x44\xAE\x0D\x5C\xC9\x62\xC4", 1024); base32_encode(data2, 30, data1, 10); - test_streq(data2, "772w2rfobvomsywe"); + tt_str_op(data2,==, "772w2rfobvomsywe"); /* Base16 tests */ strlcpy(data1, "6chrs\xff", 1024); base16_encode(data2, 13, data1, 6); - test_streq(data2, "3663687273FF"); + tt_str_op(data2,==, "3663687273FF"); strlcpy(data1, "f0d678affc000100", 1024); i = base16_decode(data2, 8, data1, 16); - test_eq(i,0); - test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); + tt_int_op(i,==, 0); + tt_mem_op(data2,==, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); /* now try some failing base16 decodes */ - test_eq(-1, base16_decode(data2, 8, data1, 15)); /* odd input len */ - test_eq(-1, base16_decode(data2, 7, data1, 16)); /* dest too short */ + tt_int_op(-1,==, base16_decode(data2, 8, data1, 15)); /* odd input len */ + tt_int_op(-1,==, base16_decode(data2, 7, data1, 16)); /* dest too short */ strlcpy(data1, "f0dz!8affc000100", 1024); - test_eq(-1, base16_decode(data2, 8, data1, 16)); + tt_int_op(-1,==, base16_decode(data2, 8, data1, 16)); tor_free(data1); tor_free(data2); @@ -680,10 +699,10 @@ test_crypto_formats(void) /* Add spaces to fingerprint */ { data1 = tor_strdup("ABCD1234ABCD56780000ABCD1234ABCD56780000"); - test_eq(strlen(data1), 40); + tt_int_op(strlen(data1),==, 40); data2 = tor_malloc(FINGERPRINT_LEN+1); crypto_add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1); - test_streq(data2, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000"); + tt_str_op(data2,==, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000"); tor_free(data1); tor_free(data2); } @@ -696,37 +715,377 @@ test_crypto_formats(void) /** Run unit tests for our secret-to-key passphrase hashing functionality. */ static void -test_crypto_s2k(void) +test_crypto_s2k_rfc2440(void *arg) { char buf[29]; char buf2[29]; char *buf3 = NULL; int i; + (void)arg; memset(buf, 0, sizeof(buf)); memset(buf2, 0, sizeof(buf2)); buf3 = tor_malloc(65536); memset(buf3, 0, 65536); - secret_to_key(buf+9, 20, "", 0, buf); + secret_to_key_rfc2440(buf+9, 20, "", 0, buf); crypto_digest(buf2+9, buf3, 1024); - test_memeq(buf, buf2, 29); + tt_mem_op(buf,==, buf2, 29); memcpy(buf,"vrbacrda",8); memcpy(buf2,"vrbacrda",8); buf[8] = 96; buf2[8] = 96; - secret_to_key(buf+9, 20, "12345678", 8, buf); + secret_to_key_rfc2440(buf+9, 20, "12345678", 8, buf); for (i = 0; i < 65536; i += 16) { memcpy(buf3+i, "vrbacrda12345678", 16); } crypto_digest(buf2+9, buf3, 65536); - test_memeq(buf, buf2, 29); + tt_mem_op(buf,==, buf2, 29); done: tor_free(buf3); } +static void +run_s2k_tests(const unsigned flags, const unsigned type, + int speclen, const int keylen, int legacy) +{ + uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN], buf3[S2K_MAXLEN]; + int r; + size_t sz; + const char pw1[] = "You can't come in here unless you say swordfish!"; + const char pw2[] = "Now, I give you one more guess."; + + r = secret_to_key_new(buf, sizeof(buf), &sz, + pw1, strlen(pw1), flags); + tt_int_op(r, ==, S2K_OKAY); + tt_int_op(buf[0], ==, type); + + tt_int_op(sz, ==, keylen + speclen); + + if (legacy) { + memmove(buf, buf+1, sz-1); + --sz; + --speclen; + } + + tt_int_op(S2K_OKAY, ==, + secret_to_key_check(buf, sz, pw1, strlen(pw1))); + + tt_int_op(S2K_BAD_SECRET, ==, + secret_to_key_check(buf, sz, pw2, strlen(pw2))); + + /* Move key to buf2, and clear it. */ + memset(buf3, 0, sizeof(buf3)); + memcpy(buf2, buf+speclen, keylen); + memset(buf+speclen, 0, sz - speclen); + + /* Derivekey should produce the same results. */ + tt_int_op(S2K_OKAY, ==, + secret_to_key_derivekey(buf3, keylen, buf, speclen, pw1, strlen(pw1))); + + tt_mem_op(buf2, ==, buf3, keylen); + + /* Derivekey with a longer output should fill the output. */ + memset(buf2, 0, sizeof(buf2)); + tt_int_op(S2K_OKAY, ==, + secret_to_key_derivekey(buf2, sizeof(buf2), buf, speclen, + pw1, strlen(pw1))); + + tt_mem_op(buf2, !=, buf3, sizeof(buf2)); + + memset(buf3, 0, sizeof(buf3)); + tt_int_op(S2K_OKAY, ==, + secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen, + pw1, strlen(pw1))); + tt_mem_op(buf2, ==, buf3, sizeof(buf3)); + tt_assert(!tor_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen)); + + done: + ; +} + +static void +test_crypto_s2k_general(void *arg) +{ + const char *which = arg; + + if (!strcmp(which, "scrypt")) { + run_s2k_tests(0, 2, 19, 32, 0); + } else if (!strcmp(which, "scrypt-low")) { + run_s2k_tests(S2K_FLAG_LOW_MEM, 2, 19, 32, 0); + } else if (!strcmp(which, "pbkdf2")) { + run_s2k_tests(S2K_FLAG_USE_PBKDF2, 1, 18, 20, 0); + } else if (!strcmp(which, "rfc2440")) { + run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 0); + } else if (!strcmp(which, "rfc2440-legacy")) { + run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 1); + } else { + tt_fail(); + } +} + +static void +test_crypto_s2k_errors(void *arg) +{ + uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN]; + size_t sz; + + (void)arg; + + /* Bogus specifiers: simple */ + tt_int_op(S2K_BAD_LEN, ==, + secret_to_key_derivekey(buf, sizeof(buf), + (const uint8_t*)"", 0, "ABC", 3)); + tt_int_op(S2K_BAD_ALGORITHM, ==, + secret_to_key_derivekey(buf, sizeof(buf), + (const uint8_t*)"\x10", 1, "ABC", 3)); + tt_int_op(S2K_BAD_LEN, ==, + secret_to_key_derivekey(buf, sizeof(buf), + (const uint8_t*)"\x01\x02", 2, "ABC", 3)); + + tt_int_op(S2K_BAD_LEN, ==, + secret_to_key_check((const uint8_t*)"", 0, "ABC", 3)); + tt_int_op(S2K_BAD_ALGORITHM, ==, + secret_to_key_check((const uint8_t*)"\x10", 1, "ABC", 3)); + tt_int_op(S2K_BAD_LEN, ==, + secret_to_key_check((const uint8_t*)"\x01\x02", 2, "ABC", 3)); + + /* too long gets "BAD_LEN" too */ + memset(buf, 0, sizeof(buf)); + buf[0] = 2; + tt_int_op(S2K_BAD_LEN, ==, + secret_to_key_derivekey(buf2, sizeof(buf2), + buf, sizeof(buf), "ABC", 3)); + + /* Truncated output */ +#ifdef HAVE_LIBSCRYPT_H + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 50, &sz, + "ABC", 3, 0)); + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 50, &sz, + "ABC", 3, S2K_FLAG_LOW_MEM)); +#endif + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 37, &sz, + "ABC", 3, S2K_FLAG_USE_PBKDF2)); + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 29, &sz, + "ABC", 3, S2K_FLAG_NO_SCRYPT)); + +#ifdef HAVE_LIBSCRYPT_H + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 18, 0)); + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 18, + S2K_FLAG_LOW_MEM)); +#endif + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 17, + S2K_FLAG_USE_PBKDF2)); + tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 9, + S2K_FLAG_NO_SCRYPT)); + + /* Now try using type-specific bogus specifiers. */ + + /* It's a bad pbkdf2 buffer if it has an iteration count that would overflow + * int32_t. */ + memset(buf, 0, sizeof(buf)); + buf[0] = 1; /* pbkdf2 */ + buf[17] = 100; /* 1<<100 is much bigger than INT32_MAX */ + tt_int_op(S2K_BAD_PARAMS, ==, + secret_to_key_derivekey(buf2, sizeof(buf2), + buf, 18, "ABC", 3)); + +#ifdef HAVE_LIBSCRYPT_H + /* It's a bad scrypt buffer if N would overflow uint64 */ + memset(buf, 0, sizeof(buf)); + buf[0] = 2; /* scrypt */ + buf[17] = 100; /* 1<<100 is much bigger than UINT64_MAX */ + tt_int_op(S2K_BAD_PARAMS, ==, + secret_to_key_derivekey(buf2, sizeof(buf2), + buf, 19, "ABC", 3)); +#endif + + done: + ; +} + +static void +test_crypto_scrypt_vectors(void *arg) +{ + char *mem_op_hex_tmp = NULL; + uint8_t spec[64], out[64]; + + (void)arg; +#ifndef HAVE_LIBSCRYPT_H + if (1) + tt_skip(); +#endif + + /* Test vectors from + http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00 section 11. + + Note that the names of 'r' and 'N' are switched in that section. Or + possibly in libscrypt. + */ + + base16_decode((char*)spec, sizeof(spec), + "0400", 4); + memset(out, 0x00, sizeof(out)); + tt_int_op(64, ==, + secret_to_key_compute_key(out, 64, spec, 2, "", 0, 2)); + test_memeq_hex(out, + "77d6576238657b203b19ca42c18a0497" + "f16b4844e3074ae8dfdffa3fede21442" + "fcd0069ded0948f8326a753a0fc81f17" + "e8d3e0fb2e0d3628cf35e20c38d18906"); + + base16_decode((char*)spec, sizeof(spec), + "4e61436c" "0A34", 12); + memset(out, 0x00, sizeof(out)); + tt_int_op(64, ==, + secret_to_key_compute_key(out, 64, spec, 6, "password", 8, 2)); + test_memeq_hex(out, + "fdbabe1c9d3472007856e7190d01e9fe" + "7c6ad7cbc8237830e77376634b373162" + "2eaf30d92e22a3886ff109279d9830da" + "c727afb94a83ee6d8360cbdfa2cc0640"); + + base16_decode((char*)spec, sizeof(spec), + "536f6469756d43686c6f72696465" "0e30", 32); + memset(out, 0x00, sizeof(out)); + tt_int_op(64, ==, + secret_to_key_compute_key(out, 64, spec, 16, + "pleaseletmein", 13, 2)); + test_memeq_hex(out, + "7023bdcb3afd7348461c06cd81fd38eb" + "fda8fbba904f8e3ea9b543f6545da1f2" + "d5432955613f0fcf62d49705242a9af9" + "e61e85dc0d651e40dfcf017b45575887"); + + base16_decode((char*)spec, sizeof(spec), + "536f6469756d43686c6f72696465" "1430", 32); + memset(out, 0x00, sizeof(out)); + tt_int_op(64, ==, + secret_to_key_compute_key(out, 64, spec, 16, + "pleaseletmein", 13, 2)); + test_memeq_hex(out, + "2101cb9b6a511aaeaddbbe09cf70f881" + "ec568d574a2ffd4dabe5ee9820adaa47" + "8e56fd8f4ba5d09ffa1c6d927c40f4c3" + "37304049e8a952fbcbf45c6fa77a41a4"); + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_crypto_pbkdf2_vectors(void *arg) +{ + char *mem_op_hex_tmp = NULL; + uint8_t spec[64], out[64]; + (void)arg; + + /* Test vectors from RFC6070, section 2 */ + base16_decode((char*)spec, sizeof(spec), + "73616c74" "00" , 10); + memset(out, 0x00, sizeof(out)); + tt_int_op(20, ==, + secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1)); + test_memeq_hex(out, "0c60c80f961f0e71f3a9b524af6012062fe037a6"); + + base16_decode((char*)spec, sizeof(spec), + "73616c74" "01" , 10); + memset(out, 0x00, sizeof(out)); + tt_int_op(20, ==, + secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1)); + test_memeq_hex(out, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"); + + base16_decode((char*)spec, sizeof(spec), + "73616c74" "0C" , 10); + memset(out, 0x00, sizeof(out)); + tt_int_op(20, ==, + secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1)); + test_memeq_hex(out, "4b007901b765489abead49d926f721d065a429c1"); + + base16_decode((char*)spec, sizeof(spec), + "73616c74" "18" , 10); + memset(out, 0x00, sizeof(out)); + tt_int_op(20, ==, + secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1)); + test_memeq_hex(out, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"); + + base16_decode((char*)spec, sizeof(spec), + "73616c7453414c5473616c7453414c5473616c745" + "3414c5473616c7453414c5473616c74" "0C" , 74); + memset(out, 0x00, sizeof(out)); + tt_int_op(25, ==, + secret_to_key_compute_key(out, 25, spec, 37, + "passwordPASSWORDpassword", 24, 1)); + test_memeq_hex(out, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"); + + base16_decode((char*)spec, sizeof(spec), + "7361006c74" "0c" , 12); + memset(out, 0x00, sizeof(out)); + tt_int_op(16, ==, + secret_to_key_compute_key(out, 16, spec, 6, "pass\0word", 9, 1)); + test_memeq_hex(out, "56fa6aa75548099dcc37d7f03425e0c3"); + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_crypto_pwbox(void *arg) +{ + uint8_t *boxed=NULL, *decoded=NULL; + size_t len, dlen; + unsigned i; + const char msg[] = "This bunny reminds you that you still have a " + "salamander in your sylladex. She is holding the bunny Dave got you. " + "It’s sort of uncanny how similar they are, aside from the knitted " + "enhancements. Seriously, what are the odds?? So weird."; + const char pw[] = "I'm a night owl and a wise bird too"; + + const unsigned flags[] = { 0, + S2K_FLAG_NO_SCRYPT, + S2K_FLAG_LOW_MEM, + S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM, + S2K_FLAG_USE_PBKDF2 }; + (void)arg; + + for (i = 0; i < ARRAY_LENGTH(flags); ++i) { + tt_int_op(0, ==, crypto_pwbox(&boxed, &len, + (const uint8_t*)msg, strlen(msg), + pw, strlen(pw), flags[i])); + tt_assert(boxed); + tt_assert(len > 128+32); + + tt_int_op(0, ==, crypto_unpwbox(&decoded, &dlen, boxed, len, + pw, strlen(pw))); + + tt_assert(decoded); + tt_uint_op(dlen, ==, strlen(msg)); + tt_mem_op(decoded, ==, msg, dlen); + + tor_free(decoded); + + tt_int_op(UNPWBOX_BAD_SECRET, ==, crypto_unpwbox(&decoded, &dlen, + boxed, len, + pw, strlen(pw)-1)); + boxed[len-1] ^= 1; + tt_int_op(UNPWBOX_BAD_SECRET, ==, crypto_unpwbox(&decoded, &dlen, + boxed, len, + pw, strlen(pw))); + boxed[0] = 255; + tt_int_op(UNPWBOX_CORRUPTED, ==, crypto_unpwbox(&decoded, &dlen, + boxed, len, + pw, strlen(pw))); + + tor_free(boxed); + } + + done: + tor_free(boxed); + tor_free(decoded); +} + /** Test AES-CTR encryption and decryption with IV. */ static void test_crypto_aes_iv(void *arg) @@ -757,79 +1116,79 @@ test_crypto_aes_iv(void *arg) encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 4095, plain, 4095); - test_eq(encrypted_size, 16 + 4095); + tt_int_op(encrypted_size,==, 16 + 4095); tt_assert(encrypted_size > 0); /* This is obviously true, since 4111 is * greater than 0, but its truth is not * obvious to all analysis tools. */ decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 4095, encrypted1, encrypted_size); - test_eq(decrypted_size, 4095); + tt_int_op(decrypted_size,==, 4095); tt_assert(decrypted_size > 0); - test_memeq(plain, decrypted1, 4095); + tt_mem_op(plain,==, decrypted1, 4095); /* Encrypt a second time (with a new random initialization vector). */ encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted2, 16 + 4095, plain, 4095); - test_eq(encrypted_size, 16 + 4095); + tt_int_op(encrypted_size,==, 16 + 4095); tt_assert(encrypted_size > 0); decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted2, 4095, encrypted2, encrypted_size); - test_eq(decrypted_size, 4095); + tt_int_op(decrypted_size,==, 4095); tt_assert(decrypted_size > 0); - test_memeq(plain, decrypted2, 4095); - test_memneq(encrypted1, encrypted2, encrypted_size); + tt_mem_op(plain,==, decrypted2, 4095); + tt_mem_op(encrypted1,!=, encrypted2, encrypted_size); /* Decrypt with the wrong key. */ decrypted_size = crypto_cipher_decrypt_with_iv(key2, decrypted2, 4095, encrypted1, encrypted_size); - test_eq(decrypted_size, 4095); - test_memneq(plain, decrypted2, decrypted_size); + tt_int_op(decrypted_size,==, 4095); + tt_mem_op(plain,!=, decrypted2, decrypted_size); /* Alter the initialization vector. */ encrypted1[0] += 42; decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 4095, encrypted1, encrypted_size); - test_eq(decrypted_size, 4095); - test_memneq(plain, decrypted2, 4095); + tt_int_op(decrypted_size,==, 4095); + tt_mem_op(plain,!=, decrypted2, 4095); /* Special length case: 1. */ encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 1, plain_1, 1); - test_eq(encrypted_size, 16 + 1); + tt_int_op(encrypted_size,==, 16 + 1); tt_assert(encrypted_size > 0); decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 1, encrypted1, encrypted_size); - test_eq(decrypted_size, 1); + tt_int_op(decrypted_size,==, 1); tt_assert(decrypted_size > 0); - test_memeq(plain_1, decrypted1, 1); + tt_mem_op(plain_1,==, decrypted1, 1); /* Special length case: 15. */ encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 15, plain_15, 15); - test_eq(encrypted_size, 16 + 15); + tt_int_op(encrypted_size,==, 16 + 15); tt_assert(encrypted_size > 0); decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 15, encrypted1, encrypted_size); - test_eq(decrypted_size, 15); + tt_int_op(decrypted_size,==, 15); tt_assert(decrypted_size > 0); - test_memeq(plain_15, decrypted1, 15); + tt_mem_op(plain_15,==, decrypted1, 15); /* Special length case: 16. */ encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 16, plain_16, 16); - test_eq(encrypted_size, 16 + 16); + tt_int_op(encrypted_size,==, 16 + 16); tt_assert(encrypted_size > 0); decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 16, encrypted1, encrypted_size); - test_eq(decrypted_size, 16); + tt_int_op(decrypted_size,==, 16); tt_assert(decrypted_size > 0); - test_memeq(plain_16, decrypted1, 16); + tt_mem_op(plain_16,==, decrypted1, 16); /* Special length case: 17. */ encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 17, plain_17, 17); - test_eq(encrypted_size, 16 + 17); + tt_int_op(encrypted_size,==, 16 + 17); tt_assert(encrypted_size > 0); decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 17, encrypted1, encrypted_size); - test_eq(decrypted_size, 17); + tt_int_op(decrypted_size,==, 17); tt_assert(decrypted_size > 0); - test_memeq(plain_17, decrypted1, 17); + tt_mem_op(plain_17,==, decrypted1, 17); done: /* Free memory. */ @@ -842,34 +1201,35 @@ test_crypto_aes_iv(void *arg) /** Test base32 decoding. */ static void -test_crypto_base32_decode(void) +test_crypto_base32_decode(void *arg) { char plain[60], encoded[96 + 1], decoded[60]; int res; + (void)arg; crypto_rand(plain, 60); /* Encode and decode a random string. */ base32_encode(encoded, 96 + 1, plain, 60); res = base32_decode(decoded, 60, encoded, 96); - test_eq(res, 0); - test_memeq(plain, decoded, 60); + tt_int_op(res,==, 0); + tt_mem_op(plain,==, decoded, 60); /* Encode, uppercase, and decode a random string. */ base32_encode(encoded, 96 + 1, plain, 60); tor_strupper(encoded); res = base32_decode(decoded, 60, encoded, 96); - test_eq(res, 0); - test_memeq(plain, decoded, 60); + tt_int_op(res,==, 0); + tt_mem_op(plain,==, decoded, 60); /* Change encoded string and decode. */ if (encoded[0] == 'A' || encoded[0] == 'a') encoded[0] = 'B'; else encoded[0] = 'A'; res = base32_decode(decoded, 60, encoded, 96); - test_eq(res, 0); - test_memneq(plain, decoded, 60); + tt_int_op(res,==, 0); + tt_mem_op(plain,!=, decoded, 60); /* Bad encodings. */ encoded[0] = '!'; res = base32_decode(decoded, 60, encoded, 96); - test_assert(res < 0); + tt_int_op(0, >, res); done: ; @@ -1024,7 +1384,7 @@ test_crypto_curve25519_impl(void *arg) e2k[31] |= (byte & 0x80); } curve25519_impl(e1e2k,e1,e2k); - test_memeq(e1e2k, e2e1k, 32); + tt_mem_op(e1e2k,==, e2e1k, 32); if (loop == loop_max-1) { break; } @@ -1056,11 +1416,11 @@ test_crypto_curve25519_wrappers(void *arg) curve25519_secret_key_generate(&seckey2, 1); curve25519_public_key_generate(&pubkey1, &seckey1); curve25519_public_key_generate(&pubkey2, &seckey2); - test_assert(curve25519_public_key_is_ok(&pubkey1)); - test_assert(curve25519_public_key_is_ok(&pubkey2)); + tt_assert(curve25519_public_key_is_ok(&pubkey1)); + tt_assert(curve25519_public_key_is_ok(&pubkey2)); curve25519_handshake(output1, &seckey1, &pubkey2); curve25519_handshake(output2, &seckey2, &pubkey1); - test_memeq(output1, output2, sizeof(output1)); + tt_mem_op(output1,==, output2, sizeof(output1)); done: ; @@ -1081,12 +1441,12 @@ test_crypto_curve25519_encode(void *arg) tt_int_op(CURVE25519_BASE64_PADDED_LEN, ==, strlen(buf)); tt_int_op(0, ==, curve25519_public_from_base64(&key2, buf)); - test_memeq(key1.public_key, key2.public_key, CURVE25519_PUBKEY_LEN); + tt_mem_op(key1.public_key,==, key2.public_key, CURVE25519_PUBKEY_LEN); buf[CURVE25519_BASE64_PADDED_LEN - 1] = '\0'; tt_int_op(CURVE25519_BASE64_PADDED_LEN-1, ==, strlen(buf)); tt_int_op(0, ==, curve25519_public_from_base64(&key3, buf)); - test_memeq(key1.public_key, key3.public_key, CURVE25519_PUBKEY_LEN); + tt_mem_op(key1.public_key,==, key3.public_key, CURVE25519_PUBKEY_LEN); /* Now try bogus parses. */ strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$=", sizeof(buf)); @@ -1122,10 +1482,10 @@ test_crypto_curve25519_persist(void *arg) tt_str_op(tag,==,"testing"); tor_free(tag); - test_memeq(keypair.pubkey.public_key, + tt_mem_op(keypair.pubkey.public_key,==, keypair2.pubkey.public_key, CURVE25519_PUBKEY_LEN); - test_memeq(keypair.seckey.secret_key, + tt_mem_op(keypair.seckey.secret_key,==, keypair2.seckey.secret_key, CURVE25519_SECKEY_LEN); @@ -1137,11 +1497,11 @@ test_crypto_curve25519_persist(void *arg) tt_assert(fast_memeq(content, "== c25519v1: testing ==", taglen)); tt_assert(tor_mem_is_zero(content+taglen, 32-taglen)); cp = content + 32; - test_memeq(keypair.seckey.secret_key, + tt_mem_op(keypair.seckey.secret_key,==, cp, CURVE25519_SECKEY_LEN); cp += CURVE25519_SECKEY_LEN; - test_memeq(keypair.pubkey.public_key, + tt_mem_op(keypair.pubkey.public_key,==, cp, CURVE25519_SECKEY_LEN); @@ -1161,7 +1521,362 @@ test_crypto_curve25519_persist(void *arg) tor_free(tag); } -#endif +static void +test_crypto_ed25519_simple(void *arg) +{ + ed25519_keypair_t kp1, kp2; + ed25519_public_key_t pub1, pub2; + ed25519_secret_key_t sec1, sec2; + ed25519_signature_t sig1, sig2; + const uint8_t msg[] = + "GNU will be able to run Unix programs, " + "but will not be identical to Unix."; + const uint8_t msg2[] = + "Microsoft Windows extends the features of the DOS operating system, " + "yet is compatible with most existing applications that run under DOS."; + size_t msg_len = strlen((const char*)msg); + size_t msg2_len = strlen((const char*)msg2); + + (void)arg; + + tt_int_op(0, ==, ed25519_secret_key_generate(&sec1, 0)); + tt_int_op(0, ==, ed25519_secret_key_generate(&sec2, 1)); + + tt_int_op(0, ==, ed25519_public_key_generate(&pub1, &sec1)); + tt_int_op(0, ==, ed25519_public_key_generate(&pub2, &sec1)); + + tt_mem_op(pub1.pubkey, ==, pub2.pubkey, sizeof(pub1.pubkey)); + + memcpy(&kp1.pubkey, &pub1, sizeof(pub1)); + memcpy(&kp1.seckey, &sec1, sizeof(sec1)); + tt_int_op(0, ==, ed25519_sign(&sig1, msg, msg_len, &kp1)); + tt_int_op(0, ==, ed25519_sign(&sig2, msg, msg_len, &kp1)); + + /* Ed25519 signatures are deterministic */ + tt_mem_op(sig1.sig, ==, sig2.sig, sizeof(sig1.sig)); + + /* Basic signature is valid. */ + tt_int_op(0, ==, ed25519_checksig(&sig1, msg, msg_len, &pub1)); + + /* Altered signature doesn't work. */ + sig1.sig[0] ^= 3; + tt_int_op(-1, ==, ed25519_checksig(&sig1, msg, msg_len, &pub1)); + + /* Wrong public key doesn't work. */ + tt_int_op(0, ==, ed25519_public_key_generate(&pub2, &sec2)); + tt_int_op(-1, ==, ed25519_checksig(&sig2, msg, msg_len, &pub2)); + + /* Wrong message doesn't work. */ + tt_int_op(0, ==, ed25519_checksig(&sig2, msg, msg_len, &pub1)); + tt_int_op(-1, ==, ed25519_checksig(&sig2, msg, msg_len-1, &pub1)); + tt_int_op(-1, ==, ed25519_checksig(&sig2, msg2, msg2_len, &pub1)); + + /* Batch signature checking works with some bad. */ + tt_int_op(0, ==, ed25519_keypair_generate(&kp2, 0)); + tt_int_op(0, ==, ed25519_sign(&sig1, msg, msg_len, &kp2)); + { + ed25519_checkable_t ch[] = { + { &pub1, sig2, msg, msg_len }, /*ok*/ + { &pub1, sig2, msg, msg_len-1 }, /*bad*/ + { &kp2.pubkey, sig2, msg2, msg2_len }, /*bad*/ + { &kp2.pubkey, sig1, msg, msg_len }, /*ok*/ + }; + int okay[4]; + tt_int_op(-2, ==, ed25519_checksig_batch(okay, ch, 4)); + tt_int_op(okay[0], ==, 1); + tt_int_op(okay[1], ==, 0); + tt_int_op(okay[2], ==, 0); + tt_int_op(okay[3], ==, 1); + tt_int_op(-2, ==, ed25519_checksig_batch(NULL, ch, 4)); + } + + /* Batch signature checking works with all good. */ + { + ed25519_checkable_t ch[] = { + { &pub1, sig2, msg, msg_len }, /*ok*/ + { &kp2.pubkey, sig1, msg, msg_len }, /*ok*/ + }; + int okay[2]; + tt_int_op(0, ==, ed25519_checksig_batch(okay, ch, 2)); + tt_int_op(okay[0], ==, 1); + tt_int_op(okay[1], ==, 1); + tt_int_op(0, ==, ed25519_checksig_batch(NULL, ch, 2)); + } + + done: + ; +} + +static void +test_crypto_ed25519_test_vectors(void *arg) +{ + char *mem_op_hex_tmp=NULL; + int i; + struct { + const char *sk; + const char *pk; + const char *sig; + const char *msg; + } items[] = { + /* These test vectors were generated with the "ref" implementation of + * ed25519 from SUPERCOP-20130419 */ + { "4c6574277320686f706520746865726520617265206e6f206275677320696e20", + "f3e0e493b30f56e501aeb868fc912fe0c8b76621efca47a78f6d75875193dd87", + "b5d7fd6fd3adf643647ce1fe87a2931dedd1a4e38e6c662bedd35cdd80bfac51" + "1b2c7d1ee6bd929ac213014e1a8dc5373854c7b25dbe15ec96bf6c94196fae06", + "506c6561736520657863757365206d7920667269656e642e2048652069736e2774" + "204e554c2d7465726d696e617465642e" + }, + + { "74686520696d706c656d656e746174696f6e20776869636820617265206e6f74", + "407f0025a1e1351a4cb68e92f5c0ebaf66e7aaf93a4006a4d1a66e3ede1cfeac", + "02884fde1c3c5944d0ecf2d133726fc820c303aae695adceabf3a1e01e95bf28" + "da88c0966f5265e9c6f8edc77b3b96b5c91baec3ca993ccd21a3f64203600601", + "506c6561736520657863757365206d7920667269656e642e2048652069736e2774" + "204e554c2d7465726d696e617465642e" + }, + { "6578706f73656420627920456e676c697368207465787420617320696e707574", + "61681cb5fbd69f9bc5a462a21a7ab319011237b940bc781cdc47fcbe327e7706", + "6a127d0414de7510125d4bc214994ffb9b8857a46330832d05d1355e882344ad" + "f4137e3ca1f13eb9cc75c887ef2309b98c57528b4acd9f6376c6898889603209", + "506c6561736520657863757365206d7920667269656e642e2048652069736e2774" + "204e554c2d7465726d696e617465642e" + }, + + /* These come from "sign.input" in ed25519's page */ + { "5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef9", + "6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257", + "0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258" + "c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e", + "5a8d9d0a22357e6655f9c785" + }, + { "940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800", + "a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd", + "d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d" + "640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0c", + "b87d3813e03f58cf19fd0b6395" + }, + { "9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738", + "cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291", + "6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0" + "671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf06", + "55c7fa434f5ed8cdec2b7aeac173", + }, + { "d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300", + "fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5", + "f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f3550395" + "1fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b00", + "0a688e79be24f866286d4646b5d81c" + }, + + { NULL, NULL, NULL, NULL} + }; + + (void)arg; + + for (i = 0; items[i].pk; ++i) { + ed25519_keypair_t kp; + ed25519_signature_t sig; + uint8_t sk_seed[32]; + uint8_t *msg; + size_t msg_len; + base16_decode((char*)sk_seed, sizeof(sk_seed), + items[i].sk, 64); + ed25519_secret_key_from_seed(&kp.seckey, sk_seed); + tt_int_op(0, ==, ed25519_public_key_generate(&kp.pubkey, &kp.seckey)); + test_memeq_hex(kp.pubkey.pubkey, items[i].pk); + + msg_len = strlen(items[i].msg) / 2; + msg = tor_malloc(msg_len); + base16_decode((char*)msg, msg_len, items[i].msg, strlen(items[i].msg)); + + tt_int_op(0, ==, ed25519_sign(&sig, msg, msg_len, &kp)); + test_memeq_hex(sig.sig, items[i].sig); + + tor_free(msg); + } + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_crypto_ed25519_encode(void *arg) +{ + char buf[ED25519_BASE64_LEN+1]; + ed25519_keypair_t kp; + ed25519_public_key_t pk; + char *mem_op_hex_tmp = NULL; + (void) arg; + + /* Test roundtrip. */ + tt_int_op(0, ==, ed25519_keypair_generate(&kp, 0)); + tt_int_op(0, ==, ed25519_public_to_base64(buf, &kp.pubkey)); + tt_int_op(ED25519_BASE64_LEN, ==, strlen(buf)); + tt_int_op(0, ==, ed25519_public_from_base64(&pk, buf)); + tt_mem_op(kp.pubkey.pubkey, ==, pk.pubkey, ED25519_PUBKEY_LEN); + + /* Test known value. */ + tt_int_op(0, ==, ed25519_public_from_base64(&pk, + "lVIuIctLjbGZGU5wKMNXxXlSE3cW4kaqkqm04u6pxvM")); + test_memeq_hex(pk.pubkey, + "95522e21cb4b8db199194e7028c357c57952137716e246aa92a9b4e2eea9c6f3"); + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_crypto_ed25519_convert(void *arg) +{ + const uint8_t msg[] = + "The eyes are not here / There are no eyes here."; + const int N = 30; + int i; + (void)arg; + + for (i = 0; i < N; ++i) { + curve25519_keypair_t curve25519_keypair; + ed25519_keypair_t ed25519_keypair; + ed25519_public_key_t ed25519_pubkey; + + int bit=0; + ed25519_signature_t sig; + + tt_int_op(0,==,curve25519_keypair_generate(&curve25519_keypair, i&1)); + tt_int_op(0,==,ed25519_keypair_from_curve25519_keypair( + &ed25519_keypair, &bit, &curve25519_keypair)); + tt_int_op(0,==,ed25519_public_key_from_curve25519_public_key( + &ed25519_pubkey, &curve25519_keypair.pubkey, bit)); + tt_mem_op(ed25519_pubkey.pubkey, ==, ed25519_keypair.pubkey.pubkey, 32); + + tt_int_op(0,==,ed25519_sign(&sig, msg, sizeof(msg), &ed25519_keypair)); + tt_int_op(0,==,ed25519_checksig(&sig, msg, sizeof(msg), + &ed25519_pubkey)); + + tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg)-1, + &ed25519_pubkey)); + sig.sig[0] ^= 15; + tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg), + &ed25519_pubkey)); + } + + done: + ; +} + +static void +test_crypto_ed25519_blinding(void *arg) +{ + const uint8_t msg[] = + "Eyes I dare not meet in dreams / In death's dream kingdom"; + + const int N = 30; + int i; + (void)arg; + + for (i = 0; i < N; ++i) { + uint8_t blinding[32]; + ed25519_keypair_t ed25519_keypair; + ed25519_keypair_t ed25519_keypair_blinded; + ed25519_public_key_t ed25519_pubkey_blinded; + + ed25519_signature_t sig; + + crypto_rand((char*) blinding, sizeof(blinding)); + + tt_int_op(0,==,ed25519_keypair_generate(&ed25519_keypair, 0)); + tt_int_op(0,==,ed25519_keypair_blind(&ed25519_keypair_blinded, + &ed25519_keypair, blinding)); + + tt_int_op(0,==,ed25519_public_blind(&ed25519_pubkey_blinded, + &ed25519_keypair.pubkey, blinding)); + + tt_mem_op(ed25519_pubkey_blinded.pubkey, ==, + ed25519_keypair_blinded.pubkey.pubkey, 32); + + tt_int_op(0,==,ed25519_sign(&sig, msg, sizeof(msg), + &ed25519_keypair_blinded)); + + tt_int_op(0,==,ed25519_checksig(&sig, msg, sizeof(msg), + &ed25519_pubkey_blinded)); + + tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg)-1, + &ed25519_pubkey_blinded)); + sig.sig[0] ^= 15; + tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg), + &ed25519_pubkey_blinded)); + } + + done: + ; +} + +static void +test_crypto_ed25519_testvectors(void *arg) +{ + unsigned i; + char *mem_op_hex_tmp = NULL; + (void)arg; + + for (i = 0; i < ARRAY_LENGTH(ED25519_SECRET_KEYS); ++i) { + uint8_t sk[32]; + ed25519_secret_key_t esk; + ed25519_public_key_t pk, blind_pk, pkfromcurve; + ed25519_keypair_t keypair, blind_keypair; + curve25519_keypair_t curvekp; + uint8_t blinding_param[32]; + ed25519_signature_t sig; + int sign; + +#define DECODE(p,s) base16_decode((char*)(p),sizeof(p),(s),strlen(s)) +#define EQ(a,h) test_memeq_hex((const char*)(a), (h)) + + tt_int_op(0, ==, DECODE(sk, ED25519_SECRET_KEYS[i])); + tt_int_op(0, ==, DECODE(blinding_param, ED25519_BLINDING_PARAMS[i])); + + tt_int_op(0, ==, ed25519_secret_key_from_seed(&esk, sk)); + EQ(esk.seckey, ED25519_EXPANDED_SECRET_KEYS[i]); + + tt_int_op(0, ==, ed25519_public_key_generate(&pk, &esk)); + EQ(pk.pubkey, ED25519_PUBLIC_KEYS[i]); + + memcpy(&curvekp.seckey.secret_key, esk.seckey, 32); + curve25519_public_key_generate(&curvekp.pubkey, &curvekp.seckey); + + tt_int_op(0, ==, + ed25519_keypair_from_curve25519_keypair(&keypair, &sign, &curvekp)); + tt_int_op(0, ==, ed25519_public_key_from_curve25519_public_key( + &pkfromcurve, &curvekp.pubkey, sign)); + tt_mem_op(keypair.pubkey.pubkey, ==, pkfromcurve.pubkey, 32); + EQ(curvekp.pubkey.public_key, ED25519_CURVE25519_PUBLIC_KEYS[i]); + + /* Self-signing */ + memcpy(&keypair.seckey, &esk, sizeof(esk)); + memcpy(&keypair.pubkey, &pk, sizeof(pk)); + + tt_int_op(0, ==, ed25519_sign(&sig, pk.pubkey, 32, &keypair)); + + EQ(sig.sig, ED25519_SELF_SIGNATURES[i]); + + /* Blinding */ + tt_int_op(0, ==, + ed25519_keypair_blind(&blind_keypair, &keypair, blinding_param)); + tt_int_op(0, ==, + ed25519_public_blind(&blind_pk, &pk, blinding_param)); + + EQ(blind_keypair.seckey.seckey, ED25519_BLINDED_SECRET_KEYS[i]); + EQ(blind_pk.pubkey, ED25519_BLINDED_PUBLIC_KEYS[i]); + + tt_mem_op(blind_pk.pubkey, ==, blind_keypair.pubkey.pubkey, 32); + +#undef DECODE +#undef EQ + } + done: + tor_free(mem_op_hex_tmp); +} +#endif /* CURVE25519_ENABLED */ static void test_crypto_siphash(void *arg) @@ -1276,7 +1991,7 @@ static const struct testcase_setup_t pass_data = { }; #define CRYPTO_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_crypto_ ## name } + { #name, test_crypto_ ## name , 0, NULL, NULL } struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), @@ -1288,7 +2003,23 @@ struct testcase_t crypto_tests[] = { { "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL }, CRYPTO_LEGACY(digests), CRYPTO_LEGACY(dh), - CRYPTO_LEGACY(s2k), + CRYPTO_LEGACY(s2k_rfc2440), +#ifdef HAVE_LIBSCRYPT_H + { "s2k_scrypt", test_crypto_s2k_general, 0, &pass_data, + (void*)"scrypt" }, + { "s2k_scrypt_low", test_crypto_s2k_general, 0, &pass_data, + (void*)"scrypt-low" }, +#endif + { "s2k_pbkdf2", test_crypto_s2k_general, 0, &pass_data, + (void*)"pbkdf2" }, + { "s2k_rfc2440_general", test_crypto_s2k_general, 0, &pass_data, + (void*)"rfc2440" }, + { "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &pass_data, + (void*)"rfc2440-legacy" }, + { "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL }, + { "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL }, + { "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL }, + { "pwbox", test_crypto_pwbox, 0, NULL, NULL }, { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"aes" }, { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"evp" }, CRYPTO_LEGACY(base32_decode), @@ -1300,6 +2031,12 @@ struct testcase_t crypto_tests[] = { { "curve25519_wrappers", test_crypto_curve25519_wrappers, 0, NULL, NULL }, { "curve25519_encode", test_crypto_curve25519_encode, 0, NULL, NULL }, { "curve25519_persist", test_crypto_curve25519_persist, 0, NULL, NULL }, + { "ed25519_simple", test_crypto_ed25519_simple, 0, NULL, NULL }, + { "ed25519_test_vectors", test_crypto_ed25519_test_vectors, 0, NULL, NULL }, + { "ed25519_encode", test_crypto_ed25519_encode, 0, NULL, NULL }, + { "ed25519_convert", test_crypto_ed25519_convert, 0, NULL, NULL }, + { "ed25519_blinding", test_crypto_ed25519_blinding, 0, NULL, NULL }, + { "ed25519_testvectors", test_crypto_ed25519_testvectors, 0, NULL, NULL }, #endif { "siphash", test_crypto_siphash, 0, NULL, NULL }, END_OF_TESTCASES diff --git a/src/test/test_descriptors.inc b/src/test/test_descriptors.inc new file mode 100644 index 0000000000..ecbccbd43a --- /dev/null +++ b/src/test/test_descriptors.inc @@ -0,0 +1,305 @@ +const char TEST_DESCRIPTORS[] = +"@uploaded-at 2014-06-08 19:20:11\n" +"@source \"127.0.0.1\"\n" +"router test000a 127.0.0.1 5000 0 7000\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n" +"caches-extra-info\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n" +"HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n" +"DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n" +"O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n" +"3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"contact auth0@test.test\n" +"ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n" +"reject *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n" +"aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n" +"eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:11\n" +"@source \"127.0.0.1\"\n" +"router test001a 127.0.0.1 5001 0 7001\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 35DA 711C FC62 F88B C243 DE32 DC0B C28A 3F62 2610\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 9E12278D6CF7608071FE98CE9DCEE48FA264518A\n" +"caches-extra-info\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAPbyUrorqoXMW4oezqd307ZGxgobqvQs2nb3TdQyWrwsHtJmS3utdrJS\n" +"xJUZPNHOQ2hrDWW1VvevYqRTGeXGZr9TDZ3+t/gVUttqYRhuzzgEKVAZSsTo5ctO\n" +"QNHnzJ6Xx/w/trhWqPTeJ7R0TCyAbWW7aE3KaKdwvZilRZp/oRUnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALwOJ7XZHBnjJEuwF3Os6eashNbTH9YnH8TBZBdKgu3iFJYqDslcMIPX\n" +"gWCJ9apPHyh1+/8OLRWeEYlwoZzgGi0rjm/+BNeOOmJbjfyjk97DuB9/2O5zr1BM\n" +"CvOHqQSzMD+vz1ebvfM039a2mO8lXruUFPZQaFVxk8371XP2khqhAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"contact auth1@test.test\n" +"ntor-onion-key t5bI1ksTdigOksMKRHUDwx/34ajEvDN1IpArOxIEWgk=\n" +"reject *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"KtMW7A/pzu+np6aKJSy6d7drIb4yjz8SPCo+oQNxj2IqNHJir2O2nWu69xy+K0c1\n" +"RL05KkcDaYzr5hC80FD1H+sTpGYD28SPkQkzPw+0pReSDl93pVXh0rU6Cdcm75FC\n" +"t0UZzDt4TsMuFB0ZYpM3phKcQPpiDG6aR0LskL/YUvY=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:11\n" +"@source \"127.0.0.1\"\n" +"router test004r 127.0.0.1 5004 0 7004\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:10\n" +"fingerprint CC6A 48BD 52BD 9A2C 6670 5863 AC31 AE17 6E63 8B02\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest B5CC249CEF394B5AFCA0C77FA7D5605615FA487C\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAMze36Hupy7HACcF3TMv5mJuZbx3d3cS0WYLl6vTeChBgpS5CEXq6zIu\n" +"d31YmtUcxH6fOjDOudhbnXuoh1nH4CP+LocVHAdlGG1giAm7u8yZudVvVJiIqFgQ\n" +"wVDcWx8LbGCi5P9J/ZPKAIVsSyS7xkOqHjz3VMo/uYLbQCFAwfkdAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAM/qGP365x6bH+ug7rKVy7V5lC9Ff2Jfk0wlTFIzzwn+DMSG6xDvulKe\n" +"wcIzgGNdQu7qlKlQUif3GPMr0KSS32cRsmoRQJcsm9+lGUK871NyZ8AyrHT+LhyF\n" +"cs718P0iN5yKF2FikNr727kEANCzvC1l9eP4qF5GGzsNtglbJ7bTAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key a9Pavqnx7DFhMWUO0d17qF9Py8+iie4FnxTHaTgfIXY=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"HVW7kjBgEt+Qdvcrq+NQE1F9B8uV9D38KA2Bp6cYHLWCxL6N4GS8JQqbOEtnqaj7\n" +"Vxrv7uy1Fzb15Zr+1sUVMxNv+LLRfr+JzfETMNYVkYDrNgr1cAAVEQzFWbIziond\n" +"xMFp64yjEW9/I+82lb5GBZEiKdEd4QqWMmQosoYMTM8=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test002a 127.0.0.1 5002 0 7002\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 29C7 BBB6 C437 32D5 BDF1 5671 F5C5 F1FB 6E36 4B47\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 9BB181EA86E0130680C3CC04AD7DE4C341ADC2C7\n" +"caches-extra-info\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALNH19oF8Ajf+djlH/g7L+enFBf5Wwjmf3bPwNKWZ9G+B+Lg8SpfhZiw\n" +"rUqi7h21f45BV/dN05dK6leWD8rj1T9kuM9TKBOEZxIWeq7zbXihyu4XPxP4FNTS\n" +"+0G7BhdP4biALENmeyLhUCZaw5Ic/jFkHT4gV9S0iVZiEDwC9twXAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALeyQGMQBHgTxpO/i30uHjflTm9MNi3ZBNcOKpvBXWYgY42qTqOZ7Uam\n" +"c5pmZhTLrQ1W8XlGDw8Cl8ktZ0ylodLZyUNajBtJvSFWTb8iwdZsshW6Ahb8TyfI\n" +"Y7MwTlQ/7xw4mj1NEaui6bwGgEZUs18RTqhDrUc2Mcj1Yf61Rq+7AgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"contact auth2@test.test\n" +"ntor-onion-key ukR41RjtiZ69KO0SrFTvL0LoZK/ZTT01FQWmCXTCUlE=\n" +"reject *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"IY2s/RY4tdahrgfGG+vW7lOvpfofoxxSo7guGpSKGxVApiroCQtumoYifnnJ88G2\n" +"K4IbxwEO8pgO8fnz1mibblUWw2vdDNjCifc1wtXJUE+ONA0UcLRlfQ94GbL8h2PG\n" +"72z6i1+NN0QahXMk7MUbzI7bOXTJOiO8e2Zjk9vRnxI=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test006r 127.0.0.1 5006 0 7006\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 829B 3FAA A42B 605A EB0B F380 8F32 8ED1 73E7 0D25\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 7ECB757002EB9B5838B13AE6F2357A5E585131B8\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALsNBChcLVndlS4HNXL3hxBJVgXctATz6yXcJt3bkDB5cjv7Q9fqN3Ue\n" +"j3SI1OUBx4YrLcSLD/hELHVilLrrfbaraAFfAsydlRLjTVcMRx5FFlDd0E7TAadc\n" +"71CkTipNnjwqz1mTRKkEFeepnh/JaFDidY9ER1rMBA5JRyBvqrD9AgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAPgipA8yLj1kqrMlAH7cK7IQEdmqmfNHGXdkYQ+TKtfLh0zeEIvvh9yh\n" +"k+vKHS+HVoHo3tecB9QjJyDyyJTiETXCupSOY+ebG648JADAvv8v1WiE+KBXtjpl\n" +"qgDTrDj5CwGuY6cvQdej5yg1UAVlMMZSg3thL3tCYtQbOq66lAlnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key q02F3AQsCX7+zXNpfTqBF8O8lusPhRJpQVxOnBvbOwc=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"L1fdgoN/eXgdzIIXO63W4yGoC9lRozMU+T0Fimhd/XFV8qxeUT83Vgf63vxLUHIb\n" +"D4a80Wj7Pm4y5a766qLGXxlz2FYjCdkp070UpgZneB+VifUlFd/bNAjsiYTstBKM\n" +"EI2L0mhl9d/7KK8vgtadHdX1z1u7QjyF6ccnzhfqeiY=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test003r 127.0.0.1 5003 0 7003\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 71FD 3A35 F705 8020 D595 B711 D52A 9A0A 99BB B467\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 3796BE0A95B699595445DFD3453CA2074E75BCE8\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAL44ctIioIfCYFzMTYNfK5qFAPGGUpsAFmS8pThQEY/tJU14+frJDBrC\n" +"BkLvBs05Bw7xOUb0f2geiYGowBA6028smiq5HzTO7Kaga8vfV7AnANPX+n9cfHCr\n" +"/2cMnKkT/GZzpdk0WbUw5Kc/G1ATIPFQHA8gZAi1fsSIDDn3GRV5AgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALlPo5AI1mVTi+194yOSf40caoFlxSTfXt8KjGVa1dO/bpX7L3noOjYg\n" +"goU4Aqim7BHmBWQDE/tZNTrchFoLQFHi9N4pv/0ND3sY904pzqGpe3FeTuU8P9Jg\n" +"q2w3MeO3GwG8CJf4FOdSkgi8UKkJhOld4g4kViQbrFLXfdFvnT/zAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key qluYCRrsesOTkavCLnNK6H1ToywyDquCyYeP0h/qol4=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"d09K7rW/OpVzoUpfZXJuJW7a+P4pROCOZTgvDUIy/Nv+EAjcYqv95PlJ8cAMqnn3\n" +"1oQibRmmQwn0OmG5cB8NaZiueaVIRheGzHEM8rndpHn5oFXdFvV7KKjScvfuBbTk\n" +"RYME8XyawRaqsEZnwirDDlZuiZOjdQs8bbGsko3grJE=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test005r 127.0.0.1 5005 0 7005\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint EB6E 42ED E6BF 5EE0 19F5 EFC1 53AD 094C 1327 7B76\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest C031EE4E1AE826C1E3C4E21D81C961869E63F5D2\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAMd9Fm4KTSjFDzEABPZ1fwBCC2DNgee6nAmlde8FRbCVfcIHRiJyv9YG\n" +"h530yUJal3hBfiWwy/SBA4LDz1flNCEwJm81s3waj4T9c676dAOLPcnOcJM5SbaQ\n" +"hYPDrIZLEZHAk+IoM+avKYYocwCJXwx6WTtsedF0wJBZ9mQAJERJAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAKT7ldhV43S1CgoER/pU0Rigf0NzcSy25DQJrMRQnNmXnL03Dwuv/Iu7\n" +"dCjgg64odnvSkXHFhkbjGcg8aXikvfbMyZTbsD8NrrP6FS6pfgPgZD9W2TK7QdHI\n" +"QXwx1IYaaJK4nDUNfJhjrclydEdxmHbO1nLG1aS0ypn/G0EBpOSnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key umFmyRPA0dIsi0CFYCbGIPe2+OUkyslTkKKDEohjQQg=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"JiXEbqPgDPWEb9DzCYINRXfmvMIc/IRtvshS8Vmmn7DW67TrTLKCEAnisGo92gMA\n" +"bhxGb9G5Mxq/8YqGoqdI2Vp6tfKlz/9AmjHzFAo01y42gafXIdr1oUS2RimA8jfF\n" +"hwfQkbG0FYEsJrH3EUa8sMhcjsEaohK/kgklMR7OgQY=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test007r 127.0.0.1 5007 0 7007\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint DABD 2AAF 8C9F 3B71 7839 9C08 DCD8 CD9D 341D 0002\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest F80104A0DFFB4EB429325D41D1F71E5BF8C6C726\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAL42fYAriR/JeB/9NpVq5Y5EEHca+ugIpaSdRfbopWDtFjXLEk2jmO5A\n" +"KoAGIkTKDr7e9101x63H+0Nh/7w3uYs/WqTXEH8/1sHwe+0PY2HL0S6qhlOo6X54\n" +"EfK0nDDBAWFOpyiAMHRk8JVikKb56+FVIhCJgi1RIbLIiUQK2/kxAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAKQj2U5hmB68V6NQBqD8DfIkJjovvM8t6nGfYpkT8ORsROnmgI5mjM38\n" +"cmh5GIjY9RgoOWolLmsWQ4SXtS0FvrPft1M61UMTSHzlrEeuod5KenV7vGlX2TxT\n" +"0DoA5TL9yY7CmxCk8CNRCtN/g7WocgIiP4KCIiEZ4VE6LIb6sxUnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key 1UBS8rTlL39u9YxRJWhz+GTG1dS15VRi4au1i5qZOyI=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"m7xHh+XPdLN+qcMLz1dBAEAmcdCFrtdseMHCc0FyAP2kXdayxqe3o2IOOHN++bTH\n" +"Y5iHsZembsIJJ+D/d0YEKWKh42TUWCXBu0Gbfc4OcNuR6PFlTWO2wk7rDT3HOiFr\n" +"pe3wJqZYkLxlBDamROAlMMRe71iag89H/4EulC18opw=\n" +"-----END SIGNATURE-----\n"; diff --git a/src/test/test_dir.c b/src/test/test_dir.c index c03b63be27..3042ec281f 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -25,55 +25,56 @@ #include "test.h" static void -test_dir_nicknames(void) +test_dir_nicknames(void *arg) { - test_assert( is_legal_nickname("a")); - test_assert(!is_legal_nickname("")); - test_assert(!is_legal_nickname("abcdefghijklmnopqrst")); /* 20 chars */ - test_assert(!is_legal_nickname("hyphen-")); /* bad char */ - test_assert( is_legal_nickname("abcdefghijklmnopqrs")); /* 19 chars */ - test_assert(!is_legal_nickname("$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); + (void)arg; + tt_assert( is_legal_nickname("a")); + tt_assert(!is_legal_nickname("")); + tt_assert(!is_legal_nickname("abcdefghijklmnopqrst")); /* 20 chars */ + tt_assert(!is_legal_nickname("hyphen-")); /* bad char */ + tt_assert( is_legal_nickname("abcdefghijklmnopqrs")); /* 19 chars */ + tt_assert(!is_legal_nickname("$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); /* valid */ - test_assert( is_legal_nickname_or_hexdigest( + tt_assert( is_legal_nickname_or_hexdigest( "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); - test_assert( is_legal_nickname_or_hexdigest( + tt_assert( is_legal_nickname_or_hexdigest( "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA=fred")); - test_assert( is_legal_nickname_or_hexdigest( + tt_assert( is_legal_nickname_or_hexdigest( "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA~fred")); /* too short */ - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); /* illegal char */ - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); /* hex part too long */ - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=fred")); /* Bad nickname */ - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")); - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~")); - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~hyphen-")); - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~" "abcdefghijklmnoppqrst")); /* Bad extra char. */ - test_assert(!is_legal_nickname_or_hexdigest( + tt_assert(!is_legal_nickname_or_hexdigest( "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!")); - test_assert(is_legal_nickname_or_hexdigest("xyzzy")); - test_assert(is_legal_nickname_or_hexdigest("abcdefghijklmnopqrs")); - test_assert(!is_legal_nickname_or_hexdigest("abcdefghijklmnopqrst")); + tt_assert(is_legal_nickname_or_hexdigest("xyzzy")); + tt_assert(is_legal_nickname_or_hexdigest("abcdefghijklmnopqrs")); + tt_assert(!is_legal_nickname_or_hexdigest("abcdefghijklmnopqrst")); done: ; } /** Run unit tests for router descriptor generation logic. */ static void -test_dir_formats(void) +test_dir_formats(void *arg) { char *buf = NULL; char buf2[8192]; @@ -89,10 +90,11 @@ test_dir_formats(void) or_options_t *options = get_options_mutable(); const addr_policy_t *p; + (void)arg; pk1 = pk_generate(0); pk2 = pk_generate(1); - test_assert(pk1 && pk2); + tt_assert(pk1 && pk2); hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE); @@ -140,9 +142,9 @@ test_dir_formats(void) smartlist_add(r2->exit_policy, ex2); r2->nickname = tor_strdup("Fred"); - test_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str, + tt_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str, &pk1_str_len)); - test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str, + tt_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str, &pk2_str_len)); /* XXXX025 router_dump_to_string should really take this from ri.*/ @@ -150,7 +152,7 @@ test_dir_formats(void) "<magri@elsewhere.example.com>"); buf = router_dump_router_to_string(r1, pk2); tor_free(options->ContactInfo); - test_assert(buf); + tt_assert(buf); strlcpy(buf2, "router Magri 192.168.0.1 9000 0 9003\n" "or-address [1:2:3:4::]:9999\n" @@ -160,7 +162,7 @@ test_dir_formats(void) "protocols Link 1 2 Circuit 1\n" "published 1970-01-01 00:00:00\n" "fingerprint ", sizeof(buf2)); - test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); + tt_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); strlcat(buf2, fingerprint, sizeof(buf2)); strlcat(buf2, "\nuptime 0\n" /* XXX the "0" above is hard-coded, but even if we made it reflect @@ -178,23 +180,23 @@ test_dir_formats(void) buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same * twice */ - test_streq(buf, buf2); + tt_str_op(buf,==, buf2); tor_free(buf); buf = router_dump_router_to_string(r1, pk2); - test_assert(buf); + tt_assert(buf); cp = buf; rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); - test_assert(rp1); - test_eq(rp1->addr, r1->addr); - test_eq(rp1->or_port, r1->or_port); + tt_assert(rp1); + tt_int_op(rp1->addr,==, r1->addr); + tt_int_op(rp1->or_port,==, r1->or_port); //test_eq(rp1->dir_port, r1->dir_port); - test_eq(rp1->bandwidthrate, r1->bandwidthrate); - test_eq(rp1->bandwidthburst, r1->bandwidthburst); - test_eq(rp1->bandwidthcapacity, r1->bandwidthcapacity); - test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0); - test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0); - //test_assert(rp1->exit_policy == NULL); + tt_int_op(rp1->bandwidthrate,==, r1->bandwidthrate); + tt_int_op(rp1->bandwidthburst,==, r1->bandwidthburst); + tt_int_op(rp1->bandwidthcapacity,==, r1->bandwidthcapacity); + tt_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0); + tt_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0); + //tt_assert(rp1->exit_policy == NULL); tor_free(buf); strlcpy(buf2, @@ -205,7 +207,7 @@ test_dir_formats(void) "protocols Link 1 2 Circuit 1\n" "published 1970-01-01 00:00:05\n" "fingerprint ", sizeof(buf2)); - test_assert(!crypto_pk_get_fingerprint(pk1, fingerprint, 1)); + tt_assert(!crypto_pk_get_fingerprint(pk1, fingerprint, 1)); strlcat(buf2, fingerprint, sizeof(buf2)); strlcat(buf2, "\nuptime 0\n" "bandwidth 3000 3000 3000\n", sizeof(buf2)); @@ -224,51 +226,51 @@ test_dir_formats(void) buf = router_dump_router_to_string(r2, pk1); buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same * twice */ - test_streq(buf, buf2); + tt_str_op(buf,==, buf2); tor_free(buf); buf = router_dump_router_to_string(r2, pk1); cp = buf; rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); - test_assert(rp2); - test_eq(rp2->addr, r2->addr); - test_eq(rp2->or_port, r2->or_port); - test_eq(rp2->dir_port, r2->dir_port); - test_eq(rp2->bandwidthrate, r2->bandwidthrate); - test_eq(rp2->bandwidthburst, r2->bandwidthburst); - test_eq(rp2->bandwidthcapacity, r2->bandwidthcapacity); + tt_assert(rp2); + tt_int_op(rp2->addr,==, r2->addr); + tt_int_op(rp2->or_port,==, r2->or_port); + tt_int_op(rp2->dir_port,==, r2->dir_port); + tt_int_op(rp2->bandwidthrate,==, r2->bandwidthrate); + tt_int_op(rp2->bandwidthburst,==, r2->bandwidthburst); + tt_int_op(rp2->bandwidthcapacity,==, r2->bandwidthcapacity); #ifdef CURVE25519_ENABLED - test_memeq(rp2->onion_curve25519_pkey->public_key, + tt_mem_op(rp2->onion_curve25519_pkey->public_key,==, r2->onion_curve25519_pkey->public_key, CURVE25519_PUBKEY_LEN); #endif - test_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0); - test_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0); + tt_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0); + tt_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0); - test_eq(smartlist_len(rp2->exit_policy), 2); + tt_int_op(smartlist_len(rp2->exit_policy),==, 2); p = smartlist_get(rp2->exit_policy, 0); - test_eq(p->policy_type, ADDR_POLICY_ACCEPT); - test_assert(tor_addr_is_null(&p->addr)); - test_eq(p->maskbits, 0); - test_eq(p->prt_min, 80); - test_eq(p->prt_max, 80); + tt_int_op(p->policy_type,==, ADDR_POLICY_ACCEPT); + tt_assert(tor_addr_is_null(&p->addr)); + tt_int_op(p->maskbits,==, 0); + tt_int_op(p->prt_min,==, 80); + tt_int_op(p->prt_max,==, 80); p = smartlist_get(rp2->exit_policy, 1); - test_eq(p->policy_type, ADDR_POLICY_REJECT); - test_assert(tor_addr_eq(&p->addr, &ex2->addr)); - test_eq(p->maskbits, 8); - test_eq(p->prt_min, 24); - test_eq(p->prt_max, 24); + tt_int_op(p->policy_type,==, ADDR_POLICY_REJECT); + tt_assert(tor_addr_eq(&p->addr, &ex2->addr)); + tt_int_op(p->maskbits,==, 8); + tt_int_op(p->prt_min,==, 24); + tt_int_op(p->prt_max,==, 24); #if 0 /* Okay, now for the directories. */ { fingerprint_list = smartlist_new(); crypto_pk_get_fingerprint(pk2, buf, 1); - add_fingerprint_to_dir("Magri", buf, fingerprint_list); + add_fingerprint_to_dir(buf, fingerprint_list, 0); crypto_pk_get_fingerprint(pk1, buf, 1); - add_fingerprint_to_dir("Fred", buf, fingerprint_list); + add_fingerprint_to_dir(buf, fingerprint_list, 0); } #endif @@ -293,49 +295,50 @@ test_dir_formats(void) } static void -test_dir_versions(void) +test_dir_versions(void *arg) { tor_version_t ver1; /* Try out version parsing functionality */ - test_eq(0, tor_version_parse("0.3.4pre2-cvs", &ver1)); - test_eq(0, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_PRE, ver1.status); - test_eq(2, ver1.patchlevel); - test_eq(0, tor_version_parse("0.3.4rc1", &ver1)); - test_eq(0, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_RC, ver1.status); - test_eq(1, ver1.patchlevel); - test_eq(0, tor_version_parse("1.3.4", &ver1)); - test_eq(1, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_RELEASE, ver1.status); - test_eq(0, ver1.patchlevel); - test_eq(0, tor_version_parse("1.3.4.999", &ver1)); - test_eq(1, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_RELEASE, ver1.status); - test_eq(999, ver1.patchlevel); - test_eq(0, tor_version_parse("0.1.2.4-alpha", &ver1)); - test_eq(0, ver1.major); - test_eq(1, ver1.minor); - test_eq(2, ver1.micro); - test_eq(4, ver1.patchlevel); - test_eq(VER_RELEASE, ver1.status); - test_streq("alpha", ver1.status_tag); - test_eq(0, tor_version_parse("0.1.2.4", &ver1)); - test_eq(0, ver1.major); - test_eq(1, ver1.minor); - test_eq(2, ver1.micro); - test_eq(4, ver1.patchlevel); - test_eq(VER_RELEASE, ver1.status); - test_streq("", ver1.status_tag); + (void)arg; + tt_int_op(0,==, tor_version_parse("0.3.4pre2-cvs", &ver1)); + tt_int_op(0,==, ver1.major); + tt_int_op(3,==, ver1.minor); + tt_int_op(4,==, ver1.micro); + tt_int_op(VER_PRE,==, ver1.status); + tt_int_op(2,==, ver1.patchlevel); + tt_int_op(0,==, tor_version_parse("0.3.4rc1", &ver1)); + tt_int_op(0,==, ver1.major); + tt_int_op(3,==, ver1.minor); + tt_int_op(4,==, ver1.micro); + tt_int_op(VER_RC,==, ver1.status); + tt_int_op(1,==, ver1.patchlevel); + tt_int_op(0,==, tor_version_parse("1.3.4", &ver1)); + tt_int_op(1,==, ver1.major); + tt_int_op(3,==, ver1.minor); + tt_int_op(4,==, ver1.micro); + tt_int_op(VER_RELEASE,==, ver1.status); + tt_int_op(0,==, ver1.patchlevel); + tt_int_op(0,==, tor_version_parse("1.3.4.999", &ver1)); + tt_int_op(1,==, ver1.major); + tt_int_op(3,==, ver1.minor); + tt_int_op(4,==, ver1.micro); + tt_int_op(VER_RELEASE,==, ver1.status); + tt_int_op(999,==, ver1.patchlevel); + tt_int_op(0,==, tor_version_parse("0.1.2.4-alpha", &ver1)); + tt_int_op(0,==, ver1.major); + tt_int_op(1,==, ver1.minor); + tt_int_op(2,==, ver1.micro); + tt_int_op(4,==, ver1.patchlevel); + tt_int_op(VER_RELEASE,==, ver1.status); + tt_str_op("alpha",==, ver1.status_tag); + tt_int_op(0,==, tor_version_parse("0.1.2.4", &ver1)); + tt_int_op(0,==, ver1.major); + tt_int_op(1,==, ver1.minor); + tt_int_op(2,==, ver1.micro); + tt_int_op(4,==, ver1.patchlevel); + tt_int_op(VER_RELEASE,==, ver1.status); + tt_str_op("",==, ver1.status_tag); #define tt_versionstatus_op(vs1, op, vs2) \ tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \ @@ -368,53 +371,54 @@ test_dir_versions(void) /* On list, not newer than any on same series. */ test_v_i_o(VS_UNRECOMMENDED, "0.1.0.1", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); - test_eq(0, tor_version_as_new_as("Tor 0.0.5", "0.0.9pre1-cvs")); - test_eq(1, tor_version_as_new_as( + tt_int_op(0,==, tor_version_as_new_as("Tor 0.0.5", "0.0.9pre1-cvs")); + tt_int_op(1,==, tor_version_as_new_as( "Tor 0.0.8 on Darwin 64-121-192-100.c3-0." "sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", "0.0.8rc2")); - test_eq(0, tor_version_as_new_as( + tt_int_op(0,==, tor_version_as_new_as( "Tor 0.0.8 on Darwin 64-121-192-100.c3-0." "sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", "0.0.8.2")); /* Now try svn revisions. */ - test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", + tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", "Tor 0.2.1.0-dev (r99)")); - test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100) on Banana Jr", + tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r100) on Banana Jr", "Tor 0.2.1.0-dev (r99) on Hal 9000")); - test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", + tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", "Tor 0.2.1.0-dev on Colossus")); - test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99)", + tt_int_op(0,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r99)", "Tor 0.2.1.0-dev (r100)")); - test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99) on MCP", + tt_int_op(0,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r99) on MCP", "Tor 0.2.1.0-dev (r100) on AM")); - test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev", + tt_int_op(0,==, tor_version_as_new_as("Tor 0.2.1.0-dev", "Tor 0.2.1.0-dev (r99)")); - test_eq(1, tor_version_as_new_as("Tor 0.2.1.1", + tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.1", "Tor 0.2.1.0-dev (r99)")); /* Now try git revisions */ - test_eq(0, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1)); - test_eq(0, ver1.major); - test_eq(5, ver1.minor); - test_eq(6, ver1.micro); - test_eq(7, ver1.patchlevel); - test_eq(3, ver1.git_tag_len); - test_memeq(ver1.git_tag, "\xff\x00\xff", 3); - test_eq(-1, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1)); - test_eq(-1, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1)); - test_eq(0, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1)); + tt_int_op(0,==, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1)); + tt_int_op(0,==, ver1.major); + tt_int_op(5,==, ver1.minor); + tt_int_op(6,==, ver1.micro); + tt_int_op(7,==, ver1.patchlevel); + tt_int_op(3,==, ver1.git_tag_len); + tt_mem_op(ver1.git_tag,==, "\xff\x00\xff", 3); + tt_int_op(-1,==, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1)); + tt_int_op(-1,==, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1)); + tt_int_op(0,==, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1)); done: ; } /** Run unit tests for directory fp_pair functions. */ static void -test_dir_fp_pairs(void) +test_dir_fp_pairs(void *arg) { smartlist_t *sl = smartlist_new(); fp_pair_t *pair; + (void)arg; dir_split_resource_into_fingerprint_pairs( /* Two pairs, out of order, with one duplicate. */ "73656372657420646174612E0000000000FFFFFF-" @@ -424,13 +428,13 @@ test_dir_fp_pairs(void) "48657861646563696d616c2069736e277420736f-" "676f6f6420666f7220686964696e6720796f7572.z", sl); - test_eq(smartlist_len(sl), 2); + tt_int_op(smartlist_len(sl),==, 2); pair = smartlist_get(sl, 0); - test_memeq(pair->first, "Hexadecimal isn't so", DIGEST_LEN); - test_memeq(pair->second, "good for hiding your", DIGEST_LEN); + tt_mem_op(pair->first,==, "Hexadecimal isn't so", DIGEST_LEN); + tt_mem_op(pair->second,==, "good for hiding your", DIGEST_LEN); pair = smartlist_get(sl, 1); - test_memeq(pair->first, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN); - test_memeq(pair->second, "Use AES-256 instead.", DIGEST_LEN); + tt_mem_op(pair->first,==, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN); + tt_mem_op(pair->second,==, "Use AES-256 instead.", DIGEST_LEN); done: SMARTLIST_FOREACH(sl, fp_pair_t *, pair, tor_free(pair)); @@ -557,7 +561,7 @@ test_dir_split_fps(void *testdata) } static void -test_dir_measured_bw_kb(void) +test_dir_measured_bw_kb(void *arg) { measured_bw_line_t mbwl; int i; @@ -605,16 +609,17 @@ test_dir_measured_bw_kb(void) "end" }; + (void)arg; for (i = 0; strcmp(lines_fail[i], "end"); i++) { //fprintf(stderr, "Testing: %s\n", lines_fail[i]); - test_assert(measured_bw_line_parse(&mbwl, lines_fail[i]) == -1); + tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i]) == -1); } for (i = 0; strcmp(lines_pass[i], "end"); i++) { //fprintf(stderr, "Testing: %s %d\n", lines_pass[i], TOR_ISSPACE('\n')); - test_assert(measured_bw_line_parse(&mbwl, lines_pass[i]) == 0); - test_assert(mbwl.bw_kb == 1024); - test_assert(strcmp(mbwl.node_hex, + tt_assert(measured_bw_line_parse(&mbwl, lines_pass[i]) == 0); + tt_assert(mbwl.bw_kb == 1024); + tt_assert(strcmp(mbwl.node_hex, "557365204145532d32353620696e73746561642e") == 0); } @@ -626,7 +631,7 @@ test_dir_measured_bw_kb(void) /** Do the measured bandwidth cache unit test */ static void -test_dir_measured_bw_kb_cache(void) +test_dir_measured_bw_kb_cache(void *arg) { /* Initial fake time_t for testing */ time_t curr = MBWC_INIT_TIME; @@ -637,8 +642,9 @@ test_dir_measured_bw_kb_cache(void) time_t as_of; /* First, clear the cache and assert that it's empty */ + (void)arg; dirserv_clear_measured_bw_cache(); - test_eq(dirserv_get_measured_bw_cache_size(), 0); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 0); /* * Set up test mbwls; none of the dirserv_cache_*() functions care about * the node_hex field. @@ -651,56 +657,56 @@ test_dir_measured_bw_kb_cache(void) mbwl[2].bw_kb = 80; /* Try caching something */ dirserv_cache_measured_bw(&(mbwl[0]), curr); - test_eq(dirserv_get_measured_bw_cache_size(), 1); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 1); /* Okay, let's see if we can retrieve it */ - test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, &as_of)); - test_eq(bw, 20); - test_eq(as_of, MBWC_INIT_TIME); + tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, &as_of)); + tt_int_op(bw,==, 20); + tt_int_op(as_of,==, MBWC_INIT_TIME); /* Try retrieving it without some outputs */ - test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL, NULL)); - test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, NULL)); - test_eq(bw, 20); - test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL,&as_of)); - test_eq(as_of, MBWC_INIT_TIME); + tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL, NULL)); + tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, NULL)); + tt_int_op(bw,==, 20); + tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL,&as_of)); + tt_int_op(as_of,==, MBWC_INIT_TIME); /* Now expire it */ curr += MAX_MEASUREMENT_AGE + 1; dirserv_expire_measured_bw_cache(curr); /* Check that the cache is empty */ - test_eq(dirserv_get_measured_bw_cache_size(), 0); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 0); /* Check that we can't retrieve it */ - test_assert(!dirserv_query_measured_bw_cache_kb(mbwl[0].node_id, NULL,NULL)); + tt_assert(!dirserv_query_measured_bw_cache_kb(mbwl[0].node_id, NULL,NULL)); /* Try caching a few things now */ dirserv_cache_measured_bw(&(mbwl[0]), curr); - test_eq(dirserv_get_measured_bw_cache_size(), 1); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 1); curr += MAX_MEASUREMENT_AGE / 4; dirserv_cache_measured_bw(&(mbwl[1]), curr); - test_eq(dirserv_get_measured_bw_cache_size(), 2); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 2); curr += MAX_MEASUREMENT_AGE / 4; dirserv_cache_measured_bw(&(mbwl[2]), curr); - test_eq(dirserv_get_measured_bw_cache_size(), 3); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 3); curr += MAX_MEASUREMENT_AGE / 4 + 1; /* Do an expire that's too soon to get any of them */ dirserv_expire_measured_bw_cache(curr); - test_eq(dirserv_get_measured_bw_cache_size(), 3); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 3); /* Push the oldest one off the cliff */ curr += MAX_MEASUREMENT_AGE / 4; dirserv_expire_measured_bw_cache(curr); - test_eq(dirserv_get_measured_bw_cache_size(), 2); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 2); /* And another... */ curr += MAX_MEASUREMENT_AGE / 4; dirserv_expire_measured_bw_cache(curr); - test_eq(dirserv_get_measured_bw_cache_size(), 1); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 1); /* This should empty it out again */ curr += MAX_MEASUREMENT_AGE / 4; dirserv_expire_measured_bw_cache(curr); - test_eq(dirserv_get_measured_bw_cache_size(), 0); + tt_int_op(dirserv_get_measured_bw_cache_size(),==, 0); done: return; } static void -test_dir_param_voting(void) +test_dir_param_voting(void *arg) { networkstatus_t vote1, vote2, vote3, vote4; smartlist_t *votes = smartlist_new(); @@ -709,6 +715,7 @@ test_dir_param_voting(void) /* dirvote_compute_params only looks at the net_params field of the votes, so that's all we need to set. */ + (void)arg; memset(&vote1, 0, sizeof(vote1)); memset(&vote2, 0, sizeof(vote2)); memset(&vote3, 0, sizeof(vote3)); @@ -725,87 +732,71 @@ test_dir_param_voting(void) "abcd=20 c=60 cw=500 x-yz=-9 zzzzz=101", NULL, 0, 0); smartlist_split_string(vote4.net_params, "ab=900 abcd=200 c=1 cw=51 x-yz=100", NULL, 0, 0); - test_eq(100, networkstatus_get_param(&vote4, "x-yz", 50, 0, 300)); - test_eq(222, networkstatus_get_param(&vote4, "foobar", 222, 0, 300)); - test_eq(80, networkstatus_get_param(&vote4, "ab", 12, 0, 80)); - test_eq(-8, networkstatus_get_param(&vote4, "ab", -12, -100, -8)); - test_eq(0, networkstatus_get_param(&vote4, "foobar", 0, -100, 8)); + tt_int_op(100,==, networkstatus_get_param(&vote4, "x-yz", 50, 0, 300)); + tt_int_op(222,==, networkstatus_get_param(&vote4, "foobar", 222, 0, 300)); + tt_int_op(80,==, networkstatus_get_param(&vote4, "ab", 12, 0, 80)); + tt_int_op(-8,==, networkstatus_get_param(&vote4, "ab", -12, -100, -8)); + tt_int_op(0,==, networkstatus_get_param(&vote4, "foobar", 0, -100, 8)); smartlist_add(votes, &vote1); /* Do the first tests without adding all the other votes, for * networks without many dirauths. */ - res = dirvote_compute_params(votes, 11, 6); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 2); - test_streq(res, ""); + tt_str_op(res,==, ""); tor_free(res); res = dirvote_compute_params(votes, 12, 1); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99"); + tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-99"); tor_free(res); smartlist_add(votes, &vote2); - res = dirvote_compute_params(votes, 11, 2); - test_streq(res, "ab=27 abcd=20 cw=5 x-yz=-99"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 2); - test_streq(res, "ab=27 cw=5 x-yz=-99"); + tt_str_op(res,==, "ab=27 cw=5 x-yz=-99"); tor_free(res); res = dirvote_compute_params(votes, 12, 3); - test_streq(res, "ab=27 cw=5 x-yz=-99"); + tt_str_op(res,==, "ab=27 cw=5 x-yz=-99"); tor_free(res); res = dirvote_compute_params(votes, 12, 6); - test_streq(res, ""); + tt_str_op(res,==, ""); tor_free(res); smartlist_add(votes, &vote3); - res = dirvote_compute_params(votes, 11, 3); - test_streq(res, "ab=27 abcd=20 c=60 cw=50 x-yz=-9 zzzzz=101"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 3); - test_streq(res, "ab=27 abcd=20 cw=50 x-yz=-9"); + tt_str_op(res,==, "ab=27 abcd=20 cw=50 x-yz=-9"); tor_free(res); res = dirvote_compute_params(votes, 12, 5); - test_streq(res, "cw=50 x-yz=-9"); + tt_str_op(res,==, "cw=50 x-yz=-9"); tor_free(res); res = dirvote_compute_params(votes, 12, 9); - test_streq(res, "cw=50 x-yz=-9"); + tt_str_op(res,==, "cw=50 x-yz=-9"); tor_free(res); smartlist_add(votes, &vote4); - res = dirvote_compute_params(votes, 11, 4); - test_streq(res, "ab=90 abcd=20 c=1 cw=50 x-yz=-9 zzzzz=101"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 4); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9"); tor_free(res); res = dirvote_compute_params(votes, 12, 5); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9"); tor_free(res); /* Test that the special-cased "at least three dirauths voted for * this param" logic works as expected. */ res = dirvote_compute_params(votes, 12, 6); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9"); tor_free(res); res = dirvote_compute_params(votes, 12, 10); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9"); tor_free(res); done: @@ -837,14 +828,14 @@ static void test_same_voter(networkstatus_voter_info_t *v1, networkstatus_voter_info_t *v2) { - test_streq(v1->nickname, v2->nickname); - test_memeq(v1->identity_digest, v2->identity_digest, DIGEST_LEN); - test_streq(v1->address, v2->address); - test_eq(v1->addr, v2->addr); - test_eq(v1->dir_port, v2->dir_port); - test_eq(v1->or_port, v2->or_port); - test_streq(v1->contact, v2->contact); - test_memeq(v1->vote_digest, v2->vote_digest, DIGEST_LEN); + tt_str_op(v1->nickname,==, v2->nickname); + tt_mem_op(v1->identity_digest,==, v2->identity_digest, DIGEST_LEN); + tt_str_op(v1->address,==, v2->address); + tt_int_op(v1->addr,==, v2->addr); + tt_int_op(v1->dir_port,==, v2->dir_port); + tt_int_op(v1->or_port,==, v2->or_port); + tt_str_op(v1->contact,==, v2->contact); + tt_mem_op(v1->vote_digest,==, v2->vote_digest, DIGEST_LEN); done: ; } @@ -981,7 +972,7 @@ gen_routerstatus_for_v3ns(int idx, time_t now) break; default: /* Shouldn't happen */ - test_assert(0); + tt_assert(0); } if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); @@ -1002,14 +993,14 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now) vote_routerstatus_t *vrs; const char *msg = NULL; - test_assert(v); + tt_assert(v); (void)now; if (voter == 1) { measured_bw_line_t mbw; memset(mbw.node_id, 33, sizeof(mbw.node_id)); mbw.bw_kb = 1024; - test_assert(measured_bw_line_apply(&mbw, + tt_assert(measured_bw_line_apply(&mbw, v->routerstatus_list) == 1); } else if (voter == 2 || voter == 3) { /* Monkey around with the list a bit */ @@ -1025,7 +1016,7 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now) vote_routerstatus_free(vrs); vrs = smartlist_get(v->routerstatus_list, 0); memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN); - test_assert(router_add_to_routerlist( + tt_assert(router_add_to_routerlist( generate_ri_from_rs(vrs), &msg,0,0) >= 0); } } @@ -1043,9 +1034,9 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) routerstatus_t *rs; tor_addr_t addr_ipv6; - test_assert(vrs); + tt_assert(vrs); rs = &(vrs->status); - test_assert(rs); + tt_assert(rs); /* Split out by digests to test */ if (tor_memeq(rs->identity_digest, @@ -1054,17 +1045,17 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) DIGEST_LEN) && (voter == 1)) { /* Check the first routerstatus. */ - test_streq(vrs->version, "0.1.2.14"); - test_eq(rs->published_on, now-1500); - test_streq(rs->nickname, "router2"); - test_memeq(rs->identity_digest, + tt_str_op(vrs->version,==, "0.1.2.14"); + tt_int_op(rs->published_on,==, now-1500); + tt_str_op(rs->nickname,==, "router2"); + tt_mem_op(rs->identity_digest,==, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3" "\x3\x3\x3\x3", DIGEST_LEN); - test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); - test_eq(rs->addr, 0x99008801); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 8000); + tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); + tt_int_op(rs->addr,==, 0x99008801); + tt_int_op(rs->or_port,==, 443); + tt_int_op(rs->dir_port,==, 8000); /* no flags except "running" (16) and "v2dir" (64) */ tt_u64_op(vrs->flags, ==, U64_LITERAL(80)); } else if (tor_memeq(rs->identity_digest, @@ -1072,24 +1063,24 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) "\x5\x5\x5\x5", DIGEST_LEN) && (voter == 1 || voter == 2)) { - test_memeq(rs->identity_digest, + tt_mem_op(rs->identity_digest,==, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5", DIGEST_LEN); if (voter == 1) { /* Check the second routerstatus. */ - test_streq(vrs->version, "0.2.0.5"); - test_eq(rs->published_on, now-1000); - test_streq(rs->nickname, "router1"); + tt_str_op(vrs->version,==, "0.2.0.5"); + tt_int_op(rs->published_on,==, now-1000); + tt_str_op(rs->nickname,==, "router1"); } - test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); - test_eq(rs->addr, 0x99009901); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 0); + tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); + tt_int_op(rs->addr,==, 0x99009901); + tt_int_op(rs->or_port,==, 443); + tt_int_op(rs->dir_port,==, 0); tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); - test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); - test_eq(rs->ipv6_orport, 4711); + tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + tt_int_op(rs->ipv6_orport,==, 4711); if (voter == 1) { /* all except "authority" (1) and "v2dir" (64) */ tt_u64_op(vrs->flags, ==, U64_LITERAL(190)); @@ -1103,14 +1094,14 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) DIGEST_LEN) && (voter == 1 || voter == 2)) { /* Check the measured bandwidth bits */ - test_assert(vrs->has_measured_bw && + tt_assert(vrs->has_measured_bw && vrs->measured_bw_kb == 1024); } else { /* * Didn't expect this, but the old unit test only checked some of them, * so don't assert. */ - /* test_assert(0); */ + /* tt_assert(0); */ } done: @@ -1125,9 +1116,9 @@ test_consensus_for_v3ns(networkstatus_t *con, time_t now) { (void)now; - test_assert(con); - test_assert(!con->cert); - test_eq(2, smartlist_len(con->routerstatus_list)); + tt_assert(con); + tt_assert(!con->cert); + tt_int_op(2,==, smartlist_len(con->routerstatus_list)); /* There should be two listed routers: one with identity 3, one with * identity 5. */ @@ -1143,7 +1134,7 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now) { tor_addr_t addr_ipv6; - test_assert(rs); + tt_assert(rs); /* There should be two listed routers: one with identity 3, one with * identity 5. */ @@ -1152,49 +1143,49 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now) "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3" "\x3\x3", DIGEST_LEN)) { - test_memeq(rs->identity_digest, + tt_mem_op(rs->identity_digest,==, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", DIGEST_LEN); - test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); - test_assert(!rs->is_authority); - test_assert(!rs->is_exit); - test_assert(!rs->is_fast); - test_assert(!rs->is_possible_guard); - test_assert(!rs->is_stable); + tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); + tt_assert(!rs->is_authority); + tt_assert(!rs->is_exit); + tt_assert(!rs->is_fast); + tt_assert(!rs->is_possible_guard); + tt_assert(!rs->is_stable); /* (If it wasn't running it wouldn't be here) */ - test_assert(rs->is_flagged_running); - test_assert(!rs->is_valid); - test_assert(!rs->is_named); + tt_assert(rs->is_flagged_running); + tt_assert(!rs->is_valid); + tt_assert(!rs->is_named); /* XXXX check version */ } else if (tor_memeq(rs->identity_digest, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5", DIGEST_LEN)) { /* This one showed up in 3 digests. Twice with ID 'M', once with 'Z'. */ - test_memeq(rs->identity_digest, + tt_mem_op(rs->identity_digest,==, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", DIGEST_LEN); - test_streq(rs->nickname, "router1"); - test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); - test_eq(rs->published_on, now-1000); - test_eq(rs->addr, 0x99009901); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 0); + tt_str_op(rs->nickname,==, "router1"); + tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); + tt_int_op(rs->published_on,==, now-1000); + tt_int_op(rs->addr,==, 0x99009901); + tt_int_op(rs->or_port,==, 443); + tt_int_op(rs->dir_port,==, 0); tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); - test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); - test_eq(rs->ipv6_orport, 4711); - test_assert(!rs->is_authority); - test_assert(rs->is_exit); - test_assert(rs->is_fast); - test_assert(rs->is_possible_guard); - test_assert(rs->is_stable); - test_assert(rs->is_flagged_running); - test_assert(rs->is_valid); - test_assert(!rs->is_named); + tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + tt_int_op(rs->ipv6_orport,==, 4711); + tt_assert(!rs->is_authority); + tt_assert(rs->is_exit); + tt_assert(rs->is_fast); + tt_assert(rs->is_possible_guard); + tt_assert(rs->is_stable); + tt_assert(rs->is_flagged_running); + tt_assert(rs->is_valid); + tt_assert(!rs->is_named); /* XXXX check version */ } else { /* Weren't expecting this... */ - test_assert(0); + tt_assert(0); } done: @@ -1242,31 +1233,31 @@ test_a_networkstatus( networkstatus_t *con2=NULL, *con_md2=NULL, *con3=NULL, *con_md3=NULL; ns_detached_signatures_t *dsig1=NULL, *dsig2=NULL; - test_assert(vrs_gen); - test_assert(rs_test); - test_assert(vrs_test); + tt_assert(vrs_gen); + tt_assert(rs_test); + tt_assert(vrs_test); /* Parse certificates and keys. */ cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); - test_assert(cert1); + tt_assert(cert1); cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL); - test_assert(cert2); + tt_assert(cert2); cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL); - test_assert(cert3); + tt_assert(cert3); sign_skey_1 = crypto_pk_new(); sign_skey_2 = crypto_pk_new(); sign_skey_3 = crypto_pk_new(); sign_skey_leg1 = pk_generate(4); - test_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, + tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, AUTHORITY_SIGNKEY_1, -1)); - test_assert(!crypto_pk_read_private_key_from_string(sign_skey_2, + tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_2, AUTHORITY_SIGNKEY_2, -1)); - test_assert(!crypto_pk_read_private_key_from_string(sign_skey_3, + tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_3, AUTHORITY_SIGNKEY_3, -1)); - test_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key)); - test_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key)); + tt_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key)); + tt_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key)); /* * Set up a vote; generate it; try to parse it. @@ -1308,7 +1299,7 @@ test_a_networkstatus( vrs = vrs_gen(idx, now); if (vrs) { smartlist_add(vote->routerstatus_list, vrs); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), + tt_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); ++idx; } @@ -1317,41 +1308,41 @@ test_a_networkstatus( /* dump the vote and try to parse it. */ v1_text = format_networkstatus_vote(sign_skey_1, vote); - test_assert(v1_text); + tt_assert(v1_text); v1 = networkstatus_parse_vote_from_string(v1_text, NULL, NS_TYPE_VOTE); - test_assert(v1); + tt_assert(v1); /* Make sure the parsed thing was right. */ - test_eq(v1->type, NS_TYPE_VOTE); - test_eq(v1->published, vote->published); - test_eq(v1->valid_after, vote->valid_after); - test_eq(v1->fresh_until, vote->fresh_until); - test_eq(v1->valid_until, vote->valid_until); - test_eq(v1->vote_seconds, vote->vote_seconds); - test_eq(v1->dist_seconds, vote->dist_seconds); - test_streq(v1->client_versions, vote->client_versions); - test_streq(v1->server_versions, vote->server_versions); - test_assert(v1->voters && smartlist_len(v1->voters)); + tt_int_op(v1->type,==, NS_TYPE_VOTE); + tt_int_op(v1->published,==, vote->published); + tt_int_op(v1->valid_after,==, vote->valid_after); + tt_int_op(v1->fresh_until,==, vote->fresh_until); + tt_int_op(v1->valid_until,==, vote->valid_until); + tt_int_op(v1->vote_seconds,==, vote->vote_seconds); + tt_int_op(v1->dist_seconds,==, vote->dist_seconds); + tt_str_op(v1->client_versions,==, vote->client_versions); + tt_str_op(v1->server_versions,==, vote->server_versions); + tt_assert(v1->voters && smartlist_len(v1->voters)); voter = smartlist_get(v1->voters, 0); - test_streq(voter->nickname, "Voter1"); - test_streq(voter->address, "1.2.3.4"); - test_eq(voter->addr, 0x01020304); - test_eq(voter->dir_port, 80); - test_eq(voter->or_port, 9000); - test_streq(voter->contact, "voter@example.com"); - test_assert(v1->cert); - test_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key)); + tt_str_op(voter->nickname,==, "Voter1"); + tt_str_op(voter->address,==, "1.2.3.4"); + tt_int_op(voter->addr,==, 0x01020304); + tt_int_op(voter->dir_port,==, 80); + tt_int_op(voter->or_port,==, 9000); + tt_str_op(voter->contact,==, "voter@example.com"); + tt_assert(v1->cert); + tt_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key)); cp = smartlist_join_strings(v1->known_flags, ":", 0, NULL); - test_streq(cp, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid"); + tt_str_op(cp,==, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid"); tor_free(cp); - test_eq(smartlist_len(v1->routerstatus_list), n_vrs); + tt_int_op(smartlist_len(v1->routerstatus_list),==, n_vrs); if (vote_tweaks) params_tweaked += vote_tweaks(v1, 1, now); /* Check the routerstatuses. */ for (idx = 0; idx < n_vrs; ++idx) { vrs = smartlist_get(v1->routerstatus_list, idx); - test_assert(vrs); + tt_assert(vrs); vrs_test(vrs, 1, now); } @@ -1381,15 +1372,15 @@ test_a_networkstatus( /* generate and parse v2. */ v2_text = format_networkstatus_vote(sign_skey_2, vote); - test_assert(v2_text); + tt_assert(v2_text); v2 = networkstatus_parse_vote_from_string(v2_text, NULL, NS_TYPE_VOTE); - test_assert(v2); + tt_assert(v2); if (vote_tweaks) params_tweaked += vote_tweaks(v2, 2, now); /* Check that flags come out right.*/ cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL); - test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" + tt_str_op(cp,==, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" "Running:Stable:V2Dir:Valid"); tor_free(cp); @@ -1397,7 +1388,7 @@ test_a_networkstatus( n_vrs = smartlist_len(v2->routerstatus_list); for (idx = 0; idx < n_vrs; ++idx) { vrs = smartlist_get(v2->routerstatus_list, idx); - test_assert(vrs); + tt_assert(vrs); vrs_test(vrs, 2, now); } @@ -1425,10 +1416,10 @@ test_a_networkstatus( memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN); v3_text = format_networkstatus_vote(sign_skey_3, vote); - test_assert(v3_text); + tt_assert(v3_text); v3 = networkstatus_parse_vote_from_string(v3_text, NULL, NS_TYPE_VOTE); - test_assert(v3); + tt_assert(v3); if (vote_tweaks) params_tweaked += vote_tweaks(v3, 3, now); @@ -1442,10 +1433,10 @@ test_a_networkstatus( "AAAAAAAAAAAAAAAAAAAA", sign_skey_leg1, FLAV_NS); - test_assert(consensus_text); + tt_assert(consensus_text); con = networkstatus_parse_vote_from_string(consensus_text, NULL, NS_TYPE_CONSENSUS); - test_assert(con); + tt_assert(con); //log_notice(LD_GENERAL, "<<%s>>\n<<%s>>\n<<%s>>\n", // v1_text, v2_text, v3_text); consensus_text_md = networkstatus_compute_consensus(votes, 3, @@ -1454,38 +1445,38 @@ test_a_networkstatus( "AAAAAAAAAAAAAAAAAAAA", sign_skey_leg1, FLAV_MICRODESC); - test_assert(consensus_text_md); + tt_assert(consensus_text_md); con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL, NS_TYPE_CONSENSUS); - test_assert(con_md); - test_eq(con_md->flavor, FLAV_MICRODESC); + tt_assert(con_md); + tt_int_op(con_md->flavor,==, FLAV_MICRODESC); /* Check consensus contents. */ - test_assert(con->type == NS_TYPE_CONSENSUS); - test_eq(con->published, 0); /* this field only appears in votes. */ - test_eq(con->valid_after, now+1000); - test_eq(con->fresh_until, now+2003); /* median */ - test_eq(con->valid_until, now+3000); - test_eq(con->vote_seconds, 100); - test_eq(con->dist_seconds, 250); /* median */ - test_streq(con->client_versions, "0.1.2.14"); - test_streq(con->server_versions, "0.1.2.15,0.1.2.16"); + tt_assert(con->type == NS_TYPE_CONSENSUS); + tt_int_op(con->published,==, 0); /* this field only appears in votes. */ + tt_int_op(con->valid_after,==, now+1000); + tt_int_op(con->fresh_until,==, now+2003); /* median */ + tt_int_op(con->valid_until,==, now+3000); + tt_int_op(con->vote_seconds,==, 100); + tt_int_op(con->dist_seconds,==, 250); /* median */ + tt_str_op(con->client_versions,==, "0.1.2.14"); + tt_str_op(con->server_versions,==, "0.1.2.15,0.1.2.16"); cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL); - test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" + tt_str_op(cp,==, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" "Running:Stable:V2Dir:Valid"); tor_free(cp); if (!params_tweaked) { /* Skip this one if vote_tweaks() messed with the param lists */ cp = smartlist_join_strings(con->net_params, ":", 0, NULL); - test_streq(cp, "circuitwindow=80:foo=660"); + tt_str_op(cp,==, "circuitwindow=80:foo=660"); tor_free(cp); } - test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/ + tt_int_op(4,==, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/ /* The voter id digests should be in this order. */ - test_assert(memcmp(cert2->cache_info.identity_digest, + tt_assert(memcmp(cert2->cache_info.identity_digest, cert1->cache_info.identity_digest,DIGEST_LEN)<0); - test_assert(memcmp(cert1->cache_info.identity_digest, + tt_assert(memcmp(cert1->cache_info.identity_digest, cert3->cache_info.identity_digest,DIGEST_LEN)<0); test_same_voter(smartlist_get(con->voters, 1), smartlist_get(v2->voters, 0)); @@ -1500,26 +1491,26 @@ test_a_networkstatus( n_rs = smartlist_len(con->routerstatus_list); for (idx = 0; idx < n_rs; ++idx) { rs = smartlist_get(con->routerstatus_list, idx); - test_assert(rs); + tt_assert(rs); rs_test(rs, now); } /* Check signatures. the first voter is a pseudo-entry with a legacy key. * The second one hasn't signed. The fourth one has signed: validate it. */ voter = smartlist_get(con->voters, 1); - test_eq(smartlist_len(voter->sigs), 0); + tt_int_op(smartlist_len(voter->sigs),==, 0); voter = smartlist_get(con->voters, 3); - test_eq(smartlist_len(voter->sigs), 1); + tt_int_op(smartlist_len(voter->sigs),==, 1); sig = smartlist_get(voter->sigs, 0); - test_assert(sig->signature); - test_assert(!sig->good_signature); - test_assert(!sig->bad_signature); + tt_assert(sig->signature); + tt_assert(!sig->good_signature); + tt_assert(!sig->bad_signature); - test_assert(!networkstatus_check_document_signature(con, sig, cert3)); - test_assert(sig->signature); - test_assert(sig->good_signature); - test_assert(!sig->bad_signature); + tt_assert(!networkstatus_check_document_signature(con, sig, cert3)); + tt_assert(sig->signature); + tt_assert(sig->good_signature); + tt_assert(!sig->bad_signature); { const char *msg=NULL; @@ -1542,10 +1533,10 @@ test_a_networkstatus( cert1->identity_key, sign_skey_1, NULL,NULL, FLAV_MICRODESC); - test_assert(consensus_text2); - test_assert(consensus_text3); - test_assert(consensus_text_md2); - test_assert(consensus_text_md3); + tt_assert(consensus_text2); + tt_assert(consensus_text3); + tt_assert(consensus_text_md2); + tt_assert(consensus_text_md3); con2 = networkstatus_parse_vote_from_string(consensus_text2, NULL, NS_TYPE_CONSENSUS); con3 = networkstatus_parse_vote_from_string(consensus_text3, NULL, @@ -1554,17 +1545,17 @@ test_a_networkstatus( NS_TYPE_CONSENSUS); con_md3 = networkstatus_parse_vote_from_string(consensus_text_md3, NULL, NS_TYPE_CONSENSUS); - test_assert(con2); - test_assert(con3); - test_assert(con_md2); - test_assert(con_md3); + tt_assert(con2); + tt_assert(con3); + tt_assert(con_md2); + tt_assert(con_md3); /* All three should have the same digest. */ - test_memeq(&con->digests, &con2->digests, sizeof(digests_t)); - test_memeq(&con->digests, &con3->digests, sizeof(digests_t)); + tt_mem_op(&con->digests,==, &con2->digests, sizeof(digests_t)); + tt_mem_op(&con->digests,==, &con3->digests, sizeof(digests_t)); - test_memeq(&con_md->digests, &con_md2->digests, sizeof(digests_t)); - test_memeq(&con_md->digests, &con_md3->digests, sizeof(digests_t)); + tt_mem_op(&con_md->digests,==, &con_md2->digests, sizeof(digests_t)); + tt_mem_op(&con_md->digests,==, &con_md3->digests, sizeof(digests_t)); /* Extract a detached signature from con3. */ detached_text1 = get_detached_sigs(con3, con_md3); @@ -1574,50 +1565,51 @@ test_a_networkstatus( tt_assert(dsig1); /* Are parsed values as expected? */ - test_eq(dsig1->valid_after, con3->valid_after); - test_eq(dsig1->fresh_until, con3->fresh_until); - test_eq(dsig1->valid_until, con3->valid_until); + tt_int_op(dsig1->valid_after,==, con3->valid_after); + tt_int_op(dsig1->fresh_until,==, con3->fresh_until); + tt_int_op(dsig1->valid_until,==, con3->valid_until); { digests_t *dsig_digests = strmap_get(dsig1->digests, "ns"); - test_assert(dsig_digests); - test_memeq(dsig_digests->d[DIGEST_SHA1], con3->digests.d[DIGEST_SHA1], + tt_assert(dsig_digests); + tt_mem_op(dsig_digests->d[DIGEST_SHA1],==, con3->digests.d[DIGEST_SHA1], DIGEST_LEN); dsig_digests = strmap_get(dsig1->digests, "microdesc"); - test_assert(dsig_digests); - test_memeq(dsig_digests->d[DIGEST_SHA256], + tt_assert(dsig_digests); + tt_mem_op(dsig_digests->d[DIGEST_SHA256],==, con_md3->digests.d[DIGEST_SHA256], DIGEST256_LEN); } { smartlist_t *dsig_signatures = strmap_get(dsig1->signatures, "ns"); - test_assert(dsig_signatures); - test_eq(1, smartlist_len(dsig_signatures)); + tt_assert(dsig_signatures); + tt_int_op(1,==, smartlist_len(dsig_signatures)); sig = smartlist_get(dsig_signatures, 0); - test_memeq(sig->identity_digest, cert1->cache_info.identity_digest, + tt_mem_op(sig->identity_digest,==, cert1->cache_info.identity_digest, DIGEST_LEN); - test_eq(sig->alg, DIGEST_SHA1); + tt_int_op(sig->alg,==, DIGEST_SHA1); dsig_signatures = strmap_get(dsig1->signatures, "microdesc"); - test_assert(dsig_signatures); - test_eq(1, smartlist_len(dsig_signatures)); + tt_assert(dsig_signatures); + tt_int_op(1,==, smartlist_len(dsig_signatures)); sig = smartlist_get(dsig_signatures, 0); - test_memeq(sig->identity_digest, cert1->cache_info.identity_digest, + tt_mem_op(sig->identity_digest,==, cert1->cache_info.identity_digest, DIGEST_LEN); - test_eq(sig->alg, DIGEST_SHA256); + tt_int_op(sig->alg,==, DIGEST_SHA256); } /* Try adding it to con2. */ detached_text2 = get_detached_sigs(con2,con_md2); - test_eq(1, networkstatus_add_detached_signatures(con2, dsig1, "test", + tt_int_op(1,==, networkstatus_add_detached_signatures(con2, dsig1, "test", LOG_INFO, &msg)); tor_free(detached_text2); - test_eq(1, networkstatus_add_detached_signatures(con_md2, dsig1, "test", + tt_int_op(1,==, + networkstatus_add_detached_signatures(con_md2, dsig1, "test", LOG_INFO, &msg)); tor_free(detached_text2); detached_text2 = get_detached_sigs(con2,con_md2); //printf("\n<%s>\n", detached_text2); dsig2 = networkstatus_parse_detached_signatures(detached_text2, NULL); - test_assert(dsig2); + tt_assert(dsig2); /* printf("\n"); SMARTLIST_FOREACH(dsig2->signatures, networkstatus_voter_info_t *, vi, { @@ -1626,28 +1618,28 @@ test_a_networkstatus( printf("%s\n", hd); }); */ - test_eq(2, + tt_int_op(2,==, smartlist_len((smartlist_t*)strmap_get(dsig2->signatures, "ns"))); - test_eq(2, + tt_int_op(2,==, smartlist_len((smartlist_t*)strmap_get(dsig2->signatures, "microdesc"))); /* Try adding to con2 twice; verify that nothing changes. */ - test_eq(0, networkstatus_add_detached_signatures(con2, dsig1, "test", + tt_int_op(0,==, networkstatus_add_detached_signatures(con2, dsig1, "test", LOG_INFO, &msg)); /* Add to con. */ - test_eq(2, networkstatus_add_detached_signatures(con, dsig2, "test", + tt_int_op(2,==, networkstatus_add_detached_signatures(con, dsig2, "test", LOG_INFO, &msg)); /* Check signatures */ voter = smartlist_get(con->voters, 1); sig = smartlist_get(voter->sigs, 0); - test_assert(sig); - test_assert(!networkstatus_check_document_signature(con, sig, cert2)); + tt_assert(sig); + tt_assert(!networkstatus_check_document_signature(con, sig, cert2)); voter = smartlist_get(con->voters, 2); sig = smartlist_get(voter->sigs, 0); - test_assert(sig); - test_assert(!networkstatus_check_document_signature(con, sig, cert1)); + tt_assert(sig); + tt_assert(!networkstatus_check_document_signature(con, sig, cert1)); } done: @@ -1709,8 +1701,9 @@ test_a_networkstatus( /** Run unit tests for generating and parsing V3 consensus networkstatus * documents. */ static void -test_dir_v3_networkstatus(void) +test_dir_v3_networkstatus(void *arg) { + (void)arg; test_a_networkstatus(gen_routerstatus_for_v3ns, vote_tweaks_for_v3ns, test_vrs_for_v3ns, @@ -1749,10 +1742,37 @@ test_dir_scale_bw(void *testdata) tt_assert(total <= (U64_LITERAL(1)<<62)); for (i=0; i<8; ++i) { + /* vals[2].u64 is the scaled value of 1.0 */ double ratio = ((double)vals[i].u64) / vals[2].u64; tt_double_op(fabs(ratio - v[i]), <, .00001); } + /* test handling of no entries */ + total = 1; + scale_array_elements_to_u64(vals, 0, &total); + tt_assert(total == 0); + + /* make sure we don't read the array when we have no entries + * may require compiler flags to catch NULL dereferences */ + total = 1; + scale_array_elements_to_u64(NULL, 0, &total); + tt_assert(total == 0); + + scale_array_elements_to_u64(NULL, 0, NULL); + + /* test handling of zero totals */ + total = 1; + vals[0].dbl = 0.0; + scale_array_elements_to_u64(vals, 1, &total); + tt_assert(total == 0); + tt_assert(vals[0].u64 == 0); + + vals[0].dbl = 0.0; + vals[1].dbl = 0.0; + scale_array_elements_to_u64(vals, 2, NULL); + tt_assert(vals[0].u64 == 0); + tt_assert(vals[1].u64 == 0); + done: ; } @@ -1958,7 +1978,7 @@ gen_routerstatus_for_umbw(int idx, time_t now) break; default: /* Shouldn't happen */ - test_assert(0); + tt_assert(0); } if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); @@ -1980,11 +2000,11 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now) char *maxbw_param = NULL; int rv = 0; - test_assert(v); + tt_assert(v); (void)voter; (void)now; - test_assert(v->supported_methods); + tt_assert(v->supported_methods); SMARTLIST_FOREACH(v->supported_methods, char *, c, tor_free(c)); smartlist_clear(v->supported_methods); /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */ @@ -1994,7 +2014,7 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now) /* If we're using a non-default clip bandwidth, add it to net_params */ if (alternate_clip_bw > 0) { tor_asprintf(&maxbw_param, "maxunmeasuredbw=%u", alternate_clip_bw); - test_assert(maxbw_param); + tt_assert(maxbw_param); if (maxbw_param) { smartlist_add(v->net_params, maxbw_param); rv = 1; @@ -2017,9 +2037,9 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB; (void)voter; - test_assert(vrs); + tt_assert(vrs); rs = &(vrs->status); - test_assert(rs); + tt_assert(rs); /* Split out by digests to test */ if (tor_memeq(rs->identity_digest, @@ -2030,21 +2050,21 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) * Check the first routerstatus - measured bandwidth below the clip * cutoff. */ - test_streq(vrs->version, "0.1.2.14"); - test_eq(rs->published_on, now-1500); - test_streq(rs->nickname, "router2"); - test_memeq(rs->identity_digest, + tt_str_op(vrs->version,==, "0.1.2.14"); + tt_int_op(rs->published_on,==, now-1500); + tt_str_op(rs->nickname,==, "router2"); + tt_mem_op(rs->identity_digest,==, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3" "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", DIGEST_LEN); - test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); - test_eq(rs->addr, 0x99008801); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 8000); - test_assert(rs->has_bandwidth); - test_assert(vrs->has_measured_bw); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); - test_eq(vrs->measured_bw_kb, max_unmeasured_bw_kb / 2); + tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); + tt_int_op(rs->addr,==, 0x99008801); + tt_int_op(rs->or_port,==, 443); + tt_int_op(rs->dir_port,==, 8000); + tt_assert(rs->has_bandwidth); + tt_assert(vrs->has_measured_bw); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2); + tt_int_op(vrs->measured_bw_kb,==, max_unmeasured_bw_kb / 2); } else if (tor_memeq(rs->identity_digest, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", @@ -2054,24 +2074,24 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) * Check the second routerstatus - measured bandwidth above the clip * cutoff. */ - test_streq(vrs->version, "0.2.0.5"); - test_eq(rs->published_on, now-1000); - test_streq(rs->nickname, "router1"); - test_memeq(rs->identity_digest, + tt_str_op(vrs->version,==, "0.2.0.5"); + tt_int_op(rs->published_on,==, now-1000); + tt_str_op(rs->nickname,==, "router1"); + tt_mem_op(rs->identity_digest,==, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", DIGEST_LEN); - test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); - test_eq(rs->addr, 0x99009901); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 0); + tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); + tt_int_op(rs->addr,==, 0x99009901); + tt_int_op(rs->or_port,==, 443); + tt_int_op(rs->dir_port,==, 0); tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); - test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); - test_eq(rs->ipv6_orport, 4711); - test_assert(rs->has_bandwidth); - test_assert(vrs->has_measured_bw); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2); - test_eq(vrs->measured_bw_kb, max_unmeasured_bw_kb * 2); + tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + tt_int_op(rs->ipv6_orport,==, 4711); + tt_assert(rs->has_bandwidth); + tt_assert(vrs->has_measured_bw); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb * 2); + tt_int_op(vrs->measured_bw_kb,==, max_unmeasured_bw_kb * 2); } else if (tor_memeq(rs->identity_digest, "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33", @@ -2081,10 +2101,10 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) * cutoff; this one should be clipped later on in the consensus, but * appears unclipped in the vote. */ - test_assert(rs->has_bandwidth); - test_assert(!(vrs->has_measured_bw)); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2); - test_eq(vrs->measured_bw_kb, 0); + tt_assert(rs->has_bandwidth); + tt_assert(!(vrs->has_measured_bw)); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb * 2); + tt_int_op(vrs->measured_bw_kb,==, 0); } else if (tor_memeq(rs->identity_digest, "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34" "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34", @@ -2093,12 +2113,12 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) * Check the fourth routerstatus - unmeasured bandwidth below the clip * cutoff; this one should not be clipped. */ - test_assert(rs->has_bandwidth); - test_assert(!(vrs->has_measured_bw)); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); - test_eq(vrs->measured_bw_kb, 0); + tt_assert(rs->has_bandwidth); + tt_assert(!(vrs->has_measured_bw)); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2); + tt_int_op(vrs->measured_bw_kb,==, 0); } else { - test_assert(0); + tt_assert(0); } done: @@ -2113,11 +2133,11 @@ test_consensus_for_umbw(networkstatus_t *con, time_t now) { (void)now; - test_assert(con); - test_assert(!con->cert); - // test_assert(con->consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB); - test_assert(con->consensus_method >= 16); - test_eq(4, smartlist_len(con->routerstatus_list)); + tt_assert(con); + tt_assert(!con->cert); + // tt_assert(con->consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB); + tt_assert(con->consensus_method >= 16); + tt_int_op(4,==, smartlist_len(con->routerstatus_list)); /* There should be four listed routers; all voters saw the same in this */ done: @@ -2134,61 +2154,61 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) uint32_t max_unmeasured_bw_kb = (alternate_clip_bw > 0) ? alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB; - test_assert(rs); + tt_assert(rs); /* There should be four listed routers, as constructed above */ if (tor_memeq(rs->identity_digest, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3" "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", DIGEST_LEN)) { - test_memeq(rs->identity_digest, + tt_mem_op(rs->identity_digest,==, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3" "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", DIGEST_LEN); - test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); - test_assert(!rs->is_authority); - test_assert(!rs->is_exit); - test_assert(!rs->is_fast); - test_assert(!rs->is_possible_guard); - test_assert(!rs->is_stable); + tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); + tt_assert(!rs->is_authority); + tt_assert(!rs->is_exit); + tt_assert(!rs->is_fast); + tt_assert(!rs->is_possible_guard); + tt_assert(!rs->is_stable); /* (If it wasn't running it wouldn't be here) */ - test_assert(rs->is_flagged_running); - test_assert(!rs->is_valid); - test_assert(!rs->is_named); + tt_assert(rs->is_flagged_running); + tt_assert(!rs->is_valid); + tt_assert(!rs->is_named); /* This one should have measured bandwidth below the clip cutoff */ - test_assert(rs->has_bandwidth); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); - test_assert(!(rs->bw_is_unmeasured)); + tt_assert(rs->has_bandwidth); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2); + tt_assert(!(rs->bw_is_unmeasured)); } else if (tor_memeq(rs->identity_digest, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", DIGEST_LEN)) { /* This one showed up in 3 digests. Twice with ID 'M', once with 'Z'. */ - test_memeq(rs->identity_digest, + tt_mem_op(rs->identity_digest,==, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", DIGEST_LEN); - test_streq(rs->nickname, "router1"); - test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); - test_eq(rs->published_on, now-1000); - test_eq(rs->addr, 0x99009901); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 0); + tt_str_op(rs->nickname,==, "router1"); + tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); + tt_int_op(rs->published_on,==, now-1000); + tt_int_op(rs->addr,==, 0x99009901); + tt_int_op(rs->or_port,==, 443); + tt_int_op(rs->dir_port,==, 0); tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); - test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); - test_eq(rs->ipv6_orport, 4711); - test_assert(!rs->is_authority); - test_assert(rs->is_exit); - test_assert(rs->is_fast); - test_assert(rs->is_possible_guard); - test_assert(rs->is_stable); - test_assert(rs->is_flagged_running); - test_assert(rs->is_valid); - test_assert(!rs->is_named); + tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + tt_int_op(rs->ipv6_orport,==, 4711); + tt_assert(!rs->is_authority); + tt_assert(rs->is_exit); + tt_assert(rs->is_fast); + tt_assert(rs->is_possible_guard); + tt_assert(rs->is_stable); + tt_assert(rs->is_flagged_running); + tt_assert(rs->is_valid); + tt_assert(!rs->is_named); /* This one should have measured bandwidth above the clip cutoff */ - test_assert(rs->has_bandwidth); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2); - test_assert(!(rs->bw_is_unmeasured)); + tt_assert(rs->has_bandwidth); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb * 2); + tt_assert(!(rs->bw_is_unmeasured)); } else if (tor_memeq(rs->identity_digest, "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33", @@ -2197,9 +2217,9 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) * This one should have unmeasured bandwidth above the clip cutoff, * and so should be clipped */ - test_assert(rs->has_bandwidth); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb); - test_assert(rs->bw_is_unmeasured); + tt_assert(rs->has_bandwidth); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb); + tt_assert(rs->bw_is_unmeasured); } else if (tor_memeq(rs->identity_digest, "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34" "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34", @@ -2208,12 +2228,12 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) * This one should have unmeasured bandwidth below the clip cutoff, * and so should not be clipped */ - test_assert(rs->has_bandwidth); - test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); - test_assert(rs->bw_is_unmeasured); + tt_assert(rs->has_bandwidth); + tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2); + tt_assert(rs->bw_is_unmeasured); } else { /* Weren't expecting this... */ - test_assert(0); + tt_assert(0); } done: @@ -2227,9 +2247,10 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) */ static void -test_dir_clip_unmeasured_bw_kb(void) +test_dir_clip_unmeasured_bw_kb(void *arg) { /* Run the test with the default clip bandwidth */ + (void)arg; alternate_clip_bw = 0; test_a_networkstatus(gen_routerstatus_for_umbw, vote_tweaks_for_umbw, @@ -2244,7 +2265,7 @@ test_dir_clip_unmeasured_bw_kb(void) */ static void -test_dir_clip_unmeasured_bw_kb_alt(void) +test_dir_clip_unmeasured_bw_kb_alt(void *arg) { /* * Try a different one; this value is chosen so that the below-the-cutoff @@ -2252,6 +2273,7 @@ test_dir_clip_unmeasured_bw_kb_alt(void) * DEFAULT_MAX_UNMEASURED_BW_KB and if the consensus incorrectly uses that * cutoff it will fail the test. */ + (void)arg; alternate_clip_bw = 3 * DEFAULT_MAX_UNMEASURED_BW_KB; test_a_networkstatus(gen_routerstatus_for_umbw, vote_tweaks_for_umbw, @@ -2302,60 +2324,60 @@ test_dir_http_handling(void *args) /* Parse http url tests: */ /* Good headers */ - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1\r\n" + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1\r\n" "Host: example.com\r\n" "User-Agent: Mozilla/5.0 (Windows;" " U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n", - &url), 0); - test_streq(url, "/tor/a/b/c.txt"); + &url),==, 0); + tt_str_op(url,==, "/tor/a/b/c.txt"); tor_free(url); - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.0\r\n", &url), 0); - test_streq(url, "/tor/a/b/c.txt"); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.0\r\n", &url),==, 0); + tt_str_op(url,==, "/tor/a/b/c.txt"); tor_free(url); - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.600\r\n", &url), 0); - test_streq(url, "/tor/a/b/c.txt"); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.600\r\n", &url),==, 0); + tt_str_op(url,==, "/tor/a/b/c.txt"); tor_free(url); /* Should prepend '/tor/' to url if required */ - test_eq(parse_http_url("GET /a/b/c.txt HTTP/1.1\r\n" + tt_int_op(parse_http_url("GET /a/b/c.txt HTTP/1.1\r\n" "Host: example.com\r\n" "User-Agent: Mozilla/5.0 (Windows;" " U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n", - &url), 0); - test_streq(url, "/tor/a/b/c.txt"); + &url),==, 0); + tt_str_op(url,==, "/tor/a/b/c.txt"); tor_free(url); /* Bad headers -- no HTTP/1.x*/ - test_eq(parse_http_url("GET /a/b/c.txt\r\n" + tt_int_op(parse_http_url("GET /a/b/c.txt\r\n" "Host: example.com\r\n" "User-Agent: Mozilla/5.0 (Windows;" " U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n", - &url), -1); + &url),==, -1); tt_assert(!url); /* Bad headers */ - test_eq(parse_http_url("GET /a/b/c.txt\r\n" + tt_int_op(parse_http_url("GET /a/b/c.txt\r\n" "Host: example.com\r\n" "User-Agent: Mozilla/5.0 (Windows;" " U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n", - &url), -1); + &url),==, -1); tt_assert(!url); - test_eq(parse_http_url("GET /tor/a/b/c.txt", &url), -1); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt", &url),==, -1); tt_assert(!url); - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1", &url), -1); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1", &url),==, -1); tt_assert(!url); - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1x\r\n", &url), -1); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1x\r\n", &url),==, -1); tt_assert(!url); - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.", &url), -1); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.", &url),==, -1); tt_assert(!url); - test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.\r", &url), -1); + tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.\r", &url),==, -1); tt_assert(!url); done: @@ -2363,7 +2385,7 @@ test_dir_http_handling(void *args) } #define DIR_LEGACY(name) \ - { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name } + { #name, test_dir_ ## name , TT_FORK, NULL, NULL } #define DIR(name,flags) \ { #name, test_dir_##name, (flags), NULL, NULL } diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c new file mode 100644 index 0000000000..bddc0f11e0 --- /dev/null +++ b/src/test/test_entrynodes.c @@ -0,0 +1,727 @@ +/* Copyright (c) 2014, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define STATEFILE_PRIVATE +#define ENTRYNODES_PRIVATE +#define ROUTERLIST_PRIVATE + +#include "or.h" +#include "test.h" +#include "entrynodes.h" +#include "routerparse.h" +#include "nodelist.h" +#include "util.h" +#include "routerlist.h" +#include "routerset.h" +#include "statefile.h" +#include "config.h" + +#include "test_descriptors.inc" + +/* TODO: + * choose_random_entry() test with state set. + * + * parse_state() tests with more than one guards. + * + * More tests for set_from_config(): Multiple nodes, use fingerprints, + * use country codes. + */ + +/** Dummy Tor state used in unittests. */ +static or_state_t *dummy_state = NULL; +static or_state_t * +get_or_state_replacement(void) +{ + return dummy_state; +} + +/* NOP replacement for router_descriptor_is_older_than() */ +static int +router_descriptor_is_older_than_replacement(const routerinfo_t *router, + int seconds) +{ + (void) router; + (void) seconds; + return 0; +} + +/* Number of descriptors contained in test_descriptors.txt. */ +#define NUMBER_OF_DESCRIPTORS 8 + +/** Parse a file containing router descriptors and load them to our + routerlist. This function is used to setup an artificial network + so that we can conduct entry guard tests. */ +static void +setup_fake_routerlist(void) +{ + int retval; + routerlist_t *our_routerlist = NULL; + smartlist_t *our_nodelist = NULL; + + /* Read the file that contains our test descriptors. */ + + /* We need to mock this function otherwise the descriptors will not + accepted as they are too old. */ + MOCK(router_descriptor_is_older_than, + router_descriptor_is_older_than_replacement); + + /* Load all the test descriptors to the routerlist. */ + retval = router_load_routers_from_string(TEST_DESCRIPTORS, + NULL, SAVED_IN_JOURNAL, + NULL, 0, NULL); + tt_int_op(retval, ==, NUMBER_OF_DESCRIPTORS); + + /* Sanity checking of routerlist and nodelist. */ + our_routerlist = router_get_routerlist(); + tt_int_op(smartlist_len(our_routerlist->routers), ==, NUMBER_OF_DESCRIPTORS); + routerlist_assert_ok(our_routerlist); + + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS); + + /* Mark all routers as non-guards but up and running! */ + SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) { + node->is_running = 1; + node->is_valid = 1; + node->is_possible_guard = 0; + } SMARTLIST_FOREACH_END(node); + + done: + UNMOCK(router_descriptor_is_older_than); +} + +/* Unittest cleanup function: Cleanup the fake network. */ +static int +fake_network_cleanup(const struct testcase_t *testcase, void *ptr) +{ + (void) testcase; + (void) ptr; + + routerlist_free_all(); + nodelist_free_all(); + entry_guards_free_all(); + or_state_free(dummy_state); + + return 1; /* NOP */ +} + +/* Unittest setup function: Setup a fake network. */ +static void * +fake_network_setup(const struct testcase_t *testcase) +{ + (void) testcase; + + /* Setup fake state */ + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + MOCK(get_or_state, + get_or_state_replacement); + + /* Setup fake routerlist. */ + setup_fake_routerlist(); + + /* Return anything but NULL (it's interpreted as test fail) */ + return dummy_state; +} + +/** Test choose_random_entry() with none of our routers being guard nodes. */ +static void +test_choose_random_entry_no_guards(void *arg) +{ + const node_t *chosen_entry = NULL; + + (void) arg; + + /* Try to pick an entry even though none of our routers are guards. */ + chosen_entry = choose_random_entry(NULL); + + /* Unintuitively, we actually pick a random node as our entry, + because router_choose_random_node() relaxes its constraints if it + can't find a proper entry guard. */ + tt_assert(chosen_entry); + + done: + ; +} + +/** Test choose_random_entry() with only one of our routers being a + guard node. */ +static void +test_choose_random_entry_one_possible_guard(void *arg) +{ + const node_t *chosen_entry = NULL; + node_t *the_guard = NULL; + smartlist_t *our_nodelist = NULL; + + (void) arg; + + /* Set one of the nodes to be a guard. */ + our_nodelist = nodelist_get_list(); + the_guard = smartlist_get(our_nodelist, 4); /* chosen by fair dice roll */ + the_guard->is_possible_guard = 1; + + /* Pick an entry. Make sure we pick the node we marked as guard. */ + chosen_entry = choose_random_entry(NULL); + tt_ptr_op(chosen_entry, ==, the_guard); + + done: + ; +} + +/** Helper to conduct tests for populate_live_entry_guards(). + + This test adds some entry guards to our list, and then tests + populate_live_entry_guards() to mke sure it filters them correctly. + + <b>num_needed</b> is the number of guard nodes we support. It's + configurable to make sure we function properly with 1 or 3 guard + nodes configured. +*/ +static void +populate_live_entry_guards_test_helper(int num_needed) +{ + smartlist_t *our_nodelist = NULL; + smartlist_t *live_entry_guards = smartlist_new(); + const smartlist_t *all_entry_guards = get_entry_guards(); + or_options_t *options = get_options_mutable(); + int retval; + + /* Set NumEntryGuards to the provided number. */ + options->NumEntryGuards = num_needed; + tt_int_op(num_needed, ==, decide_num_guards(options, 0)); + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + /* Walk the nodelist and add all nodes as entry guards. */ + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS); + + SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { + const node_t *node_tmp; + node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + tt_assert(node_tmp); + } SMARTLIST_FOREACH_END(node); + + /* Make sure the nodes were added as entry guards. */ + tt_int_op(smartlist_len(all_entry_guards), ==, NUMBER_OF_DESCRIPTORS); + + /* Ensure that all the possible entry guards are enough to satisfy us. */ + tt_int_op(smartlist_len(all_entry_guards), >=, num_needed); + + /* Walk the entry guard list for some sanity checking */ + SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { + /* Since we called add_an_entry_guard() with 'for_discovery' being + False, all guards should have made_contact enabled. */ + tt_int_op(entry->made_contact, ==, 1); + + /* Since we don't have a routerstatus, all of the entry guards are + not directory servers. */ + tt_int_op(entry->is_dir_cache, ==, 0); + } SMARTLIST_FOREACH_END(entry); + + /* First, try to get some fast guards. This should fail. */ + retval = populate_live_entry_guards(live_entry_guards, + all_entry_guards, + NULL, + NO_DIRINFO, /* Don't care about DIRINFO*/ + 0, 0, + 1); /* We want fast guard! */ + tt_int_op(retval, ==, 0); + tt_int_op(smartlist_len(live_entry_guards), ==, 0); + + /* Now try to get some stable guards. This should fail too. */ + retval = populate_live_entry_guards(live_entry_guards, + all_entry_guards, + NULL, + NO_DIRINFO, + 0, + 1, /* We want stable guard! */ + 0); + tt_int_op(retval, ==, 0); + tt_int_op(smartlist_len(live_entry_guards), ==, 0); + + /* Now try to get any guard we can find. This should succeed. */ + retval = populate_live_entry_guards(live_entry_guards, + all_entry_guards, + NULL, + NO_DIRINFO, + 0, 0, 0); /* No restrictions! */ + + /* Since we had more than enough guards in 'all_entry_guards', we + should have added 'num_needed' of them to live_entry_guards. + 'retval' should be 1 since we now have enough live entry guards + to pick one. */ + tt_int_op(retval, ==, 1); + tt_int_op(smartlist_len(live_entry_guards), ==, num_needed); + + done: + smartlist_free(live_entry_guards); +} + +/* Test populate_live_entry_guards() for 1 guard node. */ +static void +test_populate_live_entry_guards_1guard(void *arg) +{ + (void) arg; + + populate_live_entry_guards_test_helper(1); +} + +/* Test populate_live_entry_guards() for 3 guard nodes. */ +static void +test_populate_live_entry_guards_3guards(void *arg) +{ + (void) arg; + + populate_live_entry_guards_test_helper(3); +} + +/** Append some EntryGuard lines to the Tor state at <b>state</b>. + + <b>entry_guard_lines</b> is a smartlist containing 2-tuple + smartlists that carry the key and values of the statefile. + As an example: + entry_guard_lines = + (("EntryGuard", "name 67E72FF33D7D41BF11C569646A0A7B4B188340DF DirCache"), + ("EntryGuardDownSince", "2014-06-07 16:02:46 2014-06-07 16:02:46")) +*/ +static void +state_insert_entry_guard_helper(or_state_t *state, + smartlist_t *entry_guard_lines) +{ + config_line_t **next, *line; + + next = &state->EntryGuards; + *next = NULL; + + /* Loop over all the state lines in the smartlist */ + SMARTLIST_FOREACH_BEGIN(entry_guard_lines, const smartlist_t *,state_lines) { + /* Get key and value for each line */ + const char *state_key = smartlist_get(state_lines, 0); + const char *state_value = smartlist_get(state_lines, 1); + + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup(state_key); + tor_asprintf(&line->value, "%s", state_value); + next = &(line->next); + } SMARTLIST_FOREACH_END(state_lines); +} + +/** Free memory occupied by <b>entry_guard_lines</b>. */ +static void +state_lines_free(smartlist_t *entry_guard_lines) +{ + SMARTLIST_FOREACH_BEGIN(entry_guard_lines, smartlist_t *, state_lines) { + char *state_key = smartlist_get(state_lines, 0); + char *state_value = smartlist_get(state_lines, 1); + + tor_free(state_key); + tor_free(state_value); + smartlist_free(state_lines); + } SMARTLIST_FOREACH_END(state_lines); + + smartlist_free(entry_guard_lines); +} + +/* Return a statically allocated string representing yesterday's date + * in ISO format. We use it so that state file items are not found to + * be outdated. */ +static const char * +get_yesterday_date_str(void) +{ + static char buf[ISO_TIME_LEN+1]; + + time_t yesterday = time(NULL) - 24*60*60; + format_iso_time(buf, yesterday); + return buf; +} + +/* Tests entry_guards_parse_state(). It creates a fake Tor state with + a saved entry guard and makes sure that Tor can parse it and + creates the right entry node out of it. +*/ +static void +test_entry_guards_parse_state_simple(void *arg) +{ + or_state_t *state = or_state_new(); + const smartlist_t *all_entry_guards = get_entry_guards(); + smartlist_t *entry_state_lines = smartlist_new(); + char *msg = NULL; + int retval; + + /* Details of our fake guard node */ + const char *nickname = "hagbard"; + const char *fpr = "B29D536DD1752D542E1FBB3C9CE4449D51298212"; + const char *tor_version = "0.2.5.3-alpha-dev"; + const char *added_at = get_yesterday_date_str(); + const char *unlisted_since = "2014-06-08 16:16:50"; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + { /* Prepare the state entry */ + + /* Prepare the smartlist to hold the key/value of each line */ + smartlist_t *state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuard"); + smartlist_add_asprintf(state_line, "%s %s %s", nickname, fpr, "DirCache"); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardAddedBy"); + smartlist_add_asprintf(state_line, "%s %s %s", fpr, tor_version, added_at); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince"); + smartlist_add_asprintf(state_line, "%s", unlisted_since); + smartlist_add(entry_state_lines, state_line); + } + + /* Inject our lines in the state */ + state_insert_entry_guard_helper(state, entry_state_lines); + + /* Parse state */ + retval = entry_guards_parse_state(state, 1, &msg); + tt_int_op(retval, >=, 0); + + /* Test that the guard was registered. + We need to re-get the entry guard list since its pointer was + overwritten in entry_guards_parse_state(). */ + all_entry_guards = get_entry_guards(); + tt_int_op(smartlist_len(all_entry_guards), ==, 1); + + { /* Test the entry guard structure */ + char hex_digest[1024]; + char str_time[1024]; + + const entry_guard_t *e = smartlist_get(all_entry_guards, 0); + tt_str_op(e->nickname, ==, nickname); /* Verify nickname */ + + base16_encode(hex_digest, sizeof(hex_digest), + e->identity, DIGEST_LEN); + tt_str_op(hex_digest, ==, fpr); /* Verify fingerprint */ + + tt_assert(e->is_dir_cache); /* Verify dirness */ + + tt_str_op(e->chosen_by_version, ==, tor_version); /* Verify tor version */ + + tt_assert(e->made_contact); /* All saved guards have been contacted */ + + tt_assert(e->bad_since); /* Verify bad_since timestamp */ + format_iso_time(str_time, e->bad_since); + tt_str_op(str_time, ==, unlisted_since); + + /* The rest should be unset */ + tt_assert(!e->unreachable_since); + tt_assert(!e->can_retry); + tt_assert(!e->path_bias_noticed); + tt_assert(!e->path_bias_warned); + tt_assert(!e->path_bias_extreme); + tt_assert(!e->path_bias_disabled); + tt_assert(!e->path_bias_use_noticed); + tt_assert(!e->path_bias_use_extreme); + tt_assert(!e->last_attempted); + } + + done: + state_lines_free(entry_state_lines); + or_state_free(state); + tor_free(msg); +} + +/** Similar to test_entry_guards_parse_state_simple() but aims to test + the PathBias-related details of the entry guard. */ +static void +test_entry_guards_parse_state_pathbias(void *arg) +{ + or_state_t *state = or_state_new(); + const smartlist_t *all_entry_guards = get_entry_guards(); + char *msg = NULL; + int retval; + smartlist_t *entry_state_lines = smartlist_new(); + + /* Path bias details of the fake guard */ + const double circ_attempts = 9; + const double circ_successes = 8; + const double successful_closed = 4; + const double collapsed = 2; + const double unusable = 0; + const double timeouts = 1; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + { /* Prepare the state entry */ + + /* Prepare the smartlist to hold the key/value of each line */ + smartlist_t *state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuard"); + smartlist_add_asprintf(state_line, + "givethanks B29D536DD1752D542E1FBB3C9CE4449D51298212 NoDirCache"); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardAddedBy"); + smartlist_add_asprintf(state_line, + "B29D536DD1752D542E1FBB3C9CE4449D51298212 0.2.5.3-alpha-dev " + "%s", get_yesterday_date_str()); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince"); + smartlist_add_asprintf(state_line, "2014-06-08 16:16:50"); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardPathBias"); + smartlist_add_asprintf(state_line, "%f %f %f %f %f %f", + circ_attempts, circ_successes, successful_closed, + collapsed, unusable, timeouts); + smartlist_add(entry_state_lines, state_line); + } + + /* Inject our lines in the state */ + state_insert_entry_guard_helper(state, entry_state_lines); + + /* Parse state */ + retval = entry_guards_parse_state(state, 1, &msg); + tt_int_op(retval, >=, 0); + + /* Test that the guard was registered */ + all_entry_guards = get_entry_guards(); + tt_int_op(smartlist_len(all_entry_guards), ==, 1); + + { /* Test the path bias of this guard */ + const entry_guard_t *e = smartlist_get(all_entry_guards, 0); + + tt_assert(!e->is_dir_cache); + tt_assert(!e->can_retry); + + /* XXX tt_double_op doesn't support equality. Cast to int for now. */ + tt_int_op((int)e->circ_attempts, ==, (int)circ_attempts); + tt_int_op((int)e->circ_successes, ==, (int)circ_successes); + tt_int_op((int)e->successful_circuits_closed, ==, (int)successful_closed); + tt_int_op((int)e->timeouts, ==, (int)timeouts); + tt_int_op((int)e->collapsed_circuits, ==, (int)collapsed); + tt_int_op((int)e->unusable_circuits, ==, (int)unusable); + } + + done: + or_state_free(state); + state_lines_free(entry_state_lines); + tor_free(msg); +} + +/* Simple test of entry_guards_set_from_config() by specifying a + particular EntryNode and making sure it gets picked. */ +static void +test_entry_guards_set_from_config(void *arg) +{ + or_options_t *options = get_options_mutable(); + const smartlist_t *all_entry_guards = get_entry_guards(); + const char *entrynodes_str = "test003r"; + const node_t *chosen_entry = NULL; + int retval; + + (void) arg; + + /* Prase EntryNodes as a routerset. */ + options->EntryNodes = routerset_new(); + retval = routerset_parse(options->EntryNodes, + entrynodes_str, + "test_entrynodes"); + tt_int_op(retval, >=, 0); + + /* Read nodes from EntryNodes */ + entry_guards_set_from_config(options); + + /* Test that only one guard was added. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 1); + + /* Make sure it was the guard we specified. */ + chosen_entry = choose_random_entry(NULL); + tt_str_op(chosen_entry->ri->nickname, ==, entrynodes_str); + + done: + routerset_free(options->EntryNodes); +} + +static void +test_entry_is_time_to_retry(void *arg) +{ + entry_guard_t *test_guard; + time_t now; + int retval; + (void)arg; + + now = time(NULL); + + test_guard = tor_malloc_zero(sizeof(entry_guard_t)); + + test_guard->last_attempted = now - 10; + test_guard->unreachable_since = now - 1; + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (6*60*60 - 1); + test_guard->last_attempted = now - (60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->last_attempted = now - (60*60 - 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,0); + + test_guard->unreachable_since = now - (6*60*60 + 1); + test_guard->last_attempted = now - (4*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (3*24*60*60 - 1); + test_guard->last_attempted = now - (4*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (3*24*60*60 + 1); + test_guard->last_attempted = now - (18*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (7*24*60*60 - 1); + test_guard->last_attempted = now - (18*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->last_attempted = now - (18*60*60 - 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,0); + + test_guard->unreachable_since = now - (7*24*60*60 + 1); + test_guard->last_attempted = now - (36*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (7*24*60*60 + 1); + test_guard->last_attempted = now - (36*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + done: + tor_free(test_guard); +} + +/** XXX Do some tests that entry_is_live() */ +static void +test_entry_is_live(void *arg) +{ + smartlist_t *our_nodelist = NULL; + const smartlist_t *all_entry_guards = get_entry_guards(); + const node_t *test_node = NULL; + const entry_guard_t *test_entry = NULL; + const char *msg; + int which_node; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + /* Walk the nodelist and add all nodes as entry guards. */ + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS); + + SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { + const node_t *node_tmp; + node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + tt_assert(node_tmp); + + tt_int_op(node->is_stable, ==, 0); + tt_int_op(node->is_fast, ==, 0); + } SMARTLIST_FOREACH_END(node); + + /* Make sure the nodes were added as entry guards. */ + tt_int_op(smartlist_len(all_entry_guards), ==, NUMBER_OF_DESCRIPTORS); + + /* Now get a random test entry that we will use for this unit test. */ + which_node = 3; /* (chosen by fair dice roll) */ + test_entry = smartlist_get(all_entry_guards, which_node); + + /* Let's do some entry_is_live() tests! */ + + /* Require the node to be stable, but it's not. Should fail. + Also enable 'assume_reachable' because why not. */ + test_node = entry_is_live(test_entry, + ENTRY_NEED_UPTIME | ENTRY_ASSUME_REACHABLE, + &msg); + tt_assert(!test_node); + + /* Require the node to be fast, but it's not. Should fail. */ + test_node = entry_is_live(test_entry, + ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, + &msg); + tt_assert(!test_node); + + /* Don't impose any restrictions on the node. Should succeed. */ + test_node = entry_is_live(test_entry, 0, &msg); + tt_assert(test_node); + tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity)); + + /* Require descriptor for this node. It has one so it should succeed. */ + test_node = entry_is_live(test_entry, ENTRY_NEED_DESCRIPTOR, &msg); + tt_assert(test_node); + tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity)); + + done: + ; /* XXX */ +} + +static const struct testcase_setup_t fake_network = { + fake_network_setup, fake_network_cleanup +}; + +struct testcase_t entrynodes_tests[] = { + { "entry_is_time_to_retry", test_entry_is_time_to_retry, + TT_FORK, NULL, NULL }, + { "choose_random_entry_no_guards", test_choose_random_entry_no_guards, + TT_FORK, &fake_network, NULL }, + { "choose_random_entry_one_possibleguard", + test_choose_random_entry_one_possible_guard, + TT_FORK, &fake_network, NULL }, + { "populate_live_entry_guards_1guard", + test_populate_live_entry_guards_1guard, + TT_FORK, &fake_network, NULL }, + { "populate_live_entry_guards_3guards", + test_populate_live_entry_guards_3guards, + TT_FORK, &fake_network, NULL }, + { "entry_guards_parse_state_simple", + test_entry_guards_parse_state_simple, + TT_FORK, &fake_network, NULL }, + { "entry_guards_parse_state_pathbias", + test_entry_guards_parse_state_pathbias, + TT_FORK, &fake_network, NULL }, + { "entry_guards_set_from_config", + test_entry_guards_set_from_config, + TT_FORK, &fake_network, NULL }, + { "entry_is_live", + test_entry_is_live, + TT_FORK, &fake_network, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index 93c8f77d5b..35e7fe5ad9 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -42,7 +42,7 @@ test_ext_or_id_map(void *arg) /* Give c2 a new ID. */ connection_or_set_ext_or_identifier(c2); - test_mem_op(idp, !=, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN); + tt_mem_op(idp, !=, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN); idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN); tt_assert(!tor_digest_is_zero(idp2)); @@ -119,7 +119,7 @@ test_ext_or_write_command(void *arg) ==, 0); cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz); tt_int_op(sz, ==, 4); - test_mem_op(cp, ==, "\x00\x99\x00\x00", 4); + tt_mem_op(cp, ==, "\x00\x99\x00\x00", 4); tor_free(cp); /* Medium command. */ @@ -127,7 +127,7 @@ test_ext_or_write_command(void *arg) "Wai\0Hello", 9), ==, 0); cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz); tt_int_op(sz, ==, 13); - test_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13); + tt_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13); tor_free(cp); /* Long command */ @@ -137,8 +137,8 @@ test_ext_or_write_command(void *arg) buf, 65535), ==, 0); cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz); tt_int_op(sz, ==, 65539); - test_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4); - test_mem_op(cp+4, ==, buf, 65535); + tt_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4); + tt_mem_op(cp+4, ==, buf, 65535); tor_free(cp); done: @@ -181,7 +181,7 @@ test_ext_or_init_auth(void *arg) /* Shouldn't be initialized already, or our tests will be a bit * meaningless */ ext_or_auth_cookie = tor_malloc_zero(32); - test_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32)); + tt_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32)); /* Now make sure we use a temporary file */ fn = get_fname("ext_cookie_file"); @@ -203,14 +203,14 @@ test_ext_or_init_auth(void *arg) cp = read_file_to_str(fn, RFTS_BIN, &st); tt_ptr_op(cp, !=, NULL); tt_u64_op((uint64_t)st.st_size, ==, 64); - test_memeq(cp, "! Extended ORPort Auth Cookie !\x0a", 32); - test_memeq(cp+32, ext_or_auth_cookie, 32); + tt_mem_op(cp,==, "! Extended ORPort Auth Cookie !\x0a", 32); + tt_mem_op(cp+32,==, ext_or_auth_cookie, 32); memcpy(cookie0, ext_or_auth_cookie, 32); - test_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32)); + tt_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32)); /* Operation should be idempotent. */ tt_int_op(0, ==, init_ext_or_cookie_authentication(1)); - test_memeq(cookie0, ext_or_auth_cookie, 32); + tt_mem_op(cookie0,==, ext_or_auth_cookie, 32); done: tor_free(cp); @@ -280,15 +280,15 @@ test_ext_or_cookie_auth(void *arg) 46+32+32); crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input, 46+32+32); - test_memeq(hmac1, reply, 32); - test_memeq(hmac2, client_hash, 32); + tt_mem_op(hmac1,==, reply, 32); + tt_mem_op(hmac2,==, client_hash, 32); /* Now do it again and make sure that the results are *different* */ tt_int_op(0, ==, handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2, &reply_len)); - test_memneq(reply2, reply, reply_len); - test_memneq(client_hash2, client_hash, 32); + tt_mem_op(reply2,!=, reply, reply_len); + tt_mem_op(client_hash2,!=, client_hash, 32); /* But that this one checks out too. */ memcpy(server_hash_input+46+32, reply2+32, 32); memcpy(client_hash_input+46+32, reply2+32, 32); @@ -297,8 +297,8 @@ test_ext_or_cookie_auth(void *arg) 46+32+32); crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input, 46+32+32); - test_memeq(hmac1, reply2, 32); - test_memeq(hmac2, client_hash2, 32); + tt_mem_op(hmac1,==, reply2, 32); + tt_mem_op(hmac2,==, client_hash2, 32); done: tor_free(reply); @@ -339,7 +339,7 @@ test_ext_or_cookie_auth_testvec(void *arg) &reply_len)); tt_ptr_op(reply, !=, NULL ); tt_uint_op(reply_len, ==, 64); - test_memeq(reply+32, "te road There is always another ", 32); + tt_mem_op(reply+32,==, "te road There is always another ", 32); /* HMACSHA256("Gliding wrapt in a brown mantle," * "ExtORPort authentication server-to-client hash" * "But when I look ahead up the write road There is always another "); @@ -406,7 +406,7 @@ handshake_start(or_connection_t *conn, int receiving) tt_int_op(buf_datalen(TO_CONN(conn)->outbuf), ==, (n)); \ if ((n)) { \ fetch_from_buf(b, (n), TO_CONN(conn)->outbuf); \ - test_memeq(b, (s), (n)); \ + tt_mem_op(b, ==, (s), (n)); \ } \ } while (0) diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 99ef7dd570..0ee46c2a58 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -84,8 +84,8 @@ test_hs_desc_event(void *arg) STR_HS_ID); expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\ STR_HSDIR_EXIST_LONGNAME" "STR_HS_ID"\r\n"; - test_assert(received_msg); - test_streq(received_msg, expected_msg); + tt_assert(received_msg); + tt_str_op(received_msg,==, expected_msg); tor_free(received_msg); /* test received event */ @@ -93,8 +93,8 @@ test_hs_desc_event(void *arg) control_event_hs_descriptor_received(&rend_query, HSDIR_EXIST_ID); expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\ STR_HSDIR_EXIST_LONGNAME"\r\n"; - test_assert(received_msg); - test_streq(received_msg, expected_msg); + tt_assert(received_msg); + tt_str_op(received_msg,==, expected_msg); tor_free(received_msg); /* test failed event */ @@ -102,8 +102,8 @@ test_hs_desc_event(void *arg) control_event_hs_descriptor_failed(&rend_query, HSDIR_NONE_EXIST_ID); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\ STR_HSDIR_NONE_EXIST_LONGNAME"\r\n"; - test_assert(received_msg); - test_streq(received_msg, expected_msg); + tt_assert(received_msg); + tt_str_op(received_msg,==, expected_msg); tor_free(received_msg); /* test invalid auth type */ @@ -111,8 +111,8 @@ test_hs_desc_event(void *arg) control_event_hs_descriptor_failed(&rend_query, HSDIR_EXIST_ID); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\ STR_HSDIR_EXIST_LONGNAME"\r\n"; - test_assert(received_msg); - test_streq(received_msg, expected_msg); + tt_assert(received_msg); + tt_str_op(received_msg,==, expected_msg); tor_free(received_msg); done: diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c index 69c1152229..17ee01d9b8 100644 --- a/src/test/test_introduce.c +++ b/src/test/test_introduce.c @@ -290,48 +290,48 @@ do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase) /* Get a key */ k = crypto_pk_new(); - test_assert(k); + tt_assert(k); r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_1, -1); - test_assert(!r); + tt_assert(!r); /* Get digest for future comparison */ r = crypto_pk_get_digest(k, digest); - test_assert(r >= 0); + tt_assert(r >= 0); /* Make a cell out of it */ r = make_intro_from_plaintext( plaintext, plaintext_len, k, (void **)(&cell)); - test_assert(r > 0); - test_assert(cell); + tt_assert(r > 0); + tt_assert(cell); cell_len = r; /* Do early parsing */ parsed_req = rend_service_begin_parse_intro(cell, cell_len, 2, &err_msg); - test_assert(parsed_req); - test_assert(!err_msg); - test_memeq(parsed_req->pk, digest, DIGEST_LEN); - test_assert(parsed_req->ciphertext); - test_assert(parsed_req->ciphertext_len > 0); + tt_assert(parsed_req); + tt_assert(!err_msg); + tt_mem_op(parsed_req->pk,==, digest, DIGEST_LEN); + tt_assert(parsed_req->ciphertext); + tt_assert(parsed_req->ciphertext_len > 0); if (phase == EARLY_PARSE_ONLY) goto done; /* Do decryption */ r = rend_service_decrypt_intro(parsed_req, k, &err_msg); - test_assert(!r); - test_assert(!err_msg); - test_assert(parsed_req->plaintext); - test_assert(parsed_req->plaintext_len > 0); + tt_assert(!r); + tt_assert(!err_msg); + tt_assert(parsed_req->plaintext); + tt_assert(parsed_req->plaintext_len > 0); if (phase == DECRYPT_ONLY) goto done; /* Do late parsing */ r = rend_service_parse_intro_plaintext(parsed_req, &err_msg); - test_assert(!r); - test_assert(!err_msg); - test_assert(parsed_req->parsed); + tt_assert(!r); + tt_assert(!err_msg); + tt_assert(parsed_req->parsed); done: tor_free(cell); @@ -371,14 +371,14 @@ make_intro_from_plaintext( /* Compute key digest (will be first DIGEST_LEN octets of cell) */ r = crypto_pk_get_digest(key, cell); - test_assert(r >= 0); + tt_assert(r >= 0); /* Do encryption */ r = crypto_pk_public_hybrid_encrypt( key, cell + DIGEST_LEN, ciphertext_size, buf, len, PK_PKCS1_OAEP_PADDING, 0); - test_assert(r >= 0); + tt_assert(r >= 0); /* Figure out cell length */ cell_len = DIGEST_LEN + r; @@ -394,8 +394,9 @@ make_intro_from_plaintext( */ static void -test_introduce_decrypt_v0(void) +test_introduce_decrypt_v0(void *arg) { + (void)arg; do_decrypt_test(v0_test_plaintext, sizeof(v0_test_plaintext)); } @@ -403,8 +404,9 @@ test_introduce_decrypt_v0(void) */ static void -test_introduce_decrypt_v1(void) +test_introduce_decrypt_v1(void *arg) { + (void)arg; do_decrypt_test(v1_test_plaintext, sizeof(v1_test_plaintext)); } @@ -412,8 +414,9 @@ test_introduce_decrypt_v1(void) */ static void -test_introduce_decrypt_v2(void) +test_introduce_decrypt_v2(void *arg) { + (void)arg; do_decrypt_test(v2_test_plaintext, sizeof(v2_test_plaintext)); } @@ -421,8 +424,9 @@ test_introduce_decrypt_v2(void) */ static void -test_introduce_decrypt_v3(void) +test_introduce_decrypt_v3(void *arg) { + (void)arg; do_decrypt_test( v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext)); do_decrypt_test( @@ -433,8 +437,9 @@ test_introduce_decrypt_v3(void) */ static void -test_introduce_early_parse_v0(void) +test_introduce_early_parse_v0(void *arg) { + (void)arg; do_early_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext)); } @@ -442,8 +447,9 @@ test_introduce_early_parse_v0(void) */ static void -test_introduce_early_parse_v1(void) +test_introduce_early_parse_v1(void *arg) { + (void)arg; do_early_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext)); } @@ -451,8 +457,9 @@ test_introduce_early_parse_v1(void) */ static void -test_introduce_early_parse_v2(void) +test_introduce_early_parse_v2(void *arg) { + (void)arg; do_early_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext)); } @@ -460,8 +467,9 @@ test_introduce_early_parse_v2(void) */ static void -test_introduce_early_parse_v3(void) +test_introduce_early_parse_v3(void *arg) { + (void)arg; do_early_parse_test( v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext)); do_early_parse_test( @@ -472,8 +480,9 @@ test_introduce_early_parse_v3(void) */ static void -test_introduce_late_parse_v0(void) +test_introduce_late_parse_v0(void *arg) { + (void)arg; do_late_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext)); } @@ -481,8 +490,9 @@ test_introduce_late_parse_v0(void) */ static void -test_introduce_late_parse_v1(void) +test_introduce_late_parse_v1(void *arg) { + (void)arg; do_late_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext)); } @@ -490,8 +500,9 @@ test_introduce_late_parse_v1(void) */ static void -test_introduce_late_parse_v2(void) +test_introduce_late_parse_v2(void *arg) { + (void)arg; do_late_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext)); } @@ -499,8 +510,9 @@ test_introduce_late_parse_v2(void) */ static void -test_introduce_late_parse_v3(void) +test_introduce_late_parse_v3(void *arg) { + (void)arg; do_late_parse_test( v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext)); do_late_parse_test( @@ -508,7 +520,7 @@ test_introduce_late_parse_v3(void) } #define INTRODUCE_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_introduce_ ## name } + { #name, test_introduce_ ## name , 0, NULL, NULL } struct testcase_t introduce_tests[] = { INTRODUCE_LEGACY(early_parse_v0), diff --git a/src/test/test_logging.c b/src/test/test_logging.c index 7e558f83b1..9f57000bea 100644 --- a/src/test/test_logging.c +++ b/src/test/test_logging.c @@ -89,7 +89,7 @@ test_sigsafe_err(void *arg) init_logging(); mark_logs_temp(); - add_file_log(&include_bug, fn); + add_file_log(&include_bug, fn, 0); tor_log_update_sigsafe_err_fds(); close_temp_logs(); diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 78f4823b87..23e636fbf1 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -108,7 +108,7 @@ test_md_cache(void *data) md2 = smartlist_get(added, 0); /* And it should have gotten removed from 'wanted' */ tt_int_op(smartlist_len(wanted), ==, 1); - test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN); + tt_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN); smartlist_free(added); added = NULL; @@ -144,18 +144,18 @@ test_md_cache(void *data) tt_int_op(md1->bodylen, ==, strlen(test_md1)); tt_int_op(md2->bodylen, ==, strlen(test_md2)); tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation)); - test_mem_op(md1->body, ==, test_md1, strlen(test_md1)); - test_mem_op(md2->body, ==, test_md2, strlen(test_md2)); - test_mem_op(md3->body, ==, test_md3_noannotation, + tt_mem_op(md1->body, ==, test_md1, strlen(test_md1)); + tt_mem_op(md2->body, ==, test_md2, strlen(test_md2)); + tt_mem_op(md3->body, ==, test_md3_noannotation, strlen(test_md3_noannotation)); tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new", options->DataDirectory); s = read_file_to_str(fn, RFTS_BIN, NULL); tt_assert(s); - test_mem_op(md1->body, ==, s + md1->off, md1->bodylen); - test_mem_op(md2->body, ==, s + md2->off, md2->bodylen); - test_mem_op(md3->body, ==, s + md3->off, md3->bodylen); + tt_mem_op(md1->body, ==, s + md1->off, md1->bodylen); + tt_mem_op(md2->body, ==, s + md2->off, md2->bodylen); + tt_mem_op(md3->body, ==, s + md3->off, md3->bodylen); tt_ptr_op(md1->family, ==, NULL); tt_ptr_op(md3->family, !=, NULL); @@ -180,9 +180,9 @@ test_md_cache(void *data) tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs", options->DataDirectory); s = read_file_to_str(fn, RFTS_BIN, NULL); - test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1)); - test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2)); - test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation)); + tt_mem_op(md1->body, ==, s + md1->off, strlen(test_md1)); + tt_mem_op(md2->body, ==, s + md2->off, strlen(test_md2)); + tt_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation)); /* Okay, now we are going to forget about the cache entirely, and reload it * from the disk. */ @@ -191,12 +191,12 @@ test_md_cache(void *data) md1 = microdesc_cache_lookup_by_digest256(mc, d1); md2 = microdesc_cache_lookup_by_digest256(mc, d2); md3 = microdesc_cache_lookup_by_digest256(mc, d3); - test_assert(md1); - test_assert(md2); - test_assert(md3); - test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1)); - test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2)); - test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation)); + tt_assert(md1); + tt_assert(md2); + tt_assert(md3); + tt_mem_op(md1->body, ==, s + md1->off, strlen(test_md1)); + tt_mem_op(md2->body, ==, s + md2->off, strlen(test_md2)); + tt_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation)); tt_int_op(md1->last_listed, ==, time1); tt_int_op(md2->last_listed, ==, time2); diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c index 600e6a89d4..6d270db960 100644 --- a/src/test/test_nodelist.c +++ b/src/test/test_nodelist.c @@ -23,9 +23,9 @@ test_nodelist_node_get_verbose_nickname_by_id_null_node(void *arg) (void) arg; /* make sure node_get_by_id returns NULL */ - test_assert(!node_get_by_id(ID)); + tt_assert(!node_get_by_id(ID)); node_get_verbose_nickname_by_id(ID, vname); - test_streq(vname, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + tt_str_op(vname,==, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); done: return; } @@ -54,7 +54,7 @@ test_nodelist_node_get_verbose_nickname_not_named(void *arg) "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", DIGEST_LEN); node_get_verbose_nickname(&mock_node, vname); - test_streq(vname, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR"); + tt_str_op(vname,==, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR"); done: return; diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 4cdcd034bb..388251a61f 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -47,17 +47,20 @@ test_policy_summary_helper(const char *policy_str, line.value = (char *)policy_str; line.next = NULL; - r = policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1); - test_eq(r, 0); + r = policies_parse_exit_policy(&line, &policy, + EXIT_POLICY_IPV6_ENABLED | + EXIT_POLICY_ADD_DEFAULT ,0); + tt_int_op(r,==, 0); + summary = policy_summarize(policy, AF_INET); - test_assert(summary != NULL); - test_streq(summary, expected_summary); + tt_assert(summary != NULL); + tt_str_op(summary,==, expected_summary); short_policy = parse_short_policy(summary); tt_assert(short_policy); summary_after = write_short_policy(short_policy); - test_streq(summary, summary_after); + tt_str_op(summary,==, summary_after); done: tor_free(summary_after); @@ -86,104 +89,108 @@ test_policies_general(void *arg) policy = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); - test_assert(p != NULL); - test_eq(ADDR_POLICY_REJECT, p->policy_type); + tt_assert(p != NULL); + tt_int_op(ADDR_POLICY_REJECT,==, p->policy_type); tor_addr_from_ipv4h(&tar, 0xc0a80000u); - test_eq(0, tor_addr_compare(&p->addr, &tar, CMP_EXACT)); - test_eq(16, p->maskbits); - test_eq(1, p->prt_min); - test_eq(65535, p->prt_max); + tt_int_op(0,==, tor_addr_compare(&p->addr, &tar, CMP_EXACT)); + tt_int_op(16,==, p->maskbits); + tt_int_op(1,==, p->prt_min); + tt_int_op(65535,==, p->prt_max); smartlist_add(policy, p); tor_addr_from_ipv4h(&tar, 0x01020304u); - test_assert(ADDR_POLICY_ACCEPTED == + tt_assert(ADDR_POLICY_ACCEPTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); tor_addr_make_unspec(&tar); - test_assert(ADDR_POLICY_PROBABLY_ACCEPTED == + tt_assert(ADDR_POLICY_PROBABLY_ACCEPTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); tor_addr_from_ipv4h(&tar, 0xc0a80102); - test_assert(ADDR_POLICY_REJECTED == + tt_assert(ADDR_POLICY_REJECTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); - test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, 1, 0, 1)); - test_assert(policy2); + tt_int_op(0, ==, policies_parse_exit_policy(NULL, &policy2, + EXIT_POLICY_IPV6_ENABLED | + EXIT_POLICY_REJECT_PRIVATE | + EXIT_POLICY_ADD_DEFAULT, 0)); + + tt_assert(policy2); policy3 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject *:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy3, p); p = router_parse_addr_policy_item_from_string("accept *:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy3, p); policy4 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept *:443",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy4, p); p = router_parse_addr_policy_item_from_string("accept *:443",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy4, p); policy5 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject *:65535",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy5, p); policy6 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy6, p); policy7 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1); - test_assert(p != NULL); + tt_assert(p != NULL); smartlist_add(policy7, p); - test_assert(!exit_policy_is_general_exit(policy)); - test_assert(exit_policy_is_general_exit(policy2)); - test_assert(!exit_policy_is_general_exit(NULL)); - test_assert(!exit_policy_is_general_exit(policy3)); - test_assert(!exit_policy_is_general_exit(policy4)); - test_assert(!exit_policy_is_general_exit(policy5)); - test_assert(!exit_policy_is_general_exit(policy6)); - test_assert(!exit_policy_is_general_exit(policy7)); + tt_assert(!exit_policy_is_general_exit(policy)); + tt_assert(exit_policy_is_general_exit(policy2)); + tt_assert(!exit_policy_is_general_exit(NULL)); + tt_assert(!exit_policy_is_general_exit(policy3)); + tt_assert(!exit_policy_is_general_exit(policy4)); + tt_assert(!exit_policy_is_general_exit(policy5)); + tt_assert(!exit_policy_is_general_exit(policy6)); + tt_assert(!exit_policy_is_general_exit(policy7)); - test_assert(cmp_addr_policies(policy, policy2)); - test_assert(cmp_addr_policies(policy, NULL)); - test_assert(!cmp_addr_policies(policy2, policy2)); - test_assert(!cmp_addr_policies(NULL, NULL)); + tt_assert(cmp_addr_policies(policy, policy2)); + tt_assert(cmp_addr_policies(policy, NULL)); + tt_assert(!cmp_addr_policies(policy2, policy2)); + tt_assert(!cmp_addr_policies(NULL, NULL)); - test_assert(!policy_is_reject_star(policy2, AF_INET)); - test_assert(policy_is_reject_star(policy, AF_INET)); - test_assert(policy_is_reject_star(NULL, AF_INET)); + tt_assert(!policy_is_reject_star(policy2, AF_INET)); + tt_assert(policy_is_reject_star(policy, AF_INET)); + tt_assert(policy_is_reject_star(NULL, AF_INET)); addr_policy_list_free(policy); policy = NULL; @@ -193,11 +200,14 @@ test_policies_general(void *arg) line.key = (char*)"foo"; line.value = (char*)"accept *:80,reject private:*,reject *:*"; line.next = NULL; - test_assert(0 == policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1)); - test_assert(policy); + tt_int_op(0, ==, policies_parse_exit_policy(&line,&policy, + EXIT_POLICY_IPV6_ENABLED | + EXIT_POLICY_ADD_DEFAULT,0)); + tt_assert(policy); + //test_streq(policy->string, "accept *:80"); //test_streq(policy->next->string, "reject *:*"); - test_eq(smartlist_len(policy), 4); + tt_int_op(smartlist_len(policy),==, 4); /* test policy summaries */ /* check if we properly ignore private IP addresses */ @@ -359,7 +369,7 @@ test_dump_exit_policy_to_string(void *arg) ri->exit_policy = NULL; // expecting "reject *:*" ep = router_dump_exit_policy_to_string(ri,1,1); - test_streq("reject *:*",ep); + tt_str_op("reject *:*",==, ep); tor_free(ep); @@ -372,7 +382,7 @@ test_dump_exit_policy_to_string(void *arg) ep = router_dump_exit_policy_to_string(ri,1,1); - test_streq("accept *:*",ep); + tt_str_op("accept *:*",==, ep); tor_free(ep); @@ -382,7 +392,7 @@ test_dump_exit_policy_to_string(void *arg) ep = router_dump_exit_policy_to_string(ri,1,1); - test_streq("accept *:*\nreject *:25",ep); + tt_str_op("accept *:*\nreject *:25",==, ep); tor_free(ep); @@ -393,7 +403,7 @@ test_dump_exit_policy_to_string(void *arg) ep = router_dump_exit_policy_to_string(ri,1,1); - test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*",ep); + tt_str_op("accept *:*\nreject *:25\nreject 8.8.8.8:*",==, ep); tor_free(ep); policy_entry = @@ -403,8 +413,8 @@ test_dump_exit_policy_to_string(void *arg) ep = router_dump_exit_policy_to_string(ri,1,1); - test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*\n" - "reject6 [fc00::]/7:*",ep); + tt_str_op("accept *:*\nreject *:25\nreject 8.8.8.8:*\n" + "reject6 [fc00::]/7:*",==, ep); tor_free(ep); policy_entry = @@ -414,8 +424,8 @@ test_dump_exit_policy_to_string(void *arg) ep = router_dump_exit_policy_to_string(ri,1,1); - test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*\n" - "reject6 [fc00::]/7:*\naccept6 [c000::]/3:*",ep); + tt_str_op("accept *:*\nreject *:25\nreject 8.8.8.8:*\n" + "reject6 [fc00::]/7:*\naccept6 [c000::]/3:*",==, ep); done: diff --git a/src/test/test_pt.c b/src/test/test_pt.c index f71627df1e..61ade84e3a 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -27,75 +27,76 @@ reset_mp(managed_proxy_t *mp) } static void -test_pt_parsing(void) +test_pt_parsing(void *arg) { char line[200]; transport_t *transport = NULL; tor_addr_t test_addr; - managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t)); + managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t)); + (void)arg; mp->conf_state = PT_PROTO_INFANT; mp->transports = smartlist_new(); /* incomplete cmethod */ strlcpy(line,"CMETHOD trebuchet",sizeof(line)); - test_assert(parse_cmethod_line(line, mp) < 0); + tt_assert(parse_cmethod_line(line, mp) < 0); reset_mp(mp); /* wrong proxy type */ strlcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line)); - test_assert(parse_cmethod_line(line, mp) < 0); + tt_assert(parse_cmethod_line(line, mp) < 0); reset_mp(mp); /* wrong addrport */ strlcpy(line,"CMETHOD trebuchet socks4 abcd",sizeof(line)); - test_assert(parse_cmethod_line(line, mp) < 0); + tt_assert(parse_cmethod_line(line, mp) < 0); reset_mp(mp); /* correct line */ strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line)); - test_assert(parse_cmethod_line(line, mp) == 0); - test_assert(smartlist_len(mp->transports) == 1); + tt_assert(parse_cmethod_line(line, mp) == 0); + tt_assert(smartlist_len(mp->transports) == 1); transport = smartlist_get(mp->transports, 0); /* test registered address of transport */ tor_addr_parse(&test_addr, "127.0.0.1"); - test_assert(tor_addr_eq(&test_addr, &transport->addr)); + tt_assert(tor_addr_eq(&test_addr, &transport->addr)); /* test registered port of transport */ - test_assert(transport->port == 1999); + tt_assert(transport->port == 1999); /* test registered SOCKS version of transport */ - test_assert(transport->socks_version == PROXY_SOCKS5); + tt_assert(transport->socks_version == PROXY_SOCKS5); /* test registered name of transport */ - test_streq(transport->name, "trebuchet"); + tt_str_op(transport->name,==, "trebuchet"); reset_mp(mp); /* incomplete smethod */ strlcpy(line,"SMETHOD trebuchet",sizeof(line)); - test_assert(parse_smethod_line(line, mp) < 0); + tt_assert(parse_smethod_line(line, mp) < 0); reset_mp(mp); /* wrong addr type */ strlcpy(line,"SMETHOD trebuchet abcd",sizeof(line)); - test_assert(parse_smethod_line(line, mp) < 0); + tt_assert(parse_smethod_line(line, mp) < 0); reset_mp(mp); /* cowwect */ strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line)); - test_assert(parse_smethod_line(line, mp) == 0); - test_assert(smartlist_len(mp->transports) == 1); + tt_assert(parse_smethod_line(line, mp) == 0); + tt_assert(smartlist_len(mp->transports) == 1); transport = smartlist_get(mp->transports, 0); /* test registered address of transport */ tor_addr_parse(&test_addr, "127.0.0.2"); - test_assert(tor_addr_eq(&test_addr, &transport->addr)); + tt_assert(tor_addr_eq(&test_addr, &transport->addr)); /* test registered port of transport */ - test_assert(transport->port == 2999); + tt_assert(transport->port == 2999); /* test registered name of transport */ - test_streq(transport->name, "trebuchy"); + tt_str_op(transport->name,==, "trebuchy"); reset_mp(mp); @@ -103,7 +104,7 @@ test_pt_parsing(void) strlcpy(line,"SMETHOD trebuchet 127.0.0.1:9999 " "ARGS:counterweight=3,sling=snappy", sizeof(line)); - test_assert(parse_smethod_line(line, mp) == 0); + tt_assert(parse_smethod_line(line, mp) == 0); tt_int_op(1, ==, smartlist_len(mp->transports)); { const transport_t *transport = smartlist_get(mp->transports, 0); @@ -118,15 +119,15 @@ test_pt_parsing(void) /* unsupported version */ strlcpy(line,"VERSION 666",sizeof(line)); - test_assert(parse_version(line, mp) < 0); + tt_assert(parse_version(line, mp) < 0); /* incomplete VERSION */ strlcpy(line,"VERSION ",sizeof(line)); - test_assert(parse_version(line, mp) < 0); + tt_assert(parse_version(line, mp) < 0); /* correct VERSION */ strlcpy(line,"VERSION 1",sizeof(line)); - test_assert(parse_version(line, mp) == 0); + tt_assert(parse_version(line, mp) == 0); done: reset_mp(mp); @@ -187,46 +188,47 @@ test_pt_get_transport_options(void *arg) } static void -test_pt_protocol(void) +test_pt_protocol(void *arg) { char line[200]; managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t)); + (void)arg; mp->conf_state = PT_PROTO_LAUNCHED; mp->transports = smartlist_new(); - mp->argv = tor_malloc_zero(sizeof(char*)*2); + mp->argv = tor_calloc(sizeof(char *), 2); mp->argv[0] = tor_strdup("<testcase>"); /* various wrong protocol runs: */ strlcpy(line,"VERSION 1",sizeof(line)); handle_proxy_line(line, mp); - test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); strlcpy(line,"VERSION 1",sizeof(line)); handle_proxy_line(line, mp); - test_assert(mp->conf_state == PT_PROTO_BROKEN); + tt_assert(mp->conf_state == PT_PROTO_BROKEN); reset_mp(mp); strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line)); handle_proxy_line(line, mp); - test_assert(mp->conf_state == PT_PROTO_BROKEN); + tt_assert(mp->conf_state == PT_PROTO_BROKEN); reset_mp(mp); /* correct protocol run: */ strlcpy(line,"VERSION 1",sizeof(line)); handle_proxy_line(line, mp); - test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line)); handle_proxy_line(line, mp); - test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); strlcpy(line,"CMETHODS DONE",sizeof(line)); handle_proxy_line(line, mp); - test_assert(mp->conf_state == PT_PROTO_CONFIGURED); + tt_assert(mp->conf_state == PT_PROTO_CONFIGURED); done: reset_mp(mp); @@ -363,7 +365,7 @@ test_pt_configure_proxy(void *arg) control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED); - mp = tor_malloc(sizeof(managed_proxy_t)); + mp = tor_malloc_zero(sizeof(managed_proxy_t)); mp->conf_state = PT_PROTO_ACCEPTING_METHODS; mp->transports = smartlist_new(); mp->transports_to_launch = smartlist_new(); @@ -378,19 +380,19 @@ test_pt_configure_proxy(void *arg) for (i = 0 ; i < 5 ; i++) { retval = configure_proxy(mp); /* retval should be zero because proxy hasn't finished configuring yet */ - test_assert(retval == 0); + tt_int_op(retval, ==, 0); /* check the number of registered transports */ - test_assert(smartlist_len(mp->transports) == i+1); + tt_assert(smartlist_len(mp->transports) == i+1); /* check that the mp is still waiting for transports */ - test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); } /* this last configure_proxy() should finalize the proxy configuration. */ retval = configure_proxy(mp); /* retval should be 1 since the proxy finished configuring */ - test_assert(retval == 1); + tt_int_op(retval, ==, 1); /* check the mp state */ - test_assert(mp->conf_state == PT_PROTO_COMPLETED); + tt_assert(mp->conf_state == PT_PROTO_COMPLETED); tt_int_op(controlevent_n, ==, 5); tt_int_op(controlevent_event, ==, EVENT_TRANSPORT_LAUNCHED); @@ -416,7 +418,7 @@ test_pt_configure_proxy(void *arg) /* Get the bindaddr for "mock1" and check it against the bindaddr that the mocked tor_get_lines_from_handle() generated. */ transport_in_state = get_transport_in_state_by_name("mock1"); - test_assert(transport_in_state); + tt_assert(transport_in_state); smartlist_split_string(transport_info_sl, transport_in_state->value, NULL, 0, 0); name_of_transport = smartlist_get(transport_info_sl, 0); @@ -450,8 +452,86 @@ test_pt_configure_proxy(void *arg) tor_free(mp); } +/* Test the get_pt_proxy_uri() function. */ +static void +test_get_pt_proxy_uri(void *arg) +{ + or_options_t *options = get_options_mutable(); + char *uri = NULL; + int ret; + (void) arg; + + /* Test with no proxy. */ + uri = get_pt_proxy_uri(); + tt_assert(uri == NULL); + + /* Test with a SOCKS4 proxy. */ + options->Socks4Proxy = tor_strdup("192.0.2.1:1080"); + ret = tor_addr_port_lookup(options->Socks4Proxy, + &options->Socks4ProxyAddr, + &options->Socks4ProxyPort); + tt_int_op(ret, ==, 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks4a://192.0.2.1:1080"); + tor_free(uri); + tor_free(options->Socks4Proxy); + + /* Test with a SOCKS5 proxy, no username/password. */ + options->Socks5Proxy = tor_strdup("192.0.2.1:1080"); + ret = tor_addr_port_lookup(options->Socks5Proxy, + &options->Socks5ProxyAddr, + &options->Socks5ProxyPort); + tt_int_op(ret, ==, 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks5://192.0.2.1:1080"); + tor_free(uri); + + /* Test with a SOCKS5 proxy, with username/password. */ + options->Socks5ProxyUsername = tor_strdup("hwest"); + options->Socks5ProxyPassword = tor_strdup("r34n1m470r"); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks5://hwest:r34n1m470r@192.0.2.1:1080"); + tor_free(uri); + tor_free(options->Socks5Proxy); + tor_free(options->Socks5ProxyUsername); + tor_free(options->Socks5ProxyPassword); + + /* Test with a HTTPS proxy, no authenticator. */ + options->HTTPSProxy = tor_strdup("192.0.2.1:80"); + ret = tor_addr_port_lookup(options->HTTPSProxy, + &options->HTTPSProxyAddr, + &options->HTTPSProxyPort); + tt_int_op(ret, ==, 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "http://192.0.2.1:80"); + tor_free(uri); + + /* Test with a HTTPS proxy, with authenticator. */ + options->HTTPSProxyAuthenticator = tor_strdup("hwest:r34n1m470r"); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "http://hwest:r34n1m470r@192.0.2.1:80"); + tor_free(uri); + tor_free(options->HTTPSProxy); + tor_free(options->HTTPSProxyAuthenticator); + + /* Token nod to the fact that IPv6 exists. */ + options->Socks4Proxy = tor_strdup("[2001:db8::1]:1080"); + ret = tor_addr_port_lookup(options->Socks4Proxy, + &options->Socks4ProxyAddr, + &options->Socks4ProxyPort); + tt_int_op(ret, ==, 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks4a://[2001:db8::1]:1080"); + tor_free(uri); + tor_free(options->Socks4Proxy); + + done: + if (uri) + tor_free(uri); +} + #define PT_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name } + { #name, test_pt_ ## name , 0, NULL, NULL } struct testcase_t pt_tests[] = { PT_LEGACY(parsing), @@ -462,6 +542,8 @@ struct testcase_t pt_tests[] = { NULL, NULL }, { "configure_proxy",test_pt_configure_proxy, TT_FORK, NULL, NULL }, + { "get_pt_proxy_uri", test_get_pt_proxy_uri, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_replay.c b/src/test/test_replay.c index b48f582f5e..2f543512b0 100644 --- a/src/test/test_replay.c +++ b/src/test/test_replay.c @@ -18,12 +18,13 @@ static const char *test_buffer = " mollit anim id est laborum."; static void -test_replaycache_alloc(void) +test_replaycache_alloc(void *arg) { replaycache_t *r = NULL; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); done: if (r) replaycache_free(r); @@ -32,21 +33,22 @@ test_replaycache_alloc(void) } static void -test_replaycache_badalloc(void) +test_replaycache_badalloc(void *arg) { replaycache_t *r = NULL; /* Negative horizon should fail */ + (void)arg; r = replaycache_new(-600, 300); - test_assert(r == NULL); + tt_assert(r == NULL); /* Negative interval should get adjusted to zero */ r = replaycache_new(600, -300); - test_assert(r != NULL); - test_eq(r->scrub_interval, 0); + tt_assert(r != NULL); + tt_int_op(r->scrub_interval,==, 0); replaycache_free(r); /* Negative horizon and negative interval should still fail */ r = replaycache_new(-600, -300); - test_assert(r == NULL); + tt_assert(r == NULL); done: if (r) replaycache_free(r); @@ -55,35 +57,37 @@ test_replaycache_badalloc(void) } static void -test_replaycache_free_null(void) +test_replaycache_free_null(void *arg) { + (void)arg; replaycache_free(NULL); /* Assert that we're here without horrible death */ - test_assert(1); + tt_assert(1); done: return; } static void -test_replaycache_miss(void) +test_replaycache_miss(void *arg) { replaycache_t *r = NULL; int result; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); /* poke the bad-parameter error case too */ result = replaycache_add_and_test_internal(1200, NULL, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); done: if (r) replaycache_free(r); @@ -92,23 +96,24 @@ test_replaycache_miss(void) } static void -test_replaycache_hit(void) +test_replaycache_hit(void *arg) { replaycache_t *r = NULL; int result; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); result = replaycache_add_and_test_internal(1300, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 1); + tt_int_op(result,==, 1); done: if (r) replaycache_free(r); @@ -117,28 +122,29 @@ test_replaycache_hit(void) } static void -test_replaycache_age(void) +test_replaycache_age(void *arg) { replaycache_t *r = NULL; int result; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); result = replaycache_add_and_test_internal(1300, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 1); + tt_int_op(result,==, 1); result = replaycache_add_and_test_internal(3000, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); done: if (r) replaycache_free(r); @@ -147,25 +153,26 @@ test_replaycache_age(void) } static void -test_replaycache_elapsed(void) +test_replaycache_elapsed(void *arg) { replaycache_t *r = NULL; int result; time_t elapsed; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); result = replaycache_add_and_test_internal(1300, r, test_buffer, strlen(test_buffer), &elapsed); - test_eq(result, 1); - test_eq(elapsed, 100); + tt_int_op(result,==, 1); + tt_int_op(elapsed,==, 100); done: if (r) replaycache_free(r); @@ -174,28 +181,29 @@ test_replaycache_elapsed(void) } static void -test_replaycache_noexpire(void) +test_replaycache_noexpire(void *arg) { replaycache_t *r = NULL; int result; + (void)arg; r = replaycache_new(0, 0); - test_assert(r != NULL); + tt_assert(r != NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); result = replaycache_add_and_test_internal(1300, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 1); + tt_int_op(result,==, 1); result = replaycache_add_and_test_internal(3000, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 1); + tt_int_op(result,==, 1); done: if (r) replaycache_free(r); @@ -204,24 +212,25 @@ test_replaycache_noexpire(void) } static void -test_replaycache_scrub(void) +test_replaycache_scrub(void *arg) { replaycache_t *r = NULL; int result; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); /* Set up like in test_replaycache_hit() */ result = replaycache_add_and_test_internal(100, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 0); + tt_int_op(result,==, 0); result = replaycache_add_and_test_internal(200, r, test_buffer, strlen(test_buffer), NULL); - test_eq(result, 1); + tt_int_op(result,==, 1); /* * Poke a few replaycache_scrub_if_needed_internal() error cases that @@ -231,12 +240,12 @@ test_replaycache_scrub(void) /* Null cache */ replaycache_scrub_if_needed_internal(300, NULL); /* Assert we're still here */ - test_assert(1); + tt_assert(1); /* Make sure we hit the aging-out case too */ replaycache_scrub_if_needed_internal(1500, r); /* Assert that we aged it */ - test_eq(digestmap_size(r->digests_seen), 0); + tt_int_op(digestmap_size(r->digests_seen),==, 0); done: if (r) replaycache_free(r); @@ -245,29 +254,30 @@ test_replaycache_scrub(void) } static void -test_replaycache_future(void) +test_replaycache_future(void *arg) { replaycache_t *r = NULL; int result; time_t elapsed = 0; + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); /* Set up like in test_replaycache_hit() */ result = replaycache_add_and_test_internal(100, r, test_buffer, strlen(test_buffer), &elapsed); - test_eq(result, 0); + tt_int_op(result,==, 0); /* elapsed should still be 0, since it wasn't written */ - test_eq(elapsed, 0); + tt_int_op(elapsed,==, 0); result = replaycache_add_and_test_internal(200, r, test_buffer, strlen(test_buffer), &elapsed); - test_eq(result, 1); + tt_int_op(result,==, 1); /* elapsed should be the time since the last hit */ - test_eq(elapsed, 100); + tt_int_op(elapsed,==, 100); /* * Now let's turn the clock back to get coverage on the cache entry from the @@ -277,9 +287,9 @@ test_replaycache_future(void) replaycache_add_and_test_internal(150, r, test_buffer, strlen(test_buffer), &elapsed); /* We should still get a hit */ - test_eq(result, 1); + tt_int_op(result,==, 1); /* ...but it shouldn't let us see a negative elapsed time */ - test_eq(elapsed, 0); + tt_int_op(elapsed,==, 0); done: if (r) replaycache_free(r); @@ -288,7 +298,7 @@ test_replaycache_future(void) } static void -test_replaycache_realtime(void) +test_replaycache_realtime(void *arg) { replaycache_t *r = NULL; /* @@ -299,26 +309,27 @@ test_replaycache_realtime(void) int result; /* Test the realtime as well as *_internal() entry points */ + (void)arg; r = replaycache_new(600, 300); - test_assert(r != NULL); + tt_assert(r != NULL); /* This should miss */ result = replaycache_add_and_test(r, test_buffer, strlen(test_buffer)); - test_eq(result, 0); + tt_int_op(result,==, 0); /* This should hit */ result = replaycache_add_and_test(r, test_buffer, strlen(test_buffer)); - test_eq(result, 1); + tt_int_op(result,==, 1); /* This should hit and return a small elapsed time */ result = replaycache_add_test_and_elapsed(r, test_buffer, strlen(test_buffer), &elapsed); - test_eq(result, 1); - test_assert(elapsed >= 0); - test_assert(elapsed <= 5); + tt_int_op(result,==, 1); + tt_assert(elapsed >= 0); + tt_assert(elapsed <= 5); /* Scrub it to exercise that entry point too */ replaycache_scrub_if_needed(r); @@ -329,7 +340,7 @@ test_replaycache_realtime(void) } #define REPLAYCACHE_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_replaycache_ ## name } + { #name, test_replaycache_ ## name , 0, NULL, NULL } struct testcase_t replaycache_tests[] = { REPLAYCACHE_LEGACY(alloc), diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c new file mode 100644 index 0000000000..81e4dbb1eb --- /dev/null +++ b/src/test/test_routerset.c @@ -0,0 +1,2122 @@ +#define ROUTERSET_PRIVATE + +#include "or.h" +#include "geoip.h" +#include "routerset.h" +#include "routerparse.h" +#include "policies.h" +#include "nodelist.h" +#include "test.h" + +#define NS_MODULE routerset + +#define NS_SUBMODULE routerset_new + +/* + * Functional (blackbox) test to determine that each member of the routerset + * is non-NULL + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *rs; + (void)arg; + + rs = routerset_new(); + + tt_ptr_op(rs, !=, NULL); + tt_ptr_op(rs->list, !=, NULL); + tt_ptr_op(rs->names, !=, NULL); + tt_ptr_op(rs->digests, !=, NULL); + tt_ptr_op(rs->policies, !=, NULL); + tt_ptr_op(rs->country_names, !=, NULL); + + done: + routerset_free(rs); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_get_countryname + +/* + * Functional test to strip the braces from a "{xx}" country code string. + */ + +static void +NS(test_main)(void *arg) +{ + const char *input; + char *name; + (void)arg; + + /* strlen(c) < 4 */ + input = "xxx"; + name = routerset_get_countryname(input); + tt_ptr_op(name, ==, NULL); + tor_free(name); + + /* c[0] != '{' */ + input = "xxx}"; + name = routerset_get_countryname(input); + tt_ptr_op(name, ==, NULL); + tor_free(name); + + /* c[3] != '}' */ + input = "{xxx"; + name = routerset_get_countryname(input); + tt_ptr_op(name, ==, NULL); + tor_free(name); + + /* tor_strlower */ + input = "{XX}"; + name = routerset_get_countryname(input); + tt_str_op(name, ==, "xx"); + tor_free(name); + + input = "{xx}"; + name = routerset_get_countryname(input); + tt_str_op(name, ==, "xx"); + done: + tor_free(name); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, geoip_not_loaded) + +/* + * Structural (whitebox) test for routerset_refresh_counties, when the GeoIP DB + * is not loaded. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, ==, NULL); + tt_int_op(set->n_countries, ==, 0); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 0; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, no_countries) + +/* + * Structural test for routerset_refresh_counties, when there are no countries. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + NS_MOCK(geoip_get_country); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, !=, NULL); + tt_int_op(set->n_countries, ==, 1); + tt_int_op((unsigned int)(*set->countries), ==, 0); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 1); + tt_int_op(CALLED(geoip_get_country), ==, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + NS_UNMOCK(geoip_get_country); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 1; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 1; +} + +static country_t +NS(geoip_get_country)(const char *countrycode) +{ + (void)countrycode; + CALLED(geoip_get_country)++; + + return 1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_valid_country) + +/* + * Structural test for routerset_refresh_counties, with one valid country. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + NS_MOCK(geoip_get_country); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, !=, NULL); + tt_int_op(set->n_countries, ==, 2); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 1); + tt_int_op(CALLED(geoip_get_country), ==, 1); + tt_int_op((unsigned int)(*set->countries), !=, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + NS_UNMOCK(geoip_get_country); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 1; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 2; +} + +static country_t +NS(geoip_get_country)(const char *countrycode) +{ + (void)countrycode; + CALLED(geoip_get_country)++; + + return 1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_invalid_country) + +/* + * Structural test for routerset_refresh_counties, with one invalid + * country code.. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + NS_MOCK(geoip_get_country); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, !=, NULL); + tt_int_op(set->n_countries, ==, 2); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 1); + tt_int_op(CALLED(geoip_get_country), ==, 1); + tt_int_op((unsigned int)(*set->countries), ==, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + NS_UNMOCK(geoip_get_country); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 1; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 2; +} + +static country_t +NS(geoip_get_country)(const char *countrycode) +{ + (void)countrycode; + CALLED(geoip_get_country)++; + + return -1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, malformed) + +/* + * Functional test, with a malformed string to parse. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + const char *s = "_"; + int r; + (void)arg; + + r = routerset_parse(set, s, ""); + + tt_int_op(r, ==, -1); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, valid_hexdigest) + +/* + * Functional test for routerset_parse, that routerset_parse returns 0 + * on a valid hexdigest entry. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + set = routerset_new(); + s = "$0000000000000000000000000000000000000000"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(digestmap_isempty(set->digests), !=, 1); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, valid_nickname) + +/* + * Functional test for routerset_parse, when given a valid nickname as input. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + set = routerset_new(); + s = "fred"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(strmap_isempty(set->names), !=, 1); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, get_countryname) + +/* + * Functional test for routerset_parse, when given a valid countryname. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + set = routerset_new(); + s = "{cc}"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(set->country_names), !=, 0); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, policy) + +/* + * Structural test for routerset_parse, when given a valid policy. + */ + +NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string, + (const char *s, int assume_action)); + +addr_policy_t *NS(mock_addr_policy); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + NS_MOCK(router_parse_addr_policy_item_from_string); + NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t)); + + set = routerset_new(); + s = "*"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(set->policies), !=, 0); + tt_int_op(CALLED(router_parse_addr_policy_item_from_string), ==, 1); + + done: + routerset_free(set); +} + +addr_policy_t * +NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action) +{ + (void)s; + (void)assume_action; + CALLED(router_parse_addr_policy_item_from_string)++; + + return NS(mock_addr_policy); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_union, source_bad) + +/* + * Structural test for routerset_union, when given a bad source argument. + */ + +NS_DECL(smartlist_t *, smartlist_new, (void)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set, *bad_set; + (void)arg; + + set = routerset_new(); + bad_set = routerset_new(); + smartlist_free(bad_set->list); + bad_set->list = NULL; + + NS_MOCK(smartlist_new); + + routerset_union(set, NULL); + tt_int_op(CALLED(smartlist_new), ==, 0); + + routerset_union(set, bad_set); + tt_int_op(CALLED(smartlist_new), ==, 0); + + done: + NS_UNMOCK(smartlist_new); + routerset_free(set); + + /* Just recreate list, so we can simply use routerset_free. */ + bad_set->list = smartlist_new(); + routerset_free(bad_set); +} + +static smartlist_t * +NS(smartlist_new)(void) +{ + CALLED(smartlist_new)++; + + return NULL; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_union, one) + +/* + * Functional test for routerset_union. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *src = routerset_new(); + routerset_t *tgt; + (void)arg; + + tgt = routerset_new(); + smartlist_add(src->list, tor_strdup("{xx}")); + routerset_union(tgt, src); + + tt_int_op(smartlist_len(tgt->list), !=, 0); + + done: + routerset_free(src); + routerset_free(tgt); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_is_list + +/* + * Functional tests for routerset_is_list. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + addr_policy_t *policy; + int is_list; + (void)arg; + + /* len(set->country_names) == 0, len(set->policies) == 0 */ + set = routerset_new(); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, !=, 0); + + /* len(set->country_names) != 0, len(set->policies) == 0 */ + set = routerset_new(); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, ==, 0); + + /* len(set->country_names) == 0, len(set->policies) != 0 */ + set = routerset_new(); + policy = tor_malloc_zero(sizeof(addr_policy_t)); + smartlist_add(set->policies, (void *)policy); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, ==, 0); + + /* len(set->country_names) != 0, len(set->policies) != 0 */ + set = routerset_new(); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + policy = tor_malloc_zero(sizeof(addr_policy_t)); + smartlist_add(set->policies, (void *)policy); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_needs_geoip + +/* + * Functional tests for routerset_needs_geoip. + */ + +static void +NS(test_main)(void *arg) +{ + const routerset_t *set; + int needs_geoip; + (void)arg; + + set = NULL; + needs_geoip = routerset_needs_geoip(set); + tt_int_op(needs_geoip, ==, 0); + + set = routerset_new(); + needs_geoip = routerset_needs_geoip(set); + routerset_free((routerset_t *)set); + tt_int_op(needs_geoip, ==, 0); + set = NULL; + + set = routerset_new(); + smartlist_add(set->country_names, tor_strndup("xx", 2)); + needs_geoip = routerset_needs_geoip(set); + routerset_free((routerset_t *)set); + set = NULL; + tt_int_op(needs_geoip, !=, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_is_empty + +/* + * Functional tests for routerset_is_empty. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + int is_empty; + (void)arg; + + is_empty = routerset_is_empty(set); + tt_int_op(is_empty, !=, 0); + + set = routerset_new(); + is_empty = routerset_is_empty(set); + routerset_free(set); + set = NULL; + tt_int_op(is_empty, !=, 0); + + set = routerset_new(); + smartlist_add(set->list, tor_strdup("{xx}")); + is_empty = routerset_is_empty(set); + routerset_free(set); + set = NULL; + tt_int_op(is_empty, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, null_set_or_null_set_list) + +/* + * Functional test for routerset_contains, when given a NULL set or the + * set has a NULL list. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + int contains; + (void)arg; + + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + + tt_int_op(contains, ==, 0); + + set = tor_malloc_zero(sizeof(routerset_t)); + set->list = NULL; + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + tor_free(set); + tt_int_op(contains, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_nickname) + +/* + * Functional test for routerset_contains, when given a valid routerset but a + * NULL nickname. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + char *nickname = NULL; + int contains; + (void)arg; + + contains = routerset_contains(set, NULL, 0, nickname, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_nickname) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the nickname is in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + const char *nickname; + int contains; + (void)arg; + + nickname = "Foo"; /* This tests the lowercase comparison as well. */ + strmap_set_lc(set->names, nickname, (void *)1); + contains = routerset_contains(set, NULL, 0, nickname, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 4); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_nickname) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the nickname is not in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + strmap_set_lc(set->names, "bar", (void *)1); + contains = routerset_contains(set, NULL, 0, "foo", NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_digest) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the digest is contained in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + uint8_t foo[20] = { 2, 3, 4 }; + (void)arg; + + digestmap_set(set->digests, (const char*)foo, (void *)1); + contains = routerset_contains(set, NULL, 0, NULL, (const char*)foo, 0); + routerset_free(set); + + tt_int_op(contains, ==, 4); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_digest) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the digest is not contained in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + uint8_t bar[20] = { 9, 10, 11, 55 }; + uint8_t foo[20] = { 1, 2, 3, 4}; + (void)arg; + + digestmap_set(set->digests, (const char*)bar, (void *)1); + contains = routerset_contains(set, NULL, 0, NULL, (const char*)foo, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_digest) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the digest is NULL. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + uint8_t bar[20] = { 9, 10, 11, 55 }; + (void)arg; + + digestmap_set(set->digests, (const char*)bar, (void *)1); + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_addr) + +/* + * Structural test for routerset_contains, when given a valid routerset + * and the address is rejected by policy. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); + +static tor_addr_t MOCK_TOR_ADDR; +#define MOCK_TOR_ADDR_PTR (&MOCK_TOR_ADDR) + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + tor_addr_t *addr = MOCK_TOR_ADDR_PTR; + int contains; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + + contains = routerset_contains(set, addr, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(contains, ==, 3); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + return ADDR_POLICY_REJECTED; + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_addr) + +/* + * Structural test for routerset_contains, when given a valid routerset + * and the address is not rejected by policy. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + tor_addr_t *addr = MOCK_TOR_ADDR_PTR; + int contains; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + + contains = routerset_contains(set, addr, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(contains, ==, 0); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + return ADDR_POLICY_ACCEPTED; + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_addr) + +/* + * Structural test for routerset_contains, when given a valid routerset + * and the address is NULL. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + return ADDR_POLICY_ACCEPTED; + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, countries_no_geoip) + +/* + * Structural test for routerset_contains, when there is no matching country + * for the address. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); +NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains = 1; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + NS_MOCK(geoip_get_country_by_addr); + + set->countries = bitarray_init_zero(1); + bitarray_set(set->countries, 1); + contains = routerset_contains(set, MOCK_TOR_ADDR_PTR, 0, NULL, NULL, -1); + routerset_free(set); + + tt_int_op(contains, ==, 0); + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(CALLED(geoip_get_country_by_addr), ==, 1); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return ADDR_POLICY_ACCEPTED; +} + +int +NS(geoip_get_country_by_addr)(const tor_addr_t *addr) +{ + CALLED(geoip_get_country_by_addr)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return -1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, countries_geoip) + +/* + * Structural test for routerset_contains, when there a matching country + * for the address. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); +NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains = 1; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + NS_MOCK(geoip_get_country_by_addr); + + set->n_countries = 2; + set->countries = bitarray_init_zero(1); + bitarray_set(set->countries, 1); + contains = routerset_contains(set, MOCK_TOR_ADDR_PTR, 0, NULL, NULL, -1); + routerset_free(set); + + tt_int_op(contains, ==, 2); + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(CALLED(geoip_get_country_by_addr), ==, 1); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return ADDR_POLICY_ACCEPTED; +} + +int +NS(geoip_get_country_by_addr)(const tor_addr_t *addr) +{ + CALLED(geoip_get_country_by_addr)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return 1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs) + +/* + * Functional test for routerset_add_unknown_ccs, where only_if_some_cc_set + * is set and there are no country names. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerset_t **setp = &set; + int r; + (void)arg; + + r = routerset_add_unknown_ccs(setp, 1); + + tt_int_op(r, ==, 0); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, creates_set) + +/* + * Functional test for routerset_add_unknown_ccs, where the set argument + * is created if passed in as NULL. + */ + +/* The mock is only used to stop the test from asserting erroneously. */ +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + routerset_t **setp = &set; + int r; + (void)arg; + + NS_MOCK(geoip_get_country); + + r = routerset_add_unknown_ccs(setp, 0); + + tt_ptr_op(*setp, !=, NULL); + tt_int_op(r, ==, 0); + + done: + if (set != NULL) + routerset_free(set); +} + +country_t +NS(geoip_get_country)(const char *country) +{ + (void)country; + CALLED(geoip_get_country)++; + + return -1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_unknown) + +/* + * Structural test for routerset_add_unknown_ccs, that the "{??}" + * country code is added to the list. + */ + +NS_DECL(country_t, geoip_get_country, (const char *country)); +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerset_t **setp = &set; + int r; + (void)arg; + + NS_MOCK(geoip_get_country); + NS_MOCK(geoip_is_loaded); + + r = routerset_add_unknown_ccs(setp, 0); + + tt_int_op(r, ==, 1); + tt_int_op(smartlist_contains_string(set->country_names, "??"), ==, 1); + tt_int_op(smartlist_contains_string(set->list, "{??}"), ==, 1); + + done: + if (set != NULL) + routerset_free(set); +} + +country_t +NS(geoip_get_country)(const char *country) +{ + int arg_is_qq, arg_is_a1; + + CALLED(geoip_get_country)++; + + arg_is_qq = !strcmp(country, "??"); + arg_is_a1 = !strcmp(country, "A1"); + + tt_int_op(arg_is_qq || arg_is_a1, ==, 1); + + if (arg_is_qq) + return 1; + + done: + return -1; +} + +int +NS(geoip_is_loaded)(sa_family_t family) +{ + CALLED(geoip_is_loaded)++; + + tt_int_op(family, ==, AF_INET); + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_a1) + +/* + * Structural test for routerset_add_unknown_ccs, that the "{a1}" + * country code is added to the list. + */ + +NS_DECL(country_t, geoip_get_country, (const char *country)); +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerset_t **setp = &set; + int r; + (void)arg; + + NS_MOCK(geoip_get_country); + NS_MOCK(geoip_is_loaded); + + r = routerset_add_unknown_ccs(setp, 0); + + tt_int_op(r, ==, 1); + tt_int_op(smartlist_contains_string(set->country_names, "a1"), ==, 1); + tt_int_op(smartlist_contains_string(set->list, "{a1}"), ==, 1); + + done: + if (set != NULL) + routerset_free(set); +} + +country_t +NS(geoip_get_country)(const char *country) +{ + int arg_is_qq, arg_is_a1; + + CALLED(geoip_get_country)++; + + arg_is_qq = !strcmp(country, "??"); + arg_is_a1 = !strcmp(country, "A1"); + + tt_int_op(arg_is_qq || arg_is_a1, ==, 1); + + if (arg_is_a1) + return 1; + + done: + return -1; +} + +int +NS(geoip_is_loaded)(sa_family_t family) +{ + CALLED(geoip_is_loaded)++; + + tt_int_op(family, ==, AF_INET); + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_contains_extendinfo + +/* + * Functional test for routerset_contains_extendinfo. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + extend_info_t ei; + int r; + const char *nickname = "foo"; + (void)arg; + + memset(&ei, 0, sizeof(ei)); + strmap_set_lc(set->names, nickname, (void *)1); + strncpy(ei.nickname, nickname, sizeof(ei.nickname) - 1); + ei.nickname[sizeof(ei.nickname) - 1] = '\0'; + + r = routerset_contains_extendinfo(set, &ei); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_contains_router + +/* + * Functional test for routerset_contains_router. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerinfo_t ri; + country_t country = 1; + int r; + const char *nickname = "foo"; + (void)arg; + + memset(&ri, 0, sizeof(ri)); + strmap_set_lc(set->names, nickname, (void *)1); + ri.nickname = (char *)nickname; + + r = routerset_contains_router(set, &ri, country); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_contains_routerstatus + +/* + * Functional test for routerset_contains_routerstatus. + */ + +// XXX: This is a bit brief. It only populates and tests the nickname fields +// ie., enough to make the containment check succeed. Perhaps it should do +// a bit more or test a bit more. + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerstatus_t rs; + country_t country = 1; + int r; + const char *nickname = "foo"; + (void)arg; + + memset(&rs, 0, sizeof(rs)); + strmap_set_lc(set->names, nickname, (void *)1); + strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); + rs.nickname[sizeof(rs.nickname) - 1] = '\0'; + + r = routerset_contains_routerstatus(set, &rs, country); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains_node, none) + +/* + * Functional test for routerset_contains_node, when the node has no + * routerset or routerinfo. + */ + +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int r; + (void)arg; + + NS(mock_node).ri = NULL; + NS(mock_node).rs = NULL; + + r = routerset_contains_node(set, &NS(mock_node)); + tt_int_op(r, ==, 0); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains_node, routerstatus) + +/* + * Functional test for routerset_contains_node, when the node has a + * routerset and no routerinfo. + */ + +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int r; + const char *nickname = "foo"; + routerstatus_t rs; + (void)arg; + + strmap_set_lc(set->names, nickname, (void *)1); + + strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); + rs.nickname[sizeof(rs.nickname) - 1] = '\0'; + NS(mock_node).ri = NULL; + NS(mock_node).rs = &rs; + + r = routerset_contains_node(set, &NS(mock_node)); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains_node, routerinfo) + +/* + * Functional test for routerset_contains_node, when the node has no + * routerset and a routerinfo. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int r; + const char *nickname = "foo"; + routerinfo_t ri; + node_t mock_node; + (void)arg; + + strmap_set_lc(set->names, nickname, (void *)1); + + ri.nickname = (char *)nickname; + mock_node.ri = &ri; + mock_node.rs = NULL; + + r = routerset_contains_node(set, &mock_node); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, no_routerset) + +/* + * Functional test for routerset_get_all_nodes, when routerset is NULL or + * the routerset list is NULL. + */ + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = NULL; + (void)arg; + + tt_int_op(smartlist_len(out), ==, 0); + routerset_get_all_nodes(out, NULL, NULL, 0); + + tt_int_op(smartlist_len(out), ==, 0); + + set = routerset_new(); + smartlist_free(set->list); + routerset_get_all_nodes(out, NULL, NULL, 0); + tt_int_op(smartlist_len(out), ==, 0); + + /* Just recreate list, so we can simply use routerset_free. */ + set->list = smartlist_new(); + + done: + routerset_free(set); + smartlist_free(out); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_with_no_nodes) + +/* + * Structural test for routerset_get_all_nodes, when the routerset list + * is empty. + */ + +NS_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unused)); +const char *NS(mock_nickname); + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = routerset_new(); + int out_len; + (void)arg; + + NS_MOCK(node_get_by_nickname); + + NS(mock_nickname) = "foo"; + smartlist_add(set->list, tor_strdup(NS(mock_nickname))); + + routerset_get_all_nodes(out, set, NULL, 0); + out_len = smartlist_len(out); + + smartlist_free(out); + routerset_free(set); + + tt_int_op(out_len, ==, 0); + tt_int_op(CALLED(node_get_by_nickname), ==, 1); + + done: + ; +} + +const node_t * +NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +{ + CALLED(node_get_by_nickname)++; + tt_str_op(nickname, ==, NS(mock_nickname)); + tt_int_op(warn_if_unused, ==, 1); + + done: + return NULL; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_flag_not_running) + +/* + * Structural test for routerset_get_all_nodes, with the running_only flag + * is set but the nodes are not running. + */ + +NS_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unused)); +const char *NS(mock_nickname); +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = routerset_new(); + int out_len; + (void)arg; + + NS_MOCK(node_get_by_nickname); + + NS(mock_node).is_running = 0; + NS(mock_nickname) = "foo"; + smartlist_add(set->list, tor_strdup(NS(mock_nickname))); + + routerset_get_all_nodes(out, set, NULL, 1); + out_len = smartlist_len(out); + + smartlist_free(out); + routerset_free(set); + + tt_int_op(out_len, ==, 0); + tt_int_op(CALLED(node_get_by_nickname), ==, 1); + + done: + ; +} + +const node_t * +NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +{ + CALLED(node_get_by_nickname)++; + tt_str_op(nickname, ==, NS(mock_nickname)); + tt_int_op(warn_if_unused, ==, 1); + + done: + return &NS(mock_node); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list) + +/* + * Structural test for routerset_get_all_nodes. + */ + +NS_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unused)); +char *NS(mock_nickname); +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = routerset_new(); + int out_len; + node_t *ent; + (void)arg; + + NS_MOCK(node_get_by_nickname); + + NS(mock_nickname) = tor_strdup("foo"); + smartlist_add(set->list, NS(mock_nickname)); + + routerset_get_all_nodes(out, set, NULL, 0); + out_len = smartlist_len(out); + ent = (node_t *)smartlist_get(out, 0); + + smartlist_free(out); + routerset_free(set); + + tt_int_op(out_len, ==, 1); + tt_ptr_op(ent, ==, &NS(mock_node)); + tt_int_op(CALLED(node_get_by_nickname), ==, 1); + + done: + ; +} + +const node_t * +NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +{ + CALLED(node_get_by_nickname)++; + tt_str_op(nickname, ==, NS(mock_nickname)); + tt_int_op(warn_if_unused, ==, 1); + + done: + return &NS(mock_node); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes) + +/* + * Structural test for routerset_get_all_nodes, when the nodelist has no nodes. + */ + +NS_DECL(smartlist_t *, nodelist_get_list, (void)); + +smartlist_t *NS(mock_smartlist); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + smartlist_t *out = smartlist_new(); + int r; + (void)arg; + + NS_MOCK(nodelist_get_list); + + smartlist_add(set->country_names, tor_strdup("{xx}")); + NS(mock_smartlist) = smartlist_new(); + + routerset_get_all_nodes(out, set, NULL, 1); + r = smartlist_len(out); + routerset_free(set); + smartlist_free(out); + smartlist_free(NS(mock_smartlist)); + + tt_int_op(r, ==, 0); + tt_int_op(CALLED(nodelist_get_list), ==, 1); + + done: + ; +} + +smartlist_t * +NS(nodelist_get_list)(void) +{ + CALLED(nodelist_get_list)++; + + return NS(mock_smartlist); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_flag_not_running) + +/* + * Structural test for routerset_get_all_nodes, with a non-list routerset + * the running_only flag is set, but the nodes are not running. + */ + +NS_DECL(smartlist_t *, nodelist_get_list, (void)); + +smartlist_t *NS(mock_smartlist); +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + smartlist_t *out = smartlist_new(); + int r; + (void)arg; + + NS_MOCK(nodelist_get_list); + + smartlist_add(set->country_names, tor_strdup("{xx}")); + NS(mock_smartlist) = smartlist_new(); + NS(mock_node).is_running = 0; + smartlist_add(NS(mock_smartlist), (void *)&NS(mock_node)); + + routerset_get_all_nodes(out, set, NULL, 1); + r = smartlist_len(out); + routerset_free(set); + smartlist_free(out); + smartlist_free(NS(mock_smartlist)); + + tt_int_op(r, ==, 0); + tt_int_op(CALLED(nodelist_get_list), ==, 1); + + done: + ; +} + +smartlist_t * +NS(nodelist_get_list)(void) +{ + CALLED(nodelist_get_list)++; + + return NS(mock_smartlist); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_subtract_nodes + +/* + * Functional test for routerset_subtract_nodes. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + smartlist_t *list = smartlist_new(); + const char *nickname = "foo"; + routerinfo_t ri; + node_t mock_node; + (void)arg; + + strmap_set_lc(set->names, nickname, (void *)1); + + ri.nickname = (char *)nickname; + mock_node.rs = NULL; + mock_node.ri = &ri; + smartlist_add(list, (void *)&mock_node); + + tt_int_op(smartlist_len(list), !=, 0); + routerset_subtract_nodes(list, set); + + tt_int_op(smartlist_len(list), ==, 0); + done: + routerset_free(set); + smartlist_free(list); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_subtract_nodes, null_routerset) + +/* + * Functional test for routerset_subtract_nodes, with a NULL routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + smartlist_t *list = smartlist_new(); + const char *nickname = "foo"; + routerinfo_t ri; + node_t mock_node; + (void)arg; + + ri.nickname = (char *)nickname; + mock_node.ri = &ri; + smartlist_add(list, (void *)&mock_node); + + tt_int_op(smartlist_len(list), !=, 0); + routerset_subtract_nodes(list, set); + + tt_int_op(smartlist_len(list), !=, 0); + done: + routerset_free(set); + smartlist_free(list); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_to_string + +/* + * Functional test for routerset_to_string. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + char *s = NULL; + (void)arg; + + set = NULL; + s = routerset_to_string(set); + tt_str_op(s, ==, ""); + tor_free(s); + + set = routerset_new(); + s = routerset_to_string(set); + tt_str_op(s, ==, ""); + tor_free(s); + routerset_free(set); set = NULL; + + set = routerset_new(); + smartlist_add(set->list, tor_strndup("a", 1)); + s = routerset_to_string(set); + tt_str_op(s, ==, "a"); + tor_free(s); + routerset_free(set); set = NULL; + + set = routerset_new(); + smartlist_add(set->list, tor_strndup("a", 1)); + smartlist_add(set->list, tor_strndup("b", 1)); + s = routerset_to_string(set); + tt_str_op(s, ==, "a,b"); + tor_free(s); + routerset_free(set); set = NULL; + + done: + tor_free(s); + routerset_free((routerset_t *)set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, empty_empty) + +/* + * Functional test for routerset_equal, with both routersets empty. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 1); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, empty_not_empty) + +/* + * Functional test for routerset_equal, with one routersets empty. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(b->list, tor_strdup("{xx}")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, differing_lengths) + +/* + * Functional test for routerset_equal, with the routersets having + * differing lengths. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(a->list, tor_strdup("{aa}")); + smartlist_add(b->list, tor_strdup("{b1}")); + smartlist_add(b->list, tor_strdup("{b2}")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, unequal) + +/* + * Functional test for routerset_equal, with the routersets being + * different. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(a->list, tor_strdup("foo")); + smartlist_add(b->list, tor_strdup("bar")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, equal) + +/* + * Functional test for routerset_equal, with the routersets being + * equal. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(a->list, tor_strdup("foo")); + smartlist_add(b->list, tor_strdup("foo")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 1); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_free, null_routerset) + +/* + * Structural test for routerset_free, where the routerset is NULL. + */ + +NS_DECL(void, smartlist_free, (smartlist_t *sl)); + +static void +NS(test_main)(void *arg) +{ + (void)arg; + + NS_MOCK(smartlist_free); + + routerset_free(NULL); + + tt_int_op(CALLED(smartlist_free), ==, 0); + + done: + ; +} + +void +NS(smartlist_free)(smartlist_t *s) +{ + (void)s; + CALLED(smartlist_free)++; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_free + +/* + * Structural test for routerset_free. + */ + +NS_DECL(void, smartlist_free, (smartlist_t *sl)); +NS_DECL(void, strmap_free,(strmap_t *map, void (*free_val)(void*))); +NS_DECL(void, digestmap_free, (digestmap_t *map, void (*free_val)(void*))); + +static void +NS(test_main)(void *arg) +{ + routerset_t *routerset = routerset_new(); + (void)arg; + + NS_MOCK(smartlist_free); + NS_MOCK(strmap_free); + NS_MOCK(digestmap_free); + + routerset_free(routerset); + + tt_int_op(CALLED(smartlist_free), !=, 0); + tt_int_op(CALLED(strmap_free), !=, 0); + tt_int_op(CALLED(digestmap_free), !=, 0); + + done: + ; +} + +void +NS(smartlist_free)(smartlist_t *s) +{ + CALLED(smartlist_free)++; + smartlist_free__real(s); +} + +void +NS(strmap_free)(strmap_t *map, void (*free_val)(void*)) +{ + CALLED(strmap_free)++; + strmap_free__real(map, free_val); +} + +void +NS(digestmap_free)(digestmap_t *map, void (*free_val)(void*)) +{ + CALLED(digestmap_free)++; + digestmap_free__real(map, free_val); +} + +#undef NS_SUBMODULE + +struct testcase_t routerset_tests[] = { + TEST_CASE(routerset_new), + TEST_CASE(routerset_get_countryname), + TEST_CASE(routerset_is_list), + TEST_CASE(routerset_needs_geoip), + TEST_CASE(routerset_is_empty), + TEST_CASE_ASPECT(routerset_contains, null_set_or_null_set_list), + TEST_CASE_ASPECT(routerset_contains, set_and_nickname), + TEST_CASE_ASPECT(routerset_contains, set_and_null_nickname), + TEST_CASE_ASPECT(routerset_contains, set_and_no_nickname), + TEST_CASE_ASPECT(routerset_contains, set_and_digest), + TEST_CASE_ASPECT(routerset_contains, set_and_no_digest), + TEST_CASE_ASPECT(routerset_contains, set_and_null_digest), + TEST_CASE_ASPECT(routerset_contains, set_and_addr), + TEST_CASE_ASPECT(routerset_contains, set_and_no_addr), + TEST_CASE_ASPECT(routerset_contains, set_and_null_addr), + TEST_CASE_ASPECT(routerset_contains, countries_no_geoip), + TEST_CASE_ASPECT(routerset_contains, countries_geoip), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, creates_set), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_unknown), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_a1), + TEST_CASE(routerset_contains_extendinfo), + TEST_CASE(routerset_contains_router), + TEST_CASE(routerset_contains_routerstatus), + TEST_CASE_ASPECT(routerset_contains_node, none), + TEST_CASE_ASPECT(routerset_contains_node, routerinfo), + TEST_CASE_ASPECT(routerset_contains_node, routerstatus), + TEST_CASE_ASPECT(routerset_get_all_nodes, no_routerset), + TEST_CASE_ASPECT(routerset_get_all_nodes, list_with_no_nodes), + TEST_CASE_ASPECT(routerset_get_all_nodes, list_flag_not_running), + TEST_CASE_ASPECT(routerset_get_all_nodes, list), + TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes), + TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_flag_not_running), + TEST_CASE_ASPECT(routerset_refresh_counties, geoip_not_loaded), + TEST_CASE_ASPECT(routerset_refresh_counties, no_countries), + TEST_CASE_ASPECT(routerset_refresh_counties, one_valid_country), + TEST_CASE_ASPECT(routerset_refresh_counties, one_invalid_country), + TEST_CASE_ASPECT(routerset_union, source_bad), + TEST_CASE_ASPECT(routerset_union, one), + TEST_CASE_ASPECT(routerset_parse, malformed), + TEST_CASE_ASPECT(routerset_parse, valid_hexdigest), + TEST_CASE_ASPECT(routerset_parse, valid_nickname), + TEST_CASE_ASPECT(routerset_parse, get_countryname), + TEST_CASE_ASPECT(routerset_parse, policy), + TEST_CASE(routerset_subtract_nodes), + TEST_CASE_ASPECT(routerset_subtract_nodes, null_routerset), + TEST_CASE(routerset_to_string), + TEST_CASE_ASPECT(routerset_equal, empty_empty), + TEST_CASE_ASPECT(routerset_equal, empty_not_empty), + TEST_CASE_ASPECT(routerset_equal, differing_lengths), + TEST_CASE_ASPECT(routerset_equal, unequal), + TEST_CASE_ASPECT(routerset_equal, equal), + TEST_CASE_ASPECT(routerset_free, null_routerset), + TEST_CASE(routerset_free), + END_OF_TESTCASES +}; + diff --git a/src/test/test_socks.c b/src/test/test_socks.c index 4ce61e068b..2b8f824b50 100644 --- a/src/test/test_socks.c +++ b/src/test/test_socks.c @@ -61,10 +61,10 @@ test_socks_4_unsupported_commands(void *ptr) /* SOCKS 4 Send BIND [02] to IP address 2.2.2.2:4369 */ ADD_DATA(buf, "\x04\x02\x11\x11\x02\x02\x02\x02\x00"); - test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == -1); - test_eq(4, socks->socks_version); - test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ + tt_int_op(4,==, socks->socks_version); + tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */ done: ; @@ -76,49 +76,49 @@ test_socks_4_supported_commands(void *ptr) { SOCKS_TEST_INIT(); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00"); - test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == 1); - test_eq(4, socks->socks_version); - test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ - test_eq(SOCKS_COMMAND_CONNECT, socks->command); - test_streq("2.2.2.3", socks->address); - test_eq(4370, socks->port); - test_assert(socks->got_auth == 0); - test_assert(! socks->username); - - test_eq(0, buf_datalen(buf)); + tt_int_op(4,==, socks->socks_version); + tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */ + tt_int_op(SOCKS_COMMAND_CONNECT,==, socks->command); + tt_str_op("2.2.2.3",==, socks->address); + tt_int_op(4370,==, socks->port); + tt_assert(socks->got_auth == 0); + tt_assert(! socks->username); + + tt_int_op(0,==, buf_datalen(buf)); socks_request_clear(socks); /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00"); - test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == 1); - test_eq(4, socks->socks_version); - test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ - test_eq(SOCKS_COMMAND_CONNECT, socks->command); - test_streq("2.2.2.4", socks->address); - test_eq(4370, socks->port); - test_assert(socks->got_auth == 1); - test_assert(socks->username); - test_eq(2, socks->usernamelen); - test_memeq("me", socks->username, 2); - - test_eq(0, buf_datalen(buf)); + tt_int_op(4,==, socks->socks_version); + tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */ + tt_int_op(SOCKS_COMMAND_CONNECT,==, socks->command); + tt_str_op("2.2.2.4",==, socks->address); + tt_int_op(4370,==, socks->port); + tt_assert(socks->got_auth == 1); + tt_assert(socks->username); + tt_int_op(2,==, socks->usernamelen); + tt_mem_op("me",==, socks->username, 2); + + tt_int_op(0,==, buf_datalen(buf)); socks_request_clear(socks); /* SOCKS 4a Send RESOLVE [F0] request for torproject.org */ ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00"); - test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == 1); - test_eq(4, socks->socks_version); - test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ - test_streq("torproject.org", socks->address); + tt_int_op(4,==, socks->socks_version); + tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */ + tt_str_op("torproject.org",==, socks->address); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); done: ; @@ -133,33 +133,43 @@ test_socks_5_unsupported_commands(void *ptr) /* SOCKS 5 Send unsupported BIND [02] command */ ADD_DATA(buf, "\x05\x02\x00\x01"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), 0); - test_eq(0, buf_datalen(buf)); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(0, socks->reply[1]); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, 0); + tt_int_op(0,==, buf_datalen(buf)); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); ADD_DATA(buf, "\x05\x02\x00\x01\x02\x02\x02\x01\x01\x01"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), -1); - /* XXX: shouldn't tor reply 'command not supported' [07]? */ + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, -1); + + tt_int_op(5,==,socks->socks_version); + tt_int_op(10,==,socks->replylen); + tt_int_op(5,==,socks->reply[0]); + tt_int_op(SOCKS5_COMMAND_NOT_SUPPORTED,==,socks->reply[1]); + tt_int_op(1,==,socks->reply[3]); buf_clear(buf); socks_request_clear(socks); /* SOCKS 5 Send unsupported UDP_ASSOCIATE [03] command */ - ADD_DATA(buf, "\x05\x03\x00\x01\x02"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), 0); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(2, socks->reply[1]); + ADD_DATA(buf, "\x05\x02\x00\x01"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, 0); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), -1); - /* XXX: shouldn't tor reply 'command not supported' [07]? */ + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, -1); + + tt_int_op(5,==,socks->socks_version); + tt_int_op(10,==,socks->replylen); + tt_int_op(5,==,socks->reply[0]); + tt_int_op(SOCKS5_COMMAND_NOT_SUPPORTED,==,socks->reply[1]); + tt_int_op(1,==,socks->reply[3]); done: ; @@ -173,64 +183,64 @@ test_socks_5_supported_commands(void *ptr) /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */ ADD_DATA(buf, "\x05\x01\x00"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), 0); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(0, socks->reply[1]); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, 0); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), 1); - test_streq("2.2.2.2", socks->address); - test_eq(4369, socks->port); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, 1); + tt_str_op("2.2.2.2",==, socks->address); + tt_int_op(4369,==, socks->port); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); socks_request_clear(socks); /* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11"); - test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks), 1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),==, 1); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(0, socks->reply[1]); - test_streq("torproject.org", socks->address); - test_eq(4369, socks->port); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); + tt_str_op("torproject.org",==, socks->address); + tt_int_op(4369,==, socks->port); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); socks_request_clear(socks); /* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02"); - test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == 1); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(0, socks->reply[1]); - test_streq("torproject.org", socks->address); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); + tt_str_op("torproject.org",==, socks->address); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); socks_request_clear(socks); /* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03"); - test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == 1); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(0, socks->reply[1]); - test_streq("2.2.2.5", socks->address); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); + tt_str_op("2.2.2.5",==, socks->address); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); done: ; @@ -244,30 +254,30 @@ test_socks_5_no_authenticate(void *ptr) /*SOCKS 5 No Authentication */ ADD_DATA(buf,"\x05\x01\x00"); - test_assert(!fetch_from_buf_socks(buf, socks, + tt_assert(!fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks)); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(SOCKS_NO_AUTH, socks->reply[1]); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(SOCKS_NO_AUTH,==, socks->reply[1]); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); /*SOCKS 5 Send username/password anyway - pretend to be broken */ ADD_DATA(buf,"\x01\x02\x01\x01\x02\x01\x01"); - test_assert(!fetch_from_buf_socks(buf, socks, + tt_assert(!fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks)); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(1, socks->reply[0]); - test_eq(0, socks->reply[1]); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(1,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); - test_eq(2, socks->usernamelen); - test_eq(2, socks->passwordlen); + tt_int_op(2,==, socks->usernamelen); + tt_int_op(2,==, socks->passwordlen); - test_memeq("\x01\x01", socks->username, 2); - test_memeq("\x01\x01", socks->password, 2); + tt_mem_op("\x01\x01",==, socks->username, 2); + tt_mem_op("\x01\x01",==, socks->password, 2); done: ; @@ -282,31 +292,31 @@ test_socks_5_authenticate(void *ptr) /* SOCKS 5 Negotiate username/password authentication */ ADD_DATA(buf, "\x05\x01\x02"); - test_assert(!fetch_from_buf_socks(buf, socks, + tt_assert(!fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks)); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(SOCKS_USER_PASS, socks->reply[1]); - test_eq(5, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(SOCKS_USER_PASS,==, socks->reply[1]); + tt_int_op(5,==, socks->socks_version); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); /* SOCKS 5 Send username/password */ ADD_DATA(buf, "\x01\x02me\x08mypasswd"); - test_assert(!fetch_from_buf_socks(buf, socks, + tt_assert(!fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks)); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(1, socks->reply[0]); - test_eq(0, socks->reply[1]); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(1,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); - test_eq(2, socks->usernamelen); - test_eq(8, socks->passwordlen); + tt_int_op(2,==, socks->usernamelen); + tt_int_op(8,==, socks->passwordlen); - test_memeq("me", socks->username, 2); - test_memeq("mypasswd", socks->password, 8); + tt_mem_op("me",==, socks->username, 2); + tt_mem_op("mypasswd",==, socks->password, 8); done: ; @@ -321,34 +331,34 @@ test_socks_5_authenticate_with_data(void *ptr) /* SOCKS 5 Negotiate username/password authentication */ ADD_DATA(buf, "\x05\x01\x02"); - test_assert(!fetch_from_buf_socks(buf, socks, + tt_assert(!fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks)); - test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); - test_eq(SOCKS_USER_PASS, socks->reply[1]); - test_eq(5, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(5,==, socks->reply[0]); + tt_int_op(SOCKS_USER_PASS,==, socks->reply[1]); + tt_int_op(5,==, socks->socks_version); - test_eq(0, buf_datalen(buf)); + tt_int_op(0,==, buf_datalen(buf)); /* SOCKS 5 Send username/password */ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */ ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11"); - test_assert(fetch_from_buf_socks(buf, socks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == 1); - test_eq(5, socks->socks_version); - test_eq(2, socks->replylen); - test_eq(1, socks->reply[0]); - test_eq(0, socks->reply[1]); + tt_int_op(5,==, socks->socks_version); + tt_int_op(2,==, socks->replylen); + tt_int_op(1,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); - test_streq("2.2.2.2", socks->address); - test_eq(4369, socks->port); + tt_str_op("2.2.2.2",==, socks->address); + tt_int_op(4369,==, socks->port); - test_eq(2, socks->usernamelen); - test_eq(3, socks->passwordlen); - test_memeq("me", socks->username, 2); - test_memeq("you", socks->password, 3); + tt_int_op(2,==, socks->usernamelen); + tt_int_op(3,==, socks->passwordlen); + tt_mem_op("me",==, socks->username, 2); + tt_mem_op("you",==, socks->password, 3); done: ; @@ -362,13 +372,13 @@ test_socks_5_auth_before_negotiation(void *ptr) /* SOCKS 5 Send username/password */ ADD_DATA(buf, "\x01\x02me\x02me"); - test_assert(fetch_from_buf_socks(buf, socks, + tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks) == -1); - test_eq(0, socks->socks_version); - test_eq(0, socks->replylen); - test_eq(0, socks->reply[0]); - test_eq(0, socks->reply[1]); + tt_int_op(0,==, socks->socks_version); + tt_int_op(0,==, socks->replylen); + tt_int_op(0,==, socks->reply[0]); + tt_int_op(0,==, socks->reply[1]); done: ; diff --git a/src/test/test_status.c b/src/test/test_status.c index 46dd473132..8bc0152ffb 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -30,27 +30,24 @@ * global circuits. */ -struct global_circuitlist_s mock_global_circuitlist = - TOR_LIST_HEAD_INITIALIZER(global_circuitlist); +static smartlist_t * mock_global_circuitlist = NULL; -NS_DECL(struct global_circuitlist_s *, circuit_get_global_list, (void)); +NS_DECL(smartlist_t *, circuit_get_global_list, (void)); static void NS(test_main)(void *arg) { /* Choose origin_circuit_t wlog. */ origin_circuit_t *mock_circuit1, *mock_circuit2; - circuit_t *circ, *tmp; int expected_circuits = 2, actual_circuits; (void)arg; mock_circuit1 = tor_malloc_zero(sizeof(origin_circuit_t)); mock_circuit2 = tor_malloc_zero(sizeof(origin_circuit_t)); - TOR_LIST_INSERT_HEAD( - &mock_global_circuitlist, TO_CIRCUIT(mock_circuit1), head); - TOR_LIST_INSERT_HEAD( - &mock_global_circuitlist, TO_CIRCUIT(mock_circuit2), head); + mock_global_circuitlist = smartlist_new(); + smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit1)); + smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit2)); NS_MOCK(circuit_get_global_list); @@ -58,17 +55,18 @@ NS(test_main)(void *arg) tt_assert(expected_circuits == actual_circuits); - done: - TOR_LIST_FOREACH_SAFE( - circ, NS(circuit_get_global_list)(), head, tmp); - tor_free(circ); - NS_UNMOCK(circuit_get_global_list); + done: + tor_free(mock_circuit1); + tor_free(mock_circuit2); + smartlist_free(mock_global_circuitlist); + mock_global_circuitlist = NULL; + NS_UNMOCK(circuit_get_global_list); } -static struct global_circuitlist_s * +static smartlist_t * NS(circuit_get_global_list)(void) { - return &mock_global_circuitlist; + return mock_global_circuitlist; } #undef NS_SUBMODULE diff --git a/src/test/test_util.c b/src/test/test_util.c index 151ec69127..c67aa71b02 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -64,8 +64,8 @@ test_util_read_until_eof_impl(const char *fname, size_t file_len, else tt_int_op(sz, ==, file_len); - test_mem_op(test_str, ==, str, sz); - test_assert(str[sz] == '\0'); + tt_mem_op(test_str, ==, str, sz); + tt_int_op(str[sz], ==, '\0'); done: unlink(fifo_name); @@ -87,6 +87,20 @@ test_util_read_file_eof_tiny_limit(void *arg) } static void +test_util_read_file_eof_one_loop_a(void *arg) +{ + (void)arg; + test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023); +} + +static void +test_util_read_file_eof_one_loop_b(void *arg) +{ + (void)arg; + test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024); +} + +static void test_util_read_file_eof_two_loops(void *arg) { (void)arg; @@ -98,6 +112,14 @@ test_util_read_file_eof_two_loops(void *arg) } static void +test_util_read_file_eof_two_loops_b(void *arg) +{ + (void)arg; + + test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048); +} + +static void test_util_read_file_eof_zero_bytes(void *arg) { (void)arg; @@ -155,7 +177,7 @@ test_util_write_chunks_to_file(void *arg) str = read_file_to_str(fname, RFTS_BIN, &st); tt_assert(str != NULL); tt_u64_op((uint64_t)st.st_size, ==, data_str_len); - test_mem_op(data_str, ==, str, data_str_len); + tt_mem_op(data_str, ==, str, data_str_len); tor_free(str); // assert that the tempfile is removed (should not leave artifacts) @@ -186,14 +208,14 @@ test_util_write_chunks_to_file(void *arg) str = read_file_to_str(fname, RFTS_BIN, &st); tt_assert(str != NULL); tt_u64_op((uint64_t)st.st_size, ==, data_str_len); - test_mem_op(data_str, ==, str, data_str_len); + tt_mem_op(data_str, ==, str, data_str_len); tor_free(str); // assert the tempfile still contains the known string str = read_file_to_str(tempname, RFTS_BIN, &st); tt_assert(str != NULL); tt_u64_op((uint64_t)st.st_size, ==, temp_str_len); - test_mem_op(temp_str, ==, str, temp_str_len); + tt_mem_op(temp_str, ==, str, temp_str_len); done: unlink(fname); @@ -207,7 +229,7 @@ test_util_write_chunks_to_file(void *arg) } static void -test_util_time(void) +test_util_time(void *arg) { struct timeval start, end; struct tm a_time; @@ -218,29 +240,30 @@ test_util_time(void) /* Test tv_udiff */ + (void)arg; start.tv_sec = 5; start.tv_usec = 5000; end.tv_sec = 5; end.tv_usec = 5000; - test_eq(0L, tv_udiff(&start, &end)); + tt_int_op(0L,==, tv_udiff(&start, &end)); end.tv_usec = 7000; - test_eq(2000L, tv_udiff(&start, &end)); + tt_int_op(2000L,==, tv_udiff(&start, &end)); end.tv_sec = 6; - test_eq(1002000L, tv_udiff(&start, &end)); + tt_int_op(1002000L,==, tv_udiff(&start, &end)); end.tv_usec = 0; - test_eq(995000L, tv_udiff(&start, &end)); + tt_int_op(995000L,==, tv_udiff(&start, &end)); end.tv_sec = 4; - test_eq(-1005000L, tv_udiff(&start, &end)); + tt_int_op(-1005000L,==, tv_udiff(&start, &end)); /* Test tor_timegm */ @@ -252,45 +275,53 @@ test_util_time(void) a_time.tm_hour = 6; a_time.tm_min = 14; a_time.tm_sec = 55; - test_eq((time_t) 1062224095UL, tor_timegm(&a_time)); + tt_int_op((time_t) 1062224095UL,==, tor_timegm(&a_time)); a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */ - test_eq((time_t) 1093846495UL, tor_timegm(&a_time)); + tt_int_op((time_t) 1093846495UL,==, tor_timegm(&a_time)); a_time.tm_mon = 1; /* Try a leap year, in feb. */ a_time.tm_mday = 10; - test_eq((time_t) 1076393695UL, tor_timegm(&a_time)); + tt_int_op((time_t) 1076393695UL,==, tor_timegm(&a_time)); a_time.tm_mon = 0; a_time.tm_mday = 10; - test_eq((time_t) 1073715295UL, tor_timegm(&a_time)); + tt_int_op((time_t) 1073715295UL,==, tor_timegm(&a_time)); a_time.tm_mon = 12; /* Wrong month, it's 0-based */ a_time.tm_mday = 10; - test_eq((time_t) -1, tor_timegm(&a_time)); + tt_int_op((time_t) -1,==, tor_timegm(&a_time)); a_time.tm_mon = -1; /* Wrong month */ a_time.tm_mday = 10; - test_eq((time_t) -1, tor_timegm(&a_time)); + tt_int_op((time_t) -1,==, tor_timegm(&a_time)); /* Test {format,parse}_rfc1123_time */ format_rfc1123_time(timestr, 0); - test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr); + tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",==, timestr); format_rfc1123_time(timestr, (time_t)1091580502UL); - test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr); + tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",==, timestr); t_res = 0; i = parse_rfc1123_time(timestr, &t_res); - test_eq(0,i); - test_eq(t_res, (time_t)1091580502UL); + tt_int_op(0,==, i); + tt_int_op(t_res,==, (time_t)1091580502UL); /* The timezone doesn't matter */ t_res = 0; - test_eq(0, parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res)); - test_eq(t_res, (time_t)1091580502UL); - test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res)); - test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res)); + tt_int_op(0,==, parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res)); + tt_int_op(t_res,==, (time_t)1091580502UL); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res)); + tt_int_op(-1,==, + parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res)); #if 0 /* This fails, I imagine it's important and should be fixed? */ @@ -304,31 +335,31 @@ test_util_time(void) t_res = 0; i = parse_iso_time("", &t_res); - test_eq(-1, i); + tt_int_op(-1,==, i); t_res = 0; i = parse_iso_time("2004-08-32 00:48:22", &t_res); - test_eq(-1, i); + tt_int_op(-1,==, i); t_res = 0; i = parse_iso_time("1969-08-03 00:48:22", &t_res); - test_eq(-1, i); + tt_int_op(-1,==, i); t_res = 0; i = parse_iso_time("2004-08-04 00:48:22", &t_res); - test_eq(0,i); - test_eq(t_res, (time_t)1091580502UL); + tt_int_op(0,==, i); + tt_int_op(t_res,==, (time_t)1091580502UL); t_res = 0; i = parse_iso_time("2004-8-4 0:48:22", &t_res); - test_eq(0, i); - test_eq(t_res, (time_t)1091580502UL); - test_eq(-1, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res)); - test_eq(-1, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res)); - test_eq(-1, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res)); - test_eq(-1, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res)); - test_eq(-1, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res)); - test_eq(-1, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res)); - test_eq(-1, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res)); - test_eq(-1, parse_iso_time("2147483647-08-29 14:00:00", &t_res)); - test_eq(-1, parse_iso_time("2011-03-30 23:59", &t_res)); + tt_int_op(0,==, i); + tt_int_op(t_res,==, (time_t)1091580502UL); + tt_int_op(-1,==, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res)); + tt_int_op(-1,==, parse_iso_time("2147483647-08-29 14:00:00", &t_res)); + tt_int_op(-1,==, parse_iso_time("2011-03-30 23:59", &t_res)); /* Test tor_gettimeofday */ @@ -348,7 +379,7 @@ test_util_time(void) tv.tv_sec = (time_t)1326296338; tv.tv_usec = 3060; format_iso_time(timestr, (time_t)tv.tv_sec); - test_streq("2012-01-11 15:38:58", timestr); + tt_str_op("2012-01-11 15:38:58",==, timestr); /* The output of format_local_iso_time will vary by timezone, and setting our timezone for testing purposes would be a nontrivial flaky pain. Skip this test for now. @@ -356,11 +387,11 @@ test_util_time(void) test_streq("2012-01-11 10:38:58", timestr); */ format_iso_time_nospace(timestr, (time_t)tv.tv_sec); - test_streq("2012-01-11T15:38:58", timestr); - test_eq(strlen(timestr), ISO_TIME_LEN); + tt_str_op("2012-01-11T15:38:58",==, timestr); + tt_int_op(strlen(timestr),==, ISO_TIME_LEN); format_iso_time_nospace_usec(timestr, &tv); - test_streq("2012-01-11T15:38:58.003060", timestr); - test_eq(strlen(timestr), ISO_TIME_USEC_LEN); + tt_str_op("2012-01-11T15:38:58.003060",==, timestr); + tt_int_op(strlen(timestr),==, ISO_TIME_USEC_LEN); done: ; @@ -381,55 +412,66 @@ test_util_parse_http_time(void *arg) /* Test parse_http_time */ - test_eq(-1, parse_http_time("", &a_time)); - test_eq(-1, parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time)); - test_eq(-1, parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time)); - test_eq(-1, parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time)); - test_eq(-1, parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time)); - test_eq(-1, parse_http_time("Sunday, August the third", &a_time)); - test_eq(-1, parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time)); - - test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(-1,==, + parse_http_time("", &a_time)); + tt_int_op(-1,==, + parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time)); + tt_int_op(-1,==, + parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time)); + tt_int_op(-1,==, + parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time)); + tt_int_op(-1,==, + parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time)); + tt_int_op(-1,==, + parse_http_time("Sunday, August the third", &a_time)); + tt_int_op(-1,==, + parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time)); + + tt_int_op(0,==, + parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, + parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, + parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, + parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time)); - test_eq((time_t)775961302UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time)); + tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time)); T("1994-08-04 00:48:22"); - test_eq(0, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time)); - test_eq((time_t)1325376000UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time)); + tt_int_op((time_t)1325376000UL,==, tor_timegm(&a_time)); T("2012-01-01 00:00:00"); - test_eq(0, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time)); - test_eq((time_t)1356912000UL, tor_timegm(&a_time)); + tt_int_op(0,==, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time)); + tt_int_op((time_t)1356912000UL,==, tor_timegm(&a_time)); T("2012-12-31 00:00:00"); - test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time)); - test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time)); - test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time)); - test_eq(-1, parse_http_time("2011-03-30 23:60:00 GMT", &a_time)); - test_eq(-1, parse_http_time("2011-03-30 23:59:62 GMT", &a_time)); - test_eq(-1, parse_http_time("1969-03-30 23:59:59 GMT", &a_time)); - test_eq(-1, parse_http_time("2011-00-30 23:59:59 GMT", &a_time)); - test_eq(-1, parse_http_time("2011-03-30 23:59", &a_time)); + tt_int_op(-1,==, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("2011-03-32 00:00:00 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("2011-03-30 24:00:00 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("2011-03-30 23:60:00 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("2011-03-30 23:59:62 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("1969-03-30 23:59:59 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("2011-00-30 23:59:59 GMT", &a_time)); + tt_int_op(-1,==, parse_http_time("2011-03-30 23:59", &a_time)); #undef T done: @@ -437,13 +479,14 @@ test_util_parse_http_time(void *arg) } static void -test_util_config_line(void) +test_util_config_line(void *arg) { char buf[1024]; char *k=NULL, *v=NULL; const char *str; /* Test parse_config_line_from_str */ + (void)arg; strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n" "k2\n" "k3 \n" "\n" " \n" "#comment\n" @@ -463,110 +506,110 @@ test_util_config_line(void) str = buf; str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k"); - test_streq(v, "v"); + tt_str_op(k,==, "k"); + tt_str_op(v,==, "v"); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "key value with")); + tt_assert(!strcmpstart(str, "key value with")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "key"); - test_streq(v, "value with spaces"); + tt_str_op(k,==, "key"); + tt_str_op(v,==, "value with spaces"); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "keykey")); + tt_assert(!strcmpstart(str, "keykey")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "keykey"); - test_streq(v, "val"); + tt_str_op(k,==, "keykey"); + tt_str_op(v,==, "val"); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k2\n")); + tt_assert(!strcmpstart(str, "k2\n")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k2"); - test_streq(v, ""); + tt_str_op(k,==, "k2"); + tt_str_op(v,==, ""); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k3 \n")); + tt_assert(!strcmpstart(str, "k3 \n")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k3"); - test_streq(v, ""); + tt_str_op(k,==, "k3"); + tt_str_op(v,==, ""); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "#comment")); + tt_assert(!strcmpstart(str, "#comment")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k4"); - test_streq(v, ""); + tt_str_op(k,==, "k4"); + tt_str_op(v,==, ""); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k5#abc")); + tt_assert(!strcmpstart(str, "k5#abc")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k5"); - test_streq(v, ""); + tt_str_op(k,==, "k5"); + tt_str_op(v,==, ""); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k6")); + tt_assert(!strcmpstart(str, "k6")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k6"); - test_streq(v, "val"); + tt_str_op(k,==, "k6"); + tt_str_op(v,==, "val"); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "kseven")); + tt_assert(!strcmpstart(str, "kseven")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "kseven"); - test_streq(v, "a quoted \'string"); + tt_str_op(k,==, "kseven"); + tt_str_op(v,==, "a quoted \'string"); tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k8 ")); + tt_assert(!strcmpstart(str, "k8 ")); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k8"); - test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\""); + tt_str_op(k,==, "k8"); + tt_str_op(v,==, "a quoted\n\"str\\ing\t\x01\x01\x01\""); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k9"); - test_streq(v, "a line that spans two lines."); + tt_str_op(k,==, "k9"); + tt_str_op(v,==, "a line that spans two lines."); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k10"); - test_streq(v, "more than one continuation"); + tt_str_op(k,==, "k10"); + tt_str_op(v,==, "more than one continuation"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k11"); - test_streq(v, "continuation at the start"); + tt_str_op(k,==, "k11"); + tt_str_op(v,==, "continuation at the start"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k12"); - test_streq(v, "line with a embedded"); + tt_str_op(k,==, "k12"); + tt_str_op(v,==, "line with a embedded"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k13"); - test_streq(v, "continuation at the very start"); + tt_str_op(k,==, "k13"); + tt_str_op(v,==, "continuation at the very start"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k14"); - test_streq(v, "a line that has a comment and" ); + tt_str_op(k,==, "k14"); + tt_str_op(v,==, "a line that has a comment and" ); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k15"); - test_streq(v, "this should be the next new line"); + tt_str_op(k,==, "k15"); + tt_str_op(v,==, "this should be the next new line"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k16"); - test_streq(v, "a line that has a comment and" ); + tt_str_op(k,==, "k16"); + tt_str_op(v,==, "a line that has a comment and" ); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k17"); - test_streq(v, "this should be the next new line"); + tt_str_op(k,==, "k17"); + tt_str_op(v,==, "this should be the next new line"); tor_free(k); tor_free(v); - test_streq(str, ""); + tt_str_op(str,==, ""); done: tor_free(k); @@ -574,7 +617,7 @@ test_util_config_line(void) } static void -test_util_config_line_quotes(void) +test_util_config_line_quotes(void *arg) { char buf1[1024]; char buf2[128]; @@ -584,6 +627,7 @@ test_util_config_line_quotes(void) const char *str; /* Test parse_config_line_from_str */ + (void)arg; strlcpy(buf1, "kTrailingSpace \"quoted value\" \n" "kTrailingGarbage \"quoted value\"trailing garbage\n" , sizeof(buf1)); @@ -596,30 +640,30 @@ test_util_config_line_quotes(void) str = buf1; str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "kTrailingSpace"); - test_streq(v, "quoted value"); + tt_str_op(k,==, "kTrailingSpace"); + tt_str_op(v,==, "quoted value"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); str = buf2; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); str = buf3; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); str = buf4; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); done: @@ -628,13 +672,14 @@ test_util_config_line_quotes(void) } static void -test_util_config_line_comment_character(void) +test_util_config_line_comment_character(void *arg) { char buf[1024]; char *k=NULL, *v=NULL; const char *str; /* Test parse_config_line_from_str */ + (void)arg; strlcpy(buf, "k1 \"# in quotes\"\n" "k2 some value # some comment\n" "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */ @@ -642,16 +687,16 @@ test_util_config_line_comment_character(void) str = buf; str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k1"); - test_streq(v, "# in quotes"); + tt_str_op(k,==, "k1"); + tt_str_op(v,==, "# in quotes"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k2"); - test_streq(v, "some value"); + tt_str_op(k,==, "k2"); + tt_str_op(v,==, "some value"); tor_free(k); tor_free(v); - test_streq(str, "k3 /home/user/myTorNetwork#2\n"); + tt_str_op(str,==, "k3 /home/user/myTorNetwork#2\n"); #if 0 str = parse_config_line_from_str(str, &k, &v); @@ -668,7 +713,7 @@ test_util_config_line_comment_character(void) } static void -test_util_config_line_escaped_content(void) +test_util_config_line_escaped_content(void *arg) { char buf1[1024]; char buf2[128]; @@ -680,6 +725,7 @@ test_util_config_line_escaped_content(void) const char *str; /* Test parse_config_line_from_str */ + (void)arg; strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n" "HexadecimalUpper \"\\x2A\"\n" "HexadecimalUpperX \"\\X2A\"\n" @@ -711,91 +757,91 @@ test_util_config_line_escaped_content(void) str = buf1; str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "HexadecimalLower"); - test_streq(v, "*"); + tt_str_op(k,==, "HexadecimalLower"); + tt_str_op(v,==, "*"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "HexadecimalUpper"); - test_streq(v, "*"); + tt_str_op(k,==, "HexadecimalUpper"); + tt_str_op(v,==, "*"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "HexadecimalUpperX"); - test_streq(v, "*"); + tt_str_op(k,==, "HexadecimalUpperX"); + tt_str_op(v,==, "*"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "Octal"); - test_streq(v, "*"); + tt_str_op(k,==, "Octal"); + tt_str_op(v,==, "*"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "Newline"); - test_streq(v, "\n"); + tt_str_op(k,==, "Newline"); + tt_str_op(v,==, "\n"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "Tab"); - test_streq(v, "\t"); + tt_str_op(k,==, "Tab"); + tt_str_op(v,==, "\t"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "CarriageReturn"); - test_streq(v, "\r"); + tt_str_op(k,==, "CarriageReturn"); + tt_str_op(v,==, "\r"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "DoubleQuote"); - test_streq(v, "\""); + tt_str_op(k,==, "DoubleQuote"); + tt_str_op(v,==, "\""); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "SimpleQuote"); - test_streq(v, "'"); + tt_str_op(k,==, "SimpleQuote"); + tt_str_op(v,==, "'"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "Backslash"); - test_streq(v, "\\"); + tt_str_op(k,==, "Backslash"); + tt_str_op(v,==, "\\"); tor_free(k); tor_free(v); str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "Mix"); - test_streq(v, "This is a \"star\":\t'*'\nAnd second line"); + tt_str_op(k,==, "Mix"); + tt_str_op(v,==, "This is a \"star\":\t'*'\nAnd second line"); tor_free(k); tor_free(v); - test_streq(str, ""); + tt_str_op(str,==, ""); str = buf2; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); str = buf3; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); str = buf4; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); #if 0 str = buf5; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str, ==, NULL); tor_free(k); tor_free(v); #endif str = buf6; str = parse_config_line_from_str(str, &k, &v); - test_eq_ptr(str, NULL); + tt_ptr_op(str,==, NULL); tor_free(k); tor_free(v); done: @@ -805,46 +851,47 @@ test_util_config_line_escaped_content(void) #ifndef _WIN32 static void -test_util_expand_filename(void) +test_util_expand_filename(void *arg) { char *str; + (void)arg; setenv("HOME", "/home/itv", 1); /* For "internal test value" */ str = expand_filename(""); - test_streq("", str); + tt_str_op("",==, str); tor_free(str); str = expand_filename("/normal/path"); - test_streq("/normal/path", str); + tt_str_op("/normal/path",==, str); tor_free(str); str = expand_filename("/normal/trailing/path/"); - test_streq("/normal/trailing/path/", str); + tt_str_op("/normal/trailing/path/",==, str); tor_free(str); str = expand_filename("~"); - test_streq("/home/itv/", str); + tt_str_op("/home/itv/",==, str); tor_free(str); str = expand_filename("$HOME/nodice"); - test_streq("$HOME/nodice", str); + tt_str_op("$HOME/nodice",==, str); tor_free(str); str = expand_filename("~/"); - test_streq("/home/itv/", str); + tt_str_op("/home/itv/",==, str); tor_free(str); str = expand_filename("~/foobarqux"); - test_streq("/home/itv/foobarqux", str); + tt_str_op("/home/itv/foobarqux",==, str); tor_free(str); str = expand_filename("~/../../etc/passwd"); - test_streq("/home/itv/../../etc/passwd", str); + tt_str_op("/home/itv/../../etc/passwd",==, str); tor_free(str); str = expand_filename("~/trailing/"); - test_streq("/home/itv/trailing/", str); + tt_str_op("/home/itv/trailing/",==, str); tor_free(str); /* Ideally we'd test ~anotheruser, but that's shady to test (we'd have to somehow inject/fake the get_user_homedir call) */ @@ -853,15 +900,15 @@ test_util_expand_filename(void) setenv("HOME", "/home/itv/", 1); str = expand_filename("~"); - test_streq("/home/itv/", str); + tt_str_op("/home/itv/",==, str); tor_free(str); str = expand_filename("~/"); - test_streq("/home/itv/", str); + tt_str_op("/home/itv/",==, str); tor_free(str); str = expand_filename("~/foo"); - test_streq("/home/itv/foo", str); + tt_str_op("/home/itv/foo",==, str); tor_free(str); /* Try with empty $HOME */ @@ -869,15 +916,15 @@ test_util_expand_filename(void) setenv("HOME", "", 1); str = expand_filename("~"); - test_streq("/", str); + tt_str_op("/",==, str); tor_free(str); str = expand_filename("~/"); - test_streq("/", str); + tt_str_op("/",==, str); tor_free(str); str = expand_filename("~/foobar"); - test_streq("/foobar", str); + tt_str_op("/foobar",==, str); tor_free(str); /* Try with $HOME unset */ @@ -885,15 +932,15 @@ test_util_expand_filename(void) unsetenv("HOME"); str = expand_filename("~"); - test_streq("/", str); + tt_str_op("/",==, str); tor_free(str); str = expand_filename("~/"); - test_streq("/", str); + tt_str_op("/",==, str); tor_free(str); str = expand_filename("~/foobar"); - test_streq("/foobar", str); + tt_str_op("/foobar",==, str); tor_free(str); done: @@ -903,37 +950,38 @@ test_util_expand_filename(void) /** Test tor_escape_str_for_pt_args(). */ static void -test_util_escape_string_socks(void) +test_util_escape_string_socks(void *arg) { char *escaped_string = NULL; /** Simple backslash escape. */ + (void)arg; escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\"); - test_assert(escaped_string); - test_streq(escaped_string, "This is a backslash: \\\\"); + tt_assert(escaped_string); + tt_str_op(escaped_string,==, "This is a backslash: \\\\"); tor_free(escaped_string); /** Simple semicolon escape. */ escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\"); - test_assert(escaped_string); - test_streq(escaped_string, "First rule:Do not use \\;"); + tt_assert(escaped_string); + tt_str_op(escaped_string,==, "First rule:Do not use \\;"); tor_free(escaped_string); /** Empty string. */ escaped_string = tor_escape_str_for_pt_args("", ";\\"); - test_assert(escaped_string); - test_streq(escaped_string, ""); + tt_assert(escaped_string); + tt_str_op(escaped_string,==, ""); tor_free(escaped_string); /** Escape all characters. */ escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\"); - test_assert(escaped_string); - test_streq(escaped_string, "\\;\\\\\\;\\\\"); + tt_assert(escaped_string); + tt_str_op(escaped_string,==, "\\;\\\\\\;\\\\"); tor_free(escaped_string); escaped_string = tor_escape_str_for_pt_args(";", ";\\"); - test_assert(escaped_string); - test_streq(escaped_string, "\\;"); + tt_assert(escaped_string); + tt_str_op(escaped_string,==, "\\;"); tor_free(escaped_string); done: @@ -944,288 +992,290 @@ static void test_util_string_is_key_value(void *ptr) { (void)ptr; - test_assert(string_is_key_value(LOG_WARN, "key=value")); - test_assert(string_is_key_value(LOG_WARN, "k=v")); - test_assert(string_is_key_value(LOG_WARN, "key=")); - test_assert(string_is_key_value(LOG_WARN, "x=")); - test_assert(string_is_key_value(LOG_WARN, "xx=")); - test_assert(!string_is_key_value(LOG_WARN, "=value")); - test_assert(!string_is_key_value(LOG_WARN, "=x")); - test_assert(!string_is_key_value(LOG_WARN, "=")); + tt_assert(string_is_key_value(LOG_WARN, "key=value")); + tt_assert(string_is_key_value(LOG_WARN, "k=v")); + tt_assert(string_is_key_value(LOG_WARN, "key=")); + tt_assert(string_is_key_value(LOG_WARN, "x=")); + tt_assert(string_is_key_value(LOG_WARN, "xx=")); + tt_assert(!string_is_key_value(LOG_WARN, "=value")); + tt_assert(!string_is_key_value(LOG_WARN, "=x")); + tt_assert(!string_is_key_value(LOG_WARN, "=")); /* ??? */ - /* test_assert(!string_is_key_value(LOG_WARN, "===")); */ + /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */ done: ; } /** Test basic string functionality. */ static void -test_util_strmisc(void) +test_util_strmisc(void *arg) { char buf[1024]; int i; char *cp, *cp_tmp = NULL; /* Test strl operations */ - test_eq(5, strlcpy(buf, "Hello", 0)); - test_eq(5, strlcpy(buf, "Hello", 10)); - test_streq(buf, "Hello"); - test_eq(5, strlcpy(buf, "Hello", 6)); - test_streq(buf, "Hello"); - test_eq(5, strlcpy(buf, "Hello", 5)); - test_streq(buf, "Hell"); + (void)arg; + tt_int_op(5,==, strlcpy(buf, "Hello", 0)); + tt_int_op(5,==, strlcpy(buf, "Hello", 10)); + tt_str_op(buf,==, "Hello"); + tt_int_op(5,==, strlcpy(buf, "Hello", 6)); + tt_str_op(buf,==, "Hello"); + tt_int_op(5,==, strlcpy(buf, "Hello", 5)); + tt_str_op(buf,==, "Hell"); strlcpy(buf, "Hello", sizeof(buf)); - test_eq(10, strlcat(buf, "Hello", 5)); + tt_int_op(10,==, strlcat(buf, "Hello", 5)); /* Test strstrip() */ strlcpy(buf, "Testing 1 2 3", sizeof(buf)); tor_strstrip(buf, ",!"); - test_streq(buf, "Testing 1 2 3"); + tt_str_op(buf,==, "Testing 1 2 3"); strlcpy(buf, "!Testing 1 2 3?", sizeof(buf)); tor_strstrip(buf, "!? "); - test_streq(buf, "Testing123"); + tt_str_op(buf,==, "Testing123"); strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf)); tor_strstrip(buf, "!? "); - test_streq(buf, "Testing123"); + tt_str_op(buf,==, "Testing123"); /* Test parse_long */ /* Empty/zero input */ - test_eq(0L, tor_parse_long("",10,0,100,&i,NULL)); - test_eq(0, i); - test_eq(0L, tor_parse_long("0",10,0,100,&i,NULL)); - test_eq(1, i); + tt_int_op(0L,==, tor_parse_long("",10,0,100,&i,NULL)); + tt_int_op(0,==, i); + tt_int_op(0L,==, tor_parse_long("0",10,0,100,&i,NULL)); + tt_int_op(1,==, i); /* Normal cases */ - test_eq(10L, tor_parse_long("10",10,0,100,&i,NULL)); - test_eq(1, i); - test_eq(10L, tor_parse_long("10",10,0,10,&i,NULL)); - test_eq(1, i); - test_eq(10L, tor_parse_long("10",10,10,100,&i,NULL)); - test_eq(1, i); - test_eq(-50L, tor_parse_long("-50",10,-100,100,&i,NULL)); - test_eq(1, i); - test_eq(-50L, tor_parse_long("-50",10,-100,0,&i,NULL)); - test_eq(1, i); - test_eq(-50L, tor_parse_long("-50",10,-50,0,&i,NULL)); - test_eq(1, i); + tt_int_op(10L,==, tor_parse_long("10",10,0,100,&i,NULL)); + tt_int_op(1,==, i); + tt_int_op(10L,==, tor_parse_long("10",10,0,10,&i,NULL)); + tt_int_op(1,==, i); + tt_int_op(10L,==, tor_parse_long("10",10,10,100,&i,NULL)); + tt_int_op(1,==, i); + tt_int_op(-50L,==, tor_parse_long("-50",10,-100,100,&i,NULL)); + tt_int_op(1,==, i); + tt_int_op(-50L,==, tor_parse_long("-50",10,-100,0,&i,NULL)); + tt_int_op(1,==, i); + tt_int_op(-50L,==, tor_parse_long("-50",10,-50,0,&i,NULL)); + tt_int_op(1,==, i); /* Extra garbage */ - test_eq(0L, tor_parse_long("10m",10,0,100,&i,NULL)); - test_eq(0, i); - test_eq(0L, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL)); - test_eq(0, i); - test_eq(10L, tor_parse_long("10m",10,0,100,&i,&cp)); - test_eq(1, i); - test_streq(cp, "m"); - test_eq(-50L, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp)); - test_eq(1, i); - test_streq(cp, " plus garbage"); + tt_int_op(0L,==, tor_parse_long("10m",10,0,100,&i,NULL)); + tt_int_op(0,==, i); + tt_int_op(0L,==, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL)); + tt_int_op(0,==, i); + tt_int_op(10L,==, tor_parse_long("10m",10,0,100,&i,&cp)); + tt_int_op(1,==, i); + tt_str_op(cp,==, "m"); + tt_int_op(-50L,==, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp)); + tt_int_op(1,==, i); + tt_str_op(cp,==, " plus garbage"); /* Out of bounds */ - test_eq(0L, tor_parse_long("10",10,50,100,&i,NULL)); - test_eq(0, i); - test_eq(0L, tor_parse_long("-50",10,0,100,&i,NULL)); - test_eq(0, i); + tt_int_op(0L,==, tor_parse_long("10",10,50,100,&i,NULL)); + tt_int_op(0,==, i); + tt_int_op(0L,==, tor_parse_long("-50",10,0,100,&i,NULL)); + tt_int_op(0,==, i); /* Base different than 10 */ - test_eq(2L, tor_parse_long("10",2,0,100,NULL,NULL)); - test_eq(0L, tor_parse_long("2",2,0,100,NULL,NULL)); - test_eq(0L, tor_parse_long("10",-2,0,100,NULL,NULL)); - test_eq(68284L, tor_parse_long("10abc",16,0,70000,NULL,NULL)); - test_eq(68284L, tor_parse_long("10ABC",16,0,70000,NULL,NULL)); - test_eq(0, tor_parse_long("10ABC",-1,0,70000,&i,NULL)); - test_eq(i, 0); + tt_int_op(2L,==, tor_parse_long("10",2,0,100,NULL,NULL)); + tt_int_op(0L,==, tor_parse_long("2",2,0,100,NULL,NULL)); + tt_int_op(0L,==, tor_parse_long("10",-2,0,100,NULL,NULL)); + tt_int_op(68284L,==, tor_parse_long("10abc",16,0,70000,NULL,NULL)); + tt_int_op(68284L,==, tor_parse_long("10ABC",16,0,70000,NULL,NULL)); + tt_int_op(0,==, tor_parse_long("10ABC",-1,0,70000,&i,NULL)); + tt_int_op(i,==, 0); /* Test parse_ulong */ - test_eq(0UL, tor_parse_ulong("",10,0,100,NULL,NULL)); - test_eq(0UL, tor_parse_ulong("0",10,0,100,NULL,NULL)); - test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL)); - test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL)); - test_eq(10UL, tor_parse_ulong("10",10,0,10,NULL,NULL)); - test_eq(10UL, tor_parse_ulong("10",10,10,100,NULL,NULL)); - test_eq(0UL, tor_parse_ulong("8",8,0,100,NULL,NULL)); - test_eq(50UL, tor_parse_ulong("50",10,50,100,NULL,NULL)); - test_eq(0UL, tor_parse_ulong("-50",10,-100,100,NULL,NULL)); - test_eq(0UL, tor_parse_ulong("50",-1,50,100,&i,NULL)); - test_eq(0, i); + tt_int_op(0UL,==, tor_parse_ulong("",10,0,100,NULL,NULL)); + tt_int_op(0UL,==, tor_parse_ulong("0",10,0,100,NULL,NULL)); + tt_int_op(10UL,==, tor_parse_ulong("10",10,0,100,NULL,NULL)); + tt_int_op(0UL,==, tor_parse_ulong("10",10,50,100,NULL,NULL)); + tt_int_op(10UL,==, tor_parse_ulong("10",10,0,10,NULL,NULL)); + tt_int_op(10UL,==, tor_parse_ulong("10",10,10,100,NULL,NULL)); + tt_int_op(0UL,==, tor_parse_ulong("8",8,0,100,NULL,NULL)); + tt_int_op(50UL,==, tor_parse_ulong("50",10,50,100,NULL,NULL)); + tt_int_op(0UL,==, tor_parse_ulong("-50",10,-100,100,NULL,NULL)); + tt_int_op(0UL,==, tor_parse_ulong("50",-1,50,100,&i,NULL)); + tt_int_op(0,==, i); /* Test parse_uint64 */ - test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp)); - test_eq(1, i); - test_streq(cp, " x"); - test_assert(U64_LITERAL(12345678901) == + tt_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp)); + tt_int_op(1,==, i); + tt_str_op(cp,==, " x"); + tt_assert(U64_LITERAL(12345678901) == tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp)); - test_eq(1, i); - test_streq(cp, ""); - test_assert(U64_LITERAL(0) == + tt_int_op(1,==, i); + tt_str_op(cp,==, ""); + tt_assert(U64_LITERAL(0) == tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp)); - test_eq(0, i); - test_assert(U64_LITERAL(0) == + tt_int_op(0,==, i); + tt_assert(U64_LITERAL(0) == tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp)); - test_eq(0, i); + tt_int_op(0,==, i); { /* Test parse_double */ double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL); - test_eq(1, i); - test_assert(DBL_TO_U64(d) == 10); + tt_int_op(1,==, i); + tt_assert(DBL_TO_U64(d) == 10); d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL); - test_eq(1, i); - test_assert(DBL_TO_U64(d) == 0); + tt_int_op(1,==, i); + tt_assert(DBL_TO_U64(d) == 0); d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL); - test_eq(0, i); + tt_int_op(0,==, i); d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL); - test_eq(0, i); + tt_int_op(0,==, i); d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp); - test_eq(1, i); + tt_int_op(1,==, i); d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL); - test_eq(1, i); - test_assert(DBL_TO_U64(d) == 0); + tt_int_op(1,==, i); + tt_assert(DBL_TO_U64(d) == 0); d = tor_parse_double("-10", -100.0, 100.0,&i,NULL); - test_eq(1, i); - test_eq(-10.0, d); + tt_int_op(1,==, i); + tt_int_op(-10.0,==, d); } { /* Test tor_parse_* where we overflow/underflow the underlying type. */ /* This string should overflow 64-bit ints. */ #define TOOBIG "100000000000000000000000000" - test_eq(0L, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL)); - test_eq(i, 0); - test_eq(0L, tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL)); - test_eq(i, 0); - test_eq(0UL, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL)); - test_eq(i, 0); + tt_int_op(0L,==, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL)); + tt_int_op(i,==, 0); + tt_int_op(0L,==, + tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL)); + tt_int_op(i,==, 0); + tt_int_op(0UL,==, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL)); + tt_int_op(i,==, 0); tt_u64_op(U64_LITERAL(0), ==, tor_parse_uint64(TOOBIG, 10, 0, UINT64_MAX, &i, NULL)); - test_eq(i, 0); + tt_int_op(i,==, 0); } /* Test snprintf */ /* Returning -1 when there's not enough room in the output buffer */ - test_eq(-1, tor_snprintf(buf, 0, "Foo")); - test_eq(-1, tor_snprintf(buf, 2, "Foo")); - test_eq(-1, tor_snprintf(buf, 3, "Foo")); - test_neq(-1, tor_snprintf(buf, 4, "Foo")); + tt_int_op(-1,==, tor_snprintf(buf, 0, "Foo")); + tt_int_op(-1,==, tor_snprintf(buf, 2, "Foo")); + tt_int_op(-1,==, tor_snprintf(buf, 3, "Foo")); + tt_int_op(-1,!=, tor_snprintf(buf, 4, "Foo")); /* Always NUL-terminate the output */ tor_snprintf(buf, 5, "abcdef"); - test_eq(0, buf[4]); + tt_int_op(0,==, buf[4]); tor_snprintf(buf, 10, "abcdef"); - test_eq(0, buf[6]); + tt_int_op(0,==, buf[6]); /* uint64 */ tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x", U64_PRINTF_ARG(U64_LITERAL(12345678901))); - test_streq("x!12345678901!x", buf); + tt_str_op("x!12345678901!x",==, buf); /* Test str{,case}cmpstart */ - test_assert(strcmpstart("abcdef", "abcdef")==0); - test_assert(strcmpstart("abcdef", "abc")==0); - test_assert(strcmpstart("abcdef", "abd")<0); - test_assert(strcmpstart("abcdef", "abb")>0); - test_assert(strcmpstart("ab", "abb")<0); - test_assert(strcmpstart("ab", "")==0); - test_assert(strcmpstart("ab", "ab ")<0); - test_assert(strcasecmpstart("abcdef", "abCdEF")==0); - test_assert(strcasecmpstart("abcDeF", "abc")==0); - test_assert(strcasecmpstart("abcdef", "Abd")<0); - test_assert(strcasecmpstart("Abcdef", "abb")>0); - test_assert(strcasecmpstart("ab", "Abb")<0); - test_assert(strcasecmpstart("ab", "")==0); - test_assert(strcasecmpstart("ab", "ab ")<0); + tt_assert(strcmpstart("abcdef", "abcdef")==0); + tt_assert(strcmpstart("abcdef", "abc")==0); + tt_assert(strcmpstart("abcdef", "abd")<0); + tt_assert(strcmpstart("abcdef", "abb")>0); + tt_assert(strcmpstart("ab", "abb")<0); + tt_assert(strcmpstart("ab", "")==0); + tt_assert(strcmpstart("ab", "ab ")<0); + tt_assert(strcasecmpstart("abcdef", "abCdEF")==0); + tt_assert(strcasecmpstart("abcDeF", "abc")==0); + tt_assert(strcasecmpstart("abcdef", "Abd")<0); + tt_assert(strcasecmpstart("Abcdef", "abb")>0); + tt_assert(strcasecmpstart("ab", "Abb")<0); + tt_assert(strcasecmpstart("ab", "")==0); + tt_assert(strcasecmpstart("ab", "ab ")<0); /* Test str{,case}cmpend */ - test_assert(strcmpend("abcdef", "abcdef")==0); - test_assert(strcmpend("abcdef", "def")==0); - test_assert(strcmpend("abcdef", "deg")<0); - test_assert(strcmpend("abcdef", "dee")>0); - test_assert(strcmpend("ab", "aab")>0); - test_assert(strcasecmpend("AbcDEF", "abcdef")==0); - test_assert(strcasecmpend("abcdef", "dEF")==0); - test_assert(strcasecmpend("abcdef", "Deg")<0); - test_assert(strcasecmpend("abcDef", "dee")>0); - test_assert(strcasecmpend("AB", "abb")<0); + tt_assert(strcmpend("abcdef", "abcdef")==0); + tt_assert(strcmpend("abcdef", "def")==0); + tt_assert(strcmpend("abcdef", "deg")<0); + tt_assert(strcmpend("abcdef", "dee")>0); + tt_assert(strcmpend("ab", "aab")>0); + tt_assert(strcasecmpend("AbcDEF", "abcdef")==0); + tt_assert(strcasecmpend("abcdef", "dEF")==0); + tt_assert(strcasecmpend("abcdef", "Deg")<0); + tt_assert(strcasecmpend("abcDef", "dee")>0); + tt_assert(strcasecmpend("AB", "abb")<0); /* Test digest_is_zero */ memset(buf,0,20); buf[20] = 'x'; - test_assert(tor_digest_is_zero(buf)); + tt_assert(tor_digest_is_zero(buf)); buf[19] = 'x'; - test_assert(!tor_digest_is_zero(buf)); + tt_assert(!tor_digest_is_zero(buf)); /* Test mem_is_zero */ memset(buf,0,128); buf[128] = 'x'; - test_assert(tor_mem_is_zero(buf, 10)); - test_assert(tor_mem_is_zero(buf, 20)); - test_assert(tor_mem_is_zero(buf, 128)); - test_assert(!tor_mem_is_zero(buf, 129)); + tt_assert(tor_mem_is_zero(buf, 10)); + tt_assert(tor_mem_is_zero(buf, 20)); + tt_assert(tor_mem_is_zero(buf, 128)); + tt_assert(!tor_mem_is_zero(buf, 129)); buf[60] = (char)255; - test_assert(!tor_mem_is_zero(buf, 128)); + tt_assert(!tor_mem_is_zero(buf, 128)); buf[0] = (char)1; - test_assert(!tor_mem_is_zero(buf, 10)); + tt_assert(!tor_mem_is_zero(buf, 10)); /* Test 'escaped' */ - test_assert(NULL == escaped(NULL)); - test_streq("\"\"", escaped("")); - test_streq("\"abcd\"", escaped("abcd")); - test_streq("\"\\\\ \\n\\r\\t\\\"\\'\"", escaped("\\ \n\r\t\"'")); - test_streq("\"unnecessary \\'backslashes\\'\"", + tt_assert(NULL == escaped(NULL)); + tt_str_op("\"\"",==, escaped("")); + tt_str_op("\"abcd\"",==, escaped("abcd")); + tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",==, escaped("\\ \n\r\t\"'")); + tt_str_op("\"unnecessary \\'backslashes\\'\"",==, escaped("unnecessary \'backslashes\'")); /* Non-printable characters appear as octal */ - test_streq("\"z\\001abc\\277d\"", escaped("z\001abc\277d")); - test_streq("\"z\\336\\255 ;foo\"", escaped("z\xde\xad\x20;foo")); + tt_str_op("\"z\\001abc\\277d\"",==, escaped("z\001abc\277d")); + tt_str_op("\"z\\336\\255 ;foo\"",==, escaped("z\xde\xad\x20;foo")); /* Test strndup and memdup */ { const char *s = "abcdefghijklmnopqrstuvwxyz"; cp_tmp = tor_strndup(s, 30); - test_streq(cp_tmp, s); /* same string, */ - test_neq_ptr(cp_tmp, s); /* but different pointers. */ + tt_str_op(cp_tmp,==, s); /* same string, */ + tt_ptr_op(cp_tmp,!=,s); /* but different pointers. */ tor_free(cp_tmp); cp_tmp = tor_strndup(s, 5); - test_streq(cp_tmp, "abcde"); + tt_str_op(cp_tmp,==, "abcde"); tor_free(cp_tmp); s = "a\0b\0c\0d\0e\0"; cp_tmp = tor_memdup(s,10); - test_memeq(cp_tmp, s, 10); /* same ram, */ - test_neq_ptr(cp_tmp, s); /* but different pointers. */ + tt_mem_op(cp_tmp,==, s, 10); /* same ram, */ + tt_ptr_op(cp_tmp,!=,s); /* but different pointers. */ tor_free(cp_tmp); } /* Test str-foo functions */ cp_tmp = tor_strdup("abcdef"); - test_assert(tor_strisnonupper(cp_tmp)); + tt_assert(tor_strisnonupper(cp_tmp)); cp_tmp[3] = 'D'; - test_assert(!tor_strisnonupper(cp_tmp)); + tt_assert(!tor_strisnonupper(cp_tmp)); tor_strupper(cp_tmp); - test_streq(cp_tmp, "ABCDEF"); + tt_str_op(cp_tmp,==, "ABCDEF"); tor_strlower(cp_tmp); - test_streq(cp_tmp, "abcdef"); - test_assert(tor_strisnonupper(cp_tmp)); - test_assert(tor_strisprint(cp_tmp)); + tt_str_op(cp_tmp,==, "abcdef"); + tt_assert(tor_strisnonupper(cp_tmp)); + tt_assert(tor_strisprint(cp_tmp)); cp_tmp[3] = 3; - test_assert(!tor_strisprint(cp_tmp)); + tt_assert(!tor_strisprint(cp_tmp)); tor_free(cp_tmp); /* Test memmem and memstr */ { const char *haystack = "abcde"; - test_assert(!tor_memmem(haystack, 5, "ef", 2)); - test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2); - test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2); - test_assert(!tor_memmem(haystack, 4, "cde", 3)); + tt_assert(!tor_memmem(haystack, 5, "ef", 2)); + tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),==, haystack + 2); + tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),==, haystack + 2); + tt_assert(!tor_memmem(haystack, 4, "cde", 3)); haystack = "ababcad"; - test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2); - test_eq_ptr(tor_memmem(haystack, 7, "ad", 2), haystack + 5); - test_eq_ptr(tor_memmem(haystack, 7, "cad", 3), haystack + 4); - test_assert(!tor_memmem(haystack, 7, "dadad", 5)); - test_assert(!tor_memmem(haystack, 7, "abcdefghij", 10)); + tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),==, haystack + 2); + tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),==, haystack + 5); + tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),==, haystack + 4); + tt_assert(!tor_memmem(haystack, 7, "dadad", 5)); + tt_assert(!tor_memmem(haystack, 7, "abcdefghij", 10)); /* memstr */ - test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2); - test_eq_ptr(tor_memstr(haystack, 7, "cad"), haystack + 4); - test_assert(!tor_memstr(haystack, 6, "cad")); - test_assert(!tor_memstr(haystack, 7, "cadd")); - test_assert(!tor_memstr(haystack, 7, "fe")); - test_assert(!tor_memstr(haystack, 7, "ababcade")); + tt_ptr_op(tor_memstr(haystack, 7, "abc"),==, haystack + 2); + tt_ptr_op(tor_memstr(haystack, 7, "cad"),==, haystack + 4); + tt_assert(!tor_memstr(haystack, 6, "cad")); + tt_assert(!tor_memstr(haystack, 7, "cadd")); + tt_assert(!tor_memstr(haystack, 7, "fe")); + tt_assert(!tor_memstr(haystack, 7, "ababcade")); } /* Test hex_str */ @@ -1234,19 +1284,20 @@ test_util_strmisc(void) size_t i; for (i = 0; i < sizeof(binary_data); ++i) binary_data[i] = i; - test_streq(hex_str(binary_data, 0), ""); - test_streq(hex_str(binary_data, 1), "00"); - test_streq(hex_str(binary_data, 17), "000102030405060708090A0B0C0D0E0F10"); - test_streq(hex_str(binary_data, 32), + tt_str_op(hex_str(binary_data, 0),==, ""); + tt_str_op(hex_str(binary_data, 1),==, "00"); + tt_str_op(hex_str(binary_data, 17),==, + "000102030405060708090A0B0C0D0E0F10"); + tt_str_op(hex_str(binary_data, 32),==, "000102030405060708090A0B0C0D0E0F" "101112131415161718191A1B1C1D1E1F"); - test_streq(hex_str(binary_data, 34), + tt_str_op(hex_str(binary_data, 34),==, "000102030405060708090A0B0C0D0E0F" "101112131415161718191A1B1C1D1E1F"); /* Repeat these tests for shorter strings after longer strings have been tried, to make sure we're correctly terminating strings */ - test_streq(hex_str(binary_data, 1), "00"); - test_streq(hex_str(binary_data, 0), ""); + tt_str_op(hex_str(binary_data, 1),==, "00"); + tt_str_op(hex_str(binary_data, 0),==, ""); } /* Test strcmp_opt */ @@ -1275,20 +1326,21 @@ test_util_strmisc(void) } static void -test_util_pow2(void) +test_util_pow2(void *arg) { /* Test tor_log2(). */ - test_eq(tor_log2(64), 6); - test_eq(tor_log2(65), 6); - test_eq(tor_log2(63), 5); - test_eq(tor_log2(0), 0); /* incorrect mathematically, but as specified */ - test_eq(tor_log2(1), 0); - test_eq(tor_log2(2), 1); - test_eq(tor_log2(3), 1); - test_eq(tor_log2(4), 2); - test_eq(tor_log2(5), 2); - test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55); - test_eq(tor_log2(UINT64_MAX), 63); + (void)arg; + tt_int_op(tor_log2(64),==, 6); + tt_int_op(tor_log2(65),==, 6); + tt_int_op(tor_log2(63),==, 5); + tt_int_op(tor_log2(0),==, 0);/* incorrect mathematically, but as specified */ + tt_int_op(tor_log2(1),==, 0); + tt_int_op(tor_log2(2),==, 1); + tt_int_op(tor_log2(3),==, 1); + tt_int_op(tor_log2(4),==, 2); + tt_int_op(tor_log2(5),==, 2); + tt_int_op(tor_log2(U64_LITERAL(40000000000000000)),==, 55); + tt_int_op(tor_log2(UINT64_MAX),==, 63); /* Test round_to_power_of_2 */ tt_u64_op(round_to_power_of_2(120), ==, 128); @@ -1373,7 +1425,7 @@ thread_test_func_(void* _s) /** Run unit tests for threading logic. */ static void -test_util_threads(void) +test_util_threads(void *arg) { char *s1 = NULL, *s2 = NULL; int done = 0, timedout = 0; @@ -1383,12 +1435,7 @@ test_util_threads(void) tv.tv_sec=0; tv.tv_usec=100*1000; #endif -#ifndef TOR_IS_MULTITHREADED - /* Skip this test if we aren't threading. We should be threading most - * everywhere by now. */ - if (1) - return; -#endif + (void)arg; thread_test_mutex_ = tor_mutex_new(); thread_test_start1_ = tor_mutex_new(); thread_test_start2_ = tor_mutex_new(); @@ -1426,15 +1473,15 @@ test_util_threads(void) if (timedout) { printf("\nTimed out: %d %d", t1_count, t2_count); - test_assert(strmap_get(thread_test_strmap_, "thread 1")); - test_assert(strmap_get(thread_test_strmap_, "thread 2")); - test_assert(!timedout); + tt_assert(strmap_get(thread_test_strmap_, "thread 1")); + tt_assert(strmap_get(thread_test_strmap_, "thread 2")); + tt_assert(!timedout); } /* different thread IDs. */ - test_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"), + tt_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"), strmap_get(thread_test_strmap_, "thread 2"))); - test_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"), + tt_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"), strmap_get(thread_test_strmap_, "last to run")) || !strcmp(strmap_get(thread_test_strmap_, "thread 2"), strmap_get(thread_test_strmap_, "last to run"))); @@ -1454,51 +1501,52 @@ test_util_threads(void) /** Run unit tests for compression functions */ static void -test_util_gzip(void) +test_util_gzip(void *arg) { char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2; const char *ccp2; size_t len1, len2; tor_zlib_state_t *state = NULL; + (void)arg; buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ"); - test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD); + tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD); if (is_gzip_supported()) { - test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, + tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, GZIP_METHOD)); - test_assert(buf2); - test_assert(len1 < strlen(buf1)); - test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD); + tt_assert(buf2); + tt_assert(len1 < strlen(buf1)); + tt_assert(detect_compression_method(buf2, len1) == GZIP_METHOD); - test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, + tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, GZIP_METHOD, 1, LOG_INFO)); - test_assert(buf3); - test_eq(strlen(buf1) + 1, len2); - test_streq(buf1, buf3); + tt_assert(buf3); + tt_int_op(strlen(buf1) + 1,==, len2); + tt_str_op(buf1,==, buf3); tor_free(buf2); tor_free(buf3); } - test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, + tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, ZLIB_METHOD)); - test_assert(buf2); - test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD); + tt_assert(buf2); + tt_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD); - test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, + tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, ZLIB_METHOD, 1, LOG_INFO)); - test_assert(buf3); - test_eq(strlen(buf1) + 1, len2); - test_streq(buf1, buf3); + tt_assert(buf3); + tt_int_op(strlen(buf1) + 1,==, len2); + tt_str_op(buf1,==, buf3); /* Check whether we can uncompress concatenated, compressed strings. */ tor_free(buf3); - buf2 = tor_realloc(buf2, len1*2); + buf2 = tor_reallocarray(buf2, len1, 2); memcpy(buf2+len1, buf2, len1); - test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2, + tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2, ZLIB_METHOD, 1, LOG_INFO)); - test_eq((strlen(buf1)+1)*2, len2); - test_memeq(buf3, + tt_int_op((strlen(buf1)+1)*2,==, len2); + tt_mem_op(buf3,==, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0", (strlen(buf1)+1)*2); @@ -1510,7 +1558,7 @@ test_util_gzip(void) /* Check whether we can uncompress partial strings. */ buf1 = tor_strdup("String with low redundancy that won't be compressed much."); - test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, + tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, ZLIB_METHOD)); tt_assert(len1>16); /* when we allow an incomplete string, we should succeed.*/ @@ -1536,22 +1584,22 @@ test_util_gzip(void) len1 = 1024; ccp2 = "ABCDEFGHIJABCDEFGHIJ"; len2 = 21; - test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0) + tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0) == TOR_ZLIB_OK); - test_eq(0, len2); /* Make sure we compressed it all. */ - test_assert(cp1 > buf1); + tt_int_op(0,==, len2); /* Make sure we compressed it all. */ + tt_assert(cp1 > buf1); len2 = 0; cp2 = cp1; - test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1) + tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1) == TOR_ZLIB_DONE); - test_eq(0, len2); - test_assert(cp1 > cp2); /* Make sure we really added something. */ + tt_int_op(0,==, len2); + tt_assert(cp1 > cp2); /* Make sure we really added something. */ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1, ZLIB_METHOD, 1, LOG_WARN)); - test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/ - test_eq(21, len2); + tt_str_op(buf3,==,"ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/ + tt_int_op(21,==, len2); done: if (state) @@ -1563,7 +1611,7 @@ test_util_gzip(void) /** Run unit tests for mmap() wrapper functionality. */ static void -test_util_mmap(void) +test_util_mmap(void *arg) { char *fname1 = tor_strdup(get_fname("mapped_1")); char *fname2 = tor_strdup(get_fname("mapped_2")); @@ -1572,25 +1620,26 @@ test_util_mmap(void) char *buf = tor_malloc(17000); tor_mmap_t *mapping = NULL; + (void)arg; crypto_rand(buf, buflen); mapping = tor_mmap_file(fname1); - test_assert(! mapping); + tt_assert(! mapping); write_str_to_file(fname1, "Short file.", 1); mapping = tor_mmap_file(fname1); - test_assert(mapping); - test_eq(mapping->size, strlen("Short file.")); - test_streq(mapping->data, "Short file."); + tt_assert(mapping); + tt_int_op(mapping->size,==, strlen("Short file.")); + tt_str_op(mapping->data,==, "Short file."); #ifdef _WIN32 tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; - test_assert(unlink(fname1) == 0); + tt_assert(unlink(fname1) == 0); #else /* make sure we can unlink. */ - test_assert(unlink(fname1) == 0); - test_streq(mapping->data, "Short file."); + tt_assert(unlink(fname1) == 0); + tt_str_op(mapping->data,==, "Short file."); tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; #endif @@ -1598,29 +1647,29 @@ test_util_mmap(void) /* Now a zero-length file. */ write_str_to_file(fname1, "", 1); mapping = tor_mmap_file(fname1); - test_eq_ptr(mapping, NULL); - test_eq(ERANGE, errno); + tt_ptr_op(mapping,==, NULL); + tt_int_op(ERANGE,==, errno); unlink(fname1); /* Make sure that we fail to map a no-longer-existent file. */ mapping = tor_mmap_file(fname1); - test_assert(! mapping); + tt_assert(! mapping); /* Now try a big file that stretches across a few pages and isn't aligned */ write_bytes_to_file(fname2, buf, buflen, 1); mapping = tor_mmap_file(fname2); - test_assert(mapping); - test_eq(mapping->size, buflen); - test_memeq(mapping->data, buf, buflen); + tt_assert(mapping); + tt_int_op(mapping->size,==, buflen); + tt_mem_op(mapping->data,==, buf, buflen); tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; /* Now try a big aligned file. */ write_bytes_to_file(fname3, buf, 16384, 1); mapping = tor_mmap_file(fname3); - test_assert(mapping); - test_eq(mapping->size, 16384); - test_memeq(mapping->data, buf, 16384); + tt_assert(mapping); + tt_int_op(mapping->size,==, 16384); + tt_mem_op(mapping->data,==, buf, 16384); tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; @@ -1639,17 +1688,18 @@ test_util_mmap(void) /** Run unit tests for escaping/unescaping data for use by controllers. */ static void -test_util_control_formats(void) +test_util_control_formats(void *arg) { char *out = NULL; const char *inp = "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n"; size_t sz; + (void)arg; sz = read_escaped_data(inp, strlen(inp), &out); - test_streq(out, + tt_str_op(out,==, ".This is a test\nof the emergency \n.system.\n\rZ.\n"); - test_eq(sz, strlen(out)); + tt_int_op(sz,==, strlen(out)); done: tor_free(out); @@ -1669,9 +1719,10 @@ test_util_control_formats(void) } while (0) static void -test_util_sscanf(void) +test_util_sscanf(void *arg) { unsigned u1, u2, u3; + unsigned long ulng; char s1[20], s2[10], s3[10], ch; int r; long lng1,lng2; @@ -1679,186 +1730,335 @@ test_util_sscanf(void) double d1,d2,d3,d4; /* Simple tests (malformed patterns, literal matching, ...) */ - test_eq(-1, tor_sscanf("123", "%i", &r)); /* %i is not supported */ - test_eq(-1, tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */ - test_eq(-1, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */ - test_eq(-1, tor_sscanf("prettylongstring", "%999999s", s1)); + (void)arg; + tt_int_op(-1,==, tor_sscanf("123", "%i", &r)); /* %i is not supported */ + tt_int_op(-1,==, + tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */ + tt_int_op(-1,==, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */ + tt_int_op(-1,==, tor_sscanf("prettylongstring", "%999999s", s1)); #if 0 /* GCC thinks these two are illegal. */ test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1)); test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL)); #endif /* No '%'-strings: always "success" */ - test_eq(0, tor_sscanf("hello world", "hello world")); - test_eq(0, tor_sscanf("hello world", "good bye")); + tt_int_op(0,==, tor_sscanf("hello world", "hello world")); + tt_int_op(0,==, tor_sscanf("hello world", "good bye")); /* Excess data */ - test_eq(0, tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */ - test_eq(0, tor_sscanf(" 3 hello", "%u", &u1)); - test_eq(0, tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */ - test_eq(1, tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */ + tt_int_op(0,==, + tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */ + tt_int_op(0,==, tor_sscanf(" 3 hello", "%u", &u1)); + tt_int_op(0,==, + tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */ + tt_int_op(1,==, + tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */ /* Numbers (ie. %u) */ - test_eq(0, tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */ - test_eq(1, tor_sscanf("12345", "%u", &u1)); - test_eq(12345u, u1); - test_eq(1, tor_sscanf("12346 ", "%u", &u1)); - test_eq(12346u, u1); - test_eq(0, tor_sscanf(" 12347", "%u", &u1)); - test_eq(1, tor_sscanf(" 12348", " %u", &u1)); - test_eq(12348u, u1); - test_eq(1, tor_sscanf("0", "%u", &u1)); - test_eq(0u, u1); - test_eq(1, tor_sscanf("0000", "%u", &u2)); - test_eq(0u, u2); - test_eq(0, tor_sscanf("", "%u", &u1)); /* absent number */ - test_eq(0, tor_sscanf("A", "%u", &u1)); /* bogus number */ - test_eq(0, tor_sscanf("-1", "%u", &u1)); /* negative number */ - test_eq(1, tor_sscanf("4294967295", "%u", &u1)); /* UINT32_MAX should work */ - test_eq(4294967295u, u1); - test_eq(0, tor_sscanf("4294967296", "%u", &u1)); /* But not at 32 bits */ - test_eq(1, tor_sscanf("4294967296", "%9u", &u1)); /* but parsing only 9... */ - test_eq(429496729u, u1); + tt_int_op(0,==, + tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */ + tt_int_op(1,==, tor_sscanf("12345", "%u", &u1)); + tt_int_op(12345u,==, u1); + tt_int_op(1,==, tor_sscanf("12346 ", "%u", &u1)); + tt_int_op(12346u,==, u1); + tt_int_op(0,==, tor_sscanf(" 12347", "%u", &u1)); + tt_int_op(1,==, tor_sscanf(" 12348", " %u", &u1)); + tt_int_op(12348u,==, u1); + tt_int_op(1,==, tor_sscanf("0", "%u", &u1)); + tt_int_op(0u,==, u1); + tt_int_op(1,==, tor_sscanf("0000", "%u", &u2)); + tt_int_op(0u,==, u2); + tt_int_op(0,==, tor_sscanf("", "%u", &u1)); /* absent number */ + tt_int_op(0,==, tor_sscanf("A", "%u", &u1)); /* bogus number */ + tt_int_op(0,==, tor_sscanf("-1", "%u", &u1)); /* negative number */ /* Numbers with size (eg. %2u) */ - test_eq(0, tor_sscanf("-1", "%2u", &u1)); - test_eq(2, tor_sscanf("123456", "%2u%u", &u1, &u2)); - test_eq(12u, u1); - test_eq(3456u, u2); - test_eq(1, tor_sscanf("123456", "%8u", &u1)); - test_eq(123456u, u1); - test_eq(1, tor_sscanf("123457 ", "%8u", &u1)); - test_eq(123457u, u1); - test_eq(0, tor_sscanf(" 123456", "%8u", &u1)); - test_eq(3, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3)); - test_eq(12u, u1); - test_eq(3u, u2); - test_eq(456u, u3); - test_eq(3, tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */ - test_eq(67u, u1); - test_eq(8u, u2); - test_eq(99u, u3); + tt_int_op(0,==, tor_sscanf("-1", "%2u", &u1)); + tt_int_op(2,==, tor_sscanf("123456", "%2u%u", &u1, &u2)); + tt_int_op(12u,==, u1); + tt_int_op(3456u,==, u2); + tt_int_op(1,==, tor_sscanf("123456", "%8u", &u1)); + tt_int_op(123456u,==, u1); + tt_int_op(1,==, tor_sscanf("123457 ", "%8u", &u1)); + tt_int_op(123457u,==, u1); + tt_int_op(0,==, tor_sscanf(" 123456", "%8u", &u1)); + tt_int_op(3,==, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3)); + tt_int_op(12u,==, u1); + tt_int_op(3u,==, u2); + tt_int_op(456u,==, u3); + tt_int_op(3,==, + tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */ + tt_int_op(67u,==, u1); + tt_int_op(8u,==, u2); + tt_int_op(99u,==, u3); /* %u does not match space.*/ - test_eq(2, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3)); - test_eq(12u, u1); - test_eq(3u, u2); + tt_int_op(2,==, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3)); + tt_int_op(12u,==, u1); + tt_int_op(3u,==, u2); /* %u does not match negative numbers. */ - test_eq(2, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3)); - test_eq(67u, u1); - test_eq(8u, u2); + tt_int_op(2,==, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3)); + tt_int_op(67u,==, u1); + tt_int_op(8u,==, u2); /* Arbitrary amounts of 0-padding are okay */ - test_eq(3, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u", + tt_int_op(3,==, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u", &u1, &u2, &u3)); - test_eq(12u, u1); - test_eq(3u, u2); - test_eq(99u, u3); + tt_int_op(12u,==, u1); + tt_int_op(3u,==, u2); + tt_int_op(99u,==, u3); /* Hex (ie. %x) */ - test_eq(3, tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3)); - test_eq(0x1234, u1); - test_eq(0x2ABCDEF, u2); - test_eq(0xFF, u3); + tt_int_op(3,==, tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3)); + tt_int_op(0x1234,==, u1); + tt_int_op(0x2ABCDEF,==, u2); + tt_int_op(0xFF,==, u3); /* Width works on %x */ - test_eq(3, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3)); - test_eq(0xf00d, u1); - test_eq(0xcafe, u2); - test_eq(444, u3); + tt_int_op(3,==, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3)); + tt_int_op(0xf00d,==, u1); + tt_int_op(0xcafe,==, u2); + tt_int_op(444,==, u3); /* Literal '%' (ie. '%%') */ - test_eq(1, tor_sscanf("99% fresh", "%3u%% fresh", &u1)); - test_eq(99, u1); - test_eq(0, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1)); - test_eq(1, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1)); - test_eq(2, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1)); - test_eq(99, u1); - test_streq(s1, "fresh"); - test_eq(1, tor_sscanf("% boo", "%% %3s", s1)); - test_streq("boo", s1); + tt_int_op(1,==, tor_sscanf("99% fresh", "%3u%% fresh", &u1)); + tt_int_op(99,==, u1); + tt_int_op(0,==, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1)); + tt_int_op(1,==, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1)); + tt_int_op(2,==, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1)); + tt_int_op(99,==, u1); + tt_str_op(s1,==, "fresh"); + tt_int_op(1,==, tor_sscanf("% boo", "%% %3s", s1)); + tt_str_op("boo",==, s1); /* Strings (ie. %s) */ - test_eq(2, tor_sscanf("hello", "%3s%7s", s1, s2)); - test_streq(s1, "hel"); - test_streq(s2, "lo"); - test_eq(2, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */ - test_streq(s3, "WD"); - test_eq(40, u1); - test_eq(2, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */ - test_streq(s3, "WD4"); - test_eq(0, u1); - test_eq(2, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */ - test_eq(76, u1); - test_streq(s1, "trombones"); - test_eq(1, tor_sscanf("prettylongstring", "%999s", s1)); - test_streq(s1, "prettylongstring"); + tt_int_op(2,==, tor_sscanf("hello", "%3s%7s", s1, s2)); + tt_str_op(s1,==, "hel"); + tt_str_op(s2,==, "lo"); + tt_int_op(2,==, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */ + tt_str_op(s3,==, "WD"); + tt_int_op(40,==, u1); + tt_int_op(2,==, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */ + tt_str_op(s3,==, "WD4"); + tt_int_op(0,==, u1); + tt_int_op(2,==, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */ + tt_int_op(76,==, u1); + tt_str_op(s1,==, "trombones"); + tt_int_op(1,==, tor_sscanf("prettylongstring", "%999s", s1)); + tt_str_op(s1,==, "prettylongstring"); /* %s doesn't eat spaces */ - test_eq(2, tor_sscanf("hello world", "%9s %9s", s1, s2)); - test_streq(s1, "hello"); - test_streq(s2, "world"); - test_eq(2, tor_sscanf("bye world?", "%9s %9s", s1, s2)); - test_streq(s1, "bye"); - test_streq(s2, ""); - test_eq(3, tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */ - test_streq(s1, "hi"); - test_streq(s2, ""); - test_streq(s3, ""); - - test_eq(3, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch)); - test_eq(4, tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch)); - test_eq(' ', ch); + tt_int_op(2,==, tor_sscanf("hello world", "%9s %9s", s1, s2)); + tt_str_op(s1,==, "hello"); + tt_str_op(s2,==, "world"); + tt_int_op(2,==, tor_sscanf("bye world?", "%9s %9s", s1, s2)); + tt_str_op(s1,==, "bye"); + tt_str_op(s2,==, ""); + tt_int_op(3,==, + tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */ + tt_str_op(s1,==, "hi"); + tt_str_op(s2,==, ""); + tt_str_op(s3,==, ""); + + tt_int_op(3,==, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch)); + tt_int_op(4,==, + tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch)); + tt_int_op(' ',==, ch); r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2); - test_eq(r,3); - test_eq(int1, 12345); - test_eq(lng1, -67890); - test_eq(int2, -1); + tt_int_op(r,==, 3); + tt_int_op(int1,==, 12345); + tt_int_op(lng1,==, -67890); + tt_int_op(int2,==, -1); #if SIZEOF_INT == 4 + /* %u */ + /* UINT32_MAX should work */ + tt_int_op(1,==, tor_sscanf("4294967295", "%u", &u1)); + tt_int_op(4294967295U,==, u1); + + /* But UINT32_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("4294967296", "%u", &u1)); + /* but parsing only 9... */ + tt_int_op(1,==, tor_sscanf("4294967296", "%9u", &u1)); + tt_int_op(429496729U,==, u1); + + /* %x */ + /* UINT32_MAX should work */ + tt_int_op(1,==, tor_sscanf("FFFFFFFF", "%x", &u1)); + tt_int_op(0xFFFFFFFF,==, u1); + + /* But UINT32_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("100000000", "%x", &u1)); + + /* %d */ + /* INT32_MIN and INT32_MAX should work */ r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2); - test_eq(r,2); - test_eq(int1, -2147483647-1); - test_eq(int2, 2147483647); + tt_int_op(r,==, 2); + tt_int_op(int1,==, -2147483647 - 1); + tt_int_op(int2,==, 2147483647); + + /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */ + r = tor_sscanf("-2147483649.", "%d.", &int1); + tt_int_op(r,==, 0); - r = tor_sscanf("-2147483679.", "%d.", &int1); - test_eq(r,0); + r = tor_sscanf("2147483648.", "%d.", &int1); + tt_int_op(r,==, 0); + + /* and the first failure stops further processing */ + r = tor_sscanf("-2147483648. 2147483648.", + "%d. %d.", &int1, &int2); + tt_int_op(r,==, 1); - r = tor_sscanf("2147483678.", "%d.", &int1); - test_eq(r,0); + r = tor_sscanf("-2147483649. 2147483647.", + "%d. %d.", &int1, &int2); + tt_int_op(r,==, 0); + + r = tor_sscanf("2147483648. -2147483649.", + "%d. %d.", &int1, &int2); + tt_int_op(r,==, 0); #elif SIZEOF_INT == 8 + /* %u */ + /* UINT64_MAX should work */ + tt_int_op(1,==, tor_sscanf("18446744073709551615", "%u", &u1)); + tt_int_op(18446744073709551615U,==, u1); + + /* But UINT64_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("18446744073709551616", "%u", &u1)); + /* but parsing only 19... */ + tt_int_op(1,==, tor_sscanf("18446744073709551616", "%19u", &u1)); + tt_int_op(1844674407370955161U,==, u1); + + /* %x */ + /* UINT64_MAX should work */ + tt_int_op(1,==, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1)); + tt_int_op(0xFFFFFFFFFFFFFFFF,==, u1); + + /* But UINT64_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("10000000000000000", "%x", &u1)); + + /* %d */ + /* INT64_MIN and INT64_MAX should work */ r = tor_sscanf("-9223372036854775808. 9223372036854775807.", "%d. %d.", &int1, &int2); - test_eq(r,2); - test_eq(int1, -9223372036854775807-1); - test_eq(int2, 9223372036854775807); + tt_int_op(r,==, 2); + tt_int_op(int1,==, -9223372036854775807 - 1); + tt_int_op(int2,==, 9223372036854775807); + /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */ r = tor_sscanf("-9223372036854775809.", "%d.", &int1); - test_eq(r,0); + tt_int_op(r,==, 0); r = tor_sscanf("9223372036854775808.", "%d.", &int1); - test_eq(r,0); + tt_int_op(r,==, 0); + + /* and the first failure stops further processing */ + r = tor_sscanf("-9223372036854775808. 9223372036854775808.", + "%d. %d.", &int1, &int2); + tt_int_op(r,==, 1); + + r = tor_sscanf("-9223372036854775809. 9223372036854775807.", + "%d. %d.", &int1, &int2); + tt_int_op(r,==, 0); + + r = tor_sscanf("9223372036854775808. -9223372036854775809.", + "%d. %d.", &int1, &int2); + tt_int_op(r,==, 0); #endif #if SIZEOF_LONG == 4 + /* %lu */ + /* UINT32_MAX should work */ + tt_int_op(1,==, tor_sscanf("4294967295", "%lu", &ulng)); + tt_int_op(4294967295UL,==, ulng); + + /* But UINT32_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("4294967296", "%lu", &ulng)); + /* but parsing only 9... */ + tt_int_op(1,==, tor_sscanf("4294967296", "%9lu", &ulng)); + tt_int_op(429496729UL,==, ulng); + + /* %lx */ + /* UINT32_MAX should work */ + tt_int_op(1,==, tor_sscanf("FFFFFFFF", "%lx", &ulng)); + tt_int_op(0xFFFFFFFFUL,==, ulng); + + /* But UINT32_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("100000000", "%lx", &ulng)); + + /* %ld */ + /* INT32_MIN and INT32_MAX should work */ r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2); - test_eq(r,2); - test_eq(lng1, -2147483647 - 1); - test_eq(lng2, 2147483647); + tt_int_op(r,==, 2); + tt_int_op(lng1,==, -2147483647L - 1L); + tt_int_op(lng2,==, 2147483647L); + + /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */ + r = tor_sscanf("-2147483649.", "%ld.", &lng1); + tt_int_op(r,==, 0); + + r = tor_sscanf("2147483648.", "%ld.", &lng1); + tt_int_op(r,==, 0); + + /* and the first failure stops further processing */ + r = tor_sscanf("-2147483648. 2147483648.", + "%ld. %ld.", &lng1, &lng2); + tt_int_op(r,==, 1); + + r = tor_sscanf("-2147483649. 2147483647.", + "%ld. %ld.", &lng1, &lng2); + tt_int_op(r,==, 0); + + r = tor_sscanf("2147483648. -2147483649.", + "%ld. %ld.", &lng1, &lng2); + tt_int_op(r,==, 0); #elif SIZEOF_LONG == 8 + /* %lu */ + /* UINT64_MAX should work */ + tt_int_op(1,==, tor_sscanf("18446744073709551615", "%lu", &ulng)); + tt_int_op(18446744073709551615UL,==, ulng); + + /* But UINT64_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("18446744073709551616", "%lu", &ulng)); + /* but parsing only 19... */ + tt_int_op(1,==, tor_sscanf("18446744073709551616", "%19lu", &ulng)); + tt_int_op(1844674407370955161UL,==, ulng); + + /* %lx */ + /* UINT64_MAX should work */ + tt_int_op(1,==, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng)); + tt_int_op(0xFFFFFFFFFFFFFFFFUL,==, ulng); + + /* But UINT64_MAX + 1 shouldn't work */ + tt_int_op(0,==, tor_sscanf("10000000000000000", "%lx", &ulng)); + + /* %ld */ + /* INT64_MIN and INT64_MAX should work */ r = tor_sscanf("-9223372036854775808. 9223372036854775807.", "%ld. %ld.", &lng1, &lng2); - test_eq(r,2); - test_eq(lng1, -9223372036854775807L - 1); - test_eq(lng2, 9223372036854775807L); + tt_int_op(r,==, 2); + tt_int_op(lng1,==, -9223372036854775807L - 1L); + tt_int_op(lng2,==, 9223372036854775807L); + + /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */ + r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1); + tt_int_op(r,==, 0); + + r = tor_sscanf("9223372036854775808.", "%ld.", &lng1); + tt_int_op(r,==, 0); + /* and the first failure stops further processing */ r = tor_sscanf("-9223372036854775808. 9223372036854775808.", "%ld. %ld.", &lng1, &lng2); - test_eq(r,1); - r = tor_sscanf("-9223372036854775809. 9223372036854775808.", + tt_int_op(r,==, 1); + + r = tor_sscanf("-9223372036854775809. 9223372036854775807.", + "%ld. %ld.", &lng1, &lng2); + tt_int_op(r,==, 0); + + r = tor_sscanf("9223372036854775808. -9223372036854775809.", "%ld. %ld.", &lng1, &lng2); - test_eq(r,0); + tt_int_op(r,==, 0); #endif r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2", "%lf %lf %lf %lf", &d1,&d2,&d3,&d4); - test_eq(r,4); + tt_int_op(r,==, 4); test_feq(d1, 123.456); test_feq(d2, .000007); test_feq(d3, -900123123.2000787); @@ -1869,33 +2069,34 @@ test_util_sscanf(void) } static void -test_util_path_is_relative(void) +test_util_path_is_relative(void *arg) { /* OS-independent tests */ - test_eq(1, path_is_relative("")); - test_eq(1, path_is_relative("dir")); - test_eq(1, path_is_relative("dir/")); - test_eq(1, path_is_relative("./dir")); - test_eq(1, path_is_relative("../dir")); + (void)arg; + tt_int_op(1,==, path_is_relative("")); + tt_int_op(1,==, path_is_relative("dir")); + tt_int_op(1,==, path_is_relative("dir/")); + tt_int_op(1,==, path_is_relative("./dir")); + tt_int_op(1,==, path_is_relative("../dir")); - test_eq(0, path_is_relative("/")); - test_eq(0, path_is_relative("/dir")); - test_eq(0, path_is_relative("/dir/")); + tt_int_op(0,==, path_is_relative("/")); + tt_int_op(0,==, path_is_relative("/dir")); + tt_int_op(0,==, path_is_relative("/dir/")); /* Windows */ #ifdef _WIN32 /* I don't have Windows so I can't test this, hence the "#ifdef 0". These are tests that look useful, so please try to get them running and uncomment if it all works as it should */ - test_eq(1, path_is_relative("dir")); - test_eq(1, path_is_relative("dir\\")); - test_eq(1, path_is_relative("dir\\a:")); - test_eq(1, path_is_relative("dir\\a:\\")); - test_eq(1, path_is_relative("http:\\dir")); - - test_eq(0, path_is_relative("\\dir")); - test_eq(0, path_is_relative("a:\\dir")); - test_eq(0, path_is_relative("z:\\dir")); + tt_int_op(1,==, path_is_relative("dir")); + tt_int_op(1,==, path_is_relative("dir\\")); + tt_int_op(1,==, path_is_relative("dir\\a:")); + tt_int_op(1,==, path_is_relative("dir\\a:\\")); + tt_int_op(1,==, path_is_relative("http:\\dir")); + + tt_int_op(0,==, path_is_relative("\\dir")); + tt_int_op(0,==, path_is_relative("a:\\dir")); + tt_int_op(0,==, path_is_relative("z:\\dir")); #endif done: @@ -1906,25 +2107,26 @@ test_util_path_is_relative(void) /** Run unittests for memory pool allocator */ static void -test_util_mempool(void) +test_util_mempool(void *arg) { mp_pool_t *pool = NULL; smartlist_t *allocated = NULL; int i; + (void)arg; pool = mp_pool_new(1, 100); - test_assert(pool); - test_assert(pool->new_chunk_capacity >= 100); - test_assert(pool->item_alloc_size >= sizeof(void*)+1); + tt_assert(pool); + tt_assert(pool->new_chunk_capacity >= 100); + tt_assert(pool->item_alloc_size >= sizeof(void*)+1); mp_pool_destroy(pool); pool = NULL; pool = mp_pool_new(241, 2500); - test_assert(pool); - test_assert(pool->new_chunk_capacity >= 10); - test_assert(pool->item_alloc_size >= sizeof(void*)+241); - test_eq(pool->item_alloc_size & 0x03, 0); - test_assert(pool->new_chunk_capacity < 60); + tt_assert(pool); + tt_assert(pool->new_chunk_capacity >= 10); + tt_assert(pool->item_alloc_size >= sizeof(void*)+241); + tt_int_op(pool->item_alloc_size & 0x03,==, 0); + tt_assert(pool->new_chunk_capacity < 60); allocated = smartlist_new(); for (i = 0; i < 20000; ++i) { @@ -1966,39 +2168,40 @@ test_util_mempool(void) /** Run unittests for memory area allocator */ static void -test_util_memarea(void) +test_util_memarea(void *arg) { memarea_t *area = memarea_new(); char *p1, *p2, *p3, *p1_orig; void *malloced_ptr = NULL; int i; - test_assert(area); + (void)arg; + tt_assert(area); p1_orig = p1 = memarea_alloc(area,64); p2 = memarea_alloc_zero(area,52); p3 = memarea_alloc(area,11); - test_assert(memarea_owns_ptr(area, p1)); - test_assert(memarea_owns_ptr(area, p2)); - test_assert(memarea_owns_ptr(area, p3)); + tt_assert(memarea_owns_ptr(area, p1)); + tt_assert(memarea_owns_ptr(area, p2)); + tt_assert(memarea_owns_ptr(area, p3)); /* Make sure we left enough space. */ - test_assert(p1+64 <= p2); - test_assert(p2+52 <= p3); + tt_assert(p1+64 <= p2); + tt_assert(p2+52 <= p3); /* Make sure we aligned. */ - test_eq(((uintptr_t)p1) % sizeof(void*), 0); - test_eq(((uintptr_t)p2) % sizeof(void*), 0); - test_eq(((uintptr_t)p3) % sizeof(void*), 0); - test_assert(!memarea_owns_ptr(area, p3+8192)); - test_assert(!memarea_owns_ptr(area, p3+30)); - test_assert(tor_mem_is_zero(p2, 52)); + tt_int_op(((uintptr_t)p1) % sizeof(void*),==, 0); + tt_int_op(((uintptr_t)p2) % sizeof(void*),==, 0); + tt_int_op(((uintptr_t)p3) % sizeof(void*),==, 0); + tt_assert(!memarea_owns_ptr(area, p3+8192)); + tt_assert(!memarea_owns_ptr(area, p3+30)); + tt_assert(tor_mem_is_zero(p2, 52)); /* Make sure we don't overalign. */ p1 = memarea_alloc(area, 1); p2 = memarea_alloc(area, 1); - test_eq_ptr(p1+sizeof(void*), p2); + tt_ptr_op(p1+sizeof(void*),==, p2); { malloced_ptr = tor_malloc(64); - test_assert(!memarea_owns_ptr(area, malloced_ptr)); + tt_assert(!memarea_owns_ptr(area, malloced_ptr)); tor_free(malloced_ptr); } @@ -2007,18 +2210,18 @@ test_util_memarea(void) malloced_ptr = tor_malloc(64); crypto_rand((char*)malloced_ptr, 64); p1 = memarea_memdup(area, malloced_ptr, 64); - test_assert(p1 != malloced_ptr); - test_memeq(p1, malloced_ptr, 64); + tt_assert(p1 != malloced_ptr); + tt_mem_op(p1,==, malloced_ptr, 64); tor_free(malloced_ptr); } /* memarea_strdup. */ p1 = memarea_strdup(area,""); p2 = memarea_strdup(area, "abcd"); - test_assert(p1); - test_assert(p2); - test_streq(p1, ""); - test_streq(p2, "abcd"); + tt_assert(p1); + tt_assert(p2); + tt_str_op(p1,==, ""); + tt_str_op(p2,==, "abcd"); /* memarea_strndup. */ { @@ -2027,33 +2230,33 @@ test_util_memarea(void) size_t len = strlen(s); p1 = memarea_strndup(area, s, 1000); p2 = memarea_strndup(area, s, 10); - test_streq(p1, s); - test_assert(p2 >= p1 + len + 1); - test_memeq(s, p2, 10); - test_eq(p2[10], '\0'); + tt_str_op(p1,==, s); + tt_assert(p2 >= p1 + len + 1); + tt_mem_op(s,==, p2, 10); + tt_int_op(p2[10],==, '\0'); p3 = memarea_strndup(area, s, len); - test_streq(p3, s); + tt_str_op(p3,==, s); p3 = memarea_strndup(area, s, len-1); - test_memeq(s, p3, len-1); - test_eq(p3[len-1], '\0'); + tt_mem_op(s,==, p3, len-1); + tt_int_op(p3[len-1],==, '\0'); } memarea_clear(area); p1 = memarea_alloc(area, 1); - test_eq_ptr(p1, p1_orig); + tt_ptr_op(p1,==, p1_orig); memarea_clear(area); /* Check for running over an area's size. */ for (i = 0; i < 512; ++i) { p1 = memarea_alloc(area, crypto_rand_int(5)+1); - test_assert(memarea_owns_ptr(area, p1)); + tt_assert(memarea_owns_ptr(area, p1)); } memarea_assert_ok(area); /* Make sure we can allocate a too-big object. */ p1 = memarea_alloc_zero(area, 9000); p2 = memarea_alloc_zero(area, 16); - test_assert(memarea_owns_ptr(area, p1)); - test_assert(memarea_owns_ptr(area, p2)); + tt_assert(memarea_owns_ptr(area, p1)); + tt_assert(memarea_owns_ptr(area, p2)); done: memarea_drop_all(area); @@ -2063,31 +2266,32 @@ test_util_memarea(void) /** Run unit tests for utility functions to get file names relative to * the data directory. */ static void -test_util_datadir(void) +test_util_datadir(void *arg) { char buf[1024]; char *f = NULL; char *temp_dir = NULL; + (void)arg; temp_dir = get_datadir_fname(NULL); f = get_datadir_fname("state"); tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir); - test_streq(f, buf); + tt_str_op(f,==, buf); tor_free(f); f = get_datadir_fname2("cache", "thingy"); tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir); - test_streq(f, buf); + tt_str_op(f,==, buf); tor_free(f); f = get_datadir_fname2_suffix("cache", "thingy", ".foo"); tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir); - test_streq(f, buf); + tt_str_op(f,==, buf); tor_free(f); f = get_datadir_fname_suffix("cache", ".foo"); tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo", temp_dir); - test_streq(f, buf); + tt_str_op(f,==, buf); done: tor_free(f); @@ -2095,13 +2299,14 @@ test_util_datadir(void) } static void -test_util_strtok(void) +test_util_strtok(void *arg) { char buf[128]; char buf2[128]; int i; char *cp1, *cp2; + (void)arg; for (i = 0; i < 3; i++) { const char *pad1="", *pad2=""; switch (i) { @@ -2118,8 +2323,8 @@ test_util_strtok(void) } tor_snprintf(buf, sizeof(buf), "%s", pad1); tor_snprintf(buf2, sizeof(buf2), "%s", pad2); - test_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1)); - test_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2)); + tt_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1)); + tt_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2)); tor_snprintf(buf, sizeof(buf), "%sGraved on the dark in gestures of descent%s", pad1, pad1); @@ -2127,43 +2332,43 @@ test_util_strtok(void) "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2); /* -- "Year's End", Richard Wilbur */ - test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1)); - test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2)); + tt_str_op("Graved",==, tor_strtok_r_impl(buf, " ", &cp1)); + tt_str_op("they",==, tor_strtok_r_impl(buf2, ".!..;!", &cp2)); #define S1() tor_strtok_r_impl(NULL, " ", &cp1) #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2) - test_streq("on", S1()); - test_streq("the", S1()); - test_streq("dark", S1()); - test_streq("seemed", S2()); - test_streq("their", S2()); - test_streq("own", S2()); - test_streq("in", S1()); - test_streq("gestures", S1()); - test_streq("of", S1()); - test_streq("most", S2()); - test_streq("perfect", S2()); - test_streq("descent", S1()); - test_streq("monument", S2()); - test_eq_ptr(NULL, S1()); - test_eq_ptr(NULL, S2()); + tt_str_op("on",==, S1()); + tt_str_op("the",==, S1()); + tt_str_op("dark",==, S1()); + tt_str_op("seemed",==, S2()); + tt_str_op("their",==, S2()); + tt_str_op("own",==, S2()); + tt_str_op("in",==, S1()); + tt_str_op("gestures",==, S1()); + tt_str_op("of",==, S1()); + tt_str_op("most",==, S2()); + tt_str_op("perfect",==, S2()); + tt_str_op("descent",==, S1()); + tt_str_op("monument",==, S2()); + tt_ptr_op(NULL,==, S1()); + tt_ptr_op(NULL,==, S2()); } buf[0] = 0; - test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1)); - test_eq_ptr(NULL, tor_strtok_r_impl(buf, "!", &cp1)); + tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, " ", &cp1)); + tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, "!", &cp1)); strlcpy(buf, "Howdy!", sizeof(buf)); - test_streq("Howdy", tor_strtok_r_impl(buf, "!", &cp1)); - test_eq_ptr(NULL, tor_strtok_r_impl(NULL, "!", &cp1)); + tt_str_op("Howdy",==, tor_strtok_r_impl(buf, "!", &cp1)); + tt_ptr_op(NULL,==, tor_strtok_r_impl(NULL, "!", &cp1)); strlcpy(buf, " ", sizeof(buf)); - test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1)); + tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, " ", &cp1)); strlcpy(buf, " ", sizeof(buf)); - test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1)); + tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, " ", &cp1)); strlcpy(buf, "something ", sizeof(buf)); - test_streq("something", tor_strtok_r_impl(buf, " ", &cp1)); - test_eq_ptr(NULL, tor_strtok_r_impl(NULL, ";", &cp1)); + tt_str_op("something",==, tor_strtok_r_impl(buf, " ", &cp1)); + tt_ptr_op(NULL,==, tor_strtok_r_impl(NULL, ";", &cp1)); done: ; } @@ -2183,23 +2388,24 @@ test_util_find_str_at_start_of_line(void *ptr) (void)ptr; - test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "")); - test_eq_ptr(NULL, find_str_at_start_of_line(short_string, "nonsense")); - test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "nonsense")); - test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "\n")); - test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "how ")); - test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "kitty")); - test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "h")); - test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "how")); - test_eq_ptr(line2, find_str_at_start_of_line(long_string, "he")); - test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hell")); - test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello k")); - test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\n")); - test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\nt")); - test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third")); - test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third line")); - test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "third line\n")); - test_eq_ptr(short_line2, find_str_at_start_of_line(short_string, + tt_ptr_op(long_string,==, find_str_at_start_of_line(long_string, "")); + tt_ptr_op(NULL,==, find_str_at_start_of_line(short_string, "nonsense")); + tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "nonsense")); + tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "\n")); + tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "how ")); + tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "kitty")); + tt_ptr_op(long_string,==, find_str_at_start_of_line(long_string, "h")); + tt_ptr_op(long_string,==, find_str_at_start_of_line(long_string, "how")); + tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "he")); + tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "hell")); + tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "hello k")); + tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "hello kitty\n")); + tt_ptr_op(line2,==, + find_str_at_start_of_line(long_string, "hello kitty\nt")); + tt_ptr_op(line3,==, find_str_at_start_of_line(long_string, "third")); + tt_ptr_op(line3,==, find_str_at_start_of_line(long_string, "third line")); + tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "third line\n")); + tt_ptr_op(short_line2,==, find_str_at_start_of_line(short_string, "second line\n")); done: ; @@ -2210,25 +2416,25 @@ test_util_string_is_C_identifier(void *ptr) { (void)ptr; - test_eq(1, string_is_C_identifier("string_is_C_identifier")); - test_eq(1, string_is_C_identifier("_string_is_C_identifier")); - test_eq(1, string_is_C_identifier("_")); - test_eq(1, string_is_C_identifier("i")); - test_eq(1, string_is_C_identifier("_____")); - test_eq(1, string_is_C_identifier("__00__")); - test_eq(1, string_is_C_identifier("__init__")); - test_eq(1, string_is_C_identifier("_0")); - test_eq(1, string_is_C_identifier("_0string_is_C_identifier")); - test_eq(1, string_is_C_identifier("_0")); - - test_eq(0, string_is_C_identifier("0_string_is_C_identifier")); - test_eq(0, string_is_C_identifier("0")); - test_eq(0, string_is_C_identifier("")); - test_eq(0, string_is_C_identifier(";")); - test_eq(0, string_is_C_identifier("i;")); - test_eq(0, string_is_C_identifier("_;")); - test_eq(0, string_is_C_identifier("Ã")); - test_eq(0, string_is_C_identifier("ñ")); + tt_int_op(1,==, string_is_C_identifier("string_is_C_identifier")); + tt_int_op(1,==, string_is_C_identifier("_string_is_C_identifier")); + tt_int_op(1,==, string_is_C_identifier("_")); + tt_int_op(1,==, string_is_C_identifier("i")); + tt_int_op(1,==, string_is_C_identifier("_____")); + tt_int_op(1,==, string_is_C_identifier("__00__")); + tt_int_op(1,==, string_is_C_identifier("__init__")); + tt_int_op(1,==, string_is_C_identifier("_0")); + tt_int_op(1,==, string_is_C_identifier("_0string_is_C_identifier")); + tt_int_op(1,==, string_is_C_identifier("_0")); + + tt_int_op(0,==, string_is_C_identifier("0_string_is_C_identifier")); + tt_int_op(0,==, string_is_C_identifier("0")); + tt_int_op(0,==, string_is_C_identifier("")); + tt_int_op(0,==, string_is_C_identifier(";")); + tt_int_op(0,==, string_is_C_identifier("i;")); + tt_int_op(0,==, string_is_C_identifier("_;")); + tt_int_op(0,==, string_is_C_identifier("Ã")); + tt_int_op(0,==, string_is_C_identifier("ñ")); done: ; @@ -2245,48 +2451,48 @@ test_util_asprintf(void *ptr) /* simple string */ r = tor_asprintf(&cp, "simple string 100%% safe"); - test_assert(cp); - test_streq("simple string 100% safe", cp); - test_eq(strlen(cp), r); + tt_assert(cp); + tt_str_op("simple string 100% safe",==, cp); + tt_int_op(strlen(cp),==, r); tor_free(cp); /* empty string */ r = tor_asprintf(&cp, "%s", ""); - test_assert(cp); - test_streq("", cp); - test_eq(strlen(cp), r); + tt_assert(cp); + tt_str_op("",==, cp); + tt_int_op(strlen(cp),==, r); tor_free(cp); /* numbers (%i) */ r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2); - test_assert(cp); - test_streq("I like numbers--1, 2, etc.", cp); - test_eq(strlen(cp), r); + tt_assert(cp); + tt_str_op("I like numbers--1, 2, etc.",==, cp); + tt_int_op(strlen(cp),==, r); /* don't free cp; next test uses it. */ /* numbers (%d) */ r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202); - test_assert(cp2); - test_eq(strlen(cp2), r); - test_streq("First=101, Second=202", cp2); - test_assert(cp != cp2); + tt_assert(cp2); + tt_int_op(strlen(cp2),==, r); + tt_str_op("First=101, Second=202",==, cp2); + tt_assert(cp != cp2); tor_free(cp); tor_free(cp2); /* Glass-box test: a string exactly 128 characters long. */ r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM); - test_assert(cp); - test_eq(128, r); - test_assert(cp[128] == '\0'); - test_streq("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM, cp); + tt_assert(cp); + tt_int_op(128,==, r); + tt_int_op(cp[128], ==, '\0'); + tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,==, cp); tor_free(cp); /* String longer than 128 characters */ r = tor_asprintf(&cp, "1: %s 2: %s 3: %s", LOREMIPSUM, LOREMIPSUM, LOREMIPSUM); - test_assert(cp); - test_eq(strlen(cp), r); - test_streq("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM, cp); + tt_assert(cp); + tt_int_op(strlen(cp),==, r); + tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,==, cp); done: tor_free(cp); @@ -2307,9 +2513,9 @@ test_util_listdir(void *ptr) dir1 = tor_strdup(get_fname("some-directory")); dirname = tor_strdup(get_fname(NULL)); - test_eq(0, write_str_to_file(fname1, "X\n", 0)); - test_eq(0, write_str_to_file(fname2, "Y\n", 0)); - test_eq(0, write_str_to_file(fname3, "Z\n", 0)); + tt_int_op(0,==, write_str_to_file(fname1, "X\n", 0)); + tt_int_op(0,==, write_str_to_file(fname2, "Y\n", 0)); + tt_int_op(0,==, write_str_to_file(fname3, "Z\n", 0)); #ifdef _WIN32 r = mkdir(dir1); #else @@ -2322,15 +2528,15 @@ test_util_listdir(void *ptr) } dir_contents = tor_listdir(dirname); - test_assert(dir_contents); + tt_assert(dir_contents); /* make sure that each filename is listed. */ - test_assert(smartlist_contains_string_case(dir_contents, "hopscotch")); - test_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg")); - test_assert(smartlist_contains_string_case(dir_contents, ".hidden-file")); - test_assert(smartlist_contains_string_case(dir_contents, "some-directory")); + tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch")); + tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg")); + tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file")); + tt_assert(smartlist_contains_string_case(dir_contents, "some-directory")); - test_assert(!smartlist_contains_string(dir_contents, ".")); - test_assert(!smartlist_contains_string(dir_contents, "..")); + tt_assert(!smartlist_contains_string(dir_contents, ".")); + tt_assert(!smartlist_contains_string(dir_contents, "..")); done: tor_free(fname1); @@ -2391,6 +2597,54 @@ test_util_parent_dir(void *ptr) tor_free(cp); } +static void +test_util_ftruncate(void *ptr) +{ + char *buf = NULL; + const char *fname; + int fd = -1; + const char *message = "Hello world"; + const char *message2 = "Hola mundo"; + struct stat st; + + (void) ptr; + + fname = get_fname("ftruncate"); + + fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600); + tt_int_op(fd, >=, 0); + + /* Make the file be there. */ + tt_int_op(strlen(message), ==, write_all(fd, message, strlen(message), 0)); + tt_int_op((int)tor_fd_getpos(fd), ==, strlen(message)); + tt_int_op(0, ==, fstat(fd, &st)); + tt_int_op((int)st.st_size, ==, strlen(message)); + + /* Truncate and see if it got truncated */ + tt_int_op(0, ==, tor_ftruncate(fd)); + tt_int_op((int)tor_fd_getpos(fd), ==, 0); + tt_int_op(0, ==, fstat(fd, &st)); + tt_int_op((int)st.st_size, ==, 0); + + /* Replace, and see if it got replaced */ + tt_int_op(strlen(message2), ==, + write_all(fd, message2, strlen(message2), 0)); + tt_int_op((int)tor_fd_getpos(fd), ==, strlen(message2)); + tt_int_op(0, ==, fstat(fd, &st)); + tt_int_op((int)st.st_size, ==, strlen(message2)); + + close(fd); + fd = -1; + + buf = read_file_to_str(fname, 0, NULL); + tt_str_op(message2, ==, buf); + + done: + if (fd >= 0) + close(fd); + tor_free(buf); +} + #ifdef _WIN32 static void test_util_load_win_lib(void *ptr) @@ -2422,30 +2676,53 @@ test_util_exit_status(void *ptr) (void)ptr; clear_hex_errno(hex_errno); + tt_str_op("",==, hex_errno); + + clear_hex_errno(hex_errno); n = format_helper_exit_status(0, 0, hex_errno); - test_streq("0/0\n", hex_errno); - test_eq(n, strlen(hex_errno)); + tt_str_op("0/0\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); + +#if SIZEOF_INT == 4 clear_hex_errno(hex_errno); n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno); - test_streq("0/7FFFFFFF\n", hex_errno); - test_eq(n, strlen(hex_errno)); + tt_str_op("0/7FFFFFFF\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); clear_hex_errno(hex_errno); n = format_helper_exit_status(0xFF, -0x80000000, hex_errno); - test_streq("FF/-80000000\n", hex_errno); - test_eq(n, strlen(hex_errno)); - test_eq(n, HEX_ERRNO_SIZE); + tt_str_op("FF/-80000000\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); + tt_int_op(n,==, HEX_ERRNO_SIZE); + +#elif SIZEOF_INT == 8 + + clear_hex_errno(hex_errno); + n = format_helper_exit_status(0, 0x7FFFFFFFFFFFFFFF, hex_errno); + tt_str_op("0/7FFFFFFFFFFFFFFF\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); + + clear_hex_errno(hex_errno); + n = format_helper_exit_status(0xFF, -0x8000000000000000, hex_errno); + tt_str_op("FF/-8000000000000000\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); + tt_int_op(n,==, HEX_ERRNO_SIZE); + +#endif clear_hex_errno(hex_errno); n = format_helper_exit_status(0x7F, 0, hex_errno); - test_streq("7F/0\n", hex_errno); - test_eq(n, strlen(hex_errno)); + tt_str_op("7F/0\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); clear_hex_errno(hex_errno); n = format_helper_exit_status(0x08, -0x242, hex_errno); - test_streq("8/-242\n", hex_errno); - test_eq(n, strlen(hex_errno)); + tt_str_op("8/-242\n",==, hex_errno); + tt_int_op(n,==, strlen(hex_errno)); + + clear_hex_errno(hex_errno); + tt_str_op("",==, hex_errno); done: ; @@ -2453,8 +2730,9 @@ test_util_exit_status(void *ptr) #endif #ifndef _WIN32 -/** Check that fgets waits until a full line, and not return a partial line, on - * a EAGAIN with a non-blocking pipe */ +/* Check that fgets with a non-blocking pipe returns partial lines and sets + * EAGAIN, returns full lines and sets no error, and returns NULL on EOF and + * sets no error */ static void test_util_fgets_eagain(void *ptr) { @@ -2463,17 +2741,19 @@ test_util_fgets_eagain(void *ptr) ssize_t retlen; char *retptr; FILE *test_stream = NULL; - char buf[10]; + char buf[4] = { 0 }; (void)ptr; + errno = 0; + /* Set up a pipe to test on */ retval = pipe(test_pipe); - tt_int_op(retval, >=, 0); + tt_int_op(retval, ==, 0); /* Set up the read-end to be non-blocking */ retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK); - tt_int_op(retval, >=, 0); + tt_int_op(retval, ==, 0); /* Open it as a stdio stream */ test_stream = fdopen(test_pipe[0], "r"); @@ -2483,51 +2763,69 @@ test_util_fgets_eagain(void *ptr) retlen = write(test_pipe[1], "A", 1); tt_int_op(retlen, ==, 1); retptr = fgets(buf, sizeof(buf), test_stream); - tt_want(retptr == NULL); tt_int_op(errno, ==, EAGAIN); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "A"); + errno = 0; /* Send in the rest */ retlen = write(test_pipe[1], "B\n", 2); tt_int_op(retlen, ==, 2); retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); - tt_str_op(buf, ==, "AB\n"); + tt_str_op(buf, ==, "B\n"); + errno = 0; /* Send in a full line */ retlen = write(test_pipe[1], "CD\n", 3); tt_int_op(retlen, ==, 3); retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); tt_str_op(buf, ==, "CD\n"); + errno = 0; /* Send in a partial line */ retlen = write(test_pipe[1], "E", 1); tt_int_op(retlen, ==, 1); retptr = fgets(buf, sizeof(buf), test_stream); - tt_ptr_op(retptr, ==, NULL); tt_int_op(errno, ==, EAGAIN); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "E"); + errno = 0; /* Send in the rest */ retlen = write(test_pipe[1], "F\n", 2); tt_int_op(retlen, ==, 2); retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); - tt_str_op(buf, ==, "EF\n"); + tt_str_op(buf, ==, "F\n"); + errno = 0; /* Send in a full line and close */ retlen = write(test_pipe[1], "GH", 2); tt_int_op(retlen, ==, 2); retval = close(test_pipe[1]); - test_pipe[1] = -1; tt_int_op(retval, ==, 0); + test_pipe[1] = -1; retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); tt_str_op(buf, ==, "GH"); + errno = 0; /* Check for EOF */ retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, NULL); - tt_int_op(feof(test_stream), >, 0); + retval = feof(test_stream); + tt_int_op(retval, !=, 0); + errno = 0; + + /* Check that buf is unchanged according to C99 and C11 */ + tt_str_op(buf, ==, "GH"); done: if (test_stream != NULL) @@ -2552,6 +2850,30 @@ test_util_fgets_eagain(void *ptr) #define EOL "\n" #endif +#ifdef _WIN32 +/* I've assumed Windows doesn't have the gap between fork and exec + * that causes the race condition on unix-like platforms */ +#define MATCH_PROCESS_STATUS(s1,s2) ((s1) == (s2)) + +#else +/* work around a race condition of the timing of SIGCHLD handler updates + * to the process_handle's fields, and checks of those fields + * + * TODO: Once we can signal failure to exec, change PROCESS_STATUS_RUNNING to + * PROCESS_STATUS_ERROR (and similarly with *_OR_NOTRUNNING) */ +#define PROCESS_STATUS_RUNNING_OR_NOTRUNNING (PROCESS_STATUS_RUNNING+1) +#define IS_RUNNING_OR_NOTRUNNING(s) \ + ((s) == PROCESS_STATUS_RUNNING || (s) == PROCESS_STATUS_NOTRUNNING) +/* well, this is ugly */ +#define MATCH_PROCESS_STATUS(s1,s2) \ + ( (s1) == (s2) \ + ||((s1) == PROCESS_STATUS_RUNNING_OR_NOTRUNNING \ + && IS_RUNNING_OR_NOTRUNNING(s2)) \ + ||((s2) == PROCESS_STATUS_RUNNING_OR_NOTRUNNING \ + && IS_RUNNING_OR_NOTRUNNING(s1))) + +#endif // _WIN32 + /** Helper function for testing tor_spawn_background */ static void run_util_spawn_background(const char *argv[], const char *expected_out, @@ -2573,26 +2895,47 @@ run_util_spawn_background(const char *argv[], const char *expected_out, notify_pending_waitpid_callbacks(); - test_eq(expected_status, status); + /* the race condition doesn't affect status, + * because status isn't updated by the SIGCHLD handler, + * but we still need to handle PROCESS_STATUS_RUNNING_OR_NOTRUNNING */ + tt_assert(MATCH_PROCESS_STATUS(expected_status, status)); if (status == PROCESS_STATUS_ERROR) { tt_ptr_op(process_handle, ==, NULL); return; } - test_assert(process_handle != NULL); - test_eq(expected_status, process_handle->status); + tt_assert(process_handle != NULL); + + /* When a spawned process forks, fails, then exits very quickly, + * (this typically occurs when exec fails) + * there is a race condition between the SIGCHLD handler + * updating the process_handle's fields, and this test + * checking the process status in those fields. + * The SIGCHLD update can occur before or after the code below executes. + * This causes intermittent failures in spawn_background_fail(), + * typically when the machine is under load. + * We use PROCESS_STATUS_RUNNING_OR_NOTRUNNING to avoid this issue. */ + + /* the race condition affects the change in + * process_handle->status from RUNNING to NOTRUNNING */ + tt_assert(MATCH_PROCESS_STATUS(expected_status, process_handle->status)); #ifndef _WIN32 notify_pending_waitpid_callbacks(); - tt_ptr_op(process_handle->waitpid_cb, !=, NULL); + /* the race condition affects the change in + * process_handle->waitpid_cb to NULL, + * so we skip the check if expected_status is ambiguous, + * that is, PROCESS_STATUS_RUNNING_OR_NOTRUNNING */ + tt_assert(process_handle->waitpid_cb != NULL + || expected_status == PROCESS_STATUS_RUNNING_OR_NOTRUNNING); #endif #ifdef _WIN32 - test_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE); - test_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE); + tt_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE); + tt_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE); #else - test_assert(process_handle->stdout_pipe >= 0); - test_assert(process_handle->stderr_pipe >= 0); + tt_assert(process_handle->stdout_pipe >= 0); + tt_assert(process_handle->stderr_pipe >= 0); #endif /* Check stdout */ @@ -2600,15 +2943,15 @@ run_util_spawn_background(const char *argv[], const char *expected_out, sizeof(stdout_buf) - 1); tt_assert(pos >= 0); stdout_buf[pos] = '\0'; - test_eq(strlen(expected_out), pos); - test_streq(expected_out, stdout_buf); + tt_int_op(strlen(expected_out),==, pos); + tt_str_op(expected_out,==, stdout_buf); notify_pending_waitpid_callbacks(); /* Check it terminated correctly */ retval = tor_get_exit_code(process_handle, 1, &exit_code); - test_eq(PROCESS_EXIT_EXITED, retval); - test_eq(expected_exit, exit_code); + tt_int_op(PROCESS_EXIT_EXITED,==, retval); + tt_int_op(expected_exit,==, exit_code); // TODO: Make test-child exit with something other than 0 #ifndef _WIN32 @@ -2619,10 +2962,10 @@ run_util_spawn_background(const char *argv[], const char *expected_out, /* Check stderr */ pos = tor_read_all_from_process_stderr(process_handle, stderr_buf, sizeof(stderr_buf) - 1); - test_assert(pos >= 0); + tt_assert(pos >= 0); stderr_buf[pos] = '\0'; - test_streq(expected_err, stderr_buf); - test_eq(strlen(expected_err), pos); + tt_str_op(expected_err,==, stderr_buf); + tt_int_op(strlen(expected_err),==, pos); notify_pending_waitpid_callbacks(); @@ -2657,10 +3000,13 @@ test_util_spawn_background_fail(void *ptr) const int expected_status = PROCESS_STATUS_ERROR; #else /* TODO: Once we can signal failure to exec, set this to be - * PROCESS_STATUS_ERROR */ - const int expected_status = PROCESS_STATUS_RUNNING; + * PROCESS_STATUS_RUNNING_OR_ERROR */ + const int expected_status = PROCESS_STATUS_RUNNING_OR_NOTRUNNING; #endif + memset(expected_out, 0xf0, sizeof(expected_out)); + memset(code, 0xf0, sizeof(code)); + (void)ptr; tor_snprintf(code, sizeof(code), "%x/%x", @@ -2708,9 +3054,9 @@ test_util_spawn_background_partial_read_impl(int exit_early) #else status = tor_spawn_background(argv[0], argv, NULL, &process_handle); #endif - test_eq(expected_status, status); - test_assert(process_handle); - test_eq(expected_status, process_handle->status); + tt_int_op(expected_status,==, status); + tt_assert(process_handle); + tt_int_op(expected_status,==, process_handle->status); /* Check stdout */ for (expected_out_ctr = 0; expected_out[expected_out_ctr] != NULL;) { @@ -2719,7 +3065,7 @@ test_util_spawn_background_partial_read_impl(int exit_early) sizeof(stdout_buf) - 1, NULL); #else /* Check that we didn't read the end of file last time */ - test_assert(!eof); + tt_assert(!eof); pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf, sizeof(stdout_buf) - 1, NULL, &eof); #endif @@ -2729,10 +3075,10 @@ test_util_spawn_background_partial_read_impl(int exit_early) if (0 == pos) continue; - test_assert(pos > 0); + tt_assert(pos > 0); stdout_buf[pos] = '\0'; - test_streq(expected_out[expected_out_ctr], stdout_buf); - test_eq(strlen(expected_out[expected_out_ctr]), pos); + tt_str_op(expected_out[expected_out_ctr],==, stdout_buf); + tt_int_op(strlen(expected_out[expected_out_ctr]),==, pos); expected_out_ctr++; } @@ -2747,33 +3093,33 @@ test_util_spawn_background_partial_read_impl(int exit_early) pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf, sizeof(stdout_buf) - 1, process_handle); - test_eq(0, pos); + tt_int_op(0,==, pos); #else if (!eof) { /* We should have got all the data, but maybe not the EOF flag */ pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf, sizeof(stdout_buf) - 1, process_handle, &eof); - test_eq(0, pos); - test_assert(eof); + tt_int_op(0,==, pos); + tt_assert(eof); } /* Otherwise, we got the EOF on the last read */ #endif /* Check it terminated correctly */ retval = tor_get_exit_code(process_handle, 1, &exit_code); - test_eq(PROCESS_EXIT_EXITED, retval); - test_eq(expected_exit, exit_code); + tt_int_op(PROCESS_EXIT_EXITED,==, retval); + tt_int_op(expected_exit,==, exit_code); // TODO: Make test-child exit with something other than 0 /* Check stderr */ pos = tor_read_all_from_process_stderr(process_handle, stderr_buf, sizeof(stderr_buf) - 1); - test_assert(pos >= 0); + tt_assert(pos >= 0); stderr_buf[pos] = '\0'; - test_streq(expected_err, stderr_buf); - test_eq(strlen(expected_err), pos); + tt_str_op(expected_err,==, stderr_buf); + tt_int_op(strlen(expected_err),==, pos); done: tor_process_handle_destroy(process_handle, 1); @@ -2848,6 +3194,13 @@ test_util_spawn_background_waitpid_notify(void *arg) #undef TEST_CHILD #undef EOL +#undef MATCH_PROCESS_STATUS + +#ifndef _WIN32 +#undef PROCESS_STATUS_RUNNING_OR_NOTRUNNING +#undef IS_RUNNING_OR_NOTRUNNING +#endif + /** * Test for format_hex_number_sigsafe() */ @@ -2878,15 +3231,15 @@ test_util_format_hex_number(void *ptr) for (i = 0; test_data[i].str != NULL; ++i) { len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf)); - test_neq(len, 0); - test_eq(len, strlen(buf)); - test_streq(buf, test_data[i].str); + tt_int_op(len,!=, 0); + tt_int_op(len,==, strlen(buf)); + tt_str_op(buf,==, test_data[i].str); } - test_eq(4, format_hex_number_sigsafe(0xffff, buf, 5)); - test_streq(buf, "FFFF"); - test_eq(0, format_hex_number_sigsafe(0xffff, buf, 4)); - test_eq(0, format_hex_number_sigsafe(0, buf, 1)); + tt_int_op(4,==, format_hex_number_sigsafe(0xffff, buf, 5)); + tt_str_op(buf,==, "FFFF"); + tt_int_op(0,==, format_hex_number_sigsafe(0xffff, buf, 4)); + tt_int_op(0,==, format_hex_number_sigsafe(0, buf, 1)); done: return; @@ -2922,21 +3275,21 @@ test_util_format_dec_number(void *ptr) for (i = 0; test_data[i].str != NULL; ++i) { len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf)); - test_neq(len, 0); - test_eq(len, strlen(buf)); - test_streq(buf, test_data[i].str); + tt_int_op(len,!=, 0); + tt_int_op(len,==, strlen(buf)); + tt_str_op(buf,==, test_data[i].str); len = format_dec_number_sigsafe(test_data[i].x, buf, (int)(strlen(test_data[i].str) + 1)); - test_eq(len, strlen(buf)); - test_streq(buf, test_data[i].str); + tt_int_op(len,==, strlen(buf)); + tt_str_op(buf,==, test_data[i].str); } - test_eq(4, format_dec_number_sigsafe(7331, buf, 5)); - test_streq(buf, "7331"); - test_eq(0, format_dec_number_sigsafe(7331, buf, 4)); - test_eq(1, format_dec_number_sigsafe(0, buf, 2)); - test_eq(0, format_dec_number_sigsafe(0, buf, 1)); + tt_int_op(4,==, format_dec_number_sigsafe(7331, buf, 5)); + tt_str_op(buf,==, "7331"); + tt_int_op(0,==, format_dec_number_sigsafe(7331, buf, 4)); + tt_int_op(1,==, format_dec_number_sigsafe(0, buf, 2)); + tt_int_op(0,==, format_dec_number_sigsafe(0, buf, 1)); done: return; @@ -2985,7 +3338,7 @@ test_util_join_win_cmdline(void *ptr) for (i=0; cmdlines[i]!=NULL; i++) { log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]); joined_argv = tor_join_win_cmdline(argvs[i]); - test_streq(cmdlines[i], joined_argv); + tt_str_op(cmdlines[i],==, joined_argv); tor_free(joined_argv); } @@ -3040,17 +3393,17 @@ test_util_split_lines(void *ptr) i, tests[i].orig_length); SMARTLIST_FOREACH_BEGIN(sl, const char *, line) { /* Check we have not got too many lines */ - test_assert(j < MAX_SPLIT_LINE_COUNT); + tt_int_op(MAX_SPLIT_LINE_COUNT, >, j); /* Check that there actually should be a line here */ - test_assert(tests[i].split_line[j] != NULL); + tt_assert(tests[i].split_line[j] != NULL); log_info(LD_GENERAL, "Line %d of test %d, should be <%s>", j, i, tests[i].split_line[j]); /* Check that the line is as expected */ - test_streq(line, tests[i].split_line[j]); + tt_str_op(line,==, tests[i].split_line[j]); j++; } SMARTLIST_FOREACH_END(line); /* Check that we didn't miss some lines */ - test_eq_ptr(NULL, tests[i].split_line[j]); + tt_ptr_op(NULL,==, tests[i].split_line[j]); tor_free(orig_line); smartlist_free(sl); sl = NULL; @@ -3062,7 +3415,7 @@ test_util_split_lines(void *ptr) } static void -test_util_di_ops(void) +test_util_di_ops(void *arg) { #define LT -1 #define GT 1 @@ -3082,10 +3435,11 @@ test_util_di_ops(void) int i; + (void)arg; 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)); + tt_int_op(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); @@ -3096,18 +3450,37 @@ test_util_di_ops(void) /* Check for correctness of cmp1 */ if (cmp1 < 0 && examples[i].want_sign != LT) - test_fail(); + TT_DIE(("Assertion failed.")); else if (cmp1 > 0 && examples[i].want_sign != GT) - test_fail(); + TT_DIE(("Assertion failed.")); else if (cmp1 == 0 && examples[i].want_sign != EQ) - test_fail(); + TT_DIE(("Assertion failed.")); /* 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); + tt_int_op(eq1,==, eq2); + tt_int_op(neq1,==, neq2); + tt_int_op(cmp1,==, -cmp2); + tt_int_op(eq1,==, cmp1 == 0); + tt_int_op(neq1,==, !eq1); + } + + { + uint8_t zz = 0; + uint8_t ii = 0; + int z; + + /* exhaustively test tor_memeq and tor_memcmp + * against each possible single-byte numeric difference + * some arithmetic bugs only appear with certain bit patterns */ + for (z = 0; z < 256; z++) { + for (i = 0; i < 256; i++) { + ii = (uint8_t)i; + zz = (uint8_t)z; + tt_int_op(tor_memeq(&zz, &ii, 1),==, zz == ii); + tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,==, zz > ii ? GT : EQ); + tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,==, ii < zz ? LT : EQ); + } + } } tt_int_op(1, ==, safe_mem_is_zero("", 0)); @@ -3131,12 +3504,12 @@ static void test_util_n_bits_set(void *ptr) { (void)ptr; - test_eq(0, n_bits_set_u8(0)); - test_eq(1, n_bits_set_u8(1)); - test_eq(3, n_bits_set_u8(7)); - test_eq(1, n_bits_set_u8(8)); - test_eq(2, n_bits_set_u8(129)); - test_eq(8, n_bits_set_u8(255)); + tt_int_op(0,==, n_bits_set_u8(0)); + tt_int_op(1,==, n_bits_set_u8(1)); + tt_int_op(3,==, n_bits_set_u8(7)); + tt_int_op(1,==, n_bits_set_u8(8)); + tt_int_op(2,==, n_bits_set_u8(129)); + tt_int_op(8,==, n_bits_set_u8(255)); done: ; } @@ -3157,78 +3530,78 @@ test_util_eat_whitespace(void *ptr) strlcpy(str, "fuubaar", sizeof(str)); for (i = 0; i < sizeof(ws); ++i) { str[0] = ws[i]; - test_eq_ptr(str + 1, eat_whitespace(str)); - test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str + 1, eat_whitespace_no_nl(str)); - test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str))); + tt_ptr_op(str + 1,==, eat_whitespace(str)); + tt_ptr_op(str + 1,==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str + 1,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str + 1,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); } str[0] = '\n'; - test_eq_ptr(str + 1, eat_whitespace(str)); - test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str, eat_whitespace_no_nl(str)); - test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str))); + tt_ptr_op(str + 1,==, eat_whitespace(str)); + tt_ptr_op(str + 1,==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); /* Empty string */ strlcpy(str, "", sizeof(str)); - test_eq_ptr(str, eat_whitespace(str)); - test_eq_ptr(str, eat_whitespace_eos(str, str)); - test_eq_ptr(str, eat_whitespace_no_nl(str)); - test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str)); + tt_ptr_op(str,==, eat_whitespace(str)); + tt_ptr_op(str,==, eat_whitespace_eos(str, str)); + tt_ptr_op(str,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str)); /* Only ws */ strlcpy(str, " \t\r\n", sizeof(str)); - test_eq_ptr(str + strlen(str), eat_whitespace(str)); - test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str + strlen(str) - 1, + tt_ptr_op(str + strlen(str),==, eat_whitespace(str)); + tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str + strlen(str) - 1,==, eat_whitespace_no_nl(str)); - test_eq_ptr(str + strlen(str) - 1, + tt_ptr_op(str + strlen(str) - 1,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); strlcpy(str, " \t\r ", sizeof(str)); - test_eq_ptr(str + strlen(str), eat_whitespace(str)); - test_eq_ptr(str + strlen(str), + tt_ptr_op(str + strlen(str),==, eat_whitespace(str)); + tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str + strlen(str), eat_whitespace_no_nl(str)); - test_eq_ptr(str + strlen(str), + tt_ptr_op(str + strlen(str),==, eat_whitespace_no_nl(str)); + tt_ptr_op(str + strlen(str),==, eat_whitespace_eos_no_nl(str, str + strlen(str))); /* Multiple ws */ strlcpy(str, "fuubaar", sizeof(str)); for (i = 0; i < sizeof(ws); ++i) str[i] = ws[i]; - test_eq_ptr(str + sizeof(ws), eat_whitespace(str)); - test_eq_ptr(str + sizeof(ws), eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str + sizeof(ws), eat_whitespace_no_nl(str)); - test_eq_ptr(str + sizeof(ws), + tt_ptr_op(str + sizeof(ws),==, eat_whitespace(str)); + tt_ptr_op(str + sizeof(ws),==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str + sizeof(ws),==, eat_whitespace_no_nl(str)); + tt_ptr_op(str + sizeof(ws),==, eat_whitespace_eos_no_nl(str, str + strlen(str))); /* Eat comment */ strlcpy(str, "# Comment \n No Comment", sizeof(str)); - test_streq("No Comment", eat_whitespace(str)); - test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str, eat_whitespace_no_nl(str)); - test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str))); + tt_str_op("No Comment",==, eat_whitespace(str)); + tt_str_op("No Comment",==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); /* Eat comment & ws mix */ strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str)); - test_streq("No Comment", eat_whitespace(str)); - test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str + 1, eat_whitespace_no_nl(str)); - test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str))); + tt_str_op("No Comment",==, eat_whitespace(str)); + tt_str_op("No Comment",==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str + 1,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str + 1,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); /* Eat entire comment */ strlcpy(str, "#Comment", sizeof(str)); - test_eq_ptr(str + strlen(str), eat_whitespace(str)); - test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str, eat_whitespace_no_nl(str)); - test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str))); + tt_ptr_op(str + strlen(str),==, eat_whitespace(str)); + tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); /* Blank line, then comment */ strlcpy(str, " \t\n # Comment", sizeof(str)); - test_eq_ptr(str + strlen(str), eat_whitespace(str)); - test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str))); - test_eq_ptr(str + 2, eat_whitespace_no_nl(str)); - test_eq_ptr(str + 2, eat_whitespace_eos_no_nl(str, str + strlen(str))); + tt_ptr_op(str + strlen(str),==, eat_whitespace(str)); + tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str))); + tt_ptr_op(str + 2,==, eat_whitespace_no_nl(str)); + tt_ptr_op(str + 2,==, eat_whitespace_eos_no_nl(str, str + strlen(str))); done: ; @@ -3556,12 +3929,12 @@ test_util_round_to_next_multiple_of(void *arg) { (void)arg; - test_assert(round_uint64_to_next_multiple_of(0,1) == 0); - test_assert(round_uint64_to_next_multiple_of(0,7) == 0); + tt_assert(round_uint64_to_next_multiple_of(0,1) == 0); + tt_assert(round_uint64_to_next_multiple_of(0,7) == 0); - test_assert(round_uint64_to_next_multiple_of(99,1) == 99); - test_assert(round_uint64_to_next_multiple_of(99,7) == 105); - test_assert(round_uint64_to_next_multiple_of(99,9) == 99); + tt_assert(round_uint64_to_next_multiple_of(99,1) == 99); + tt_assert(round_uint64_to_next_multiple_of(99,7) == 105); + tt_assert(round_uint64_to_next_multiple_of(99,9) == 99); done: ; @@ -3588,7 +3961,7 @@ test_util_strclear(void *arg) } #define UTIL_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name } + { #name, test_util_ ## name , 0, NULL, NULL } #define UTIL_TEST(name, flags) \ { #name, test_util_ ## name, flags, NULL, NULL } @@ -3783,12 +4156,13 @@ struct testcase_t util_tests[] = { UTIL_TEST(asprintf, 0), UTIL_TEST(listdir, 0), UTIL_TEST(parent_dir, 0), + UTIL_TEST(ftruncate, 0), #ifdef _WIN32 UTIL_TEST(load_win_lib, 0), #endif #ifndef _WIN32 UTIL_TEST(exit_status, 0), - UTIL_TEST(fgets_eagain, TT_SKIP), + UTIL_TEST(fgets_eagain, 0), #endif UTIL_TEST(spawn_background_ok, 0), UTIL_TEST(spawn_background_fail, 0), @@ -3806,7 +4180,10 @@ struct testcase_t util_tests[] = { UTIL_TEST(make_environment, 0), UTIL_TEST(set_env_var_in_sl, 0), UTIL_TEST(read_file_eof_tiny_limit, 0), + UTIL_TEST(read_file_eof_one_loop_a, 0), + UTIL_TEST(read_file_eof_one_loop_b, 0), UTIL_TEST(read_file_eof_two_loops, 0), + UTIL_TEST(read_file_eof_two_loops_b, 0), UTIL_TEST(read_file_eof_zero_bytes, 0), UTIL_TEST(write_chunks_to_file, 0), UTIL_TEST(mathlog, 0), diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c index e799df5cad..fae26ef956 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -134,18 +134,30 @@ parse_commandline(int argc, char **argv) fprintf(stderr, "No argument to -i\n"); return 1; } + if (identity_key_file) { + fprintf(stderr, "Duplicate values for -i\n"); + return -1; + } identity_key_file = tor_strdup(argv[++i]); } else if (!strcmp(argv[i], "-s")) { if (i+1>=argc) { fprintf(stderr, "No argument to -s\n"); return 1; } + if (signing_key_file) { + fprintf(stderr, "Duplicate values for -s\n"); + return -1; + } signing_key_file = tor_strdup(argv[++i]); } else if (!strcmp(argv[i], "-c")) { if (i+1>=argc) { fprintf(stderr, "No argument to -c\n"); return 1; } + if (certificate_file) { + fprintf(stderr, "Duplicate values for -c\n"); + return -1; + } certificate_file = tor_strdup(argv[++i]); } else if (!strcmp(argv[i], "-m")) { if (i+1>=argc) { diff --git a/src/trunnel/include.am b/src/trunnel/include.am new file mode 100644 index 0000000000..c7ac1679d0 --- /dev/null +++ b/src/trunnel/include.am @@ -0,0 +1,29 @@ + +noinst_LIBRARIES += \ + src/trunnel/libor-trunnel.a + +if UNITTESTS_ENABLED +noinst_LIBRARIES += \ + src/trunnel/libor-trunnel-testing.a +endif + +AM_CPPFLAGS += -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel + +TRUNNELSOURCES = \ + src/ext/trunnel/trunnel.c \ + src/trunnel/pwbox.c + +TRUNNELHEADERS = \ + src/ext/trunnel/trunnel.h \ + src/ext/trunnel/trunnel-impl.h \ + src/trunnel/trunnel-local.h \ + src/trunnel/pwbox.h + +src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES) +src_trunnel_libor_trunnel_a_CPPFLAGS = -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS) + +src_trunnel_libor_trunnel_testing_a_SOURCES = $(TRUNNELSOURCES) +src_trunnel_libor_trunnel_testing_a_CPPFLAGS = -DTOR_UNIT_TESTS -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS) +src_trunnel_libor_trunnel_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) + +noinst_HEADERS+= $(TRUNNELHEADERS) diff --git a/src/trunnel/pwbox.c b/src/trunnel/pwbox.c new file mode 100644 index 0000000000..bfea3ac671 --- /dev/null +++ b/src/trunnel/pwbox.c @@ -0,0 +1,515 @@ +/* pwbox.c -- generated by Trunnel v1.2. + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +#include <stdlib.h> +#include "trunnel-impl.h" + +#include "pwbox.h" + +#define TRUNNEL_SET_ERROR_CODE(obj) \ + do { \ + (obj)->trunnel_error_code_ = 1; \ + } while (0) + +#if defined(__COVERITY__) || defined(__clang_analyzer__) +/* If we're runnning a static analysis tool, we don't want it to complain + * that some of our remaining-bytes checks are dead-code. */ +int pwbox_deadcode_dummy__ = 0; +#define OR_DEADCODE_DUMMY || pwbox_deadcode_dummy__ +#else +#define OR_DEADCODE_DUMMY +#endif + +#define CHECK_REMAINING(nbytes, label) \ + do { \ + if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \ + goto label; \ + } \ + } while (0) + +pwbox_encoded_t * +pwbox_encoded_new(void) +{ + pwbox_encoded_t *val = trunnel_calloc(1, sizeof(pwbox_encoded_t)); + if (NULL == val) + return NULL; + val->fixedbytes0 = PWBOX0_CONST0; + val->fixedbytes1 = PWBOX0_CONST1; + return val; +} + +/** Release all storage held inside 'obj', but do not free 'obj'. + */ +static void +pwbox_encoded_clear(pwbox_encoded_t *obj) +{ + (void) obj; + TRUNNEL_DYNARRAY_WIPE(&obj->skey_header); + TRUNNEL_DYNARRAY_CLEAR(&obj->skey_header); + TRUNNEL_DYNARRAY_WIPE(&obj->data); + TRUNNEL_DYNARRAY_CLEAR(&obj->data); +} + +void +pwbox_encoded_free(pwbox_encoded_t *obj) +{ + if (obj == NULL) + return; + pwbox_encoded_clear(obj); + trunnel_memwipe(obj, sizeof(pwbox_encoded_t)); + trunnel_free_(obj); +} + +uint32_t +pwbox_encoded_get_fixedbytes0(pwbox_encoded_t *inp) +{ + return inp->fixedbytes0; +} +int +pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val) +{ + if (! ((val == PWBOX0_CONST0))) { + TRUNNEL_SET_ERROR_CODE(inp); + return -1; + } + inp->fixedbytes0 = val; + return 0; +} +uint32_t +pwbox_encoded_get_fixedbytes1(pwbox_encoded_t *inp) +{ + return inp->fixedbytes1; +} +int +pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val) +{ + if (! ((val == PWBOX0_CONST1))) { + TRUNNEL_SET_ERROR_CODE(inp); + return -1; + } + inp->fixedbytes1 = val; + return 0; +} +uint8_t +pwbox_encoded_get_header_len(pwbox_encoded_t *inp) +{ + return inp->header_len; +} +int +pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val) +{ + inp->header_len = val; + return 0; +} +size_t +pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp) +{ + return TRUNNEL_DYNARRAY_LEN(&inp->skey_header); +} + +uint8_t +pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx) +{ + return TRUNNEL_DYNARRAY_GET(&inp->skey_header, idx); +} + +int +pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt) +{ + TRUNNEL_DYNARRAY_SET(&inp->skey_header, idx, elt); + return 0; +} +int +pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt) +{ +#if SIZE_MAX >= UINT8_MAX + if (inp->skey_header.n_ == UINT8_MAX) + goto trunnel_alloc_failed; +#endif + TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->skey_header, elt, {}); + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} + +uint8_t * +pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp) +{ + return inp->skey_header.elts_; +} +int +pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen) +{ + uint8_t *newptr; +#if UINT8_MAX < SIZE_MAX + if (newlen > UINT8_MAX) + goto trunnel_alloc_failed; +#endif + newptr = trunnel_dynarray_setlen(&inp->skey_header.allocated_, + &inp->skey_header.n_, inp->skey_header.elts_, newlen, + sizeof(inp->skey_header.elts_[0]), (trunnel_free_fn_t) NULL, + &inp->trunnel_error_code_); + if (newptr == NULL) + goto trunnel_alloc_failed; + inp->skey_header.elts_ = newptr; + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} +size_t +pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp) +{ + (void)inp; return 16; +} + +uint8_t +pwbox_encoded_get_iv(const pwbox_encoded_t *inp, size_t idx) +{ + trunnel_assert(idx < 16); + return inp->iv[idx]; +} + +int +pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 16); + inp->iv[idx] = elt; + return 0; +} + +uint8_t * +pwbox_encoded_getarray_iv(pwbox_encoded_t *inp) +{ + return inp->iv; +} +size_t +pwbox_encoded_getlen_data(const pwbox_encoded_t *inp) +{ + return TRUNNEL_DYNARRAY_LEN(&inp->data); +} + +uint8_t +pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx) +{ + return TRUNNEL_DYNARRAY_GET(&inp->data, idx); +} + +int +pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt) +{ + TRUNNEL_DYNARRAY_SET(&inp->data, idx, elt); + return 0; +} +int +pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt) +{ + TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data, elt, {}); + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} + +uint8_t * +pwbox_encoded_getarray_data(pwbox_encoded_t *inp) +{ + return inp->data.elts_; +} +int +pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen) +{ + uint8_t *newptr; + newptr = trunnel_dynarray_setlen(&inp->data.allocated_, + &inp->data.n_, inp->data.elts_, newlen, + sizeof(inp->data.elts_[0]), (trunnel_free_fn_t) NULL, + &inp->trunnel_error_code_); + if (newptr == NULL) + goto trunnel_alloc_failed; + inp->data.elts_ = newptr; + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} +size_t +pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +pwbox_encoded_get_hmac(const pwbox_encoded_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->hmac[idx]; +} + +int +pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->hmac[idx] = elt; + return 0; +} + +uint8_t * +pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp) +{ + return inp->hmac; +} +const char * +pwbox_encoded_check(const pwbox_encoded_t *obj) +{ + if (obj == NULL) + return "Object was NULL"; + if (obj->trunnel_error_code_) + return "A set function failed on this object"; + if (! (obj->fixedbytes0 == PWBOX0_CONST0)) + return "Integer out of bounds"; + if (! (obj->fixedbytes1 == PWBOX0_CONST1)) + return "Integer out of bounds"; + if (TRUNNEL_DYNARRAY_LEN(&obj->skey_header) != obj->header_len) + return "Length mismatch for skey_header"; + return NULL; +} + +ssize_t +pwbox_encoded_encoded_len(const pwbox_encoded_t *obj) +{ + ssize_t result = 0; + + if (NULL != pwbox_encoded_check(obj)) + return -1; + + + /* Length of u32 fixedbytes0 IN [PWBOX0_CONST0] */ + result += 4; + + /* Length of u32 fixedbytes1 IN [PWBOX0_CONST1] */ + result += 4; + + /* Length of u8 header_len */ + result += 1; + + /* Length of u8 skey_header[header_len] */ + result += TRUNNEL_DYNARRAY_LEN(&obj->skey_header); + + /* Length of u8 iv[16] */ + result += 16; + + /* Length of u8 data[] */ + result += TRUNNEL_DYNARRAY_LEN(&obj->data); + + /* Length of u8 hmac[32] */ + result += 32; + return result; +} +int +pwbox_encoded_clear_errors(pwbox_encoded_t *obj) +{ + int r = obj->trunnel_error_code_; + obj->trunnel_error_code_ = 0; + return r; +} +ssize_t +pwbox_encoded_encode(uint8_t *output, size_t avail, const pwbox_encoded_t *obj) +{ + ssize_t result = 0; + size_t written = 0; + uint8_t *ptr = output; + const char *msg; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + const ssize_t encoded_len = pwbox_encoded_encoded_len(obj); +#endif + int enforce_avail = 0; + const size_t avail_orig = avail; + + if (NULL != (msg = pwbox_encoded_check(obj))) + goto check_failed; + +#ifdef TRUNNEL_CHECK_ENCODED_LEN + trunnel_assert(encoded_len >= 0); +#endif + + /* Encode u32 fixedbytes0 IN [PWBOX0_CONST0] */ + trunnel_assert(written <= avail); + if (avail - written < 4) + goto truncated; + trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes0)); + written += 4; ptr += 4; + + /* Encode u32 fixedbytes1 IN [PWBOX0_CONST1] */ + trunnel_assert(written <= avail); + if (avail - written < 4) + goto truncated; + trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes1)); + written += 4; ptr += 4; + + /* Encode u8 header_len */ + trunnel_assert(written <= avail); + if (avail - written < 1) + goto truncated; + trunnel_set_uint8(ptr, (obj->header_len)); + written += 1; ptr += 1; + + /* Encode u8 skey_header[header_len] */ + { + size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->skey_header); + trunnel_assert(obj->header_len == elt_len); + trunnel_assert(written <= avail); + if (avail - written < elt_len) + goto truncated; + memcpy(ptr, obj->skey_header.elts_, elt_len); + written += elt_len; ptr += elt_len; + } + + /* Encode u8 iv[16] */ + trunnel_assert(written <= avail); + if (avail - written < 16) + goto truncated; + memcpy(ptr, obj->iv, 16); + written += 16; ptr += 16; + { + + /* Encode u8 data[] */ + { + size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data); + trunnel_assert(written <= avail); + if (avail - written < elt_len) + goto truncated; + memcpy(ptr, obj->data.elts_, elt_len); + written += elt_len; ptr += elt_len; + } + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + avail = written + 32; + enforce_avail = 1; + } + + /* Encode u8 hmac[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) { + if (avail_orig - written < 32) + goto truncated; + else + goto check_failed; + } + memcpy(ptr, obj->hmac, 32); + written += 32; ptr += 32; + + + trunnel_assert(ptr == output + written); + if (enforce_avail && avail != written) + goto check_failed; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + { + trunnel_assert(encoded_len >= 0); + trunnel_assert((size_t)encoded_len == written); + } + +#endif + + return written; + + truncated: + result = -2; + goto fail; + check_failed: + (void)msg; + result = -1; + goto fail; + fail: + trunnel_assert(result < 0); + return result; +} + +/** As pwbox_encoded_parse(), but do not allocate the output object. + */ +static ssize_t +pwbox_encoded_parse_into(pwbox_encoded_t *obj, const uint8_t *input, const size_t len_in) +{ + const uint8_t *ptr = input; + size_t remaining = len_in; + ssize_t result = 0; + (void)result; + + /* Parse u32 fixedbytes0 IN [PWBOX0_CONST0] */ + CHECK_REMAINING(4, truncated); + obj->fixedbytes0 = trunnel_ntohl(trunnel_get_uint32(ptr)); + remaining -= 4; ptr += 4; + if (! (obj->fixedbytes0 == PWBOX0_CONST0)) + goto fail; + + /* Parse u32 fixedbytes1 IN [PWBOX0_CONST1] */ + CHECK_REMAINING(4, truncated); + obj->fixedbytes1 = trunnel_ntohl(trunnel_get_uint32(ptr)); + remaining -= 4; ptr += 4; + if (! (obj->fixedbytes1 == PWBOX0_CONST1)) + goto fail; + + /* Parse u8 header_len */ + CHECK_REMAINING(1, truncated); + obj->header_len = (trunnel_get_uint8(ptr)); + remaining -= 1; ptr += 1; + + /* Parse u8 skey_header[header_len] */ + CHECK_REMAINING(obj->header_len, truncated); + TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->skey_header, obj->header_len, {}); + obj->skey_header.n_ = obj->header_len; + memcpy(obj->skey_header.elts_, ptr, obj->header_len); + ptr += obj->header_len; remaining -= obj->header_len; + + /* Parse u8 iv[16] */ + CHECK_REMAINING(16, truncated); + memcpy(obj->iv, ptr, 16); + remaining -= 16; ptr += 16; + { + size_t remaining_after; + CHECK_REMAINING(32, truncated); + remaining_after = 32; + remaining = remaining - 32; + + /* Parse u8 data[] */ + TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data, remaining, {}); + obj->data.n_ = remaining; + memcpy(obj->data.elts_, ptr, remaining); + ptr += remaining; remaining -= remaining; + if (remaining != 0) + goto fail; + remaining = remaining_after; + } + + /* Parse u8 hmac[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->hmac, ptr, 32); + remaining -= 32; ptr += 32; + trunnel_assert(ptr + remaining == input + len_in); + return len_in - remaining; + + truncated: + return -2; + trunnel_alloc_failed: + return -1; + fail: + result = -1; + return result; +} + +ssize_t +pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in) +{ + ssize_t result; + *output = pwbox_encoded_new(); + if (NULL == *output) + return -1; + result = pwbox_encoded_parse_into(*output, input, len_in); + if (result < 0) { + pwbox_encoded_free(*output); + *output = NULL; + } + return result; +} diff --git a/src/trunnel/pwbox.h b/src/trunnel/pwbox.h new file mode 100644 index 0000000000..5b170eb45e --- /dev/null +++ b/src/trunnel/pwbox.h @@ -0,0 +1,173 @@ +/* pwbox.h -- generated by by Trunnel v1.2. + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +#ifndef TRUNNEL_PWBOX_H +#define TRUNNEL_PWBOX_H + +#include <stdint.h> +#include "trunnel.h" + +#define PWBOX0_CONST0 1414484546 +#define PWBOX0_CONST1 1331179568 +#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_PWBOX_ENCODED) +struct pwbox_encoded_st { + uint32_t fixedbytes0; + uint32_t fixedbytes1; + uint8_t header_len; + TRUNNEL_DYNARRAY_HEAD(, uint8_t) skey_header; + uint8_t iv[16]; + TRUNNEL_DYNARRAY_HEAD(, uint8_t) data; + uint8_t hmac[32]; + uint8_t trunnel_error_code_; +}; +#endif +typedef struct pwbox_encoded_st pwbox_encoded_t; +/** Return a newly allocated pwbox_encoded with all elements set to + * zero. + */ +pwbox_encoded_t *pwbox_encoded_new(void); +/** Release all storage held by the pwbox_encoded in 'victim'. (Do + * nothing if 'victim' is NULL.) + */ +void pwbox_encoded_free(pwbox_encoded_t *victim); +/** Try to parse a pwbox_encoded from the buffer in 'input', using up + * to 'len_in' bytes from the input buffer. On success, return the + * number of bytes consumed and set *output to the newly allocated + * pwbox_encoded_t. On failure, return -2 if the input appears + * truncated, and -1 if the input is otherwise invalid. + */ +ssize_t pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in); +/** Return the number of bytes we expect to need to encode the + * pwbox_encoded in 'obj'. On failure, return a negative value. Note + * that this value may be an overestimate, and can even be an + * underestimate for certain unencodeable objects. + */ +ssize_t pwbox_encoded_encoded_len(const pwbox_encoded_t *obj); +/** Try to encode the pwbox_encoded from 'input' into the buffer at + * 'output', using up to 'avail' bytes of the output buffer. On + * success, return the number of bytes used. On failure, return -2 if + * the buffer was not long enough, and -1 if the input was invalid. + */ +ssize_t pwbox_encoded_encode(uint8_t *output, const size_t avail, const pwbox_encoded_t *input); +/** Check whether the internal state of the pwbox_encoded in 'obj' is + * consistent. Return NULL if it is, and a short message if it is not. + */ +const char *pwbox_encoded_check(const pwbox_encoded_t *obj); +/** Clear any errors that were set on the object 'obj' by its setter + * functions. Return true iff errors were cleared. + */ +int pwbox_encoded_clear_errors(pwbox_encoded_t *obj); +/** Return the value of the fixedbytes0 field of the pwbox_encoded_t + * in 'inp' + */ +uint32_t pwbox_encoded_get_fixedbytes0(pwbox_encoded_t *inp); +/** Set the value of the fixedbytes0 field of the pwbox_encoded_t in + * 'inp' to 'val'. Return 0 on success; return -1 and set the error + * code on 'inp' on failure. + */ +int pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val); +/** Return the value of the fixedbytes1 field of the pwbox_encoded_t + * in 'inp' + */ +uint32_t pwbox_encoded_get_fixedbytes1(pwbox_encoded_t *inp); +/** Set the value of the fixedbytes1 field of the pwbox_encoded_t in + * 'inp' to 'val'. Return 0 on success; return -1 and set the error + * code on 'inp' on failure. + */ +int pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val); +/** Return the value of the header_len field of the pwbox_encoded_t in + * 'inp' + */ +uint8_t pwbox_encoded_get_header_len(pwbox_encoded_t *inp); +/** Set the value of the header_len field of the pwbox_encoded_t in + * 'inp' to 'val'. Return 0 on success; return -1 and set the error + * code on 'inp' on failure. + */ +int pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val); +/** Return the length of the dynamic array holding the skey_header + * field of the pwbox_encoded_t in 'inp'. + */ +size_t pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp); +/** Return the element at position 'idx' of the dynamic array field + * skey_header of the pwbox_encoded_t in 'inp'. + */ +uint8_t pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx); +/** Change the element at position 'idx' of the dynamic array field + * skey_header of the pwbox_encoded_t in 'inp', so that it will hold + * the value 'elt'. + */ +int pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt); +/** Append a new element 'elt' to the dynamic array field skey_header + * of the pwbox_encoded_t in 'inp'. + */ +int pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt); +/** Return a pointer to the variable-length array field skey_header of + * 'inp'. + */ +uint8_t * pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp); +/** Change the length of the variable-length array field skey_header + * of 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on + * success; return -1 and set the error code on 'inp' on failure. + */ +int pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen); +/** Return the (constant) length of the array holding the iv field of + * the pwbox_encoded_t in 'inp'. + */ +size_t pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp); +/** Return the element at position 'idx' of the fixed array field iv + * of the pwbox_encoded_t in 'inp'. + */ +uint8_t pwbox_encoded_get_iv(const pwbox_encoded_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field iv + * of the pwbox_encoded_t in 'inp', so that it will hold the value + * 'elt'. + */ +int pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 16-element array field iv of 'inp'. + */ +uint8_t * pwbox_encoded_getarray_iv(pwbox_encoded_t *inp); +/** Return the length of the dynamic array holding the data field of + * the pwbox_encoded_t in 'inp'. + */ +size_t pwbox_encoded_getlen_data(const pwbox_encoded_t *inp); +/** Return the element at position 'idx' of the dynamic array field + * data of the pwbox_encoded_t in 'inp'. + */ +uint8_t pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx); +/** Change the element at position 'idx' of the dynamic array field + * data of the pwbox_encoded_t in 'inp', so that it will hold the + * value 'elt'. + */ +int pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt); +/** Append a new element 'elt' to the dynamic array field data of the + * pwbox_encoded_t in 'inp'. + */ +int pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt); +/** Return a pointer to the variable-length array field data of 'inp'. + */ +uint8_t * pwbox_encoded_getarray_data(pwbox_encoded_t *inp); +/** Change the length of the variable-length array field data of 'inp' + * to 'newlen'.Fill extra elements with 0. Return 0 on success; return + * -1 and set the error code on 'inp' on failure. + */ +int pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen); +/** Return the (constant) length of the array holding the hmac field + * of the pwbox_encoded_t in 'inp'. + */ +size_t pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp); +/** Return the element at position 'idx' of the fixed array field hmac + * of the pwbox_encoded_t in 'inp'. + */ +uint8_t pwbox_encoded_get_hmac(const pwbox_encoded_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field hmac + * of the pwbox_encoded_t in 'inp', so that it will hold the value + * 'elt'. + */ +int pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field hmac of 'inp'. + */ +uint8_t * pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp); + + +#endif diff --git a/src/trunnel/pwbox.trunnel b/src/trunnel/pwbox.trunnel new file mode 100644 index 0000000000..10db74b4e5 --- /dev/null +++ b/src/trunnel/pwbox.trunnel @@ -0,0 +1,14 @@ + +const PWBOX0_CONST0 = 0x544f5242; // TORB +const PWBOX0_CONST1 = 0x4f583030; // OX00 + +struct pwbox_encoded { + u32 fixedbytes0 IN [PWBOX0_CONST0]; + u32 fixedbytes1 IN [PWBOX0_CONST1]; + u8 header_len; + u8 skey_header[header_len]; + u8 iv[16]; + u8 data[..-32]; + u8 hmac[32]; +}; + diff --git a/src/trunnel/trunnel-local.h b/src/trunnel/trunnel-local.h new file mode 100644 index 0000000000..b7c2ab98ef --- /dev/null +++ b/src/trunnel/trunnel-local.h @@ -0,0 +1,18 @@ + +#ifndef TRUNNEL_LOCAL_H_INCLUDED +#define TRUNNEL_LOCAL_H_INCLUDED + +#include "util.h" +#include "compat.h" +#include "crypto.h" + +#define trunnel_malloc tor_malloc +#define trunnel_calloc tor_calloc +#define trunnel_strdup tor_strdup +#define trunnel_free_ tor_free_ +#define trunnel_realloc tor_realloc +#define trunnel_reallocarray tor_reallocarray +#define trunnel_assert tor_assert +#define trunnel_memwipe(mem, len) memwipe((mem), 0, (len)) + +#endif diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index 43ccbc59a1..aa29d0ccaf 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -14,8 +14,6 @@ /* Define to 1 if you have the <ctype.h> header file. */ #define HAVE_CTYPE_H -#define ENABLE_THREADS - /* Define to 1 if you have the <errno.h> header file. */ #define HAVE_ERRNO_H @@ -86,18 +84,11 @@ #define HAVE_STRING_H /* Define to 1 if you have the `strlcat' function. */ -#if defined (WINCE) -#define HAVE_STRLCAT -#else #undef HAVE_STRLCAT -#endif /* Define to 1 if you have the `strlcpy' function. */ -#if defined (WINCE) -#define HAVE_STRLCPY -#else #undef HAVE_STRLCPY -#endif + /* Define to 1 if you have the `strptime' function. */ #undef HAVE_STRPTIME @@ -241,7 +232,7 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.5.7-rc-dev" +#define VERSION "0.2.6.0-alpha-dev" |