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
+