tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit e6890ae73ceb1e8f38a60a774636d131a18bc00e
parent a7f035f7f85b1314b63fbe05a4165b4d517c75f2
Author: ValdikSS <iam@valdikss.org.ru>
Date:   Thu, 26 Jun 2025 10:24:28 -0400

tls: Set TLSv1.3 ciphers to preserve ciphersuites order

This commit fixes two issues:

1. ciphers.inc has TLSv1.3 ciphers prefixed with "TXT", while current version
   has "RFC". TLS1_3_RFC_AES_128_GCM_SHA256 should be instead of
   TLS1_3_TXT_AES_128_GCM_SHA256, in both define and CIPHER() macro.

2. Tor calls only SSL_set_cipher_list() in tlstls_openssl.c, this sets only
   TLSv1.2 ciphers, while TLSv1.3 ciphers stay in default state. TLSv1.3
   ciphersuites are set with SSL_set_ciphersuites(), but the list require to
   contain only TLSv1.3 suites (no v1.2).

Contrary to SSL_set_cipher_list(), TLSv1.3 SSL_set_ciphersuites() does NOT
accept finalizing :, so it should be stripped out.

Signed-off-by: David Goulet <dgoulet@torproject.org>

Diffstat:
Achanges/tls13-cipher | 2++
Mconfigure.ac | 3++-
Asrc/lib/tls/ciphers_v13.inc | 15+++++++++++++++
Msrc/lib/tls/include.am | 1+
Msrc/lib/tls/tortls_openssl.c | 26++++++++++++++++++++++++--
5 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/changes/tls13-cipher b/changes/tls13-cipher @@ -0,0 +1,2 @@ + o Minor feature (client, TLS): + - Set the TLS 1.3 cipher list instead of falling back on the default value. diff --git a/configure.ac b/configure.ac @@ -1141,7 +1141,8 @@ AC_CHECK_FUNCS([ \ SSL_get_client_ciphers \ SSL_get_client_random \ SSL_get_server_random \ - TLS_method \ + SSL_set_ciphersuites \ + TLS_method ]) dnl Check if OpenSSL structures are opaque diff --git a/src/lib/tls/ciphers_v13.inc b/src/lib/tls/ciphers_v13.inc @@ -0,0 +1,15 @@ +/* Here are the TLS1.3 ciphers. Note that we don't have XCIPHER instances + * here, since we don't want to ever fake them. + * + * This matches Firefox's list: + * https://searchfox.org/mozilla-central/source/security/nss/lib/ssl/ssl3con.c#100 + */ +#ifdef TLS1_3_RFC_AES_128_GCM_SHA256 + CIPHER(0x1301, TLS1_3_RFC_AES_128_GCM_SHA256) +#endif +#ifdef TLS1_3_RFC_CHACHA20_POLY1305_SHA256 + CIPHER(0x1303, TLS1_3_RFC_CHACHA20_POLY1305_SHA256) +#endif +#ifdef TLS1_3_RFC_AES_256_GCM_SHA384 + CIPHER(0x1302, TLS1_3_RFC_AES_256_GCM_SHA384) +#endif diff --git a/src/lib/tls/include.am b/src/lib/tls/include.am @@ -33,6 +33,7 @@ src_lib_libtor_tls_testing_a_CFLAGS = \ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/lib/tls/ciphers.inc \ + src/lib/tls/ciphers_v13.inc \ src/lib/tls/buffers_tls.h \ src/lib/tls/nss_countbytes.h \ src/lib/tls/tortls.h \ diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c @@ -493,6 +493,12 @@ static const char CLIENT_CIPHER_LIST[] = * of any cipher we say. */ "!SSLv2" ; +static char CLIENT_CIPHER_LIST_TLSv13[] = +#ifndef COCCI +#include "lib/tls/ciphers_v13.inc" +#endif + "" + ; #undef CIPHER #undef XCIPHER @@ -1136,8 +1142,24 @@ tor_tls_new(tor_socket_t sock, int isServer) } #endif /* defined(SSL_CTRL_SET_MAX_PROTO_VERSION) */ - if (!SSL_set_cipher_list(result->ssl, - isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) { + /* Contrary to SSL_set_cipher_list(), TLSv1.3 SSL_set_ciphersuites() does NOT + * accept the final ':' so we have to strip it out. */ + size_t TLSv13len = strlen(CLIENT_CIPHER_LIST_TLSv13); + if (TLSv13len && CLIENT_CIPHER_LIST_TLSv13[TLSv13len - 1] == ':') { + CLIENT_CIPHER_LIST_TLSv13[TLSv13len - 1] = '\0'; + } + + const bool tls12_ciphers_ok = SSL_set_cipher_list( + result->ssl, isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST); + bool tls13_ciphers_ok = true; +#ifdef HAVE_SSL_SET_CIPHERSUITES + if (!isServer) { + tls13_ciphers_ok = + SSL_set_ciphersuites(result->ssl, CLIENT_CIPHER_LIST_TLSv13); + } +#endif + + if (!tls12_ciphers_ok || !tls13_ciphers_ok) { tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers"); #ifdef SSL_set_tlsext_host_name SSL_set_tlsext_host_name(result->ssl, NULL);