aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/buf/buffers.c11
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.h4
-rw-r--r--src/lib/crypt_ops/crypto_format.c88
-rw-r--r--src/lib/crypt_ops/crypto_format.h12
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c8
-rw-r--r--src/lib/encoding/binascii.c6
-rw-r--r--src/lib/fdio/fdio.c4
-rw-r--r--src/lib/log/util_bug.c14
-rw-r--r--src/lib/log/util_bug.h8
-rw-r--r--src/lib/math/prob_distr.h2
-rw-r--r--src/lib/smartlist_core/smartlist_core.c2
-rw-r--r--src/lib/time/compat_time.c10
-rw-r--r--src/lib/time/compat_time.h50
-rw-r--r--src/lib/tls/tortls_nss.c40
14 files changed, 202 insertions, 57 deletions
diff --git a/src/lib/buf/buffers.c b/src/lib/buf/buffers.c
index e7a3b87df0..88a25b8470 100644
--- a/src/lib/buf/buffers.c
+++ b/src/lib/buf/buffers.c
@@ -283,7 +283,7 @@ buf_t *
buf_new_with_data(const char *cp, size_t sz)
{
/* Validate arguments */
- if (!cp || sz <= 0) {
+ if (!cp || sz <= 0 || sz >= INT_MAX) {
return NULL;
}
@@ -657,7 +657,7 @@ buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
char b[4096];
size_t cp, len;
- if (BUG(buf_out->datalen >= INT_MAX))
+ if (BUG(buf_out->datalen >= INT_MAX || *buf_flushlen >= INT_MAX))
return -1;
if (BUG(buf_out->datalen >= INT_MAX - *buf_flushlen))
return -1;
@@ -689,6 +689,10 @@ buf_move_all(buf_t *buf_out, buf_t *buf_in)
tor_assert(buf_out);
if (!buf_in)
return;
+ if (BUG(buf_out->datalen >= INT_MAX || buf_in->datalen >= INT_MAX))
+ return;
+ if (BUG(buf_out->datalen >= INT_MAX - buf_in->datalen))
+ return;
if (buf_out->head == NULL) {
buf_out->head = buf_in->head;
@@ -756,6 +760,7 @@ buf_find_pos_of_char(char ch, buf_pos_t *out)
static inline int
buf_pos_inc(buf_pos_t *pos)
{
+ tor_assert(pos->pos < INT_MAX - 1);
++pos->pos;
if (pos->pos == (off_t)pos->chunk->datalen) {
if (!pos->chunk->next)
@@ -836,6 +841,7 @@ buf_find_offset_of_char(buf_t *buf, char ch)
{
chunk_t *chunk;
off_t offset = 0;
+ tor_assert(buf->datalen < INT_MAX);
for (chunk = buf->head; chunk; chunk = chunk->next) {
char *cp = memchr(chunk->data, ch, chunk->datalen);
if (cp)
@@ -905,6 +911,7 @@ buf_assert_ok(buf_t *buf)
for (ch = buf->head; ch; ch = ch->next) {
total += ch->datalen;
tor_assert(ch->datalen <= ch->memlen);
+ tor_assert(ch->datalen < INT_MAX);
tor_assert(ch->data >= &ch->mem[0]);
tor_assert(ch->data <= &ch->mem[0]+ch->memlen);
if (ch->data == &ch->mem[0]+ch->memlen) {
diff --git a/src/lib/crypt_ops/crypto_curve25519.h b/src/lib/crypt_ops/crypto_curve25519.h
index 061a7a3505..cd23169cd5 100644
--- a/src/lib/crypt_ops/crypto_curve25519.h
+++ b/src/lib/crypt_ops/crypto_curve25519.h
@@ -76,8 +76,8 @@ STATIC int curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret);
int curve25519_public_from_base64(curve25519_public_key_t *pkey,
const char *input);
-int curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey);
+void curve25519_public_to_base64(char *output,
+ const curve25519_public_key_t *pkey);
void curve25519_set_impl_params(int use_ed);
void curve25519_init(void);
diff --git a/src/lib/crypt_ops/crypto_format.c b/src/lib/crypt_ops/crypto_format.c
index 84f73e5272..e11b391194 100644
--- a/src/lib/crypt_ops/crypto_format.c
+++ b/src/lib/crypt_ops/crypto_format.c
@@ -131,20 +131,27 @@ crypto_read_tagged_contents_from_file(const char *fname,
return r;
}
-/** Encode <b>pkey</b> as a base64-encoded string, without trailing "="
+/** Encode <b>pkey</b> as a base64-encoded string, including trailing "="
* characters, in the buffer <b>output</b>, which must have at least
- * CURVE25519_BASE64_PADDED_LEN+1 bytes available. Return 0 on success, -1 on
- * failure. */
-int
+ * CURVE25519_BASE64_PADDED_LEN+1 bytes available.
+ * Can not fail.
+ *
+ * Careful! CURVE25519_BASE64_PADDED_LEN is one byte longer than
+ * ED25519_BASE64_LEN.
+ */
+void
curve25519_public_to_base64(char *output,
const curve25519_public_key_t *pkey)
{
char buf[128];
- base64_encode(buf, sizeof(buf),
- (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN, 0);
- buf[CURVE25519_BASE64_PADDED_LEN] = '\0';
+ int n = base64_encode(buf, sizeof(buf),
+ (const char*)pkey->public_key,
+ CURVE25519_PUBKEY_LEN, 0);
+ /* These asserts should always succeed, unless there is a bug in
+ * base64_encode(). */
+ tor_assert(n == CURVE25519_BASE64_PADDED_LEN);
+ tor_assert(buf[CURVE25519_BASE64_PADDED_LEN] == '\0');
memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1);
- return 0;
}
/** Try to decode a base64-encoded curve25519 public key from <b>input</b>
@@ -181,8 +188,7 @@ ed25519_fmt(const ed25519_public_key_t *pkey)
if (ed25519_public_key_is_zero(pkey)) {
strlcpy(formatted, "<unset>", sizeof(formatted));
} else {
- int r = ed25519_public_to_base64(formatted, pkey);
- tor_assert(!r);
+ ed25519_public_to_base64(formatted, pkey);
}
} else {
strlcpy(formatted, "<null>", sizeof(formatted));
@@ -202,28 +208,35 @@ ed25519_public_from_base64(ed25519_public_key_t *pkey,
/** 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.
+ * plus one byte for a terminating NUL.
+ * Can not fail.
+ *
+ * Careful! ED25519_BASE64_LEN is one byte shorter than
+ * CURVE25519_BASE64_PADDED_LEN.
*/
-int
+void
ed25519_public_to_base64(char *output,
const ed25519_public_key_t *pkey)
{
- return digest256_to_base64(output, (const char *)pkey->pubkey);
+ digest256_to_base64(output, (const char *)pkey->pubkey);
}
/** Encode the signature <b>sig</b> into the buffer at <b>output</b>,
* which must have space for ED25519_SIG_BASE64_LEN bytes of encoded signature,
- * plus one byte for a terminating NUL. Return 0 on success, -1 on failure.
+ * plus one byte for a terminating NUL.
+ * Can not fail.
*/
-int
+void
ed25519_signature_to_base64(char *output,
const ed25519_signature_t *sig)
{
char buf[256];
int n = base64_encode_nopad(buf, sizeof(buf), sig->sig, ED25519_SIG_LEN);
+ /* These asserts should always succeed, unless there is a bug in
+ * base64_encode_nopad(). */
tor_assert(n == ED25519_SIG_BASE64_LEN);
+ tor_assert(buf[ED25519_SIG_BASE64_LEN] == '\0');
memcpy(output, buf, ED25519_SIG_BASE64_LEN+1);
- return 0;
}
/** Try to decode the string <b>input</b> into an ed25519 signature. On
@@ -233,16 +246,11 @@ int
ed25519_signature_from_base64(ed25519_signature_t *sig,
const char *input)
{
-
if (strlen(input) != ED25519_SIG_BASE64_LEN)
return -1;
- char buf[ED25519_SIG_BASE64_LEN+3];
- memcpy(buf, input, ED25519_SIG_BASE64_LEN);
- buf[ED25519_SIG_BASE64_LEN+0] = '=';
- buf[ED25519_SIG_BASE64_LEN+1] = '=';
- buf[ED25519_SIG_BASE64_LEN+2] = 0;
char decoded[128];
- int n = base64_decode(decoded, sizeof(decoded), buf, strlen(buf));
+ int n = base64_decode(decoded, sizeof(decoded), input,
+ ED25519_SIG_BASE64_LEN);
if (n < 0 || n != ED25519_SIG_LEN)
return -1;
memcpy(sig->sig, decoded, ED25519_SIG_LEN);
@@ -250,24 +258,26 @@ ed25519_signature_from_base64(ed25519_signature_t *sig,
return 0;
}
-/** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing =
+/** Base64 encode DIGEST_LEN bytes from <b>digest</b>, remove the trailing =
* characters, and store the nul-terminated result in the first
- * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */
-/* XXXX unify with crypto_format.c code */
-int
+ * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>.
+ * Can not fail. */
+void
digest_to_base64(char *d64, const char *digest)
{
char buf[256];
- base64_encode(buf, sizeof(buf), digest, DIGEST_LEN, 0);
- buf[BASE64_DIGEST_LEN] = '\0';
+ int n = base64_encode_nopad(buf, sizeof(buf),
+ (const uint8_t *)digest, DIGEST_LEN);
+ /* These asserts should always succeed, unless there is a bug in
+ * base64_encode_nopad(). */
+ tor_assert(n == BASE64_DIGEST_LEN);
+ tor_assert(buf[BASE64_DIGEST_LEN] == '\0');
memcpy(d64, buf, BASE64_DIGEST_LEN+1);
- return 0;
}
/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without
* trailing newline or = characters), decode it and store the result in the
* first DIGEST_LEN bytes at <b>digest</b>. */
-/* XXXX unify with crypto_format.c code */
int
digest_from_base64(char *digest, const char *d64)
{
@@ -279,22 +289,24 @@ digest_from_base64(char *digest, const char *d64)
/** Base64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the
* trailing = characters, and store the nul-terminated result in the first
- * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
- /* XXXX unify with crypto_format.c code */
-int
+ * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>.
+ * Can not fail. */
+void
digest256_to_base64(char *d64, const char *digest)
{
char buf[256];
- base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN, 0);
- buf[BASE64_DIGEST256_LEN] = '\0';
+ int n = base64_encode_nopad(buf, sizeof(buf),
+ (const uint8_t *)digest, DIGEST256_LEN);
+ /* These asserts should always succeed, unless there is a bug in
+ * base64_encode_nopad(). */
+ tor_assert(n == BASE64_DIGEST256_LEN);
+ tor_assert(buf[BASE64_DIGEST256_LEN] == '\0');
memcpy(d64, buf, BASE64_DIGEST256_LEN+1);
- return 0;
}
/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without
* trailing newline or = characters), decode it and store the result in the
* first DIGEST256_LEN bytes at <b>digest</b>. */
-/* XXXX unify with crypto_format.c code */
int
digest256_from_base64(char *digest, const char *d64)
{
diff --git a/src/lib/crypt_ops/crypto_format.h b/src/lib/crypt_ops/crypto_format.h
index fe852e6a61..b4b3aa189c 100644
--- a/src/lib/crypt_ops/crypto_format.h
+++ b/src/lib/crypt_ops/crypto_format.h
@@ -33,18 +33,18 @@ ssize_t crypto_read_tagged_contents_from_file(const char *fname,
int ed25519_public_from_base64(struct ed25519_public_key_t *pkey,
const char *input);
-int ed25519_public_to_base64(char *output,
- const struct ed25519_public_key_t *pkey);
+void ed25519_public_to_base64(char *output,
+ const struct ed25519_public_key_t *pkey);
const char *ed25519_fmt(const struct ed25519_public_key_t *pkey);
int ed25519_signature_from_base64(struct ed25519_signature_t *sig,
const char *input);
-int ed25519_signature_to_base64(char *output,
- const struct ed25519_signature_t *sig);
+void ed25519_signature_to_base64(char *output,
+ const struct ed25519_signature_t *sig);
-int digest_to_base64(char *d64, const char *digest);
+void digest_to_base64(char *d64, const char *digest);
int digest_from_base64(char *digest, const char *d64);
-int digest256_to_base64(char *d64, const char *digest);
+void digest256_to_base64(char *d64, const char *digest);
int digest256_from_base64(char *digest, const char *d64);
#endif /* !defined(TOR_CRYPTO_FORMAT_H) */
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index 60e4ea795e..c97815f9a4 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -213,6 +213,14 @@ crypto_openssl_early_init(void)
!strcmp(version_str, OPENSSL_VERSION_TEXT)) {
log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
"(%lx: %s).", version_num, version_str);
+ } else if ((version_num & 0xffff0000) ==
+ (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
+ log_notice(LD_CRYPTO,
+ "We compiled with OpenSSL %lx: %s and we "
+ "are running with OpenSSL %lx: %s. "
+ "These two versions should be binary compatible.",
+ (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
+ version_num, version_str);
} else {
log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
"version we're running with. If you get weird crashes, that "
diff --git a/src/lib/encoding/binascii.c b/src/lib/encoding/binascii.c
index 187df34243..fc64e014e7 100644
--- a/src/lib/encoding/binascii.c
+++ b/src/lib/encoding/binascii.c
@@ -321,8 +321,10 @@ base64_encode(char *dest, size_t destlen, const char *src, size_t srclen,
return (int) enclen;
}
-/** As base64_encode, but do not add any internal spaces or external padding
- * to the output stream. */
+/** As base64_encode, but do not add any internal spaces, and remove external
+ * padding from the output stream.
+ * dest must be at least base64_encode_size(srclen, 0), including space for
+ * the removed external padding. */
int
base64_encode_nopad(char *dest, size_t destlen,
const uint8_t *src, size_t srclen)
diff --git a/src/lib/fdio/fdio.c b/src/lib/fdio/fdio.c
index 6c87af791d..078af6a9ba 100644
--- a/src/lib/fdio/fdio.c
+++ b/src/lib/fdio/fdio.c
@@ -17,12 +17,16 @@
#ifdef _WIN32
#include <windows.h>
#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
#include "lib/fdio/fdio.h"
#include "lib/cc/torint.h"
#include "lib/err/torerr.h"
#include <stdlib.h>
+#include <stdio.h>
/** @{ */
/** Some old versions of Unix didn't define constants for these values,
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index 65ab7bc9c6..76b97c1a08 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -19,6 +19,7 @@
#include "lib/string/printf.h"
#include <string.h>
+#include <stdlib.h>
#ifdef TOR_UNIT_TESTS
static void (*failed_assertion_cb)(void) = NULL;
@@ -159,6 +160,19 @@ tor_bug_occurred_(const char *fname, unsigned int line,
#endif
}
+/**
+ * Call the abort() function to kill the current process with a fatal
+ * error.
+ *
+ * (This is a separate function so that we declare it in util_bug.h without
+ * including stdlib in all the users of util_bug.h)
+ **/
+void
+tor_abort_(void)
+{
+ abort();
+}
+
#ifdef _WIN32
/** Take a filename and return a pointer to its final element. This
* function is called on __FILE__ to fix a MSVC nit where __FILE__
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index 63c5309c98..2e220b7286 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -106,7 +106,7 @@
} else { \
tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr, \
fmt, ##__VA_ARGS__); \
- abort(); \
+ tor_abort_(); \
} STMT_END
#endif /* defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) */
@@ -114,7 +114,7 @@
STMT_BEGIN { \
tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, \
"line should be unreached", NULL); \
- abort(); \
+ tor_abort_(); \
} STMT_END
/* Non-fatal bug assertions. The "unreached" variants mean "this line should
@@ -149,7 +149,7 @@
#define BUG(cond) \
(ASSERT_PREDICT_UNLIKELY_(cond) ? \
(tor_assertion_failed_(SHORT_FILE__,__LINE__,__func__,"!("#cond")"), \
- abort(), 1) \
+ tor_abort_(), 1) \
: 0)
#elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
#define tor_assert_nonfatal_unreached() STMT_NIL
@@ -246,6 +246,8 @@ void tor_bug_occurred_(const char *fname, unsigned int line,
const char *func, const char *expr,
int once, const char *fmt, ...);
+void tor_abort_(void) ATTR_NORETURN;
+
#ifdef _WIN32
#define SHORT_FILE__ (tor_fix_source_file(__FILE__))
const char *tor_fix_source_file(const char *fname);
diff --git a/src/lib/math/prob_distr.h b/src/lib/math/prob_distr.h
index 2eb935e4a8..8fccf8d015 100644
--- a/src/lib/math/prob_distr.h
+++ b/src/lib/math/prob_distr.h
@@ -53,7 +53,7 @@ struct dist {
* We define this conditionally to suppress false positives from
* Coverity, which gets confused by the sizeof business.
*/
-#ifdef __COVERITY___
+#ifdef __COVERITY__
#define TYPE_CHECK_OBJ(OPS, OBJ, TYPE) 0
#else
#define TYPE_CHECK_OBJ(OPS, OBJ, TYPE) \
diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c
index 5947e76271..6b0a305a93 100644
--- a/src/lib/smartlist_core/smartlist_core.c
+++ b/src/lib/smartlist_core/smartlist_core.c
@@ -177,6 +177,8 @@ smartlist_remove_keeporder(smartlist_t *sl, const void *element)
sl->list[i++] = sl->list[j];
}
}
+ memset(sl->list + sl->num_used, 0,
+ sizeof(void *) * (num_used_orig - sl->num_used));
}
/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
diff --git a/src/lib/time/compat_time.c b/src/lib/time/compat_time.c
index c6625c7806..70802770cc 100644
--- a/src/lib/time/compat_time.c
+++ b/src/lib/time/compat_time.c
@@ -164,6 +164,8 @@ static int64_t last_tick_count = 0;
* to be monotonic; increments them as appropriate so that they actually
* _are_ monotonic.
*
+ * The returned time may be the same as the previous returned time.
+ *
* Caller must hold lock. */
STATIC int64_t
ratchet_performance_counter(int64_t count_raw)
@@ -202,6 +204,8 @@ static struct timeval timeofday_offset = { 0, 0 };
* supposed to be monotonic; increments them as appropriate so that they
* actually _are_ monotonic.
*
+ * The returned time may be the same as the previous returned time.
+ *
* Caller must hold lock. */
STATIC void
ratchet_timeval(const struct timeval *timeval_raw, struct timeval *out)
@@ -270,7 +274,9 @@ monotime_init_internal(void)
}
/**
- * Set "out" to the most recent monotonic time value
+ * Set "out" to the most recent monotonic time value.
+ *
+ * The returned time may be the same as the previous returned time.
*/
void
monotime_get(monotime_t *out)
@@ -302,6 +308,8 @@ monotime_coarse_get(monotime_coarse_t *out)
/**
* Return the number of nanoseconds between <b>start</b> and <b>end</b>.
+ *
+ * The returned value may be equal to zero.
*/
int64_t
monotime_diff_nsec(const monotime_t *start,
diff --git a/src/lib/time/compat_time.h b/src/lib/time/compat_time.h
index 2cd4b3bee3..360d92e5c9 100644
--- a/src/lib/time/compat_time.h
+++ b/src/lib/time/compat_time.h
@@ -15,11 +15,29 @@
* of tens of milliseconds.
*/
-/* Q: Should you use monotime or monotime_coarse as your source?
+/* Q: When should I use monotonic time?
+ *
+ * A: If you need a time that never decreases, use monotonic time. If you need
+ * to send a time to a user or another process, or store a time, use the
+ * wall-clock time.
+ *
+ * Q: Should you use monotime or monotime_coarse as your source?
*
* A: Generally, you get better precision with monotime, but better
* performance with monotime_coarse.
*
+ * Q: What is a "monotonic" time, exactly?
+ *
+ * A: Monotonic times are strictly non-decreasing. The difference between any
+ * previous monotonic time, and the current monotonic time, is always greater
+ * than *or equal to* zero.
+ * Zero deltas happen more often:
+ * - on Windows (due to an OS bug),
+ * - when using monotime_coarse, or on systems with low-resolution timers,
+ * - on platforms where we emulate monotonic time using wall-clock time, and
+ * - when using time units that are larger than nanoseconds (due to
+ * truncation on division).
+ *
* Q: Should you use monotime_t or monotime_coarse_t directly? Should you use
* usec? msec? "stamp units?"
*
@@ -95,7 +113,7 @@
* All, "timestamp units": Cheap everywhere: it never divides.
*
* Q: This is only somewhat related, but how much precision could I hope for
- * from a libevent time.?
+ * from a libevent time?
*
* A: Actually, it's _very_ related if you're timing in order to have a
* timeout happen.
@@ -182,26 +200,36 @@ void monotime_init(void);
void monotime_get(monotime_t *out);
/**
* Return the number of nanoseconds between <b>start</b> and <b>end</b>.
+ * The returned value may be equal to zero.
*/
int64_t monotime_diff_nsec(const monotime_t *start, const monotime_t *end);
/**
* Return the number of microseconds between <b>start</b> and <b>end</b>.
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end);
/**
* Return the number of milliseconds between <b>start</b> and <b>end</b>.
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
int64_t monotime_diff_msec(const monotime_t *start, const monotime_t *end);
/**
* Return the number of nanoseconds since the timer system was initialized.
+ * The returned value may be equal to zero.
*/
uint64_t monotime_absolute_nsec(void);
/**
* Return the number of microseconds since the timer system was initialized.
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
MOCK_DECL(uint64_t, monotime_absolute_usec,(void));
/**
* Return the number of milliseconds since the timer system was initialized.
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
uint64_t monotime_absolute_msec(void);
@@ -225,6 +253,9 @@ void monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec);
* Set <b>out</b> to the current coarse time.
*/
void monotime_coarse_get(monotime_coarse_t *out);
+/**
+ * Like monotime_absolute_*(), but faster on some platforms.
+ */
uint64_t monotime_coarse_absolute_nsec(void);
uint64_t monotime_coarse_absolute_usec(void);
uint64_t monotime_coarse_absolute_msec(void);
@@ -248,18 +279,27 @@ uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t);
/**
* Convert a difference, expressed in the units of monotime_coarse_to_stamp,
* into an approximate number of milliseconds.
+ *
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units);
uint64_t monotime_msec_to_approx_coarse_stamp_units(uint64_t msec);
uint32_t monotime_coarse_get_stamp(void);
#if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT)
+/**
+ * Like monotime_diff_*(), but faster on some platforms.
+ */
int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start,
const monotime_coarse_t *end);
int64_t monotime_coarse_diff_usec(const monotime_coarse_t *start,
const monotime_coarse_t *end);
int64_t monotime_coarse_diff_msec(const monotime_coarse_t *start,
const monotime_coarse_t *end);
+/**
+ * Like monotime_*(), but faster on some platforms.
+ */
void monotime_coarse_zero(monotime_coarse_t *out);
int monotime_coarse_is_zero(const monotime_coarse_t *val);
void monotime_coarse_add_msec(monotime_coarse_t *out,
@@ -278,6 +318,9 @@ void monotime_coarse_add_msec(monotime_coarse_t *out,
*
* Requires that the difference fit into an int32_t; not for use with
* large time differences.
+ *
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
const monotime_coarse_t *end);
@@ -287,6 +330,9 @@ int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
*
* Requires that the difference fit into an int32_t; not for use with
* large time differences.
+ *
+ * The returned value may be equal to zero.
+ * Fractional units are truncated, not rounded.
*/
static inline int32_t
monotime_coarse_diff_msec32(const monotime_coarse_t *start,
diff --git a/src/lib/tls/tortls_nss.c b/src/lib/tls/tortls_nss.c
index 00c4af0e97..3c62e98df1 100644
--- a/src/lib/tls/tortls_nss.c
+++ b/src/lib/tls/tortls_nss.c
@@ -152,6 +152,32 @@ we_like_auth_type(SSLAuthType at)
}
}
+/**
+ * Return true iff this ciphersuite will be hit by a mozilla bug 1312976,
+ * which makes TLS key exporters not work with TLS 1.2 non-SHA256
+ * ciphersuites.
+ **/
+static bool
+ciphersuite_has_nss_export_bug(const SSLCipherSuiteInfo *info)
+{
+ /* For more information on the bug, see
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1312976 */
+
+ /* This bug only exists in TLS 1.2. */
+ if (info->authType == ssl_auth_tls13_any)
+ return false;
+
+ /* Sadly, there's no way to get this information from the
+ * CipherSuiteInfo object itself other than by looking at the
+ * name. */
+ if (strstr(info->cipherSuiteName, "_SHA384") ||
+ strstr(info->cipherSuiteName, "_SHA512")) {
+ return true;
+ }
+
+ return false;
+}
+
tor_tls_context_t *
tor_tls_context_new(crypto_pk_t *identity,
unsigned int key_lifetime, unsigned flags, int is_client)
@@ -256,6 +282,12 @@ tor_tls_context_new(crypto_pk_t *identity,
!we_like_mac_algorithm(info.macAlgorithm) ||
!we_like_auth_type(info.authType)/* Requires NSS 3.24 */;
+ if (ciphersuite_has_nss_export_bug(&info)) {
+ /* SSL_ExportKeyingMaterial will fail; we can't use this cipher.
+ */
+ disable = 1;
+ }
+
s = SSL_CipherPrefSet(ctx->ctx, ciphers[i],
disable ? PR_FALSE : PR_TRUE);
if (s != SECSuccess)
@@ -726,10 +758,18 @@ tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out,
tor_assert(context_len <= UINT_MAX);
SECStatus s;
+ /* Make sure that the error code is set here, so that we can be sure that
+ * any error code set after a failure was in fact caused by
+ * SSL_ExportKeyingMaterial. */
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
s = SSL_ExportKeyingMaterial(tls->ssl,
label, (unsigned)strlen(label),
PR_TRUE, context, (unsigned)context_len,
secrets_out, DIGEST256_LEN);
+ if (s != SECSuccess) {
+ tls_log_errors(tls, LOG_WARN, LD_CRYPTO,
+ "exporting key material for a TLS handshake");
+ }
return (s == SECSuccess) ? 0 : -1;
}