From 6c6aaf5b08392b40f0fa56827d221778c9bcf273 Mon Sep 17 00:00:00 2001 From: Robert Hogan Date: Sat, 24 Jul 2010 17:44:07 +0100 Subject: [PATCH] Add compile time option --enable-highly-insecure-key-debugging This option is useful for decrypting and debugging Tor traffic originating from our own instance of Tor. The option will not log TLS and AES keys if Tor detects that it is running as a server. --- configure.in | 18 +++++++++++++ src/common/tortls.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++- src/common/tortls.h | 11 +++++++- src/or/circuitbuild.c | 49 ++++++++++++++++++++++++++++++++++++ src/or/connection_or.c | 13 +++++++++- src/or/main.c | 9 ++++++ 6 files changed, 161 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index f7cb277..62ff538 100644 --- a/configure.in +++ b/configure.in @@ -79,6 +79,24 @@ if test "$enable_threads" = "yes"; then AC_DEFINE(ENABLE_THREADS, 1, [Defined if we will try to use multithreading]) fi +# This option is useful for decrypting and debugging Tor traffic originating from +# our own instance of Tor. The option will not log TLS and AES keys if Tor detects +# that it is running as a server. +AC_ARG_ENABLE(highly-insecure-key-debugging, + AS_HELP_STRING(--enable-highly-insecure-key-debugging, Defined if we are logging \ + TLS and AES keys for use in decrypting and debugging client \ + traffic originating from our own instance of Tor. The \ + option will not log TLS and AES keys if Tor detects \ + that it is running as a server.)) +if test x$enable_highly_insecure_key_debugging = xyes; then + AC_DEFINE(HIGHLY_INSECURE_KEY_DEBUGGING, 1, + [Defined if we are logging TLS and AES keys for use in debugging \ + client traffic originating from our own instance of Tor. The \ + option will not log TLS and AES keys if Tor detects that it \ + is running as a server]) +fi + + case $host in *-*-solaris* ) AC_DEFINE(_REENTRANT, 1, [Define on some platforms to activate x_r() functions in time.h]) diff --git a/src/common/tortls.c b/src/common/tortls.c index b3c91a6..baf9224 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -93,6 +93,8 @@ struct tor_tls_t { SSL *ssl; /**< An OpenSSL SSL object. */ int socket; /**< The underlying file descriptor for this TLS connection. */ char *address; /**< An address to log when describing this connection. */ + uint16_t port; /**< A port to log when describing this connection. */ + /**< This is required for wireshark dissection */ enum { TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE, TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE, @@ -982,11 +984,12 @@ tor_tls_new(int sock, int isServer) * address. */ void -tor_tls_set_logged_address(tor_tls_t *tls, const char *address) +tor_tls_set_logged_address(tor_tls_t *tls, const char *address, uint16_t port) { tor_assert(tls); tor_free(tls->address); tls->address = tor_strdup(address); + tls->port = port; } /** Set cb to be called with argument arg whenever tls @@ -1144,6 +1147,65 @@ tor_tls_write(tor_tls_t *tls, const char *cp, size_t n) return err; } +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING +/** + * Log the TLS master key. + */ +void +tor_tls_dump_tls_key(tor_tls_t *tls) +{ + char buf[SSL_MAX_MASTER_KEY_LENGTH*2 + 1]; + SSL_SESSION *ctx = NULL; + + /* Get a reference to the OpenSSL session */ + if (tls && tls->ssl) + ctx = tls->ssl->session; + + if (! ctx) { + log_warn(LD_CRYPTO, "TLS master key: NULL"); + return; + } + + base16_encode(buf, sizeof(buf), (char *)ctx->master_key, + ctx->master_key_length); + tor_strlower(buf); + log_info(LD_CRYPTO, "TLS master key (address,port,protocol,key): " + "%s,%u,tor,%s", + ADDR(tls), (unsigned)(tls->port), buf); +} + +/** + * Log the keys specified in digest and crypto, along with the + * circuit ID circid and address from tls. If forward + * is true, this will be logged as forward direction keys, otherwise reverse. + */ +void +tor_tls_dump_circuit_key(char *digest, char *crypto, int forward, + uint16_t circid, tor_tls_t *tls) +{ + char dbuf[DIGEST_LEN*2 + 1]; + char cbuf[CIPHER_KEY_LEN*2 + 1]; + uint16_t port = 0; + const char *addr; + + base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN); + base16_encode(cbuf, sizeof(cbuf), crypto, CIPHER_KEY_LEN); + + tor_strlower(dbuf); + tor_strlower(cbuf); + + addr = ADDR(tls); + if (tls) + port = tls->port; + + log_info(LD_CRYPTO, "Circuit key (address,port," + "circid,direction,digest,crypto): " + "%s,%u,%u,%s,%s,%s", + addr, (unsigned)port, (unsigned)circid, + (forward) ? "forward" : "reverse", dbuf, cbuf); +} +#endif + /** Perform initial handshake on tls. When finished, returns * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, * or TOR_TLS_WANTWRITE. diff --git a/src/common/tortls.h b/src/common/tortls.h index e4b1ad6..083efe8 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -52,7 +52,8 @@ const char *tor_tls_err_to_string(int err); void tor_tls_free_all(void); int tor_tls_context_new(crypto_pk_env_t *rsa, unsigned int key_lifetime); tor_tls_t *tor_tls_new(int sock, int is_server); -void tor_tls_set_logged_address(tor_tls_t *tls, const char *address); +void tor_tls_set_logged_address(tor_tls_t *tls, const char *address, + uint16_t port); void tor_tls_set_renegotiate_callback(tor_tls_t *tls, void (*cb)(tor_tls_t *, void *arg), void *arg); @@ -85,5 +86,13 @@ int tor_tls_used_v1_handshake(tor_tls_t *tls); void _check_no_tls_errors(const char *fname, int line); +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING +/* Log the TLS master key */ +void tor_tls_dump_tls_key(tor_tls_t *tls); +/* Log the circuit key */ +void tor_tls_dump_circuit_key(char *digest, char *crypto, int forward, + uint16_t circid, tor_tls_t *tls); +#endif + #endif diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 792260f..c7c746e 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1285,6 +1285,11 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt) } } +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING +/** Log the keys used for the circuit */ +int circuit_log_keys(origin_circuit_t *circ, const char *key_data); +#endif + /** Iterate over values of circ_id, starting from conn-\>next_circ_id, * and with the high bit specified by conn-\>circ_id_type, until we get * a circ_id that is not in use by any other circuit on that conn. @@ -2206,6 +2211,17 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, return -END_CIRC_REASON_TORPROTOCOL; } +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING + /* Log the key material just negotiated for this circuit */ + if (server_mode(get_options())) { + log_warn(LD_CIRC,"Tor has been built to dump AES keys for debugging " + "purposes. But we are running as a server and dumping " + "AES keys could compromise the security of other " + "users. Skipping key dumping."); + } else { + circuit_log_keys(circ, keys); + } +#endif hop->state = CPATH_STATE_OPEN; log_info(LD_CIRC,"Finished building %scircuit hop:", (reply_type == CELL_CREATED_FAST) ? "fast " : ""); @@ -2215,6 +2231,39 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, return 0; } +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING +/** + * Log the key material key_data on this circ + */ +int +circuit_log_keys(origin_circuit_t *circ, const char *key_data) +{ + char f_digest[DIGEST_LEN]; + char b_digest[DIGEST_LEN]; + char f_crypto[CIPHER_KEY_LEN]; + char b_crypto[CIPHER_KEY_LEN]; + + tor_tls_t *tls = NULL; + circid_t n_circ_id = 0; + + memcpy(f_digest, key_data, DIGEST_LEN); + memcpy(b_digest, key_data+DIGEST_LEN, DIGEST_LEN); + memcpy(f_crypto, key_data+(2*DIGEST_LEN), CIPHER_KEY_LEN); + memcpy(b_crypto, key_data+(2*DIGEST_LEN)+CIPHER_KEY_LEN, CIPHER_KEY_LEN); + + if (circ) { + n_circ_id = circ->_base.n_circ_id; + if (circ->_base.n_conn) { + tls = circ->_base.n_conn->tls; + } + } + + tor_tls_dump_circuit_key(f_digest, f_crypto, 1, (uint16_t)n_circ_id, tls); + tor_tls_dump_circuit_key(b_digest, b_crypto, 0, (uint16_t)n_circ_id, tls); + return 0; +} +#endif + /** We received a relay truncated cell on circ. * * Since we don't ask for truncates currently, getting a truncated diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 247cc4e..ea36d1b 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -806,7 +806,7 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving) conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING; conn->tls = tor_tls_new(conn->_base.s, receiving); tor_tls_set_logged_address(conn->tls, // XXX client and relay? - escaped_safe_str(conn->_base.address)); + escaped_safe_str(conn->_base.address), conn->_base.port); if (!conn->tls) { log_warn(LD_BUG,"tor_tls_new failed. Closing."); return -1; @@ -867,6 +867,17 @@ connection_tls_continue_handshake(or_connection_t *conn) tor_tls_err_to_string(result)); return -1; case TOR_TLS_DONE: +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING + if (server_mode(get_options())) { + log_warn(LD_OR,"Tor has been built to dump TLS keys for debugging " + "purposes. But we are running as a server and dumping " + "TLS keys could compromise the security of other " + "users. Skipping key dumping."); + } else { + /** Log TLS master key */ + tor_tls_dump_tls_key(conn->tls); + } +#endif if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) { diff --git a/src/or/main.c b/src/or/main.c index 0dcc454..2b049db 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1875,6 +1875,15 @@ tor_init(int argc, char *argv[]) "Do not rely on it for strong anonymity. (Running on %s)",get_version(), get_uname()); +#ifdef HIGHLY_INSECURE_KEY_DEBUGGING + log_warn(LD_GENERAL, "Tor has been built with the option " + "--enable-highly-insecure-key-debugging. This " + "will dump TLS and circuit keys to Tor's log files. " + "This option is only required for debugging purposes. " + "If you did not configure Tor to do this yourself " + "you should re-install Tor from a trusted source."); +#endif + if (network_init()<0) { log_err(LD_BUG,"Error initializing network; exiting."); return -1; -- 1.7.0.4