Index: configure.in =================================================================== --- configure.in (revision 18415) +++ configure.in (working copy) @@ -26,6 +26,23 @@ CFLAGS="$CFLAGS -g" 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 + #XXXX ideally, we should make this into a no-op, and detect whether we're #compiling for the iphone by using $target. AC_ARG_ENABLE(iphone, Index: src/or/connection_or.c =================================================================== --- src/or/connection_or.c (revision 18415) +++ src/or/connection_or.c (working copy) @@ -819,7 +819,8 @@ { conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING; conn->tls = tor_tls_new(conn->_base.s, receiving); - tor_tls_set_logged_address(conn->tls, escaped_safe_str(conn->_base.address)); + tor_tls_set_logged_address(conn->tls, escaped_safe_str(conn->_base.address), + conn->_base.port); if (!conn->tls) { log_warn(LD_BUG,"tor_tls_new failed. Closing."); return -1; @@ -879,6 +880,17 @@ 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) { Index: src/or/circuitbuild.c =================================================================== --- src/or/circuitbuild.c (revision 18415) +++ src/or/circuitbuild.c (working copy) @@ -60,6 +60,11 @@ static void entry_guards_changed(void); static time_t start_of_month(time_t when); +#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. @@ -932,6 +937,17 @@ 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 " : ""); @@ -941,6 +957,39 @@ 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 Index: src/or/main.c =================================================================== --- src/or/main.c (revision 18415) +++ src/or/main.c (working copy) @@ -1800,6 +1800,15 @@ "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; Index: src/common/tortls.c =================================================================== --- src/common/tortls.c (revision 18415) +++ src/common/tortls.c (working copy) @@ -70,7 +70,9 @@ tor_tls_context_t *context; /** A link to the context object for this tls */ 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 connectinon. */ + char *address; /**< An address to log when describing this connection. */ + uint16_t port; /**< An 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, @@ -870,11 +872,12 @@ * 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 @@ -1000,6 +1003,65 @@ 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. Index: src/common/tortls.h =================================================================== --- src/common/tortls.h (revision 18415) +++ src/common/tortls.h (working copy) @@ -52,7 +52,8 @@ 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); @@ -84,5 +85,13 @@ 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 +