diff options
Diffstat (limited to 'core/net_crypto.c')
-rw-r--r-- | core/net_crypto.c | 771 |
1 files changed, 0 insertions, 771 deletions
diff --git a/core/net_crypto.c b/core/net_crypto.c deleted file mode 100644 index f421c37d..00000000 --- a/core/net_crypto.c +++ /dev/null | |||
@@ -1,771 +0,0 @@ | |||
1 | /* net_crypto.c | ||
2 | * | ||
3 | * Functions for the core network crypto. | ||
4 | * See also: http://wiki.tox.im/index.php/DHT | ||
5 | * | ||
6 | * NOTE: This code has to be perfect. We don't mess around with encryption. | ||
7 | * | ||
8 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
9 | * | ||
10 | * This file is part of Tox. | ||
11 | * | ||
12 | * Tox is free software: you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation, either version 3 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * Tox is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include "net_crypto.h" | ||
28 | |||
29 | #define CONN_NO_CONNECTION 0 | ||
30 | #define CONN_HANDSHAKE_SENT 1 | ||
31 | #define CONN_NOT_CONFIRMED 2 | ||
32 | #define CONN_ESTABLISHED 3 | ||
33 | #define CONN_TIMED_OUT 4 | ||
34 | |||
35 | /* Use this instead of memcmp; not vulnerable to timing attacks. */ | ||
36 | uint8_t crypto_iszero(uint8_t *mem, uint32_t length) | ||
37 | { | ||
38 | uint8_t check = 0; | ||
39 | uint32_t i; | ||
40 | |||
41 | for (i = 0; i < length; ++i) { | ||
42 | check |= mem[i]; | ||
43 | } | ||
44 | |||
45 | return check; // We return zero if mem is made out of zeroes. | ||
46 | } | ||
47 | |||
48 | /* Precomputes the shared key from their public_key and our secret_key. | ||
49 | This way we can avoid an expensive elliptic curve scalar multiply for each | ||
50 | encrypt/decrypt operation. | ||
51 | enc_key has to be crypto_box_BEFORENMBYTES bytes long. */ | ||
52 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) | ||
53 | { | ||
54 | crypto_box_beforenm(enc_key, public_key, secret_key); | ||
55 | } | ||
56 | |||
57 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | ||
58 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
59 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | ||
60 | { | ||
61 | if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) | ||
62 | return -1; | ||
63 | |||
64 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; | ||
65 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; | ||
66 | |||
67 | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ | ||
68 | |||
69 | crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key); | ||
70 | |||
71 | if (crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) | ||
72 | return -1; | ||
73 | |||
74 | /* unpad the encrypted message */ | ||
75 | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); | ||
76 | return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; | ||
77 | } | ||
78 | |||
79 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | ||
80 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
81 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | ||
82 | { | ||
83 | if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) | ||
84 | return -1; | ||
85 | |||
86 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; | ||
87 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; | ||
88 | |||
89 | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ | ||
90 | |||
91 | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, | ||
92 | nonce, enc_key) == -1) | ||
93 | return -1; | ||
94 | |||
95 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero | ||
96 | apparently memcmp should not be used so we do this instead:*/ | ||
97 | if (crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) | ||
98 | return -1; | ||
99 | |||
100 | /* unpad the plain message */ | ||
101 | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); | ||
102 | return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; | ||
103 | } | ||
104 | |||
105 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | ||
106 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | ||
107 | { | ||
108 | uint8_t k[crypto_box_BEFORENMBYTES]; | ||
109 | encrypt_precompute(public_key, secret_key, k); | ||
110 | return encrypt_data_fast(k, nonce, plain, length, encrypted); | ||
111 | } | ||
112 | |||
113 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | ||
114 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | ||
115 | { | ||
116 | uint8_t k[crypto_box_BEFORENMBYTES]; | ||
117 | encrypt_precompute(public_key, secret_key, k); | ||
118 | return decrypt_data_fast(k, nonce, encrypted, length, plain); | ||
119 | } | ||
120 | |||
121 | /* increment the given nonce by 1 */ | ||
122 | static void increment_nonce(uint8_t *nonce) | ||
123 | { | ||
124 | uint32_t i; | ||
125 | |||
126 | for (i = 0; i < crypto_box_NONCEBYTES; ++i) { | ||
127 | ++nonce[i]; | ||
128 | |||
129 | if (nonce[i] != 0) | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* fill the given nonce with random bytes. */ | ||
135 | void random_nonce(uint8_t *nonce) | ||
136 | { | ||
137 | uint32_t i, temp; | ||
138 | |||
139 | for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) { | ||
140 | temp = random_int(); | ||
141 | memcpy(nonce + 4 * i, &temp, 4); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* return 0 if there is no received data in the buffer | ||
146 | return -1 if the packet was discarded. | ||
147 | return length of received data if successful */ | ||
148 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) | ||
149 | { | ||
150 | if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length) | ||
151 | return 0; | ||
152 | |||
153 | if (c->crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) | ||
154 | return 0; | ||
155 | |||
156 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
157 | int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data); | ||
158 | |||
159 | if (length == 0) | ||
160 | return 0; | ||
161 | |||
162 | if (temp_data[0] != 3) | ||
163 | return -1; | ||
164 | |||
165 | int len = decrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, | ||
166 | c->crypto_connections[crypt_connection_id].recv_nonce, | ||
167 | temp_data + 1, length - 1, data); | ||
168 | |||
169 | if (len != -1) { | ||
170 | increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); | ||
171 | return len; | ||
172 | } | ||
173 | |||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | /* return 0 if data could not be put in packet queue | ||
178 | return 1 if data was put into the queue */ | ||
179 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | ||
180 | { | ||
181 | if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length) | ||
182 | return 0; | ||
183 | |||
184 | if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) | ||
185 | return 0; | ||
186 | |||
187 | if (c->crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) | ||
188 | return 0; | ||
189 | |||
190 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
191 | int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, | ||
192 | c->crypto_connections[crypt_connection_id].sent_nonce, | ||
193 | data, length, temp_data + 1); | ||
194 | |||
195 | if (len == -1) | ||
196 | return 0; | ||
197 | |||
198 | temp_data[0] = 3; | ||
199 | |||
200 | if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) | ||
201 | return 0; | ||
202 | |||
203 | increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); | ||
204 | return 1; | ||
205 | } | ||
206 | |||
207 | /* create a request to peer. | ||
208 | send_public_key and send_secret_key are the pub/secret keys of the sender | ||
209 | recv_public_key is public key of reciever | ||
210 | packet must be an array of MAX_DATA_SIZE big. | ||
211 | Data represents the data we send with the request with length being the length of the data. | ||
212 | request_id is the id of the request (32 = friend request, 254 = ping request) | ||
213 | returns -1 on failure | ||
214 | returns the length of the created packet on success */ | ||
215 | int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, | ||
216 | uint8_t *data, uint32_t length, uint8_t request_id) | ||
217 | { | ||
218 | if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING) | ||
219 | return -1; | ||
220 | |||
221 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
222 | uint8_t temp[MAX_DATA_SIZE]; | ||
223 | memcpy(temp + 1, data, length); | ||
224 | temp[0] = request_id; | ||
225 | random_nonce(nonce); | ||
226 | int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1, | ||
227 | 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); | ||
228 | |||
229 | if (len == -1) | ||
230 | return -1; | ||
231 | |||
232 | packet[0] = NET_PACKET_CRYPTO; | ||
233 | memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); | ||
234 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); | ||
235 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); | ||
236 | |||
237 | return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; | ||
238 | } | ||
239 | |||
240 | /* puts the senders public key in the request in public_key, the data from the request | ||
241 | in data if a friend or ping request was sent to us and returns the length of the data. | ||
242 | packet is the request packet and length is its length | ||
243 | return -1 if not valid request. */ | ||
244 | static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, | ||
245 | uint16_t length) | ||
246 | { | ||
247 | |||
248 | if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && | ||
249 | length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && | ||
250 | memcmp(packet + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
251 | memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); | ||
252 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
253 | uint8_t temp[MAX_DATA_SIZE]; | ||
254 | memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); | ||
255 | int len1 = decrypt_data(public_key, c->self_secret_key, nonce, | ||
256 | packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, | ||
257 | length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); | ||
258 | |||
259 | if (len1 == -1 || len1 == 0) | ||
260 | return -1; | ||
261 | |||
262 | request_id[0] = temp[0]; | ||
263 | --len1; | ||
264 | memcpy(data, temp + 1, len1); | ||
265 | return len1; | ||
266 | } else | ||
267 | return -1; | ||
268 | } | ||
269 | |||
270 | void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) | ||
271 | { | ||
272 | c->cryptopackethandlers[byte].function = cb; | ||
273 | c->cryptopackethandlers[byte].object = object; | ||
274 | } | ||
275 | |||
276 | static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
277 | { | ||
278 | DHT *dht = object; | ||
279 | |||
280 | if (packet[0] == NET_PACKET_CRYPTO) { | ||
281 | if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || | ||
282 | length > MAX_DATA_SIZE + ENCRYPTION_PADDING) | ||
283 | return 1; | ||
284 | |||
285 | if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. | ||
286 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
287 | uint8_t data[MAX_DATA_SIZE]; | ||
288 | uint8_t number; | ||
289 | int len = handle_request(dht->c, public_key, data, &number, packet, length); | ||
290 | |||
291 | if (len == -1 || len == 0) | ||
292 | return 1; | ||
293 | |||
294 | if (!dht->c->cryptopackethandlers[number].function) return 1; | ||
295 | |||
296 | dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, data, | ||
297 | len); | ||
298 | |||
299 | } else { /* if request is not for us, try routing it. */ | ||
300 | if (route_packet(dht, packet + 1, packet, length) == length) //NOTE | ||
301 | return 0; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | return 1; | ||
306 | } | ||
307 | |||
308 | /* Send a crypto handshake packet containing an encrypted secret nonce and session public key | ||
309 | to peer with connection_id and public_key | ||
310 | the packet is encrypted with a random nonce which is sent in plain text with the packet */ | ||
311 | static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | ||
312 | uint8_t *session_key) | ||
313 | { | ||
314 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
315 | uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; | ||
316 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
317 | |||
318 | random_nonce(nonce); | ||
319 | memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); | ||
320 | memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); | ||
321 | |||
322 | int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | ||
323 | 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); | ||
324 | |||
325 | if (len == -1) | ||
326 | return 0; | ||
327 | |||
328 | temp_data[0] = 2; | ||
329 | memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
330 | memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); | ||
331 | return write_packet(c->lossless_udp, connection_id, temp_data, | ||
332 | len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); | ||
333 | } | ||
334 | |||
335 | /* Extract secret nonce, session public key and public_key from a packet(data) with length length | ||
336 | return 1 if successful | ||
337 | return 0 if failure */ | ||
338 | static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, | ||
339 | uint8_t *session_key, uint8_t *data, uint16_t length) | ||
340 | { | ||
341 | int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); | ||
342 | |||
343 | if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES | ||
344 | + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | if (data[0] != 2) | ||
349 | return 0; | ||
350 | |||
351 | uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; | ||
352 | |||
353 | memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); | ||
354 | |||
355 | int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, | ||
356 | data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, | ||
357 | crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); | ||
358 | |||
359 | if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) | ||
360 | return 0; | ||
361 | |||
362 | memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); | ||
363 | memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); | ||
364 | return 1; | ||
365 | } | ||
366 | |||
367 | /* get crypto connection id from public key of peer | ||
368 | return -1 if there are no connections like we are looking for | ||
369 | return id if it found it */ | ||
370 | static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) | ||
371 | { | ||
372 | uint32_t i; | ||
373 | |||
374 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
375 | if (c->crypto_connections[i].status != CONN_NO_CONNECTION) | ||
376 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
377 | return i; | ||
378 | } | ||
379 | |||
380 | return -1; | ||
381 | } | ||
382 | |||
383 | /* set the size of the friend list to numfriends | ||
384 | return -1 if realloc fails */ | ||
385 | int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) | ||
386 | { | ||
387 | if (num == 0) { | ||
388 | free(c->crypto_connections); | ||
389 | c->crypto_connections = NULL; | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection)); | ||
394 | |||
395 | if (newcrypto_connections == NULL) | ||
396 | return -1; | ||
397 | |||
398 | c->crypto_connections = newcrypto_connections; | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | /* Start a secure connection with other peer who has public_key and ip_port | ||
403 | returns -1 if failure | ||
404 | returns crypt_connection_id of the initialized connection if everything went well. */ | ||
405 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) | ||
406 | { | ||
407 | uint32_t i; | ||
408 | int id = getcryptconnection_id(c, public_key); | ||
409 | |||
410 | if (id != -1) { | ||
411 | IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); | ||
412 | |||
413 | if (c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) | ||
414 | return -1; | ||
415 | } | ||
416 | |||
417 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) | ||
418 | return -1; | ||
419 | |||
420 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | ||
421 | c->crypto_connections[c->crypto_connections_length].number = ~0; | ||
422 | |||
423 | for (i = 0; i <= c->crypto_connections_length; ++i) { | ||
424 | if (c->crypto_connections[i].status == CONN_NO_CONNECTION) { | ||
425 | int id = new_connection(c->lossless_udp, ip_port); | ||
426 | |||
427 | if (id == -1) | ||
428 | return -1; | ||
429 | |||
430 | c->crypto_connections[i].number = id; | ||
431 | c->crypto_connections[i].status = CONN_HANDSHAKE_SENT; | ||
432 | random_nonce(c->crypto_connections[i].recv_nonce); | ||
433 | memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
434 | crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); | ||
435 | |||
436 | if (c->crypto_connections_length == i) | ||
437 | ++c->crypto_connections_length; | ||
438 | |||
439 | if (send_cryptohandshake(c, id, public_key, c->crypto_connections[i].recv_nonce, | ||
440 | c->crypto_connections[i].sessionpublic_key) == 1) { | ||
441 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
442 | return i; | ||
443 | } | ||
444 | |||
445 | return -1; /* this should never happen. */ | ||
446 | } | ||
447 | } | ||
448 | |||
449 | return -1; | ||
450 | } | ||
451 | |||
452 | /* handle an incoming connection | ||
453 | return -1 if no crypto inbound connection | ||
454 | return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection | ||
455 | Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce | ||
456 | and the session public key for the connection in session_key | ||
457 | to accept it see: accept_crypto_inbound(...) | ||
458 | to refuse it just call kill_connection(...) on the connection id */ | ||
459 | int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) | ||
460 | { | ||
461 | uint32_t i; | ||
462 | |||
463 | for (i = 0; i < MAX_INCOMING; ++i) { | ||
464 | if (c->incoming_connections[i] != -1) { | ||
465 | if (is_connected(c->lossless_udp, c->incoming_connections[i]) == 4 | ||
466 | || is_connected(c->lossless_udp, c->incoming_connections[i]) == 0) { | ||
467 | kill_connection(c->lossless_udp, c->incoming_connections[i]); | ||
468 | c->incoming_connections[i] = -1; | ||
469 | continue; | ||
470 | } | ||
471 | |||
472 | if (id_packet(c->lossless_udp, c->incoming_connections[i]) == 2) { | ||
473 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
474 | uint16_t len = read_packet(c->lossless_udp, c->incoming_connections[i], temp_data); | ||
475 | |||
476 | if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { | ||
477 | int connection_id = c->incoming_connections[i]; | ||
478 | c->incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ | ||
479 | return connection_id; | ||
480 | } | ||
481 | } | ||
482 | } | ||
483 | } | ||
484 | |||
485 | return -1; | ||
486 | } | ||
487 | |||
488 | /* kill a crypto connection | ||
489 | return 0 if killed successfully | ||
490 | return 1 if there was a problem. */ | ||
491 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) | ||
492 | { | ||
493 | if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length) | ||
494 | return 1; | ||
495 | |||
496 | if (c->crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) { | ||
497 | c->crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION; | ||
498 | kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); | ||
499 | memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); | ||
500 | c->crypto_connections[crypt_connection_id].number = ~0; | ||
501 | uint32_t i; | ||
502 | |||
503 | for (i = c->crypto_connections_length; i != 0; --i) { | ||
504 | if (c->crypto_connections[i - 1].status != CONN_NO_CONNECTION) | ||
505 | break; | ||
506 | } | ||
507 | |||
508 | c->crypto_connections_length = i; | ||
509 | realloc_cryptoconnection(c, c->crypto_connections_length); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | return 1; | ||
514 | } | ||
515 | |||
516 | /* accept an incoming connection using the parameters provided by crypto_inbound | ||
517 | return -1 if not successful | ||
518 | returns the crypt_connection_id if successful */ | ||
519 | int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | ||
520 | uint8_t *session_key) | ||
521 | { | ||
522 | uint32_t i; | ||
523 | |||
524 | if (connection_id == -1) | ||
525 | return -1; | ||
526 | |||
527 | /* | ||
528 | if(getcryptconnection_id(public_key) != -1) | ||
529 | { | ||
530 | return -1; | ||
531 | }*/ | ||
532 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) | ||
533 | return -1; | ||
534 | |||
535 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | ||
536 | c->crypto_connections[c->crypto_connections_length].number = ~0; | ||
537 | |||
538 | for (i = 0; i <= c->crypto_connections_length; ++i) { | ||
539 | if (c->crypto_connections[i].status == CONN_NO_CONNECTION) { | ||
540 | c->crypto_connections[i].number = connection_id; | ||
541 | c->crypto_connections[i].status = CONN_NOT_CONFIRMED; | ||
542 | random_nonce(c->crypto_connections[i].recv_nonce); | ||
543 | memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | ||
544 | memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | ||
545 | increment_nonce(c->crypto_connections[i].sent_nonce); | ||
546 | memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
547 | |||
548 | crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); | ||
549 | |||
550 | if (c->crypto_connections_length == i) | ||
551 | ++c->crypto_connections_length; | ||
552 | |||
553 | if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, | ||
554 | c->crypto_connections[i].sessionpublic_key) == 1) { | ||
555 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
556 | uint32_t zero = 0; | ||
557 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
558 | c->crypto_connections[i].sessionsecret_key, | ||
559 | c->crypto_connections[i].shared_key); | ||
560 | c->crypto_connections[i].status = | ||
561 | CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ | ||
562 | write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); | ||
563 | c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ | ||
564 | return i; | ||
565 | } | ||
566 | |||
567 | return -1; /* this should never happen. */ | ||
568 | } | ||
569 | } | ||
570 | |||
571 | return -1; | ||
572 | } | ||
573 | |||
574 | /* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet | ||
575 | (we have received a handshake but no empty data packet), 3 if the connection is established. | ||
576 | 4 if the connection is timed out and waiting to be killed */ | ||
577 | int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id) | ||
578 | { | ||
579 | if (crypt_connection_id >= 0 && crypt_connection_id < c->crypto_connections_length) | ||
580 | return c->crypto_connections[crypt_connection_id].status; | ||
581 | |||
582 | return CONN_NO_CONNECTION; | ||
583 | } | ||
584 | |||
585 | void new_keys(Net_Crypto *c) | ||
586 | { | ||
587 | crypto_box_keypair(c->self_public_key, c->self_secret_key); | ||
588 | } | ||
589 | |||
590 | /* save the public and private keys to the keys array | ||
591 | Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ | ||
592 | void save_keys(Net_Crypto *c, uint8_t *keys) | ||
593 | { | ||
594 | memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
595 | memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); | ||
596 | } | ||
597 | |||
598 | /* load the public and private keys from the keys array | ||
599 | Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ | ||
600 | void load_keys(Net_Crypto *c, uint8_t *keys) | ||
601 | { | ||
602 | memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); | ||
603 | memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); | ||
604 | } | ||
605 | |||
606 | /* TODO: optimize this | ||
607 | adds an incoming connection to the incoming_connection list. | ||
608 | returns 0 if successful | ||
609 | returns 1 if failure */ | ||
610 | static int new_incoming(Net_Crypto *c, int id) | ||
611 | { | ||
612 | uint32_t i; | ||
613 | |||
614 | for (i = 0; i < MAX_INCOMING; ++i) { | ||
615 | if (c->incoming_connections[i] == -1) { | ||
616 | c->incoming_connections[i] = id; | ||
617 | return 0; | ||
618 | } | ||
619 | } | ||
620 | |||
621 | return 1; | ||
622 | } | ||
623 | |||
624 | /* TODO: optimize this | ||
625 | handle all new incoming connections. */ | ||
626 | static void handle_incomings(Net_Crypto *c) | ||
627 | { | ||
628 | int income; | ||
629 | |||
630 | while (1) { | ||
631 | income = incoming_connection(c->lossless_udp); | ||
632 | |||
633 | if (income == -1 || new_incoming(c, income) ) | ||
634 | break; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | /* handle received packets for not yet established crypto connections. */ | ||
639 | static void receive_crypto(Net_Crypto *c) | ||
640 | { | ||
641 | uint32_t i; | ||
642 | |||
643 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
644 | if (c->crypto_connections[i].status == CONN_HANDSHAKE_SENT) { | ||
645 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
646 | uint8_t secret_nonce[crypto_box_NONCEBYTES]; | ||
647 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
648 | uint8_t session_key[crypto_box_PUBLICKEYBYTES]; | ||
649 | uint16_t len; | ||
650 | |||
651 | if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* handle handshake packet. */ | ||
652 | len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); | ||
653 | |||
654 | if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { | ||
655 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
656 | memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | ||
657 | memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | ||
658 | increment_nonce(c->crypto_connections[i].sent_nonce); | ||
659 | uint32_t zero = 0; | ||
660 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
661 | c->crypto_connections[i].sessionsecret_key, | ||
662 | c->crypto_connections[i].shared_key); | ||
663 | c->crypto_connections[i].status = | ||
664 | CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ | ||
665 | write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); | ||
666 | c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ | ||
667 | } | ||
668 | } | ||
669 | } else if (id_packet(c->lossless_udp, | ||
670 | c->crypto_connections[i].number) != -1) { // This should not happen kill the connection if it does | ||
671 | crypto_kill(c, i); | ||
672 | return; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | if (c->crypto_connections[i].status == CONN_NOT_CONFIRMED) { | ||
677 | if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) { | ||
678 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
679 | uint8_t data[MAX_DATA_SIZE]; | ||
680 | int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); | ||
681 | int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key, | ||
682 | c->crypto_connections[i].sessionsecret_key, | ||
683 | c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); | ||
684 | uint32_t zero = 0; | ||
685 | |||
686 | if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { | ||
687 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
688 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
689 | c->crypto_connections[i].sessionsecret_key, | ||
690 | c->crypto_connections[i].shared_key); | ||
691 | c->crypto_connections[i].status = CONN_ESTABLISHED; | ||
692 | |||
693 | /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ | ||
694 | kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000); | ||
695 | } else { | ||
696 | crypto_kill(c, i); // This should not happen kill the connection if it does | ||
697 | return; | ||
698 | } | ||
699 | } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1) | ||
700 | /* This should not happen | ||
701 | kill the connection if it does */ | ||
702 | crypto_kill(c, i); | ||
703 | |||
704 | return; | ||
705 | } | ||
706 | } | ||
707 | } | ||
708 | |||
709 | /* run this to (re)initialize net_crypto | ||
710 | sets all the global connection variables to their default values. */ | ||
711 | Net_Crypto *new_net_crypto(Networking_Core *net) | ||
712 | { | ||
713 | if (net == NULL) | ||
714 | return NULL; | ||
715 | |||
716 | Net_Crypto *temp = calloc(1, sizeof(Net_Crypto)); | ||
717 | |||
718 | if (temp == NULL) | ||
719 | return NULL; | ||
720 | |||
721 | temp->lossless_udp = new_lossless_udp(net); | ||
722 | |||
723 | if (temp->lossless_udp == NULL) | ||
724 | return NULL; | ||
725 | |||
726 | memset(temp->incoming_connections, -1 , sizeof(int) * MAX_INCOMING); | ||
727 | return temp; | ||
728 | } | ||
729 | |||
730 | void init_cryptopackets(void *dht) | ||
731 | { | ||
732 | DHT *s_dht = dht; | ||
733 | networking_registerhandler(s_dht->c->lossless_udp->net, NET_PACKET_CRYPTO, &cryptopacket_handle, s_dht); | ||
734 | } | ||
735 | |||
736 | static void kill_timedout(Net_Crypto *c) | ||
737 | { | ||
738 | uint32_t i; | ||
739 | |||
740 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
741 | if (c->crypto_connections[i].status != CONN_NO_CONNECTION | ||
742 | && is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4) | ||
743 | c->crypto_connections[i].status = CONN_TIMED_OUT; | ||
744 | else if (is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4) { | ||
745 | kill_connection(c->lossless_udp, c->crypto_connections[i].number); | ||
746 | c->crypto_connections[i].number = ~0; | ||
747 | } | ||
748 | } | ||
749 | } | ||
750 | |||
751 | /* main loop */ | ||
752 | void do_net_crypto(Net_Crypto *c) | ||
753 | { | ||
754 | do_lossless_udp(c->lossless_udp); | ||
755 | handle_incomings(c); | ||
756 | receive_crypto(c); | ||
757 | kill_timedout(c); | ||
758 | } | ||
759 | |||
760 | void kill_net_crypto(Net_Crypto *c) | ||
761 | { | ||
762 | uint32_t i; | ||
763 | |||
764 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
765 | crypto_kill(c, i); | ||
766 | } | ||
767 | |||
768 | kill_lossless_udp(c->lossless_udp); | ||
769 | memset(c, 0, sizeof(Net_Crypto)); | ||
770 | free(c); | ||
771 | } | ||