diff options
Diffstat (limited to 'src/common/tortls.c')
-rw-r--r-- | src/common/tortls.c | 83 |
1 files changed, 59 insertions, 24 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c index 221b47e009..379f7347db 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2013, The Tor Project, Inc. */ + * Copyright (c) 2007-2015, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -16,10 +16,6 @@ #include "orconfig.h" -#if defined (WINCE) -#include <WinSock2.h> -#endif - #include <assert.h> #ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/ #ifndef _WIN32_WINNT @@ -54,6 +50,8 @@ #include <openssl/asn1.h> #include <openssl/bio.h> #include <openssl/opensslv.h> +#include <openssl/bn.h> +#include <openssl/rsa.h> #if __GNUC__ && GCC_VERSION >= 402 #if GCC_VERSION >= 406 @@ -478,6 +476,8 @@ tor_tls_get_error(tor_tls_t *tls, int r, int extra, static void tor_tls_init(void) { + check_no_tls_errors(); + if (!tls_library_is_initialized) { long version; SSL_library_init(); @@ -576,6 +576,8 @@ tor_tls_init(void) void tor_tls_free_all(void) { + check_no_tls_errors(); + if (server_tls_context) { tor_tls_context_t *ctx = server_tls_context; server_tls_context = NULL; @@ -808,8 +810,7 @@ static const cipher_info_t CLIENT_CIPHER_INFO_LIST[] = { }; /** The length of CLIENT_CIPHER_INFO_LIST and CLIENT_CIPHER_DUMMIES. */ -static const int N_CLIENT_CIPHERS = - sizeof(CLIENT_CIPHER_INFO_LIST)/sizeof(CLIENT_CIPHER_INFO_LIST[0]); +static const int N_CLIENT_CIPHERS = ARRAY_LENGTH(CLIENT_CIPHER_INFO_LIST); #endif #ifndef V2_HANDSHAKE_CLIENT @@ -888,29 +889,33 @@ tor_cert_decode(const uint8_t *certificate, size_t certificate_len) const unsigned char *cp = (const unsigned char *)certificate; tor_cert_t *newcert; tor_assert(certificate); + check_no_tls_errors(); if (certificate_len > INT_MAX) - return NULL; + goto err; x509 = d2i_X509(NULL, &cp, (int)certificate_len); if (!x509) - return NULL; /* Couldn't decode */ + goto err; /* Couldn't decode */ if (cp - certificate != (int)certificate_len) { X509_free(x509); - return NULL; /* Didn't use all the bytes */ + goto err; /* Didn't use all the bytes */ } newcert = tor_cert_new(x509); if (!newcert) { - return NULL; + goto err; } if (newcert->encoded_len != certificate_len || fast_memneq(newcert->encoded, certificate, certificate_len)) { /* Cert wasn't in DER */ tor_cert_free(newcert); - return NULL; + goto err; } return newcert; + err: + tls_log_errors(NULL, LOG_INFO, LD_CRYPTO, "decoding a certificate"); + return NULL; } /** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER @@ -1052,21 +1057,24 @@ tor_tls_cert_is_valid(int severity, const tor_cert_t *signing_cert, int check_rsa_1024) { + check_no_tls_errors(); + EVP_PKEY *cert_key; EVP_PKEY *signing_key = X509_get_pubkey(signing_cert->cert); int r, key_ok = 0; + if (!signing_key) - return 0; + goto bad; r = X509_verify(cert->cert, signing_key); EVP_PKEY_free(signing_key); if (r <= 0) - return 0; + goto bad; /* okay, the signature checked out right. Now let's check the check the * lifetime. */ if (check_cert_lifetime_internal(severity, cert->cert, 48*60*60, 30*24*60*60) < 0) - return 0; + goto bad; cert_key = X509_get_pubkey(cert->cert); if (check_rsa_1024 && cert_key) { @@ -1086,11 +1094,14 @@ tor_tls_cert_is_valid(int severity, } EVP_PKEY_free(cert_key); if (!key_ok) - return 0; + goto bad; /* XXXX compare DNs or anything? */ return 1; + bad: + tls_log_errors(NULL, LOG_INFO, LD_CRYPTO, "checking a certificate"); + return 0; } /** Increase the reference count of <b>ctx</b>. */ @@ -1117,6 +1128,7 @@ tor_tls_context_init(unsigned flags, int rv1 = 0; int rv2 = 0; const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER; + check_no_tls_errors(); if (is_public_server) { tor_tls_context_t *new_ctx; @@ -1161,6 +1173,7 @@ tor_tls_context_init(unsigned flags, 1); } + tls_log_errors(NULL, LOG_WARN, LD_CRYPTO, "constructing a TLS context"); return MIN(rv1, rv2); } @@ -1197,6 +1210,9 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext, return ((new_ctx != NULL) ? 0 : -1); } +/** The group we should use for ecdhe when none was selected. */ +#define NID_tor_default_ecdhe_group NID_X9_62_prime256v1 + /** Create a new TLS context for use with Tor TLS handshakes. * <b>identity</b> should be set to the identity key used to sign the * certificate. @@ -1392,7 +1408,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, else if (flags & TOR_TLS_CTX_USE_ECDHE_P256) nid = NID_X9_62_prime256v1; else - nid = NID_X9_62_prime256v1; + nid = NID_tor_default_ecdhe_group; /* Use P-256 for ECDHE. */ ec_key = EC_KEY_new_by_curve_name(nid); if (ec_key != NULL) /*XXXX Handle errors? */ @@ -1881,11 +1897,12 @@ tor_tls_new(int sock, int isServer) client_tls_context; result->magic = TOR_TLS_MAGIC; + check_no_tls_errors(); tor_assert(context); /* make sure somebody made it first */ if (!(result->ssl = SSL_new(context->ctx))) { tls_log_errors(NULL, LOG_WARN, LD_NET, "creating SSL object"); tor_free(result); - return NULL; + goto err; } #ifdef SSL_set_tlsext_host_name @@ -1905,7 +1922,7 @@ tor_tls_new(int sock, int isServer) #endif SSL_free(result->ssl); tor_free(result); - return NULL; + goto err; } if (!isServer) rectify_client_ciphers(&result->ssl->cipher_list); @@ -1918,7 +1935,7 @@ tor_tls_new(int sock, int isServer) #endif SSL_free(result->ssl); tor_free(result); - return NULL; + goto err; } { int set_worked = @@ -1952,6 +1969,10 @@ tor_tls_new(int sock, int isServer) if (isServer) tor_tls_setup_session_secret_cb(result); + goto done; + err: + result = NULL; + done: /* Not expected to get called. */ tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object"); return result; @@ -2199,6 +2220,7 @@ int tor_tls_finish_handshake(tor_tls_t *tls) { int r = TOR_TLS_DONE; + check_no_tls_errors(); if (tls->isServer) { SSL_set_info_callback(tls->ssl, NULL); SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb); @@ -2244,6 +2266,7 @@ tor_tls_finish_handshake(tor_tls_t *tls) r = TOR_TLS_ERROR_MISC; } } + tls_log_errors(NULL, LOG_WARN, LD_NET, "finishing the handshake"); return r; } @@ -2274,6 +2297,8 @@ tor_tls_renegotiate(tor_tls_t *tls) /* We could do server-initiated renegotiation too, but that would be tricky. * Instead of "SSL_renegotiate, then SSL_do_handshake until done" */ tor_assert(!tls->isServer); + + check_no_tls_errors(); if (tls->state != TOR_TLS_ST_RENEGOTIATE) { int r = SSL_renegotiate(tls->ssl); if (r <= 0) { @@ -2302,6 +2327,7 @@ tor_tls_shutdown(tor_tls_t *tls) char buf[128]; tor_assert(tls); tor_assert(tls->ssl); + check_no_tls_errors(); while (1) { if (tls->state == TOR_TLS_ST_SENTCLOSE) { @@ -2489,6 +2515,7 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity_key) RSA *rsa; int r = -1; + check_no_tls_errors(); *identity_key = NULL; try_to_extract_certs_from_tls(severity, tls, &cert, &id_cert); @@ -2667,16 +2694,20 @@ check_no_tls_errors_(const char *fname, int line) int tor_tls_used_v1_handshake(tor_tls_t *tls) { +#if defined(V2_HANDSHAKE_SERVER) && defined(V2_HANDSHAKE_CLIENT) + return ! tls->wasV2Handshake; +#else if (tls->isServer) { -#ifdef V2_HANDSHAKE_SERVER +# ifdef V2_HANDSHAKE_SERVER return ! tls->wasV2Handshake; -#endif +# endif } else { -#ifdef V2_HANDSHAKE_CLIENT +# ifdef V2_HANDSHAKE_CLIENT return ! tls->wasV2Handshake; -#endif +# endif } return 1; +#endif } /** Return true iff <b>name</b> is a DN of a kind that could only @@ -2729,6 +2760,8 @@ dn_indicates_v3_cert(X509_NAME *name) int tor_tls_received_v3_certificate(tor_tls_t *tls) { + check_no_tls_errors(); + X509 *cert = SSL_get_peer_certificate(tls->ssl); EVP_PKEY *key = NULL; X509_NAME *issuer_name, *subject_name; @@ -2761,6 +2794,8 @@ tor_tls_received_v3_certificate(tor_tls_t *tls) } done: + tls_log_errors(tls, LOG_WARN, LD_NET, "checking for a v3 cert"); + if (key) EVP_PKEY_free(key); if (cert) |