summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c153
1 files changed, 113 insertions, 40 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 2b8ec5b5..1089e2ff 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -44,7 +44,7 @@
44#define KILL_NODE_TIMEOUT 300 44#define KILL_NODE_TIMEOUT 300
45 45
46/* Ping interval in seconds for each random sending of a get nodes request. */ 46/* Ping interval in seconds for each random sending of a get nodes request. */
47#define GET_NODE_INTERVAL 5 47#define GET_NODE_INTERVAL 20
48 48
49#define MAX_PUNCHING_PORTS 48 49#define MAX_PUNCHING_PORTS 48
50 50
@@ -56,6 +56,9 @@
56#define NAT_PING_REQUEST 0 56#define NAT_PING_REQUEST 0
57#define NAT_PING_RESPONSE 1 57#define NAT_PING_RESPONSE 1
58 58
59/* Number of get node requests to send to quickly find close nodes. */
60#define MAX_BOOTSTRAP_TIMES 10
61
59/* Used in the comparison function for sorting lists of Client_data. */ 62/* Used in the comparison function for sorting lists of Client_data. */
60typedef struct { 63typedef struct {
61 Client_data c1; 64 Client_data c1;
@@ -111,6 +114,72 @@ static int client_id_cmp(ClientPair p1, ClientPair p2)
111 return c; 114 return c;
112} 115}
113 116
117/* Shared key generations are costly, it is therefor smart to store commonly used
118 * ones so that they can re used later without being computed again.
119 *
120 * If shared key is already in shared_keys, copy it to shared_key.
121 * else generate it into shared_key and copy it to shared_keys
122 */
123void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id)
124{
125 uint32_t i, num = ~0, curr = 0;
126
127 for (i = 0; i < MAX_KEYS_PER_SLOT; ++i) {
128 int index = client_id[30] * MAX_KEYS_PER_SLOT + i;
129
130 if (shared_keys->keys[index].stored) {
131 if (memcmp(client_id, shared_keys->keys[index].client_id, CLIENT_ID_SIZE) == 0) {
132 memcpy(shared_key, shared_keys->keys[index].shared_key, crypto_box_BEFORENMBYTES);
133 ++shared_keys->keys[index].times_requested;
134 shared_keys->keys[index].time_last_requested = unix_time();
135 return;
136 }
137
138 if (num != 0) {
139 if (is_timeout(shared_keys->keys[index].time_last_requested, KEYS_TIMEOUT)) {
140 num = 0;
141 curr = index;
142 } else if (num > shared_keys->keys[index].times_requested) {
143 num = shared_keys->keys[index].times_requested;
144 curr = index;
145 }
146 }
147 } else {
148 if (num != 0) {
149 num = 0;
150 curr = index;
151 }
152 }
153 }
154
155 encrypt_precompute(client_id, secret_key, shared_key);
156
157 if (num != (uint32_t)~0) {
158 shared_keys->keys[curr].stored = 1;
159 shared_keys->keys[curr].times_requested = 1;
160 memcpy(shared_keys->keys[curr].client_id, client_id, CLIENT_ID_SIZE);
161 memcpy(shared_keys->keys[curr].shared_key, shared_key, crypto_box_BEFORENMBYTES);
162 shared_keys->keys[curr].time_last_requested = unix_time();
163 }
164}
165
166/* Copy shared_key to decrypt DHT packet from client_id into shared_key
167 * for packets that we recieve.
168 */
169void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id)
170{
171 return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id);
172}
173
174/* Copy shared_key to decrypt DHT packet from client_id into shared_key
175 * for packets that we send.
176 */
177void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id)
178{
179 return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id);
180}
181
182
114/* Check if client with client_id is already in list of length length. 183/* Check if client with client_id is already in list of length length.
115 * If it is then set its corresponding timestamp to current time. 184 * If it is then set its corresponding timestamp to current time.
116 * If the id is already in the list with a different ip_port, update it. 185 * If the id is already in the list with a different ip_port, update it.
@@ -819,12 +888,13 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
819 memcpy(plain, client_id, CLIENT_ID_SIZE); 888 memcpy(plain, client_id, CLIENT_ID_SIZE);
820 memcpy(plain + CLIENT_ID_SIZE, encrypted_message, NODES_ENCRYPTED_MESSAGE_LENGTH); 889 memcpy(plain + CLIENT_ID_SIZE, encrypted_message, NODES_ENCRYPTED_MESSAGE_LENGTH);
821 890
822 int len = encrypt_data( public_key, 891 uint8_t shared_key[crypto_box_BEFORENMBYTES];
823 dht->self_secret_key, 892 DHT_get_shared_key_sent(dht, shared_key, public_key);
824 nonce, 893 int len = encrypt_data_fast( shared_key,
825 plain, 894 nonce,
826 CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, 895 plain,
827 encrypt ); 896 CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH,
897 encrypt );
828 898
829 if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) 899 if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES)
830 return -1; 900 return -1;
@@ -841,7 +911,8 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
841/* because of BINARY compatibility, the Node_format MUST BE Node4_format, 911/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
842 * IPv6 nodes are sent in a different message 912 * IPv6 nodes are sent in a different message
843 * encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */ 913 * encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */
844static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) 914static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data,
915 uint8_t *shared_encryption_key)
845{ 916{
846 /* Check if packet is going to be sent to ourself. */ 917 /* Check if packet is going to be sent to ourself. */
847 if (id_equal(public_key, dht->self_public_key)) 918 if (id_equal(public_key, dht->self_public_key))
@@ -888,12 +959,11 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
888 } 959 }
889 960
890 memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); 961 memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
891 int len = encrypt_data( public_key, 962 int len = encrypt_data_fast( shared_encryption_key,
892 dht->self_secret_key, 963 nonce,
893 nonce, 964 plain,
894 plain, 965 num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH,
895 num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, 966 encrypt );
896 encrypt );
897 967
898 if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + 968 if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH +
899 crypto_box_MACBYTES) 969 crypto_box_MACBYTES)
@@ -927,7 +997,8 @@ void to_host_family(IP *ip)
927 ip->family = AF_INET6; 997 ip->family = AF_INET6;
928} 998}
929/* Send a send nodes response: message for IPv6 nodes */ 999/* Send a send nodes response: message for IPv6 nodes */
930static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) 1000static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data,
1001 uint8_t *shared_encryption_key)
931{ 1002{
932 /* Check if packet is going to be sent to ourself. */ 1003 /* Check if packet is going to be sent to ourself. */
933 if (id_equal(public_key, dht->self_public_key)) 1004 if (id_equal(public_key, dht->self_public_key))
@@ -955,12 +1026,11 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_
955 1026
956 memcpy(plain, nodes_list, num_nodes * Node_format_size); 1027 memcpy(plain, nodes_list, num_nodes * Node_format_size);
957 memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); 1028 memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
958 int len = encrypt_data( public_key, 1029 int len = encrypt_data_fast( shared_encryption_key,
959 dht->self_secret_key, 1030 nonce,
960 nonce, 1031 plain,
961 plain, 1032 num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH,
962 num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, 1033 encrypt );
963 encrypt );
964 1034
965 if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) 1035 if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES)
966 return -1; 1036 return -1;
@@ -986,22 +1056,23 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
986 return 1; 1056 return 1;
987 1057
988 uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; 1058 uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH];
1059 uint8_t shared_key[crypto_box_BEFORENMBYTES];
989 1060
990 int len = decrypt_data( packet + 1, 1061 DHT_get_shared_key_recv(dht, shared_key, packet + 1);
991 dht->self_secret_key, 1062 int len = decrypt_data_fast( shared_key,
992 packet + 1 + CLIENT_ID_SIZE, 1063 packet + 1 + CLIENT_ID_SIZE,
993 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 1064 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
994 CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, 1065 CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
995 plain ); 1066 plain );
996 1067
997 if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) 1068 if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH)
998 return 1; 1069 return 1;
999 1070
1000 sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE); 1071 sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key);
1001 sendnodes_ipv6(dht, source, packet + 1, plain, 1072 sendnodes_ipv6(dht, source, packet + 1, plain,
1002 plain + CLIENT_ID_SIZE); /* TODO: prevent possible amplification attacks */ 1073 plain + CLIENT_ID_SIZE, shared_key); /* TODO: prevent possible amplification attacks */
1003 1074
1004 add_toping(dht->ping, packet + 1, source); 1075 add_to_ping(dht->ping, packet + 1, source);
1005 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ 1076 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
1006 1077
1007 return 0; 1078 return 0;
@@ -1062,9 +1133,10 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet,
1062 if (num_nodes > MAX_SENT_NODES) /* too long */ 1133 if (num_nodes > MAX_SENT_NODES) /* too long */
1063 return 1; 1134 return 1;
1064 1135
1065 int len = decrypt_data( 1136 uint8_t shared_key[crypto_box_BEFORENMBYTES];
1066 packet + 1, 1137 DHT_get_shared_key_sent(dht, shared_key, packet + 1);
1067 dht->self_secret_key, 1138 int len = decrypt_data_fast(
1139 shared_key,
1068 packet + 1 + CLIENT_ID_SIZE, 1140 packet + 1 + CLIENT_ID_SIZE,
1069 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 1141 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
1070 num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, 1142 num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
@@ -1311,7 +1383,7 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
1311 1383
1312/* returns number of nodes not in kill-timeout */ 1384/* returns number of nodes not in kill-timeout */
1313static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8_t *client_id, 1385static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8_t *client_id,
1314 Client_data *list, uint32_t list_count) 1386 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times)
1315{ 1387{
1316 uint32_t i; 1388 uint32_t i;
1317 uint8_t not_kill = 0; 1389 uint8_t not_kill = 0;
@@ -1345,11 +1417,12 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, ui
1345 } 1417 }
1346 } 1418 }
1347 1419
1348 if ((num_nodes != 0) && is_timeout(*lastgetnode, GET_NODE_INTERVAL)) { 1420 if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
1349 uint32_t rand_node = rand() % num_nodes; 1421 uint32_t rand_node = rand() % num_nodes;
1350 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id, 1422 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id,
1351 client_id, NULL); 1423 client_id, NULL);
1352 *lastgetnode = temp_time; 1424 *lastgetnode = temp_time;
1425 ++*bootstrap_times;
1353 } 1426 }
1354 1427
1355 return not_kill; 1428 return not_kill;
@@ -1364,7 +1437,7 @@ static void do_DHT_friends(DHT *dht)
1364 1437
1365 for (i = 0; i < dht->num_friends; ++i) 1438 for (i = 0; i < dht->num_friends; ++i)
1366 do_ping_and_sendnode_requests(dht, &dht->friends_list[i].lastgetnode, dht->friends_list[i].client_id, 1439 do_ping_and_sendnode_requests(dht, &dht->friends_list[i].lastgetnode, dht->friends_list[i].client_id,
1367 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS); 1440 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &dht->friends_list[i].bootstrap_times);
1368} 1441}
1369 1442
1370/* Ping each client in the close nodes list every PING_INTERVAL seconds. 1443/* Ping each client in the close nodes list every PING_INTERVAL seconds.
@@ -1373,7 +1446,7 @@ static void do_DHT_friends(DHT *dht)
1373static void do_Close(DHT *dht) 1446static void do_Close(DHT *dht)
1374{ 1447{
1375 uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key, 1448 uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key,
1376 dht->close_clientlist, LCLIENT_LIST); 1449 dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times);
1377 1450
1378 if (!not_killed) { 1451 if (!not_killed) {
1379 /* all existing nodes are at least KILL_NODE_TIMEOUT, 1452 /* all existing nodes are at least KILL_NODE_TIMEOUT,
@@ -1970,8 +2043,8 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
1970} 2043}
1971 2044
1972/* Interval in seconds between hardening checks */ 2045/* Interval in seconds between hardening checks */
1973#define HARDENING_INTERVAL 20 2046#define HARDENING_INTERVAL 120
1974#define HARDEN_TIMEOUT 600 2047#define HARDEN_TIMEOUT 1200
1975 2048
1976/* Handle a received hardening packet */ 2049/* Handle a received hardening packet */
1977static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) 2050static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length)
@@ -2289,7 +2362,7 @@ void do_DHT(DHT *dht)
2289 do_Close(dht); 2362 do_Close(dht);
2290 do_DHT_friends(dht); 2363 do_DHT_friends(dht);
2291 do_NAT(dht); 2364 do_NAT(dht);
2292 do_toping(dht->ping); 2365 do_to_ping(dht->ping);
2293 do_hardening(dht); 2366 do_hardening(dht);
2294#ifdef ENABLE_ASSOC_DHT 2367#ifdef ENABLE_ASSOC_DHT
2295 2368