summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-01-19 13:53:24 -0500
committerirungentoo <irungentoo@gmail.com>2014-01-19 13:53:24 -0500
commit639b37de672b26daae6bdb4119c0eb677cde0b54 (patch)
tree229d0b8fec4e3519fca29d95012cd6e8f447650b
parentcdcb8b86007b6490557f1329f42c08732282c500 (diff)
Small protocol change for more replay attack prevention.
see the changes to Prevent_Tracking.txt
-rw-r--r--docs/Prevent_Tracking.txt12
-rw-r--r--toxcore/onion_announce.c63
-rw-r--r--toxcore/onion_announce.h16
-rw-r--r--toxcore/onion_client.c35
-rw-r--r--toxcore/onion_client.h5
5 files changed, 83 insertions, 48 deletions
diff --git a/docs/Prevent_Tracking.txt b/docs/Prevent_Tracking.txt
index ab091999..07e8ae1e 100644
--- a/docs/Prevent_Tracking.txt
+++ b/docs/Prevent_Tracking.txt
@@ -97,7 +97,8 @@ Data sent to Node D:
97 97
98announce request packet: 98announce request packet:
99[uint8_t packet id (131)][nonce][our real long term public key or a temporary one (see next)] 99[uint8_t packet id (131)][nonce][our real long term public key or a temporary one (see next)]
100encrypted (with our real long term private key if we want to announce ourselves, a temporary one if we are searching for friends) and the pub key of Node D and the nonce:[[(32 bytes) ping_id][client id we are searching for][data to send back in response(fixed size)]] 100encrypted (with our real long term private key if we want to announce ourselves, a temporary one if we are searching for friends) and the pub key of Node D and the nonce:
101[[(32 bytes) ping_id][client id we are searching for][public key that we want those sending back data packets to use.][data to send back in response(fixed size)]]
101 102
102(if the ping id is zero, respond with a announce response packet) 103(if the ping id is zero, respond with a announce response packet)
103(If the ping id matches the one the node sent in the announce response and the public key matches the one being searched for, 104(If the ping id matches the one the node sent in the announce response and the public key matches the one being searched for,
@@ -105,7 +106,7 @@ add the part used to send data to our list (if the list is full make it replace
105 106
106data to route request packet: 107data to route request packet:
107[uint8_t packet id (133)][public key of destination node][nonce][temporary just generated public key] 108[uint8_t packet id (133)][public key of destination node][nonce][temporary just generated public key]
108encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] 109encrypted with that temporary private key and the nonce and the public key from the announce response packet of the destination node:[data]
109(if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node) 110(if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node)
110 111
111The data in the previous packet is in format: [real public key of sender] 112The data in the previous packet is in format: [real public key of sender]
@@ -114,12 +115,13 @@ encrypted with real private key of the sender, the nonce in the data packet and
114Data sent to us: 115Data sent to us:
115announce response packet: 116announce response packet:
116[uint8_t packet id (132)][data to send back in response(fixed size)][nonce] 117[uint8_t packet id (132)][data to send back in response(fixed size)][nonce]
117encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[(32 bytes) ping_id][Node_Format * (maximum of 8)]] 118encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[uint8_t is_stored]
118(if the ping id is zero, it means the information to reach the client id we are searching for is stored on this node) 119[(32 bytes) ping_id if is_stored is 0, public key that must be used to send data packets if is_stored is not 0][Node_Format * (maximum of 8)]]
120(if the is_stored is not 0, it means the information to reach the client id we are searching for is stored on this node)
119 121
120data to route response packet: 122data to route response packet:
121[uint8_t packet id (134)][nonce][temporary just generated public key] 123[uint8_t packet id (134)][nonce][temporary just generated public key]
122encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] 124encrypted with that temporary private key, the nonce and the public key from the announce response packet of the destination node:[data]
123 125
124 126
125Onion packet (response): 127Onion packet (response):
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index 3e4f7e0a..8150974b 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -29,7 +29,7 @@
29 29
30#define PING_ID_TIMEOUT 20 30#define PING_ID_TIMEOUT 20
31 31
32#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES) 32#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
33#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) 33#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
34 34
35#define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) 35#define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
@@ -43,6 +43,7 @@
43 * public_key and secret_key is the kepair which will be used to encrypt the request. 43 * public_key and secret_key is the kepair which will be used to encrypt the request.
44 * ping_id is the ping id that will be sent in the request. 44 * ping_id is the ping id that will be sent in the request.
45 * client_id is the client id of the node we are searching for. 45 * client_id is the client id of the node we are searching for.
46 * data_public_key is the public key we want others to encrypt their data packets with.
46 * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to 47 * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
47 * receive back in the response. 48 * receive back in the response.
48 * 49 *
@@ -50,12 +51,14 @@
50 * return 0 on success. 51 * return 0 on success.
51 */ 52 */
52int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, 53int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id,
53 uint8_t *client_id, uint8_t *sendback_data) 54 uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
54{ 55{
55 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 56 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
56 memcpy(plain, ping_id, ONION_PING_ID_SIZE); 57 memcpy(plain, ping_id, ONION_PING_ID_SIZE);
57 memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES); 58 memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES);
58 memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, sendback_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); 59 memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES);
60 memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, sendback_data,
61 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
59 uint8_t packet[ANNOUNCE_REQUEST_SIZE]; 62 uint8_t packet[ANNOUNCE_REQUEST_SIZE];
60 packet[0] = NET_PACKET_ANNOUNCE_REQUEST; 63 packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
61 new_nonce(packet + 1); 64 new_nonce(packet + 1);
@@ -78,12 +81,15 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
78 * send the packet to that person in the form of a response) 81 * send the packet to that person in the form of a response)
79 * 82 *
80 * public_key is the real public key of the node which we want to send the data of length length to. 83 * public_key is the real public key of the node which we want to send the data of length length to.
84 * encrypt_public_key is the public key used to encrypt the data packet.
85 *
81 * nonce is the nonce to encrypt this packet with 86 * nonce is the nonce to encrypt this packet with
82 * 87 *
83 * return -1 on failure. 88 * return -1 on failure.
84 * return 0 on success. 89 * return 0 on success.
85 */ 90 */
86int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data, uint16_t length) 91int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce,
92 uint8_t *data, uint16_t length)
87{ 93{
88 uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; 94 uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
89 packet[0] = NET_PACKET_ONION_DATA_REQUEST; 95 packet[0] = NET_PACKET_ONION_DATA_REQUEST;
@@ -96,7 +102,7 @@ int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t
96 102
97 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, random_public_key, crypto_box_PUBLICKEYBYTES); 103 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, random_public_key, crypto_box_PUBLICKEYBYTES);
98 104
99 int len = encrypt_data(public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES, 105 int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES,
100 data, length, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 106 data, length, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
101 107
102 if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet)) 108 if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet))
@@ -167,10 +173,11 @@ static int cmp_entry(const void *a, const void *b)
167 173
168/* add entry to entries list 174/* add entry to entries list
169 * 175 *
170 * return 0 if failure 176 * return -1 if failure
171 * return 1 if added 177 * return position if added
172 */ 178 */
173static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t *public_key, uint8_t *ret) 179static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t *public_key, uint8_t *data_public_key,
180 uint8_t *ret)
174{ 181{
175 182
176 int pos = in_entries(onion_a, public_key); 183 int pos = in_entries(onion_a, public_key);
@@ -190,16 +197,17 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t
190 } 197 }
191 198
192 if (pos == -1) 199 if (pos == -1)
193 return 0; 200 return -1;
194 201
195 memcpy(onion_a->entries[pos].public_key, public_key, crypto_box_PUBLICKEYBYTES); 202 memcpy(onion_a->entries[pos].public_key, public_key, crypto_box_PUBLICKEYBYTES);
196 onion_a->entries[pos].ret_ip_port = ret_ip_port; 203 onion_a->entries[pos].ret_ip_port = ret_ip_port;
197 memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3); 204 memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);
205 memcpy(onion_a->entries[pos].data_public_key, data_public_key, crypto_box_PUBLICKEYBYTES);
198 onion_a->entries[pos].time = unix_time(); 206 onion_a->entries[pos].time = unix_time();
199 207
200 memcpy(cmp_public_key, onion_a->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 208 memcpy(cmp_public_key, onion_a->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
201 qsort(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, sizeof(Onion_Announce_Entry), cmp_entry); 209 qsort(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, sizeof(Onion_Announce_Entry), cmp_entry);
202 return 1; 210 return pos;
203} 211}
204 212
205static int handle_announce_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) 213static int handle_announce_request(void *object, IP_Port source, uint8_t *packet, uint32_t length)
@@ -209,10 +217,11 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
209 if (length != ANNOUNCE_REQUEST_SIZE_RECV) 217 if (length != ANNOUNCE_REQUEST_SIZE_RECV)
210 return 1; 218 return 1;
211 219
212 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 220 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
213 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, packet + 1, 221 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, packet + 1,
214 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 222 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
215 ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES, plain); 223 ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
224 crypto_box_MACBYTES, plain);
216 225
217 if ((uint32_t)len != sizeof(plain)) 226 if ((uint32_t)len != sizeof(plain))
218 return 1; 227 return 1;
@@ -223,13 +232,14 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
223 uint8_t ping_id2[ONION_PING_ID_SIZE]; 232 uint8_t ping_id2[ONION_PING_ID_SIZE];
224 generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, ping_id2); 233 generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, ping_id2);
225 234
226 int stored = 0; 235 int index = -1;
227 236
228 if (memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0 || memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) { 237 if (memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0 || memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) {
229 stored = add_to_entries(onion_a, source, packet + 1 + crypto_box_NONCEBYTES, 238 index = add_to_entries(onion_a, source, packet + 1 + crypto_box_NONCEBYTES,
230 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)); 239 plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES,
240 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
231 } else { 241 } else {
232 stored = (in_entries(onion_a, plain + ONION_PING_ID_SIZE) != -1); 242 index = in_entries(onion_a, plain + ONION_PING_ID_SIZE);
233 } 243 }
234 244
235 /*Respond with a announce response packet*/ 245 /*Respond with a announce response packet*/
@@ -245,24 +255,29 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
245 uint8_t nonce[crypto_box_NONCEBYTES]; 255 uint8_t nonce[crypto_box_NONCEBYTES];
246 new_nonce(nonce); 256 new_nonce(nonce);
247 257
248 uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0}; 258 uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)];
249 259
250 if (!stored) { 260 if (index == -1) {
251 memcpy(pl, ping_id2, ONION_PING_ID_SIZE); 261 pl[0] = 0;
262 memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
263 } else {
264 pl[0] = 1;
265 memcpy(pl + 1, onion_a->entries[index].data_public_key, crypto_box_PUBLICKEYBYTES);
252 } 266 }
253 267
254 memcpy(pl + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); 268 memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format));
255 269
256 uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; 270 uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
257 len = encrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, nonce, pl, 271 len = encrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, nonce, pl,
258 ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format), 272 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format),
259 data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); 273 data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES);
260 274
261 if ((uint32_t)len != ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) 275 if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES)
262 return 1; 276 return 1;
263 277
264 data[0] = NET_PACKET_ANNOUNCE_RESPONSE; 278 data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
265 memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); 279 memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES,
280 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
266 memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, crypto_box_NONCEBYTES); 281 memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, crypto_box_NONCEBYTES);
267 282
268 if (send_onion_response(onion_a->net, source, data, 283 if (send_onion_response(onion_a->net, source, data,
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index 01cd7243..27b25bd4 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -31,15 +31,20 @@
31 31
32#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) 32#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
33 33
34#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + ONION_PING_ID_SIZE + crypto_box_MACBYTES) 34#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
35#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) 35#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
36 36
37#define ONION_DATA_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) 37#define ONION_DATA_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
38 38
39#if ONION_PING_ID_SIZE != crypto_box_PUBLICKEYBYTES
40#error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES
41#endif
42
39typedef struct { 43typedef struct {
40 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 44 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
41 IP_Port ret_ip_port; 45 IP_Port ret_ip_port;
42 uint8_t ret[ONION_RETURN_3]; 46 uint8_t ret[ONION_RETURN_3];
47 uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
43 uint64_t time; 48 uint64_t time;
44} Onion_Announce_Entry; 49} Onion_Announce_Entry;
45 50
@@ -59,6 +64,7 @@ typedef struct {
59 * public_key and secret_key is the kepair which will be used to encrypt the request. 64 * public_key and secret_key is the kepair which will be used to encrypt the request.
60 * ping_id is the ping id that will be sent in the request. 65 * ping_id is the ping id that will be sent in the request.
61 * client_id is the client id of the node we are searching for. 66 * client_id is the client id of the node we are searching for.
67 * data_public_key is the public key we want others to encrypt their data packets with.
62 * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to 68 * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
63 * receive back in the response. 69 * receive back in the response.
64 * 70 *
@@ -66,7 +72,7 @@ typedef struct {
66 * return 0 on success. 72 * return 0 on success.
67 */ 73 */
68int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, 74int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id,
69 uint8_t *client_id, uint8_t *sendback_data); 75 uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
70 76
71/* Create and send an onion data request packet. 77/* Create and send an onion data request packet.
72 * 78 *
@@ -75,13 +81,15 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
75 * send the packet to that person in the form of a response) 81 * send the packet to that person in the form of a response)
76 * 82 *
77 * public_key is the real public key of the node which we want to send the data of length length to. 83 * public_key is the real public key of the node which we want to send the data of length length to.
84 * encrypt_public_key is the public key used to encrypt the data packet.
85 *
78 * nonce is the nonce to encrypt this packet with 86 * nonce is the nonce to encrypt this packet with
79 * 87 *
80 * return -1 on failure. 88 * return -1 on failure.
81 * return 0 on success. 89 * return 0 on success.
82 */ 90 */
83int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data, 91int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce,
84 uint16_t length); 92 uint8_t *data, uint16_t length);
85 93
86 94
87Onion_Announce *new_onion_announce(DHT *dht); 95Onion_Announce *new_onion_announce(DHT *dht);
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index e50679e5..06f64929 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -30,7 +30,6 @@
30 30
31#define ANNOUNCE_TIMEOUT 10 31#define ANNOUNCE_TIMEOUT 10
32 32
33static uint8_t zero_ping[ONION_PING_ID_SIZE];
34 33
35/* Creates a sendback for use in an announce request. 34/* Creates a sendback for use in an announce request.
36 * 35 *
@@ -126,11 +125,11 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
126 if (num == 0) { 125 if (num == 0) {
127 return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key, 126 return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key,
128 onion_c->dht->c->self_secret_key, ping_id, 127 onion_c->dht->c->self_secret_key, ping_id,
129 onion_c->dht->c->self_public_key, sendback); 128 onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
130 } else { 129 } else {
131 return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key, 130 return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key,
132 onion_c->friends_list[num - 1].temp_secret_key, ping_id, 131 onion_c->friends_list[num - 1].temp_secret_key, ping_id,
133 onion_c->friends_list[num - 1].real_client_id, sendback); 132 onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);
134 } 133 }
135} 134}
136 135
@@ -164,7 +163,7 @@ static int cmp_entry(const void *a, const void *b)
164} 163}
165 164
166static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, 165static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
167 uint8_t *ping_id) 166 uint8_t is_stored, uint8_t *pingid_or_key)
168{ 167{
169 if (num > onion_c->num_friends) 168 if (num > onion_c->num_friends)
170 return -1; 169 return -1;
@@ -204,7 +203,14 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
204 203
205 memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE); 204 memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE);
206 list_nodes[index].ip_port = ip_port; 205 list_nodes[index].ip_port = ip_port;
207 memcpy(list_nodes[index].ping_id, ping_id, ONION_PING_ID_SIZE); 206
207 if (is_stored) {
208 memcpy(list_nodes[index].data_public_key, pingid_or_key, crypto_box_PUBLICKEYBYTES);
209 } else {
210 memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
211 }
212
213 list_nodes[index].is_stored = is_stored;
208 list_nodes[index].timestamp = unix_time(); 214 list_nodes[index].timestamp = unix_time();
209 list_nodes[index].last_pinged = 0; 215 list_nodes[index].last_pinged = 0;
210 return 0; 216 return 0;
@@ -276,7 +282,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
276 if (num > onion_c->num_friends) 282 if (num > onion_c->num_friends)
277 return 1; 283 return 1;
278 284
279 uint8_t plain[ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; 285 uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)];
280 int len = -1; 286 int len = -1;
281 287
282 if (num == 0) { 288 if (num == 0) {
@@ -297,10 +303,10 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
297 return 1; 303 return 1;
298 304
299 305
300 if (client_add_to_list(onion_c, num, public_key, ip_port, plain) == -1) 306 if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1)
301 return 1; 307 return 1;
302 308
303 if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes, source) == -1) 309 if (client_ping_nodes(onion_c, num, (Node_format *)plain + 1 + ONION_PING_ID_SIZE, num_nodes, source) == -1)
304 return 1; 310 return 1;
305 311
306 return 0; 312 return 0;
@@ -319,7 +325,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u
319 return 1; 325 return 1;
320 326
321 uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE]; 327 uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
322 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->dht->c->self_secret_key, packet + 1, 328 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->temp_secret_key, packet + 1,
323 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 329 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
324 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain); 330 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain);
325 331
@@ -391,7 +397,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
391 DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); 397 DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
392 } 398 }
393 399
394 //TODO replay protection
395 return 0; 400 return 0;
396} 401}
397/* Send data of length length to friendnum. 402/* Send data of length length to friendnum.
@@ -431,7 +436,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
431 if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT)) 436 if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
432 continue; 437 continue;
433 438
434 if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) { 439 if (list_nodes[i].is_stored) {
435 Node_format nodes[4]; 440 Node_format nodes[4];
436 441
437 if (random_path(onion_c, nodes) == -1) 442 if (random_path(onion_c, nodes) == -1)
@@ -440,8 +445,8 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
440 memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES); 445 memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
441 nodes[3].ip_port = list_nodes[i].ip_port; 446 nodes[3].ip_port = list_nodes[i].ip_port;
442 447
443 if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, nonce, packet, 448 if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id,
444 sizeof(packet)) == 0) 449 list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
445 ++good; 450 ++good;
446 } 451 }
447 } 452 }
@@ -697,7 +702,7 @@ static void do_announce(Onion_Client *onion_c)
697 ++count; 702 ++count;
698 uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; 703 uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
699 704
700 if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) { 705 if (list_nodes[i].is_stored) {
701 interval = ANNOUNCE_INTERVAL_ANNOUNCED; 706 interval = ANNOUNCE_INTERVAL_ANNOUNCED;
702 } 707 }
703 708
@@ -748,7 +753,7 @@ Onion_Client *new_onion_client(DHT *dht)
748 onion_c->dht = dht; 753 onion_c->dht = dht;
749 onion_c->net = dht->c->lossless_udp->net; 754 onion_c->net = dht->c->lossless_udp->net;
750 new_symmetric_key(onion_c->secret_symmetric_key); 755 new_symmetric_key(onion_c->secret_symmetric_key);
751 756 crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
752 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); 757 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
753 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); 758 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
754 oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c); 759 oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c);
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 56adc9ee..afc29f77 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -36,6 +36,9 @@ typedef struct {
36 uint8_t client_id[CLIENT_ID_SIZE]; 36 uint8_t client_id[CLIENT_ID_SIZE];
37 IP_Port ip_port; 37 IP_Port ip_port;
38 uint8_t ping_id[ONION_PING_ID_SIZE]; 38 uint8_t ping_id[ONION_PING_ID_SIZE];
39 uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
40 uint8_t is_stored;
41
39 uint64_t timestamp; 42 uint64_t timestamp;
40 43
41 uint64_t last_pinged; 44 uint64_t last_pinged;
@@ -70,6 +73,8 @@ typedef struct {
70 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; 73 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
71 uint64_t last_run; 74 uint64_t last_run;
72 75
76 uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
77 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
73 struct { 78 struct {
74 oniondata_handler_callback function; 79 oniondata_handler_callback function;
75 void *object; 80 void *object;