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
+