summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/onion_test.c9
-rw-r--r--docs/Prevent_Tracking.txt5
-rw-r--r--toxcore/onion_announce.c5
-rw-r--r--toxcore/onion_announce.h4
-rw-r--r--toxcore/onion_client.c88
-rw-r--r--toxcore/onion_client.h20
6 files changed, 120 insertions, 11 deletions
diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c
index 1f175134..5d7eba5e 100644
--- a/auto_tests/onion_test.c
+++ b/auto_tests/onion_test.c
@@ -96,6 +96,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t
96 return 0; 96 return 0;
97} 97}
98 98
99uint8_t nonce[crypto_box_NONCEBYTES];
99static int handled_test_4; 100static int handled_test_4;
100static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t length) 101static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t length)
101{ 102{
@@ -105,6 +106,10 @@ static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t
105 return 1; 106 return 1;
106 107
107 uint8_t plain[sizeof("Install gentoo")] = {0}; 108 uint8_t plain[sizeof("Install gentoo")] = {0};
109
110 if (memcmp(nonce, packet + 1, crypto_box_NONCEBYTES) != 0)
111 return 1;
112
108 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->c->self_secret_key, packet + 1, 113 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->c->self_secret_key, packet + 1,
109 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain); 114 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain);
110 115
@@ -195,7 +200,9 @@ START_TEST(test_basic)
195 c_sleep(1000); 200 c_sleep(1000);
196 Onion *onion3 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34569)))); 201 Onion *onion3 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34569))));
197 ck_assert_msg((onion3 != NULL), "Onion failed initializing."); 202 ck_assert_msg((onion3 != NULL), "Onion failed initializing.");
198 ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, (uint8_t *)"Install gentoo", 203
204 new_nonce(nonce);
205 ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, nonce, (uint8_t *)"Install gentoo",
199 sizeof("Install gentoo")); 206 sizeof("Install gentoo"));
200 ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet."); 207 ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet.");
201 handled_test_4 = 0; 208 handled_test_4 = 0;
diff --git a/docs/Prevent_Tracking.txt b/docs/Prevent_Tracking.txt
index b44c4cf7..5f7aaf1e 100644
--- a/docs/Prevent_Tracking.txt
+++ b/docs/Prevent_Tracking.txt
@@ -108,6 +108,9 @@ data to route request packet:
108encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] 108encrypted with that temporary private key and the nonce and the real public key 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) 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 110
111The data in the previous packet is in format: [real public key of sender]
112encrypted with real private key of the sender, the nonce in the data packet and the real public key of the reciever:[[uint8_t id][data (optional)]]
113
111Data sent to us: 114Data sent to us:
112announce response packet: 115announce response packet:
113[uint8_t packet id (132)][data to send back in response(fixed size)][nonce] 116[uint8_t packet id (132)][data to send back in response(fixed size)][nonce]
@@ -117,6 +120,8 @@ encrypted with the DHT private key of Node D, the public key in the request and
117data to route response packet: 120data to route response packet:
118[uint8_t packet id (134)][nonce][temporary just generated public key] 121[uint8_t packet id (134)][nonce][temporary just generated public key]
119encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] 122encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
123
124
120Onion packet (response): 125Onion packet (response):
121 126
122initial (sent from node D to node C): 127initial (sent from node D to node C):
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index 480475be..92c9e940 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -78,16 +78,17 @@ 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) 78 * send the packet to that person in the form of a response)
79 * 79 *
80 * public_key is the real public key of the node which we want to send the data of length length to. 80 * public_key is the real public key of the node which we want to send the data of length length to.
81 * nonce is the nonce to encrypt this packet with
81 * 82 *
82 * return -1 on failure. 83 * return -1 on failure.
83 * return 0 on success. 84 * return 0 on success.
84 */ 85 */
85int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length) 86int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
86{ 87{
87 uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; 88 uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
88 packet[0] = NET_PACKET_ONION_DATA_REQUEST; 89 packet[0] = NET_PACKET_ONION_DATA_REQUEST;
89 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); 90 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
90 new_nonce(packet + 1 + crypto_box_PUBLICKEYBYTES); 91 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
91 92
92 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; 93 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
93 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; 94 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index f7d565e5..01cd7243 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -75,11 +75,13 @@ 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) 75 * send the packet to that person in the form of a response)
76 * 76 *
77 * public_key is the real public key of the node which we want to send the data of length length to. 77 * public_key is the real public key of the node which we want to send the data of length length to.
78 * nonce is the nonce to encrypt this packet with
78 * 79 *
79 * return -1 on failure. 80 * return -1 on failure.
80 * return 0 on success. 81 * return 0 on success.
81 */ 82 */
82int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length); 83int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data,
84 uint16_t length);
83 85
84 86
85Onion_Announce *new_onion_announce(DHT *dht); 87Onion_Announce *new_onion_announce(DHT *dht);
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index 2d049f7a..f865dcd9 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -30,6 +30,7 @@
30 30
31#define ANNOUNCE_TIMEOUT 10 31#define ANNOUNCE_TIMEOUT 10
32 32
33uint8_t zero_ping[ONION_PING_ID_SIZE];
33 34
34/* Creates a sendback for use in an announce request. 35/* Creates a sendback for use in an announce request.
35 * 36 *
@@ -297,26 +298,93 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
297 return 0; 298 return 0;
298} 299}
299 300
301#define DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
302
300static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) 303static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length)
301{ 304{
302 Onion_Client *onion_c = object; 305 Onion_Client *onion_c = object;
303 306
304 if (length <= ONION_DATA_RESPONSE_MIN_SIZE) 307 if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE))
305 return 1; 308 return 1;
306 309
307 if (length > MAX_DATA_SIZE) 310 if (length > MAX_DATA_SIZE)
308 return 1; 311 return 1;
309 312
310 uint8_t plain[length - ONION_DATA_RESPONSE_MIN_SIZE]; 313 uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
311 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->dht->c->self_secret_key, packet + 1, 314 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->dht->c->self_secret_key, packet + 1,
312 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 315 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
313 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); 316 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain);
317
318 if ((uint32_t)len != sizeof(temp_plain))
319 return 1;
320
321 uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE];
322 len = decrypt_data(temp_plain, onion_c->dht->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES,
323 sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain);
314 324
315 if ((uint32_t)len != sizeof(plain)) 325 if ((uint32_t)len != sizeof(plain))
316 return 1; 326 return 1;
317 327
318 //TODO do something with the plain 328 if (!onion_c->Onion_Data_Handlers[plain[0]].function)
319 return 0; 329 return 1;
330
331 return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
332 sizeof(plain));
333}
334
335/* Send data of length length to friendnum.
336 * This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
337 *
338 * Even if this function succeeds, the friend might not recieve any data.
339 *
340 * return the number of packets sent on success
341 * return -1 on failure.
342 */
343int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length)
344{
345 if ((uint32_t)friend_num >= onion_c->num_friends)
346 return -1;
347
348 if (length + DATA_IN_RESPONSE_MIN_SIZE + ONION_DATA_RESPONSE_MIN_SIZE + ONION_SEND_1 > MAX_DATA_SIZE)
349 return -1;
350
351 if (length == 0)
352 return -1;
353
354 uint8_t nonce[crypto_box_NONCEBYTES];
355 new_nonce(nonce);
356
357 uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
358 memcpy(packet, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
359 int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data,
360 length, packet + crypto_box_PUBLICKEYBYTES);
361
362 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
363 return -1;
364
365 uint32_t i, good = 0;
366 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
367
368 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
369 if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
370 continue;
371
372 if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
373 Node_format nodes[4];
374
375 if (random_path(onion_c, nodes) == -1)
376 continue;
377
378 memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
379 nodes[3].ip_port = list_nodes[i].ip_port;
380
381 if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, nonce, packet,
382 sizeof(packet)) == 0)
383 ++good;
384 }
385 }
386
387 return good;
320} 388}
321 389
322/* Get the friend_num of a friend. 390/* Get the friend_num of a friend.
@@ -382,7 +450,7 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id)
382 } 450 }
383 } 451 }
384 452
385 if (index == ~0) { 453 if (index == (uint32_t)~0) {
386 if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) 454 if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1)
387 return -1; 455 return -1;
388 456
@@ -453,7 +521,7 @@ int random_path(Onion_Client *onion_c, Node_format *nodes)
453} 521}
454 522
455#define ANNOUNCE_FRIEND 30 523#define ANNOUNCE_FRIEND 30
456uint8_t zero_ping[ONION_PING_ID_SIZE]; 524
457static void do_friend(Onion_Client *onion_c, uint16_t friendnum) 525static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
458{ 526{
459 if (friendnum >= onion_c->num_friends) 527 if (friendnum >= onion_c->num_friends)
@@ -489,6 +557,12 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
489 557
490 //TODO send packets to friend telling them our fake DHT id. 558 //TODO send packets to friend telling them our fake DHT id.
491} 559}
560/* Function to call when onion data packet with contents beginning with byte is received. */
561void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
562{
563 onion_c->Onion_Data_Handlers[byte].function = cb;
564 onion_c->Onion_Data_Handlers[byte].object = object;
565}
492 566
493#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10 567#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10
494#define ANNOUNCE_INTERVAL_ANNOUNCED 60 568#define ANNOUNCE_INTERVAL_ANNOUNCED 60
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 0ec381e6..f5940d7c 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -48,6 +48,8 @@ typedef struct {
48 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; 48 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
49} Onion_Friend; 49} Onion_Friend;
50 50
51typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
52
51typedef struct { 53typedef struct {
52 DHT *dht; 54 DHT *dht;
53 Networking_Core *net; 55 Networking_Core *net;
@@ -58,6 +60,11 @@ typedef struct {
58 60
59 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; 61 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
60 uint64_t last_run; 62 uint64_t last_run;
63
64 struct {
65 oniondata_handler_callback function;
66 void *object;
67 } Onion_Data_Handlers[256];
61} Onion_Client; 68} Onion_Client;
62 69
63/* Add a friend who we want to connect to. 70/* Add a friend who we want to connect to.
@@ -99,6 +106,19 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
99 */ 106 */
100int random_path(Onion_Client *onion_c, Node_format *nodes); 107int random_path(Onion_Client *onion_c, Node_format *nodes);
101 108
109/* Send data of length length to friendnum.
110 * This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
111 *
112 * Even if this function succeeds, the friend might not recieve any data.
113 *
114 * return the number of packets sent on success
115 * return -1 on failure.
116 */
117int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length);
118
119/* Function to call when onion data packet with contents beginning with byte is received. */
120void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
121
102void do_onion_client(Onion_Client *onion_c); 122void do_onion_client(Onion_Client *onion_c);
103 123
104Onion_Client *new_onion_client(DHT *dht); 124Onion_Client *new_onion_client(DHT *dht);