diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/aes.c | 28 | ||||
-rw-r--r-- | src/common/crypto.c | 48 | ||||
-rw-r--r-- | src/common/crypto.h | 2 | ||||
-rw-r--r-- | src/common/tortls.c | 300 | ||||
-rw-r--r-- | src/common/tortls.h | 2 | ||||
-rw-r--r-- | src/or/main.c | 15 | ||||
-rw-r--r-- | src/test/bench.c | 5 | ||||
-rw-r--r-- | src/test/test_crypto.c | 2 | ||||
-rw-r--r-- | src/test/test_workqueue.c | 2 | ||||
-rw-r--r-- | src/test/testing_common.c | 2 | ||||
-rw-r--r-- | src/tools/tor-gencert.c | 2 |
11 files changed, 184 insertions, 224 deletions
diff --git a/src/common/aes.c b/src/common/aes.c index 95026ddf6e..201cadc741 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -32,11 +32,7 @@ #include <openssl/evp.h> #include <openssl/engine.h> #include "crypto.h" -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0) -/* See comments about which counter mode implementation to use below. */ #include <openssl/modes.h> -#define CAN_USE_OPENSSL_CTR -#endif #include "compat.h" #include "aes.h" #include "util.h" @@ -189,11 +185,9 @@ struct aes_cnt_cipher { * we're testing it or because we have hardware acceleration configured */ static int should_use_EVP = 0; -#ifdef CAN_USE_OPENSSL_CTR /** True iff we have tested the counter-mode implementation and found that it * doesn't have the counter-mode bug from OpenSSL 1.0.0. */ static int should_use_openssl_CTR = 0; -#endif /** Check whether we should use the EVP interface for AES. If <b>force_val</b> * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP @@ -235,7 +229,6 @@ evaluate_evp_for_aes(int force_val) int evaluate_ctr_for_aes(void) { -#ifdef CAN_USE_OPENSSL_CTR /* Result of encrypting an all-zero block with an all-zero 128-bit AES key. * This should be the same as encrypting an all-zero block with an all-zero * 128-bit AES key in counter mode, starting at position 0 of the stream. @@ -268,10 +261,6 @@ evaluate_ctr_for_aes(void) "mode; using it."); should_use_openssl_CTR = 1; } -#else - log_info(LD_CRYPTO, "This version of OpenSSL has a slow implementation of " - "counter mode; not using it."); -#endif return 0; } @@ -356,11 +345,9 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) cipher->pos = 0; -#ifdef CAN_USE_OPENSSL_CTR if (should_use_openssl_CTR) memset(cipher->buf, 0, sizeof(cipher->buf)); else -#endif aes_fill_buf_(cipher); } @@ -386,7 +373,6 @@ aes_cipher_free(aes_cnt_cipher_t *cipher) #define UPDATE_CTR_BUF(c, n) #endif -#ifdef CAN_USE_OPENSSL_CTR /* Helper function to use EVP with openssl's counter-mode wrapper. */ static void evp_block128_fn(const uint8_t in[16], @@ -397,7 +383,6 @@ evp_block128_fn(const uint8_t in[16], int inl=16, outl=16; EVP_EncryptUpdate(ctx, out, &outl, in, inl); } -#endif /** Encrypt <b>len</b> bytes from <b>input</b>, storing the result in * <b>output</b>. Uses the key in <b>cipher</b>, and advances the counter @@ -407,7 +392,6 @@ void aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, char *output) { -#ifdef CAN_USE_OPENSSL_CTR if (should_use_openssl_CTR) { if (cipher->using_evp) { /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If @@ -431,9 +415,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, &cipher->pos); } return; - } else -#endif - { + } else { int c = cipher->pos; if (PREDICT_UNLIKELY(!len)) return; @@ -466,13 +448,10 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) { -#ifdef CAN_USE_OPENSSL_CTR if (should_use_openssl_CTR) { aes_crypt(cipher, data, len, data); return; - } else -#endif - { + } else { int c = cipher->pos; if (PREDICT_UNLIKELY(!len)) return; @@ -512,11 +491,8 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv) cipher->pos = 0; memcpy(cipher->ctr_buf.buf, iv, 16); -#ifdef CAN_USE_OPENSSL_CTR if (!should_use_openssl_CTR) -#endif aes_fill_buf_(cipher); } #endif - diff --git a/src/common/crypto.c b/src/common/crypto.c index 8038631f18..28963f52cb 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -58,8 +58,8 @@ #include "compat.h" #include "sandbox.h" -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) -#error "We require OpenSSL >= 0.9.8" +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0) +#error "We require OpenSSL >= 1.0.0" #endif #ifdef ANDROID @@ -300,16 +300,9 @@ crypto_early_init(void) SSLeay(), SSLeay_version(SSLEAY_VERSION)); } - if (SSLeay() < OPENSSL_V_SERIES(1,0,0)) { - log_notice(LD_CRYPTO, - "Your OpenSSL version seems to be %s. We recommend 1.0.0 " - "or later.", - crypto_openssl_get_version_str()); - } - crypto_force_rand_ssleay(); - if (crypto_seed_rng(1) < 0) + if (crypto_seed_rng() < 0) return -1; if (crypto_init_siphash_key() < 0) return -1; @@ -391,7 +384,7 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir) } if (crypto_force_rand_ssleay()) { - if (crypto_seed_rng(1) < 0) + if (crypto_seed_rng() < 0) return -1; } @@ -405,7 +398,11 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir) void crypto_thread_cleanup(void) { +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) + ERR_remove_thread_state(NULL); +#else ERR_remove_state(0); +#endif } /** used by tortls.c: wrap an RSA* in a crypto_pk_t. */ @@ -2246,15 +2243,6 @@ crypto_dh_free(crypto_dh_t *dh) * work for us too. */ #define ADD_ENTROPY 32 -/** True iff it's safe to use RAND_poll after setup. - * - * Versions of OpenSSL prior to 0.9.7k and 0.9.8c had a bug where RAND_poll - * would allocate an fd_set on the stack, open a new file, and try to FD_SET - * that fd without checking whether it fit in the fd_set. Thus, if the - * system has not just been started up, it is unsafe to call */ -#define RAND_POLL_IS_SAFE \ - (OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,8,'c')) - /** Set the seed of the weak RNG to a random value. */ void crypto_seed_weak_rng(tor_weak_rng_t *rng) @@ -2324,7 +2312,7 @@ crypto_strongest_rand(uint8_t *out, size_t out_len) * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. */ int -crypto_seed_rng(int startup) +crypto_seed_rng(void) { int rand_poll_ok = 0, load_entropy_ok = 0; uint8_t buf[ADD_ENTROPY]; @@ -2332,11 +2320,9 @@ crypto_seed_rng(int startup) /* OpenSSL has a RAND_poll function that knows about more kinds of * entropy than we do. We'll try calling that, *and* calling our own entropy * functions. If one succeeds, we'll accept the RNG as seeded. */ - if (startup || RAND_POLL_IS_SAFE) { - rand_poll_ok = RAND_poll(); - if (rand_poll_ok == 0) - log_warn(LD_CRYPTO, "RAND_poll() failed."); - } + rand_poll_ok = RAND_poll(); + if (rand_poll_ok == 0) + log_warn(LD_CRYPTO, "RAND_poll() failed."); load_entropy_ok = !crypto_strongest_rand(buf, sizeof(buf)); if (load_entropy_ok) { @@ -3058,13 +3044,11 @@ openssl_dynlock_destroy_cb_(struct CRYPTO_dynlock_value *v, tor_free(v); } -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0) static void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid) { CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id()); } -#endif /** @{ */ /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being @@ -3079,11 +3063,7 @@ setup_openssl_threading(void) for (i=0; i < n; ++i) openssl_mutexes_[i] = tor_mutex_new(); CRYPTO_set_locking_callback(openssl_locking_cb_); -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0) - CRYPTO_set_id_callback(tor_get_thread_id); -#else CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id); -#endif CRYPTO_set_dynlock_create_callback(openssl_dynlock_create_cb_); CRYPTO_set_dynlock_lock_callback(openssl_dynlock_lock_cb_); CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy_cb_); @@ -3096,7 +3076,11 @@ int crypto_global_cleanup(void) { EVP_cleanup(); +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) + ERR_remove_thread_state(NULL); +#else ERR_remove_state(0); +#endif ERR_free_strings(); if (dh_param_p) diff --git a/src/common/crypto.h b/src/common/crypto.h index 8b620d910c..05572f4565 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -253,7 +253,7 @@ int crypto_expand_key_material_rfc5869_sha256( uint8_t *key_out, size_t key_out_len); /* random numbers */ -int crypto_seed_rng(int startup); +int crypto_seed_rng(void); MOCK_DECL(int,crypto_rand,(char *to, size_t n)); int crypto_strongest_rand(uint8_t *out, size_t out_len); int crypto_rand_int(unsigned int max); diff --git a/src/common/tortls.c b/src/common/tortls.c index 63b40258c2..cd585f4ae5 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -75,8 +75,8 @@ #include "container.h" #include <string.h> -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) -#error "We require OpenSSL >= 0.9.8" +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0) +#error "We require OpenSSL >= 1.0.0" #endif /* Enable the "v2" TLS handshake. @@ -93,10 +93,8 @@ #define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer") -#if (OPENSSL_VERSION_NUMBER < OPENSSL_V(0,9,8,'s') || \ - (OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(0,9,9) && \ - OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f'))) -/* This is a version of OpenSSL before 0.9.8s/1.0.0f. It does not have +#if OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f') +/* This is a version of OpenSSL before 1.0.0f. It does not have * the CVE-2011-4576 fix, and as such it can't use RELEASE_BUFFERS and * SSL3 safely at the same time. */ @@ -114,13 +112,6 @@ #define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010 #endif -/** Does the run-time openssl version look like we need - * SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ -static int use_unsafe_renegotiation_op = 0; -/** Does the run-time openssl version look like we need - * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ -static int use_unsafe_renegotiation_flag = 0; - /** Structure that we use for a single certificate. */ struct tor_cert_t { X509 *cert; @@ -485,56 +476,6 @@ tor_tls_init(void) version = SSLeay(); - /* OpenSSL 0.9.8l introduced SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION - * here, but without thinking too hard about it: it turns out that the - * flag in question needed to be set at the last minute, and that it - * conflicted with an existing flag number that had already been added - * in the OpenSSL 1.0.0 betas. OpenSSL 0.9.8m thoughtfully replaced - * the flag with an option and (it seems) broke anything that used - * SSL3_FLAGS_* for the purpose. So we need to know how to do both, - * and we mustn't use the SSL3_FLAGS option with anything besides - * OpenSSL 0.9.8l. - * - * No, we can't just set flag 0x0010 everywhere. It breaks Tor with - * OpenSSL 1.0.0beta3 and later. On the other hand, we might be able to - * set option 0x00040000L everywhere. - * - * No, we can't simply detect whether the flag or the option is present - * in the headers at build-time: some vendors (notably Apple) like to - * leave their headers out of sync with their libraries. - * - * Yes, it _is_ almost as if the OpenSSL developers decided that no - * program should be allowed to use renegotiation unless it first passed - * a test of intelligence and determination. - */ - if (version > OPENSSL_V(0,9,8,'k') && version <= OPENSSL_V(0,9,8,'l')) { - log_info(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l, but " - "some vendors have backported renegotiation code from " - "0.9.8m without updating the version number. " - "I will try SSL3_FLAGS and SSL_OP to enable renegotation.", - SSLeay_version(SSLEAY_VERSION)); - use_unsafe_renegotiation_flag = 1; - use_unsafe_renegotiation_op = 1; - } else if (version > OPENSSL_V(0,9,8,'l')) { - log_info(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; " - "I will try SSL_OP to enable renegotiation", - SSLeay_version(SSLEAY_VERSION)); - use_unsafe_renegotiation_op = 1; - } else if (version <= OPENSSL_V(0,9,8,'k')) { - log_info(LD_GENERAL, "OpenSSL %s [%lx] looks like it's older than " - "0.9.8l, but some vendors have backported 0.9.8l's " - "renegotiation code to earlier versions, and some have " - "backported the code from 0.9.8m or 0.9.8n. I'll set both " - "SSL3_FLAGS and SSL_OP just to be safe.", - SSLeay_version(SSLEAY_VERSION), version); - use_unsafe_renegotiation_flag = 1; - use_unsafe_renegotiation_op = 1; - } else { - /* this is dead code, yes? */ - log_info(LD_GENERAL, "OpenSSL %s has version %lx", - SSLeay_version(SSLEAY_VERSION), version); - } - #if (SIZEOF_VOID_P >= 8 && \ !defined(OPENSSL_NO_EC) && \ OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1)) @@ -1327,24 +1268,6 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, } #endif - /* XXX This block is now obsolete. */ - if ( -#ifdef DISABLE_SSL3_HANDSHAKE - 1 || -#endif - SSLeay() < OPENSSL_V(0,9,8,'s') || - (SSLeay() >= OPENSSL_V_SERIES(0,9,9) && - SSLeay() < OPENSSL_V(1,0,0,'f'))) { - /* And not SSL3 if it's subject to CVE-2011-4576. */ - log_info(LD_NET, "Disabling SSLv3 because this OpenSSL version " - "might otherwise be vulnerable to CVE-2011-4576 " - "(compile-time version %08lx (%s); " - "runtime version %08lx (%s))", - (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, - (unsigned long)SSLeay(), SSLeay_version(SSLEAY_VERSION)); - SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3); - } - SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_ECDH_USE); @@ -1355,16 +1278,21 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. */ - if (use_unsafe_renegotiation_op) { + { SSL_CTX_set_options(result->ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); } +#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 @@ -1399,8 +1327,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, SSL_CTX_set_tmp_dh(result->ctx, crypto_dh_get_dh_(dh)); crypto_dh_free(dh); } -#if (!defined(OPENSSL_NO_EC) && \ - OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0)) +#if !defined(OPENSSL_NO_EC) if (! is_client) { int nid; EC_KEY *ec_key; @@ -1512,10 +1439,23 @@ static int v2_cipher_list_pruned = 0; /** Return 0 if <b>m</b> does not support the cipher with ID <b>cipher</b>; * return 1 if it does support it, or if we have no way to tell. */ static int -find_cipher_by_id(const SSL_METHOD *m, uint16_t cipher) +find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher) { const SSL_CIPHER *c; -#ifdef HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,2) + { + unsigned char cipherid[3]; + tor_assert(ssl); + set_uint16(cipherid, htons(cipher)); + cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting + * with a two-byte 'cipherid', it may look for a v2 + * cipher with the appropriate 3 bytes. */ + c = SSL_CIPHER_find((SSL*)ssl, cipherid); + if (c) + tor_assert((c->id & 0xffff) == cipher); + return c != NULL; + } +#elif defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR) if (m && m->get_cipher_by_char) { unsigned char cipherid[3]; set_uint16(cipherid, htons(cipher)); @@ -1528,6 +1468,7 @@ find_cipher_by_id(const SSL_METHOD *m, uint16_t cipher) return c != NULL; } else #endif +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0) if (m && m->get_cipher && m->num_ciphers) { /* It would seem that some of the "let's-clean-up-openssl" forks have * removed the get_cipher_by_char function. Okay, so now you get a @@ -1541,23 +1482,24 @@ find_cipher_by_id(const SSL_METHOD *m, uint16_t cipher) } } return 0; - } else { - return 1; /* No way to search */ } +#endif + (void) ssl; + return 1; /* No way to search */ } /** Remove from v2_cipher_list every cipher that we don't support, so that * comparing v2_cipher_list to a client's cipher list will give a sensible * result. */ static void -prune_v2_cipher_list(void) +prune_v2_cipher_list(const SSL *ssl) { uint16_t *inp, *outp; const SSL_METHOD *m = SSLv23_method(); inp = outp = v2_cipher_list; while (*inp) { - if (find_cipher_by_id(m, *inp)) { + if (find_cipher_by_id(ssl, m, *inp)) { *outp++ = *inp++; } else { inp++; @@ -1579,7 +1521,7 @@ tor_tls_classify_client_ciphers(const SSL *ssl, int i, res; tor_tls_t *tor_tls; if (PREDICT_UNLIKELY(!v2_cipher_list_pruned)) - prune_v2_cipher_list(); + prune_v2_cipher_list(ssl); tor_tls = tor_tls_get_by_ssl(ssl); if (tor_tls && tor_tls->client_cipher_list_type) @@ -1613,7 +1555,7 @@ tor_tls_classify_client_ciphers(const SSL *ssl, const uint16_t *v2_cipher = v2_cipher_list; for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); - uint16_t id = cipher->id & 0xffff; + uint16_t id = SSL_CIPHER_get_id(cipher) & 0xffff; if (id == 0x00ff) /* extended renegotiation indicator. */ continue; if (!id || id != *v2_cipher) { @@ -1657,13 +1599,39 @@ tor_tls_classify_client_ciphers(const SSL *ssl, static int tor_tls_client_is_using_v2_ciphers(const SSL *ssl) { - SSL_SESSION *session; - if (!(session = SSL_get_session((SSL *)ssl))) { - log_info(LD_NET, "No session on TLS?"); - return CIPHERS_ERR; + STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl); + +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0) + { + SSL_SESSION *session; + STACK_OF(SSL_CIPHER) *c1; + int i; + if (!(session = SSL_get_session((SSL *)ssl))) { + log_info(LD_NET, "No session on TLS?"); + return CIPHERS_ERR; + } + c1 = session->ciphers; + + if (sk_SSL_CIPHER_num(c1) != sk_SSL_CIPHER_num(ciphers)) { + log_warn(LD_BUG, "Whoops. session->ciphers doesn't " + "match SSL_get_ciphers()"); + return 0; + } + for (i = 0; i < sk_SSL_CIPHER_num(c1); ++i) { + SSL_CIPHER *a = sk_SSL_CIPHER_value(ciphers, i); + SSL_CIPHER *b = sk_SSL_CIPHER_value(c1, i); + unsigned long a_id = SSL_CIPHER_get_id(a); + unsigned long b_id = SSL_CIPHER_get_id(b); + if (a_id != b_id) { + log_warn(LD_BUG, "Cipher mismatch between session->ciphers and " + "SSL_get_ciphers() at %d: %lx vs %lx", i, + a_id, b_id); + } + } } +#endif - return tor_tls_classify_client_ciphers(ssl, session->ciphers) >= CIPHERS_V2; + return tor_tls_classify_client_ciphers(ssl, ciphers) >= CIPHERS_V2; } /** Invoked when we're accepting a connection on <b>ssl</b>, and the connection @@ -1676,14 +1644,17 @@ static void tor_tls_server_info_callback(const SSL *ssl, int type, int val) { tor_tls_t *tls; + int ssl_state; (void) val; tor_tls_debug_state_callback(ssl, type, val); if (type != SSL_CB_ACCEPT_LOOP) return; - if ((ssl->state != SSL3_ST_SW_SRVR_HELLO_A) && - (ssl->state != SSL3_ST_SW_SRVR_HELLO_B)) + + ssl_state = SSL_state(ssl); + if ((ssl_state != SSL3_ST_SW_SRVR_HELLO_A) && + (ssl_state != SSL3_ST_SW_SRVR_HELLO_B)) return; tls = tor_tls_get_by_ssl(ssl); @@ -1714,10 +1685,6 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val) if (tls) { tls->wasV2Handshake = 1; -#ifdef USE_BUFFEREVENTS - if (use_unsafe_renegotiation_flag) - tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; -#endif } else { log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); } @@ -1725,7 +1692,6 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val) } #endif -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0) /** Callback to get invoked on a server after we've read the list of ciphers * the client supports, but before we pick our own ciphersuite. * @@ -1763,9 +1729,6 @@ tor_tls_setup_session_secret_cb(tor_tls_t *tls) { SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL); } -#else -#define tor_tls_setup_session_secret_cb(tls) STMT_NIL -#endif /** Explain which ciphers we're missing. */ static void @@ -1791,21 +1754,46 @@ log_unsupported_ciphers(smartlist_t *unsupported) tor_free(joined); } -/** Replace *<b>ciphers</b> with a new list of SSL ciphersuites: specifically, - * a list designed to mimic a common web browser. We might not be able to do - * that if OpenSSL doesn't support all the ciphers we want. Some of the - * ciphers in the list won't actually be implemented by OpenSSL: that's okay - * so long as the server doesn't select them. +static void +set_ssl_ciphers_to_list(SSL *ssl, STACK_OF(SSL_CIPHER) *stack) +{ + STACK_OF(SSL_CIPHER) *ciphers; + + int r, i; + /* #1: ensure that the ssl object has its own list of ciphers. Otherwise we + * might be about to stomp the SSL_CTX ciphers list. */ + r = SSL_set_cipher_list(ssl, "HIGH"); + tor_assert(r); + + /* #2: Grab ssl_ciphers and clear it. */ + ciphers = SSL_get_ciphers(ssl); + tor_assert(ciphers); + sk_SSL_CIPHER_zero(ciphers); + + /* #3: Copy the elements from stack. */ + for (i = 0; i < sk_SSL_CIPHER_num(stack); ++i) { + SSL_CIPHER *c = sk_SSL_CIPHER_value(stack, i); + sk_SSL_CIPHER_push(ciphers, c); + } +} + +/** Replace the ciphers on <b>ssl</b> with a new list of SSL ciphersuites: + * specifically, a list designed to mimic a common web browser. We might not + * be able to do that if OpenSSL doesn't support all the ciphers we want. + * Some of the ciphers in the list won't actually be implemented by OpenSSL: + * that's okay so long as the server doesn't select them. * * [If the server <b>does</b> select a bogus cipher, we won't crash or * anything; we'll just fail later when we try to look up the cipher in * ssl->cipher_list_by_id.] */ static void -rectify_client_ciphers(STACK_OF(SSL_CIPHER) **ciphers) +rectify_client_ciphers(SSL *ssl) { #ifdef V2_HANDSHAKE_CLIENT if (PREDICT_UNLIKELY(!CLIENT_CIPHER_STACK)) { + STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl); + /* We need to set CLIENT_CIPHER_STACK to an array of the ciphers * we want to use/advertise. */ int i = 0, j = 0; @@ -1826,32 +1814,33 @@ rectify_client_ciphers(STACK_OF(SSL_CIPHER) **ciphers) tor_assert(CLIENT_CIPHER_STACK); log_debug(LD_NET, "List was: %s", CLIENT_CIPHER_LIST); - for (j = 0; j < sk_SSL_CIPHER_num(*ciphers); ++j) { - SSL_CIPHER *cipher = sk_SSL_CIPHER_value(*ciphers, j); - log_debug(LD_NET, "Cipher %d: %lx %s", j, cipher->id, cipher->name); + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); ++j) { + SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, j); + log_debug(LD_NET, "Cipher %d: %lx %s", j, + SSL_CIPHER_get_id(cipher), SSL_CIPHER_get_name(cipher)); } /* Then copy as many ciphers as we can from the good list, inserting * dummies as needed. Let j be an index into list of ciphers we have - * (*ciphers) and let i be an index into the ciphers we want + * (ciphers) and let i be an index into the ciphers we want * (CLIENT_INFO_CIPHER_LIST). We are building a list of ciphers in * CLIENT_CIPHER_STACK. */ for (i = j = 0; i < N_CLIENT_CIPHERS; ) { SSL_CIPHER *cipher = NULL; - if (j < sk_SSL_CIPHER_num(*ciphers)) - cipher = sk_SSL_CIPHER_value(*ciphers, j); - if (cipher && ((cipher->id >> 24) & 0xff) != 3) { + if (j < sk_SSL_CIPHER_num(ciphers)) + cipher = sk_SSL_CIPHER_value(ciphers, j); + if (cipher && ((SSL_CIPHER_get_id(cipher) >> 24) & 0xff) != 3) { /* Skip over non-v3 ciphers entirely. (This should no longer be * needed, thanks to saying !SSLv2 above.) */ log_debug(LD_NET, "Skipping v%d cipher %s", - (int)((cipher->id>>24) & 0xff), - cipher->name); + (int)((SSL_CIPHER_get_id(cipher)>>24) & 0xff), + SSL_CIPHER_get_name(cipher)); ++j; } else if (cipher && - (cipher->id & 0xffff) == CLIENT_CIPHER_INFO_LIST[i].id) { + (SSL_CIPHER_get_id(cipher) & 0xffff) == CLIENT_CIPHER_INFO_LIST[i].id) { /* "cipher" is the cipher we expect. Put it on the list. */ - log_debug(LD_NET, "Found cipher %s", cipher->name); + log_debug(LD_NET, "Found cipher %s", SSL_CIPHER_get_name(cipher)); sk_SSL_CIPHER_push(CLIENT_CIPHER_STACK, cipher); ++j; ++i; @@ -1877,12 +1866,10 @@ rectify_client_ciphers(STACK_OF(SSL_CIPHER) **ciphers) smartlist_free(unsupported); } - sk_SSL_CIPHER_free(*ciphers); - *ciphers = sk_SSL_CIPHER_dup(CLIENT_CIPHER_STACK); - tor_assert(*ciphers); + set_ssl_ciphers_to_list(ssl, CLIENT_CIPHER_STACK); #else - (void)ciphers; + (void)ciphers; #endif } @@ -1926,7 +1913,7 @@ tor_tls_new(int sock, int isServer) goto err; } if (!isServer) - rectify_client_ciphers(&result->ssl->cipher_list); + rectify_client_ciphers(result->ssl); result->socket = sock; bio = BIO_new_socket(sock, BIO_NOCLOSE); if (! bio) { @@ -2019,13 +2006,8 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls) { /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. */ - if (use_unsafe_renegotiation_flag) { - tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; - } - if (use_unsafe_renegotiation_op) { - SSL_set_options(tls->ssl, - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); - } + SSL_set_options(tls->ssl, + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); } /** If this version of openssl supports it, turn off renegotiation on @@ -2035,21 +2017,19 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls) void tor_tls_block_renegotiation(tor_tls_t *tls) { +#ifdef SUPPORT_UNSAFE_RENEGOTIATION_FLAG tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; +#else + (void) tls; +#endif } /** Assert that the flags that allow legacy renegotiation are still set */ void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls) { - if (use_unsafe_renegotiation_flag) { - tor_assert(0 != (tls->ssl->s3->flags & - SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); - } - if (use_unsafe_renegotiation_op) { - long options = SSL_get_options(tls->ssl); - tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); - } + long options = SSL_get_options(tls->ssl); + tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); } /** Return whether this tls initiated the connect (client) or @@ -2180,7 +2160,7 @@ tor_tls_handshake(tor_tls_t *tls) tor_assert(tls->ssl); tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE); check_no_tls_errors(); - oldstate = tls->ssl->state; + oldstate = SSL_state(tls->ssl); if (tls->isServer) { log_debug(LD_HANDSHAKE, "About to call SSL_accept on %p (%s)", tls, SSL_state_string_long(tls->ssl)); @@ -2190,7 +2170,7 @@ tor_tls_handshake(tor_tls_t *tls) SSL_state_string_long(tls->ssl)); r = SSL_connect(tls->ssl); } - if (oldstate != tls->ssl->state) + if (oldstate != SSL_state(tls->ssl)) log_debug(LD_HANDSHAKE, "After call, %p was in state %s", tls, SSL_state_string_long(tls->ssl)); /* We need to call this here and not earlier, since OpenSSL has a penchant @@ -2209,6 +2189,14 @@ tor_tls_handshake(tor_tls_t *tls) return r; } +/* SSL_clear_mode was introduced in 0.9.8m */ +#ifndef SSL_clear_mode +static void SSL_clear_mode(SSL *s, unsigned long m) +{ + s->mode &= ~m; +} +#endif + /** Perform the final part of the intial TLS handshake on <b>tls</b>. This * should be called for the first handshake only: it determines whether the v1 * or the v2 handshake was used, and adjusts things for the renegotiation @@ -2225,8 +2213,7 @@ tor_tls_finish_handshake(tor_tls_t *tls) if (tls->isServer) { SSL_set_info_callback(tls->ssl, NULL); SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb); - /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */ - tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN; + SSL_clear_mode(tls->ssl, SSL_MODE_NO_AUTO_CHAIN); #ifdef V2_HANDSHAKE_SERVER if (tor_tls_client_is_using_v2_ciphers(tls->ssl)) { /* This check is redundant, but back when we did it in the callback, @@ -2851,12 +2838,23 @@ tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out) * Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read * buffer and *<b>rbuf_bytes</b> to the amount actually used. * Set *<b>wbuf_capacity</b> to the amount of storage allocated for the write - * buffer and *<b>wbuf_bytes</b> to the amount actually used. */ -void + * buffer and *<b>wbuf_bytes</b> to the amount actually used. + * + * Return 0 on success, -1 on failure.*/ +int tor_tls_get_buffer_sizes(tor_tls_t *tls, size_t *rbuf_capacity, size_t *rbuf_bytes, size_t *wbuf_capacity, size_t *wbuf_bytes) { +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) + (void)tls; + (void)rbuf_capacity; + (void)rbuf_bytes; + (void)wbuf_capacity; + (void)wbuf_bytes; + + return -1; +#else if (tls->ssl->s3->rbuf.buf) *rbuf_capacity = tls->ssl->s3->rbuf.len; else @@ -2867,6 +2865,8 @@ tor_tls_get_buffer_sizes(tor_tls_t *tls, *wbuf_capacity = 0; *rbuf_bytes = tls->ssl->s3->rbuf.left; *wbuf_bytes = tls->ssl->s3->wbuf.left; + return 0; +#endif } #ifdef USE_BUFFEREVENTS diff --git a/src/common/tortls.h b/src/common/tortls.h index 2aac8af18e..083052f4b2 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -92,7 +92,7 @@ size_t tor_tls_get_forced_write_size(tor_tls_t *tls); void tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written); -void tor_tls_get_buffer_sizes(tor_tls_t *tls, +int tor_tls_get_buffer_sizes(tor_tls_t *tls, size_t *rbuf_capacity, size_t *rbuf_bytes, size_t *wbuf_capacity, size_t *wbuf_bytes); diff --git a/src/or/main.c b/src/or/main.c index 3fb7de6f6c..74e6b33397 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1336,7 +1336,7 @@ run_scheduled_events(time_t now) if (time_to.add_entropy < now) { if (time_to.add_entropy) { /* We already seeded once, so don't die on failure. */ - crypto_seed_rng(0); + crypto_seed_rng(); } /** How often do we add more entropy to OpenSSL's RNG pool? */ #define ENTROPY_INTERVAL (60*60) @@ -2333,12 +2333,13 @@ dumpstats(int severity) if (conn->type == CONN_TYPE_OR) { or_connection_t *or_conn = TO_OR_CONN(conn); if (or_conn->tls) { - tor_tls_get_buffer_sizes(or_conn->tls, &rbuf_cap, &rbuf_len, - &wbuf_cap, &wbuf_len); - tor_log(severity, LD_GENERAL, - "Conn %d: %d/%d bytes used on OpenSSL read buffer; " - "%d/%d bytes used on write buffer.", - i, (int)rbuf_len, (int)rbuf_cap, (int)wbuf_len, (int)wbuf_cap); + if (tor_tls_get_buffer_sizes(or_conn->tls, &rbuf_cap, &rbuf_len, + &wbuf_cap, &wbuf_len) == 0) { + tor_log(severity, LD_GENERAL, + "Conn %d: %d/%d bytes used on OpenSSL read buffer; " + "%d/%d bytes used on write buffer.", + i, (int)rbuf_len, (int)rbuf_cap, (int)wbuf_len, (int)wbuf_cap); + } } } } diff --git a/src/test/bench.c b/src/test/bench.c index 5cbc072700..a74fc776fa 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -502,8 +502,7 @@ bench_dh(void) " %f millisec each.\n", NANOCOUNT(start, end, iters)/1e6); } -#if (!defined(OPENSSL_NO_EC) \ - && OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0)) +#if !defined(OPENSSL_NO_EC) #define HAVE_EC_BENCHMARKS static void bench_ecdh_impl(int nid, const char *name) @@ -625,7 +624,7 @@ main(int argc, const char **argv) reset_perftime(); - crypto_seed_rng(1); + crypto_seed_rng(); crypto_init_siphash_key(); options = options_new(); init_logging(1); diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 84a90da7f8..7944864bd7 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -74,7 +74,7 @@ test_crypto_rng(void *arg) /* Try out RNG. */ (void)arg; - tt_assert(! crypto_seed_rng(0)); + tt_assert(! crypto_seed_rng()); crypto_rand(data1, 100); crypto_rand(data2, 100); tt_mem_op(data1,OP_NE, data2,100); diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index 83f6f3e215..77053b0760 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -358,7 +358,7 @@ main(int argc, char **argv) init_logging(1); crypto_global_init(1, NULL, NULL); - crypto_seed_rng(1); + crypto_seed_rng(); rq = replyqueue_new(as_flags); tor_assert(rq); diff --git a/src/test/testing_common.c b/src/test/testing_common.c index 60be460660..7f387c0b3d 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -270,7 +270,7 @@ main(int c, const char **v) return 1; } crypto_set_tls_dh_prime(); - crypto_seed_rng(1); + crypto_seed_rng(); rep_hist_init(); network_init(); setup_directory(); diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c index 28b1a58d52..7660be6230 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -533,7 +533,7 @@ main(int argc, char **argv) fprintf(stderr, "Couldn't initialize crypto library.\n"); return 1; } - if (crypto_seed_rng(1)) { + if (crypto_seed_rng()) { fprintf(stderr, "Couldn't seed RNG.\n"); goto done; } |