diff options
Diffstat (limited to 'src/common/tortls.c')
-rw-r--r-- | src/common/tortls.c | 105 |
1 files changed, 97 insertions, 8 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c index 50609b8ac7..6ff513b14f 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -25,6 +25,9 @@ #include <ws2tcpip.h> #endif +#include "crypto.h" +#include "crypto_rand.h" +#include "crypto_util.h" #include "compat.h" /* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in @@ -32,7 +35,6 @@ DISABLE_GCC_WARNING(redundant-decls) #include <openssl/opensslv.h> -#include "crypto.h" #ifdef OPENSSL_NO_EC #error "We require OpenSSL with ECC support" @@ -56,10 +58,25 @@ ENABLE_GCC_WARNING(redundant-decls) #include "container.h" #include <string.h> +#ifdef OPENSSL_1_1_API +#define X509_get_notBefore_const(cert) \ + X509_get0_notBefore(cert) +#define X509_get_notAfter_const(cert) \ + X509_get0_notAfter(cert) +#ifndef X509_get_notBefore +#define X509_get_notBefore(cert) \ + X509_getm_notBefore(cert) +#endif +#ifndef X509_get_notAfter +#define X509_get_notAfter(cert) \ + X509_getm_notAfter(cert) +#endif +#else /* ! OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */ #define X509_get_notBefore_const(cert) \ ((const ASN1_TIME*) X509_get_notBefore((X509 *)cert)) #define X509_get_notAfter_const(cert) \ ((const ASN1_TIME*) X509_get_notAfter((X509 *)cert)) +#endif /* Copied from or.h */ #define LEGAL_NICKNAME_CHARACTERS \ @@ -89,6 +106,9 @@ ENABLE_GCC_WARNING(redundant-decls) #define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010 #endif +/** Set to true iff openssl bug 7712 has been detected. */ +static int openssl_bug_7712_is_present = 0; + /** Return values for tor_tls_classify_client_ciphers. * * @{ @@ -355,8 +375,12 @@ tor_tls_init(void) check_no_tls_errors(); if (!tls_library_is_initialized) { +#ifdef OPENSSL_1_1_API + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); +#else SSL_library_init(); SSL_load_error_strings(); +#endif #if (SIZEOF_VOID_P >= 8 && \ OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1)) @@ -896,18 +920,20 @@ tor_tls_cert_get_key(tor_x509_cert_t *cert) MOCK_IMPL(int, tor_tls_cert_matches_key,(const tor_tls_t *tls, const tor_x509_cert_t *cert)) { - X509 *peercert = SSL_get_peer_certificate(tls->ssl); + tor_x509_cert_t *peer = tor_tls_get_peer_cert((tor_tls_t *)tls); + if (!peer) + return 0; + + X509 *peercert = peer->cert; EVP_PKEY *link_key = NULL, *cert_key = NULL; int result; - if (!peercert) - return 0; link_key = X509_get_pubkey(peercert); cert_key = X509_get_pubkey(cert->cert); result = link_key && cert_key && EVP_PKEY_cmp(cert_key, link_key) == 1; - X509_free(peercert); + tor_x509_cert_free(peer); if (link_key) EVP_PKEY_free(link_key); if (cert_key) @@ -1170,6 +1196,12 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, if (!(result->ctx = SSL_CTX_new(SSLv23_method()))) goto error; #endif /* defined(HAVE_TLS_METHOD) */ + +#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL + /* Level 1 re-enables RSA1024 and DH1024 for compatibility with old tors */ + SSL_CTX_set_security_level(result->ctx, 1); +#endif + SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3); @@ -1255,6 +1287,22 @@ 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); } +/* We check for this function in two ways, since it might be either a symbol + * or a macro. */ +#if defined(SSL_CTX_set1_groups_list) || defined(HAVE_SSL_CTX_SET1_GROUPS_LIST) + { + const char *list; + if (flags & TOR_TLS_CTX_USE_ECDHE_P224) + list = "P-224:P-256"; + else if (flags & TOR_TLS_CTX_USE_ECDHE_P256) + list = "P-256:P-224"; + else + list = "P-256:P-224"; + int r = (int) SSL_CTX_set1_groups_list(result->ctx, list); + if (r < 0) + goto error; + } +#else if (! is_client) { int nid; EC_KEY *ec_key; @@ -1270,6 +1318,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, SSL_CTX_set_tmp_ecdh(result->ctx, ec_key); EC_KEY_free(ec_key); } +#endif SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, always_accept_verify_cb); /* let us realloc bufs that we're writing from */ @@ -1521,7 +1570,7 @@ tor_tls_classify_client_ciphers(const SSL *ssl, smartlist_free(elts); } done: - if (tor_tls) + if (tor_tls && peer_ciphers) return tor_tls->client_cipher_list_type = res; return res; @@ -1676,6 +1725,13 @@ tor_tls_new(int sock, int isServer) } #endif /* defined(SSL_set_tlsext_host_name) */ +#ifdef SSL_CTRL_SET_MAX_PROTO_VERSION + if (openssl_bug_7712_is_present) { + /* We can't actually use TLS 1.3 until this bug is fixed. */ + SSL_set_max_proto_version(result->ssl, TLS1_2_VERSION); + } +#endif + if (!SSL_set_cipher_list(result->ssl, isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) { tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers"); @@ -2561,7 +2617,8 @@ tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)) * provided <b>context</b> (<b>context_len</b> bytes long) and * <b>label</b> (a NUL-terminated string), compute a 32-byte secret in * <b>secrets_out</b> that only the parties to this TLS session can - * compute. Return 0 on success and -1 on failure. + * compute. Return 0 on success; -1 on failure; and -2 on failure + * caused by OpenSSL bug 7712. */ MOCK_IMPL(int, tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out, @@ -2576,6 +2633,39 @@ tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out, secrets_out, DIGEST256_LEN, label, strlen(label), context, context_len, 1); + + if (r != 1) { + int severity = openssl_bug_7712_is_present ? LOG_WARN : LOG_DEBUG; + tls_log_errors(tls, severity, LD_NET, "exporting keying material"); + } + +#ifdef TLS1_3_VERSION + if (r != 1 && + strlen(label) > 12 && + SSL_version(tls->ssl) >= TLS1_3_VERSION) { + + if (! openssl_bug_7712_is_present) { + /* We might have run into OpenSSL issue 7712, which caused OpenSSL + * 1.1.1a to not handle long labels. Let's test to see if we have. + */ + r = SSL_export_keying_material(tls->ssl, secrets_out, DIGEST256_LEN, + "short", 5, context, context_len, 1); + if (r == 1) { + /* A short label succeeds, but a long label fails. This was openssl + * issue 7712. */ + openssl_bug_7712_is_present = 1; + log_warn(LD_GENERAL, "Detected OpenSSL bug 7712: disabling TLS 1.3 on " + "future connections. A fix is expected to appear in OpenSSL " + "1.1.1b."); + } + } + if (openssl_bug_7712_is_present) + return -2; + else + return -1; + } +#endif + return (r == 1) ? 0 : -1; } @@ -2639,4 +2729,3 @@ evaluate_ecgroup_for_tls(const char *ecgroup) return ret; } - |