summaryrefslogtreecommitdiff
path: root/core/net_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/net_crypto.c')
-rw-r--r--core/net_crypto.c771
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. */
36uint8_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. */
52void 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. */
58int 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. */
80int 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
105int 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
113int 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 */
122static 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. */
135void 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 */
148int 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 */
179int 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 */
215int 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. */
244static 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
270void 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
276static 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 */
311static 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 */
338static 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 */
370static 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 */
385int 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. */
405int 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 */
459int 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. */
491int 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 */
519int 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 */
577int 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
585void 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 */
592void 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 */
600void 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 */
610static 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. */
626static 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. */
639static 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. */
711Net_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
730void 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
736static 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 */
752void 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
760void 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}