Index: configure.in =================================================================== --- configure.in (revision 18089) +++ configure.in (working copy) @@ -26,6 +26,13 @@ CFLAGS="$CFLAGS -g" fi]) +AC_ARG_ENABLE(highly-insecure-key-logging, + AS_HELP_STRING(--enable-highly-insecure-key-logging, log TLS and AES key)) +if test x$enable_highly_insecure_key_logging == xyes; then + AC_DEFINE(HIGHLY_INSECURE_KEY_LOGGING, 1, + [Defined if we are logging TLS and AES keys for use in network trace decoding]) +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 18089) +++ src/or/connection_or.c (working copy) @@ -798,7 +798,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; @@ -858,6 +859,10 @@ tor_tls_err_to_string(result)); return -1; case TOR_TLS_DONE: +#ifdef HIGHLY_INSECURE_KEY_LOGGING + /** 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 18089) +++ 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_LOGGING +/** Log the keys used for the circuit */ +int circuit_log_keys(origin_circuit_t *circ, crypt_path_t *hop); +#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. @@ -973,7 +978,10 @@ if (circuit_init_cpath_crypto(hop, keys, 0)<0) { return -END_CIRC_REASON_TORPROTOCOL; } - +#ifdef HIGHLY_INSECURE_KEY_LOGGING + /* Log the key material just negotiated for this circuit */ + circuit_log_keys(circ, hop); +#endif hop->state = CPATH_STATE_OPEN; log_info(LD_CIRC,"Finished building %scircuit hop:", (reply_type == CELL_CREATED_FAST) ? "fast " : ""); @@ -983,6 +991,19 @@ return 0; } +#ifdef HIGHLY_INSECURE_KEY_LOGGING +/** + * Log the keys negotiated for the specified hop on this circ + */ +int +circuit_log_keys(origin_circuit_t *circ, crypt_path_t *hop) +{ + crypto_dump_crypto_key(hop->f_crypto, 1, circ->_base.n_circ_id); + crypto_dump_crypto_key(hop->b_crypto, 0, circ->_base.n_circ_id); + return 0; +} +#endif + /** We received a relay truncated cell on circ. * * Since we don't ask for truncates currently, getting a truncated Index: src/common/crypto.c =================================================================== --- src/common/crypto.c (revision 18089) +++ src/common/crypto.c (working copy) @@ -331,6 +331,40 @@ tor_free(env); } +#ifdef HIGHLY_INSECURE_KEY_LOGGING +/** + * Log the keys specified in crypto, along with the + * string purpose + */ +int +crypto_dump_crypto_key(crypto_cipher_env_t *crypto, int forward, + int circid) { + char buf[CIPHER_KEY_LEN*2 + 1]; + char tbuf[64]; + + int i; + + /* Zero buffer as it is possible length is zero and tor_snprintf will + not get called */ + bzero(buf, sizeof(buf)); + + for (i = 0; ikey[i])&0xFF); + } + + tor_snprintf(tbuf, sizeof(tbuf), "%s crypto, n_circid: %d", + (forward)?"forward":"reverse",circid); + /* Log for RH Tor wireshark dissector */ + /* A CSV line is easier to parse in C */ + log_info(LD_CRYPTO, "%i,%s,%s", circid,(forward)?"forward":"reverse", buf); + /* Log for SJM Tor decoder */ + log_info(LD_CRYPTO, "Key for %s: <%s>", tbuf, buf); + return 0; +} +#endif + /** Create a new symmetric cipher for a given key and encryption flag * (1=encrypt, 0=decrypt). Return the crypto object on success; NULL * on failure. Index: src/common/crypto.h =================================================================== --- src/common/crypto.h (revision 18089) +++ src/common/crypto.h (working copy) @@ -169,6 +169,12 @@ int crypto_expand_key_material(const char *key_in, size_t in_len, char *key_out, size_t key_out_len); +#ifdef HIGHLY_INSECURE_KEY_LOGGING +/* Logging circuit crypto keys */ +int crypto_dump_crypto_key(crypto_cipher_env_t *crypto, int forward, + int circid); +#endif + /* random numbers */ int crypto_seed_rng(int startup); int crypto_rand(char *to, size_t n); Index: src/common/tortls.c =================================================================== --- src/common/tortls.c (revision 18089) +++ 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 connectinon. */ + /** 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, @@ -565,7 +567,7 @@ SSL_CTX_set_options(result->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif - /* Don't actually allow compression; it uses ram and time, but the data + /* Don't actually allow compression; it uses ram and time, but the data * we transmit is all encrypted anyway. */ if (result->ctx->comp_methods) result->ctx->comp_methods = NULL; @@ -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,51 @@ return err; } +#ifdef HIGHLY_INSECURE_KEY_LOGGING +/** + * Log the TLS master key + */ +int +tor_tls_dump_tls_key(tor_tls_t *tls) +{ + char buf[SSL_MAX_MASTER_KEY_LENGTH*2 + 1]; + int i; + SSL_SESSION *ctx; + + /* Get a reference to the OpenSSL session */ + ctx = tls->ssl->session; + + if (! ctx) { + log_info(LD_NET, "TLS master key: NULL"); + return 0; + } + + /* Zero buffer as it is possible length is zero and tor_snprintf + will not get called */ + bzero(buf, sizeof(buf)); + + /* Convert the master key to a hex string */ + for (i = 0; i < ctx->master_key_length; ++i) { + tor_snprintf(buf + 2*i, sizeof(buf) - 2*i, "%02x", + ((int)ctx->master_key[i]) & 0xFF); + } + /* Log for SJM Tor decoder */ + log_info(LD_NET, "TLS master key for %s: <%s>", ADDR(tls), buf); + /* Log for RH Tor wireshark dissector */ + /* This is the format required by packet-ssl-utils.c in wireshark. + I have adapted packet-ssl-utils.c to accept TLS master keys + rather than private keys in the fourth CSV. Adapting the + wireshark code to accept SJM's format would require a very + detailed change to the wireshark code and conflict with the + format the routine expects for non-Tor ip/port/protocol/ + privatekey log lines. Wireshark needs the port and 'protocol' + (i.e. 'tor') information in order to register the stream + properly and hand it off to the Tor dissector as appropriate. */ + log_info(LD_NET, "%s,%u,tor,%s", ADDR(tls),(tls)->port, buf); + return 0; +} +#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 18089) +++ 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,10 @@ void _check_no_tls_errors(const char *fname, int line); +#ifdef HIGHLY_INSECURE_KEY_LOGGING +/* Log the TLS master key */ +int tor_tls_dump_tls_key(tor_tls_t *tls); #endif +#endif +