diff options
-rw-r--r-- | auto_tests/onion_test.c | 9 | ||||
-rw-r--r-- | docs/Prevent_Tracking.txt | 5 | ||||
-rw-r--r-- | toxcore/onion_announce.c | 5 | ||||
-rw-r--r-- | toxcore/onion_announce.h | 4 | ||||
-rw-r--r-- | toxcore/onion_client.c | 88 | ||||
-rw-r--r-- | toxcore/onion_client.h | 20 |
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 | ||
99 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
99 | static int handled_test_4; | 100 | static int handled_test_4; |
100 | static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 101 | static 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: | |||
108 | encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] | 108 | encrypted 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 | ||
111 | The data in the previous packet is in format: [real public key of sender] | ||
112 | encrypted 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 | |||
111 | Data sent to us: | 114 | Data sent to us: |
112 | announce response packet: | 115 | announce 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 | |||
117 | data to route response packet: | 120 | data 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] |
119 | encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] | 122 | encrypted with that temporary private key and the nonce and the real public key of the destination node:[data] |
123 | |||
124 | |||
120 | Onion packet (response): | 125 | Onion packet (response): |
121 | 126 | ||
122 | initial (sent from node D to node C): | 127 | initial (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 | */ |
85 | int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length) | 86 | int 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 | */ |
82 | int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length); | 83 | int 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 | ||
85 | Onion_Announce *new_onion_announce(DHT *dht); | 87 | Onion_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 | ||
33 | uint8_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 | |||
300 | static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 303 | static 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 | */ | ||
343 | int 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 |
456 | uint8_t zero_ping[ONION_PING_ID_SIZE]; | 524 | |
457 | static void do_friend(Onion_Client *onion_c, uint16_t friendnum) | 525 | static 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. */ | ||
561 | void 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 | ||
51 | typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); | ||
52 | |||
51 | typedef struct { | 53 | typedef 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 | */ |
100 | int random_path(Onion_Client *onion_c, Node_format *nodes); | 107 | int 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 | */ | ||
117 | int 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. */ | ||
120 | void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object); | ||
121 | |||
102 | void do_onion_client(Onion_Client *onion_c); | 122 | void do_onion_client(Onion_Client *onion_c); |
103 | 123 | ||
104 | Onion_Client *new_onion_client(DHT *dht); | 124 | Onion_Client *new_onion_client(DHT *dht); |