diff options
-rw-r--r-- | doc/TODO | 4 | ||||
-rw-r--r-- | src/common/tortls.c | 10 | ||||
-rw-r--r-- | src/common/tortls.h | 1 | ||||
-rw-r--r-- | src/or/command.c | 25 | ||||
-rw-r--r-- | src/or/connection_or.c | 43 | ||||
-rw-r--r-- | src/or/or.h | 2 |
6 files changed, 76 insertions, 9 deletions
@@ -43,7 +43,7 @@ Things we'd like to do in 0.2.0.x: o Keep copies of X509 certs around, not necessarily associated with connection. - LINK_AUTH cells - . Code to generate + o Code to generate o Remember certificate digests from TLS o Code to parse and check - Unit tests @@ -56,7 +56,7 @@ Things we'd like to do in 0.2.0.x: - Revised handshake: post-TLS. o If in 'handshaking' state (since v2+ conn is in use), accept VERSIONS and NETINFO and CERT and LINK_AUTH. - - After we send NETINFO, send CERT and LINK_AUTH if needed. + o After we send NETINFO, send CERT and LINK_AUTH if needed. - Once we get a good LINK_AUTH, the connection is OPEN. - Ban most cell types on a non-OPEN connection. o Make code work right wrt TLS context rotation. diff --git a/src/common/tortls.c b/src/common/tortls.c index 6c04a362a8..1075de977e 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -47,6 +47,7 @@ typedef struct tor_tls_context_t { SSL_CTX *ctx; X509 *my_cert; X509 *my_id_cert; + crypto_pk_env_t *key; } tor_tls_context_t; /** Holds a SSL object and its associated data. Members are only @@ -355,6 +356,7 @@ tor_tls_context_decref(tor_tls_context_t *ctx) SSL_CTX_free(ctx->ctx); X509_free(ctx->my_cert); X509_free(ctx->my_id_cert); + crypto_free_pk_env(ctx->key); tor_free(ctx); } } @@ -410,6 +412,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname, result->refcnt = 1; result->my_cert = X509_dup(cert); result->my_id_cert = X509_dup(idcert); + result->key = crypto_pk_dup_key(rsa); #ifdef EVERYONE_HAS_AES /* Tell OpenSSL to only use TLS1 */ @@ -735,6 +738,13 @@ tor_tls_get_cert_digests(tor_tls_t *tls, } /** DOCDOC */ +crypto_pk_env_t * +tor_tls_dup_private_key(tor_tls_t *tls) +{ + return crypto_pk_dup_key(tls->context->key); +} + +/** DOCDOC */ char * tor_tls_encode_my_certificate(tor_tls_t *tls, size_t *size_out, int conn_cert) diff --git a/src/common/tortls.h b/src/common/tortls.h index 639502e378..a0fad8488a 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -57,6 +57,7 @@ int tor_tls_get_cert_digests(tor_tls_t *tls, char *my_digest_out, char *peer_digest_out); char *tor_tls_encode_my_certificate(tor_tls_t *tls, size_t *size_out, int conn_cert); +crypto_pk_env_t *tor_tls_dup_private_key(tor_tls_t *tls); int tor_tls_verify_v1(int severity, tor_tls_t *tls, crypto_pk_env_t **identity); int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance); diff --git a/src/or/command.c b/src/or/command.c index dcb713f73c..e33fe8036b 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -432,15 +432,22 @@ command_process_versions_cell(cell_t *cell, or_connection_t *conn) if (!highest_supported_version) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Couldn't find a version in common; defaulting to v1."); - /*XXXX020 just break the connection?*/ + /*XXXX020 just break the connection! */ conn->link_proto = 1; return; } conn->link_proto = highest_supported_version; conn->handshake_state->received_versions = 1; - if (highest_supported_version >= 2) + if (highest_supported_version >= 2) { + /*XXXX020 check return values. */ connection_or_send_netinfo(conn); + connection_or_send_cert(conn); + if (conn->handshake_state->started_here) + connection_or_send_link_auth(conn); + } else { + /* XXXX020 finish v1 verification. */ + } } /** Process a 'netinfo' cell. DOCDOC say more. */ @@ -576,6 +583,7 @@ command_process_link_auth_cell(cell_t *cell, or_connection_t *conn) { or_handshake_state_t *s; char hmac[DIGEST_LEN]; + uint16 len; size_t sig_len; const char *sig; char *checked = NULL; @@ -599,7 +607,13 @@ command_process_link_auth_cell(cell_t *cell, or_connection_t *conn) "closing the connection"); goto err; } - if (cell->payload[0] != 0x00) { + len = ntohs(get_uint16(cell.payload)); + if (len < 2 || 2+len > CELL_PAYLOAD_SIZE) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Bad length field (%d) on LINK_AUTH cell;" + " closing the connection", (int)len); + goto err; + } + if (cell->payload[2] != 0x00) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Unrecognized LINK_AUTH signature " "version; closing the connection"); goto err; @@ -608,9 +622,8 @@ command_process_link_auth_cell(cell_t *cell, or_connection_t *conn) tor_assert(s->signing_key); - /*XXXX020 these two are wrong; fix when protocol is revised. */ - sig = cell->payload+1; - sig_len = 128; + sig = cell->payload+3; + sig_len = len-1; checked = tor_malloc(crypto_pk_keysize(s->signing_key)); checked_len = crypto_pk_public_checksig(s->signing_key,checked,sig,sig_len); if (checked_len < 0) { diff --git a/src/or/connection_or.c b/src/or/connection_or.c index a75d6df7d8..93f4d5d7b1 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -980,4 +980,47 @@ connection_or_compute_link_auth_hmac(or_connection_t *conn, return 0; } +/**DOCDOC*/ +int +connection_or_send_cert(or_connection_t *conn) +{ + (void)conn; + /*XXX020 implement.*/ + return 0; +} + +/**DOCDOC*/ +int +connection_or_send_link_auth(or_connection_t *conn) +{ + cell_t cell; + char hmac[DIGEST_LEN]; + crypto_pk_env_t *key; + int r, len; + tor_assert(conn); + tor_assert(conn->tls); + tor_assert(conn->handshake_state); + tor_assert(conn->handshake_state->started_here == 1); + tor_assert(conn->handshake_state->received_certs == 1); + + memset(&cell, 0, sizeof(cell)); + cell.command = CELL_LINK_AUTH; + key = tor_tls_dup_private_key(conn->tls); + connection_or_compute_link_auth_hmac(conn, hmac); + + cell.payload[2] = 0x00; /* Signature version */ + r = crypto_pk_private_sign(key, cell.payload+3, hmac, sizeof(hmac)); + crypto_free_pk_env(key); + if (r<0) + return -1; + len = r + 1; + + set_uint16(cell.payload, htons(len)); + + connection_or_write_cell_to_buf(&cell, conn); + + /* XXXX020 at this point, as a client, we can consider ourself + * authenticated. */ + return 0; +} diff --git a/src/or/or.h b/src/or/or.h index 87914e3c3c..8dd6dc806c 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2780,7 +2780,7 @@ void connection_or_write_cell_to_buf(const cell_t *cell, int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason); int connection_or_send_netinfo(or_connection_t *conn); -int connection_or_send_certs(or_connection_t *conn); +int connection_or_send_cert(or_connection_t *conn); int connection_or_send_link_auth(or_connection_t *conn); int connection_or_compute_link_auth_hmac(or_connection_t *conn, char *hmac_out); |