Merge branch 'bug16034_no_more_openssl_098_squashed'

Conflicts:
	src/test/testing_common.c
This commit is contained in:
Nick Mathewson 2015-05-20 15:33:22 -04:00
commit ed02a409cf
12 changed files with 191 additions and 225 deletions

6
changes/ticket16034 Normal file
View File

@ -0,0 +1,6 @@
o Removed features:
- Tor no longer supports versions of OpenSSL before 1.0. (If you
are on an operating system that has not upgraded to OpenSSL 1.0
or later, and you compile Tor from source, you will need to
install a more recent OpenSSL to link Tor against.)

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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);
return tor_tls_classify_client_ciphers(ssl, session->ciphers) >= CIPHERS_V2;
#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, 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

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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;
}