Index: configure.in
===================================================================
--- configure.in	(revision 18338)
+++ 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 18338)
+++ src/or/connection_or.c	(working copy)
@@ -821,7 +821,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;
@@ -881,6 +882,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 18338)
+++ 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,29 @@
   return 0;
 }
 
+#ifdef HIGHLY_INSECURE_KEY_DEBUGGING
+/**
+ * Log the keys negotiated for the specified <b>hop</b> on this <b>circ</b>
+ */
+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];
+
+  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);
+
+  crypto_dump_crypto_key(f_digest, f_crypto, 1, circ->_base.n_circ_id);
+  crypto_dump_crypto_key(b_digest, 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/or/main.c
===================================================================
--- src/or/main.c	(revision 18338)
+++ 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/crypto.c
===================================================================
--- src/common/crypto.c	(revision 18338)
+++ src/common/crypto.c	(working copy)
@@ -332,6 +332,29 @@
   tor_free(env);
 }
 
+#ifdef HIGHLY_INSECURE_KEY_DEBUGGING
+/**
+ * Log the keys specified in <b>crypto</b>, along with the
+ * string <b>forward</b>
+ */
+void
+crypto_dump_crypto_key(char *digest, char *crypto, int forward, int circid)
+{
+  char dbuf[DIGEST_LEN*2 + 1];
+  char cbuf[CIPHER_KEY_LEN*2 + 1];
+
+  base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN);
+  base16_encode(cbuf, sizeof(cbuf), crypto, CIPHER_KEY_LEN);
+
+  tor_strlower(dbuf);
+  tor_strlower(cbuf);
+
+  log_info(LD_CRYPTO, "Circuit key (circid,direction,digest,crypto): "
+           "%i,%s,%s,%s",
+           circid, (forward) ? "forward" : "reverse", dbuf, cbuf);
+}
+#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 18338)
+++ 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_DEBUGGING
+/* Logging circuit crypto keys */
+void crypto_dump_crypto_key(char *digest, char *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 18338)
+++ 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 @@
  * <b>address</b>.
  */
 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 <b>cb</b> to be called with argument <b>arg</b> whenever <b>tls</b>
@@ -1000,6 +1003,33 @@
   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;
+
+  /* Get a reference to the OpenSSL session */
+  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),(tls)->port, buf);
+}
+#endif
+
 /** Perform initial handshake on <b>tls</b>.  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 18338)
+++ 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_DEBUGGING
+/* Log the TLS master key */
+void tor_tls_dump_tls_key(tor_tls_t *tls);
 #endif
 
+#endif
+
