From 04e8dc90262d9ccc5ef6932cfe86feac24fde997 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 5 Apr 2004 20:53:50 +0000 Subject: [PATCH] Implement response to RENDEZVOUS2 cell. svn:r1490 --- src/or/or.h | 4 ++-- src/or/rendclient.c | 44 ++++++++++++++++++++++++++++++++++++++++---- src/or/rendservice.c | 2 +- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/or/or.h b/src/or/or.h index 81f67c9e37..4458550032 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -501,7 +501,7 @@ struct crypt_path_t { int deliver_window; }; -#define DH_KEY_LEN CRYPTO_DH_SIZE +#define DH_KEY_LEN DH_BYTES #define ONIONSKIN_CHALLENGE_LEN (16+DH_KEY_LEN) #define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+20) #define REND_COOKIE_LEN DIGEST_LEN @@ -732,7 +732,7 @@ void circuit_n_conn_open(connection_t *or_conn); int circuit_send_next_onion_skin(circuit_t *circ); int circuit_extend(cell_t *cell, circuit_t *circ); #define CPATH_KEY_MATERIAL_LEN (20*2+16*2) -int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data); +int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data,int reverse); int circuit_finish_handshake(circuit_t *circ, char *reply); int circuit_truncated(circuit_t *circ, crypt_path_t *layer); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index d02e7521fd..f7b89ca138 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -160,6 +160,10 @@ int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len) { connection_t *apconn; + crypt_path_t *hop; + char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; + char buf[DIGEST_LEN+9]; + char expected_digest[DIGEST_LEN]; if(circ->purpose != CIRCUIT_PURPOSE_C_REND_READY || !circ->build_state->pending_final_cpath) { @@ -168,17 +172,49 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request return -1; } - /* XXX - * take 'request' and 'circ->build_state->pending_final_cpath' - * and do the right thing to circ - */ + if (request_len != DH_KEY_LEN+DIGEST_LEN) { + log_fn(LOG_WARN,"Incorrect length (%d) on RENDEZVOUS2 cell.",request_len); + goto err; + } + /* first DH_KEY_LEN bytes are g^y from bob. Finish the dh handshake...*/ + assert(circ->build_state && circ->build_state->pending_final_cpath); + hop = circ->build_state->pending_final_cpath; + assert(hop->handshake_state); + if (crypto_dh_compute_secret(hop->handshake_state, request, DH_KEY_LEN, + keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { + log_fn(LOG_WARN, "Couldn't complete DH handshake"); + goto err; + } + /* ... and set up cpath. */ + if (circuit_init_cpath_crypto(hop, keys+DIGEST_LEN, 0)<0) + goto err; + + /* Check whether the digest is right... */ + memcpy(buf, keys, DIGEST_LEN); + memcpy(buf+DIGEST_LEN, "INTRODUCE", 9); + if (crypto_digest(buf, DIGEST_LEN+9, expected_digest)) { + log_fn(LOG_WARN, "Error computing digest"); + goto err; + } + if (memcmp(expected_digest, request+DH_KEY_LEN, DIGEST_LEN)) { + log_fn(LOG_WARN, "Incorrect digest of key material"); + goto err; + } + + /* All is well. Extend the circuit. */ circ->purpose = CIRCUIT_PURPOSE_C_REND_JOINED; + onion_append_to_cpath(&circ->cpath, hop); + circ->build_state->pending_final_cpath = NULL; /* prevent double-free */ + for(apconn = circ->p_streams; apconn; apconn = apconn->next_stream) { if(connection_ap_handshake_send_begin(apconn, circ) < 0) return -1; } return 0; + err: + circuit_mark_for_close(circ); + return -1; } /* Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that diff --git a/src/or/rendservice.c b/src/or/rendservice.c index b4898a3f50..b865d01e9e 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -414,7 +414,7 @@ rend_service_introduce(circuit_t *circuit, const char *request, int request_len) cpath->handshake_state = dh; dh = NULL; - if (circuit_init_cpath_crypto(cpath,keys+20)<0) + if (circuit_init_cpath_crypto(cpath,keys+20,1)<0) goto err; memcpy(cpath->handshake_digest, keys, 20);