summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/compat.c35
-rw-r--r--src/common/compress.c6
-rw-r--r--src/common/container.c4
-rw-r--r--src/common/crypto.c29
-rw-r--r--src/common/crypto.h9
-rw-r--r--src/common/crypto_ed25519.c60
-rw-r--r--src/common/crypto_ed25519.h2
-rw-r--r--src/common/memarea.c3
-rw-r--r--src/common/sandbox.c8
-rw-r--r--src/common/tortls.c7
-rw-r--r--src/common/util.c6
-rw-r--r--src/common/util.h12
-rw-r--r--src/common/util_bug.c4
-rw-r--r--src/common/util_bug.h5
14 files changed, 148 insertions, 42 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 4d110aba35..836b3813e0 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -2349,15 +2349,34 @@ get_parent_directory(char *fname)
static char *
alloc_getcwd(void)
{
-#ifdef PATH_MAX
-#define MAX_CWD PATH_MAX
+#ifdef HAVE_GET_CURRENT_DIR_NAME
+ /* Glibc makes this nice and simple for us. */
+ char *cwd = get_current_dir_name();
+ char *result = NULL;
+ if (cwd) {
+ /* We make a copy here, in case tor_malloc() is not malloc(). */
+ result = tor_strdup(cwd);
+ raw_free(cwd); // alias for free to avoid tripping check-spaces.
+ }
+ return result;
#else
-#define MAX_CWD 4096
-#endif
+ size_t size = 1024;
+ char *buf = NULL;
+ char *ptr = NULL;
- char path_buf[MAX_CWD];
- char *path = getcwd(path_buf, sizeof(path_buf));
- return path ? tor_strdup(path) : NULL;
+ while (ptr == NULL) {
+ buf = tor_realloc(buf, size);
+ ptr = getcwd(buf, size);
+
+ if (ptr == NULL && errno != ERANGE) {
+ tor_free(buf);
+ return NULL;
+ }
+
+ size *= 2;
+ }
+ return buf;
+#endif
}
#endif
@@ -2600,7 +2619,7 @@ tor_inet_pton(int af, const char *src, void *dst)
long r = strtol(src, &next, 16);
if (next == NULL || next == src) {
/* The 'next == src' error case can happen on versions of openbsd
- * where treats "0xfoo" as an error, rather than as "0" followed by
+ * which treat "0xfoo" as an error, rather than as "0" followed by
* "xfoo". */
return 0;
}
diff --git a/src/common/compress.c b/src/common/compress.c
index 7926faaa60..472268a439 100644
--- a/src/common/compress.c
+++ b/src/common/compress.c
@@ -574,6 +574,12 @@ tor_compress_process(tor_compress_state_t *state,
if (BUG((rv == TOR_COMPRESS_OK) &&
*in_len == in_len_orig &&
*out_len == out_len_orig)) {
+ log_warn(LD_GENERAL,
+ "More info on the bug: method == %s, finish == %d, "
+ " *in_len == in_len_orig == %lu, "
+ "*out_len == out_len_orig == %lu",
+ compression_method_get_human_name(state->method), finish,
+ (unsigned long)in_len_orig, (unsigned long)out_len_orig);
return TOR_COMPRESS_ERROR;
}
diff --git a/src/common/container.c b/src/common/container.c
index 689e7e55e9..8645cb4826 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -843,13 +843,13 @@ smartlist_sort_pointers(smartlist_t *sl)
* }
*
* void timer_heap_insert(smartlist_t *heap, timer_t *timer) {
- * smartlist_pqueue_add(heap, compare, STRUCT_OFFSET(timer_t, heap_index),
+ * smartlist_pqueue_add(heap, compare, offsetof(timer_t, heap_index),
* timer);
* }
*
* void timer_heap_pop(smartlist_t *heap) {
* return smartlist_pqueue_pop(heap, compare,
- * STRUCT_OFFSET(timer_t, heap_index));
+ * offsetof(timer_t, heap_index));
* }
*/
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 0fc8474832..4d6a70bc49 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -1238,9 +1238,12 @@ crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
* - The beginning of the source data prefixed with a 16-byte symmetric key,
* padded and encrypted with the public key; followed by the rest of
* the source data encrypted in AES-CTR mode with the symmetric key.
+ *
+ * NOTE that this format does not authenticate the symmetrically encrypted
+ * part of the data, and SHOULD NOT BE USED for new protocols.
*/
int
-crypto_pk_public_hybrid_encrypt(crypto_pk_t *env,
+crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env,
char *to, size_t tolen,
const char *from,
size_t fromlen,
@@ -1302,10 +1305,14 @@ crypto_pk_public_hybrid_encrypt(crypto_pk_t *env,
return -1;
}
-/** Invert crypto_pk_public_hybrid_encrypt. Returns the number of bytes
- * written on success, -1 on failure. */
+/** Invert crypto_pk_obsolete_public_hybrid_encrypt. Returns the number of
+ * bytes written on success, -1 on failure.
+ *
+ * NOTE that this format does not authenticate the symmetrically encrypted
+ * part of the data, and SHOULD NOT BE USED for new protocols.
+ */
int
-crypto_pk_private_hybrid_decrypt(crypto_pk_t *env,
+crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env,
char *to,
size_t tolen,
const char *from,
@@ -1854,6 +1861,18 @@ struct crypto_digest_t {
} d;
};
+#ifdef TOR_UNIT_TESTS
+
+digest_algorithm_t
+crypto_digest_get_algorithm(crypto_digest_t *digest)
+{
+ tor_assert(digest);
+
+ return digest->algorithm;
+}
+
+#endif
+
/**
* Return the number of bytes we need to malloc in order to get a
* crypto_digest_t for <b>alg</b>, or the number of bytes we need to wipe
@@ -1865,7 +1884,7 @@ crypto_digest_alloc_bytes(digest_algorithm_t alg)
/* Helper: returns the number of bytes in the 'f' field of 'st' */
#define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f ))
/* Gives the length of crypto_digest_t through the end of the field 'd' */
-#define END_OF_FIELD(f) (STRUCT_OFFSET(crypto_digest_t, f) + \
+#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
STRUCT_FIELD_SIZE(crypto_digest_t, f))
switch (alg) {
case DIGEST_SHA1:
diff --git a/src/common/crypto.h b/src/common/crypto.h
index c70d91c262..cde241dd37 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -20,6 +20,9 @@
#include "testsupport.h"
#include "compat.h"
+#include <openssl/engine.h>
+#include "keccak-tiny/keccak-tiny.h"
+
/*
Macro to create an arbitrary OpenSSL version number as used by
OPENSSL_VERSION_NUMBER or SSLeay(), since the actual numbers are a bit hard
@@ -194,11 +197,11 @@ int crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
const char *from, size_t fromlen);
int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
const char *from, size_t fromlen);
-int crypto_pk_public_hybrid_encrypt(crypto_pk_t *env, char *to,
+int crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env, char *to,
size_t tolen,
const char *from, size_t fromlen,
int padding, int force);
-int crypto_pk_private_hybrid_decrypt(crypto_pk_t *env, char *to,
+int crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env, char *to,
size_t tolen,
const char *from, size_t fromlen,
int padding, int warnOnFailure);
@@ -335,6 +338,7 @@ struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
#ifdef CRYPTO_PRIVATE
+
STATIC int crypto_force_rand_ssleay(void);
STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len);
@@ -346,6 +350,7 @@ extern int break_strongest_rng_fallback;
#ifdef TOR_UNIT_TESTS
void crypto_pk_assign_(crypto_pk_t *dest, const crypto_pk_t *src);
+digest_algorithm_t crypto_digest_get_algorithm(crypto_digest_t *digest);
#endif
#endif
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 188e18c710..d61549b797 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/common/crypto_ed25519.c
@@ -28,6 +28,7 @@
#include "crypto_format.h"
#include "torlog.h"
#include "util.h"
+#include "util_format.h"
#include "ed25519/ref10/ed25519_ref10.h"
#include "ed25519/donna/ed25519_donna_tor.h"
@@ -57,6 +58,9 @@ typedef struct {
int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
int);
+
+ int (*ed25519_scalarmult_with_group_order)(unsigned char *,
+ const unsigned char *);
} ed25519_impl_t;
/** The Ref10 Ed25519 implementation. This one is pure C and lightly
@@ -77,6 +81,7 @@ static const ed25519_impl_t impl_ref10 = {
ed25519_ref10_blind_public_key,
ed25519_ref10_pubkey_from_curve25519_pubkey,
+ ed25519_ref10_scalarmult_with_group_order,
};
/** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
@@ -97,6 +102,7 @@ static const ed25519_impl_t impl_donna = {
ed25519_donna_blind_public_key,
ed25519_donna_pubkey_from_curve25519_pubkey,
+ ed25519_donna_scalarmult_with_group_order,
};
/** Which Ed25519 implementation are we using? NULL if we haven't decided
@@ -491,7 +497,8 @@ ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
* 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.
- */
+ *
+ * Return 0 if blinding was successful, else return -1. */
int
ed25519_keypair_blind(ed25519_keypair_t *out,
const ed25519_keypair_t *inp,
@@ -502,7 +509,9 @@ ed25519_keypair_blind(ed25519_keypair_t *out,
get_ed_impl()->blind_secret_key(out->seckey.seckey,
inp->seckey.seckey, param);
- ed25519_public_blind(&pubkey_check, &inp->pubkey, param);
+ if (ed25519_public_blind(&pubkey_check, &inp->pubkey, param) < 0) {
+ return -1;
+ }
ed25519_public_key_generate(&out->pubkey, &out->seckey);
tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
@@ -522,8 +531,7 @@ ed25519_public_blind(ed25519_public_key_t *out,
const ed25519_public_key_t *inp,
const uint8_t *param)
{
- get_ed_impl()->blind_public_key(out->pubkey, inp->pubkey, param);
- return 0;
+ return get_ed_impl()->blind_public_key(out->pubkey, inp->pubkey, param);
}
/**
@@ -754,3 +762,47 @@ ed25519_init(void)
pick_ed25519_impl();
}
+/* Return true if <b>point</b> is the identity element of the ed25519 group. */
+static int
+ed25519_point_is_identity_element(const uint8_t *point)
+{
+ /* The identity element in ed25159 is the point with coordinates (0,1). */
+ static const uint8_t ed25519_identity[32] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN);
+ return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity));
+}
+
+/** Validate <b>pubkey</b> to ensure that it has no torsion component.
+ * Return 0 if <b>pubkey</b> is valid, else return -1. */
+int
+ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
+{
+ uint8_t result[32] = {9};
+
+ /* First check that we were not given the identity element */
+ if (ed25519_point_is_identity_element(pubkey->pubkey)) {
+ log_warn(LD_CRYPTO, "ed25519 pubkey is the identity");
+ return -1;
+ }
+
+ /* For any point on the curve, doing l*point should give the identity element
+ * (where l is the group order). Do the computation and check that the
+ * identity element is returned. */
+ if (get_ed_impl()->ed25519_scalarmult_with_group_order(result,
+ pubkey->pubkey) < 0) {
+ log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed");
+ return -1;
+ }
+
+ if (!ed25519_point_is_identity_element(result)) {
+ log_warn(LD_CRYPTO, "ed25519 validation failed");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
index 77a3313adc..3a439207b3 100644
--- a/src/common/crypto_ed25519.h
+++ b/src/common/crypto_ed25519.h
@@ -127,6 +127,8 @@ void ed25519_pubkey_copy(ed25519_public_key_t *dest,
void ed25519_set_impl_params(int use_donna);
void ed25519_init(void);
+int ed25519_validate_pubkey(const ed25519_public_key_t *pubkey);
+
#ifdef TOR_UNIT_TESTS
void crypto_ed25519_testing_force_impl(const char *name);
void crypto_ed25519_testing_restore_impl(void);
diff --git a/src/common/memarea.c b/src/common/memarea.c
index 659d1edf54..4e2a5e5fc5 100644
--- a/src/common/memarea.c
+++ b/src/common/memarea.c
@@ -7,6 +7,7 @@
*/
#include "orconfig.h"
+#include <stddef.h>
#include <stdlib.h>
#include "memarea.h"
#include "util.h"
@@ -101,7 +102,7 @@ typedef struct memarea_chunk_t {
/** How many bytes are needed for overhead before we get to the memory part
* of a chunk? */
-#define CHUNK_HEADER_SIZE STRUCT_OFFSET(memarea_chunk_t, U_MEM)
+#define CHUNK_HEADER_SIZE offsetof(memarea_chunk_t, U_MEM)
/** What's the smallest that we'll allocate a chunk? */
#define CHUNK_SIZE 4096
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index 5063717355..c06f9694b1 100644
--- a/src/common/sandbox.c
+++ b/src/common/sandbox.c
@@ -480,7 +480,7 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add chmod syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -505,7 +505,7 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add chown syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -1045,8 +1045,8 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
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);
+ log_err(LD_BUG,"(Sandbox) failed to add stat64 syscall, received "
+ "libseccomp error %d", rc);
return rc;
}
}
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 44db3aec58..dfc85ee318 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -1174,17 +1174,20 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
SSL_CTX_set_options(result->ctx,
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
}
+
+ /* Don't actually allow compression; it uses RAM and time, it makes TLS
+ * vulnerable to CRIME-style attacks, and most of the data we transmit over
+ * TLS is encrypted (and therefore uncompressible) anyway. */
#ifdef SSL_OP_NO_COMPRESSION
SSL_CTX_set_options(result->ctx, SSL_OP_NO_COMPRESSION);
#endif
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
#ifndef OPENSSL_NO_COMP
- /* Don't actually allow compression; it uses ram and time, but the data
- * we transmit is all encrypted anyway. */
if (result->ctx->comp_methods)
result->ctx->comp_methods = NULL;
#endif
#endif
+
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
diff --git a/src/common/util.c b/src/common/util.c
index 5b47028097..0858d17fe6 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1172,7 +1172,7 @@ tor_parse_long(const char *s, int base, long min, long max,
char *endptr;
long r;
- if (base < 0) {
+ if (BUG(base < 0)) {
if (ok)
*ok = 0;
return 0;
@@ -1191,7 +1191,7 @@ tor_parse_ulong(const char *s, int base, unsigned long min,
char *endptr;
unsigned long r;
- if (base < 0) {
+ if (BUG(base < 0)) {
if (ok)
*ok = 0;
return 0;
@@ -1223,7 +1223,7 @@ tor_parse_uint64(const char *s, int base, uint64_t min,
char *endptr;
uint64_t r;
- if (base < 0) {
+ if (BUG(base < 0)) {
if (ok)
*ok = 0;
return 0;
diff --git a/src/common/util.h b/src/common/util.h
index d56abcee2e..df581d2405 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -109,19 +109,11 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
void tor_log_mallinfo(int severity);
-/** Return the offset of <b>member</b> within the type <b>tp</b>, in bytes */
-#if defined(__GNUC__) && __GNUC__ > 3
-#define STRUCT_OFFSET(tp, member) __builtin_offsetof(tp, member)
-#else
- #define STRUCT_OFFSET(tp, member) \
- ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
-#endif
-
/** Macro: yield a pointer to the field at position <b>off</b> within the
* structure <b>st</b>. Example:
* <pre>
* struct a { int foo; int bar; } x;
- * off_t bar_offset = STRUCT_OFFSET(struct a, bar);
+ * off_t bar_offset = offsetof(struct a, bar);
* int *bar_p = STRUCT_VAR_P(&x, bar_offset);
* *bar_p = 3;
* </pre>
@@ -138,7 +130,7 @@ void tor_log_mallinfo(int severity);
* </pre>
*/
#define SUBTYPE_P(p, subtype, basemember) \
- ((void*) ( ((char*)(p)) - STRUCT_OFFSET(subtype, basemember) ))
+ ((void*) ( ((char*)(p)) - offsetof(subtype, basemember) ))
/* Logic */
/** Macro: true if two values have the same boolean value. */
diff --git a/src/common/util_bug.c b/src/common/util_bug.c
index 3d990e3700..cc1ac2ff84 100644
--- a/src/common/util_bug.c
+++ b/src/common/util_bug.c
@@ -13,6 +13,10 @@
#include "backtrace.h"
#include "container.h"
+#ifdef __COVERITY__
+int bug_macro_deadcode_dummy__ = 0;
+#endif
+
#ifdef TOR_UNIT_TESTS
static void (*failed_assertion_cb)(void) = NULL;
static int n_bugs_to_capture = 0;
diff --git a/src/common/util_bug.h b/src/common/util_bug.h
index ae7e7a37fd..de39317d1c 100644
--- a/src/common/util_bug.h
+++ b/src/common/util_bug.h
@@ -59,10 +59,13 @@
*/
#ifdef __COVERITY__
+extern int bug_macro_deadcode_dummy__;
#undef BUG
// Coverity defines this in global headers; let's override it. This is a
// magic coverity-only preprocessor thing.
-#nodef BUG(x) ((x)?(__coverity_panic__(),1):0)
+// We use this "deadcode_dummy__" trick to prevent coverity from
+// complaining about unreachable bug cases.
+#nodef BUG(x) ((x)?(__coverity_panic__(),1):(0+bug_macro_deadcode_dummy__))
#endif
#if defined(__COVERITY__) || defined(__clang_analyzer__)