summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-05-04 20:04:43 -0400
committerirungentoo <irungentoo@gmail.com>2014-05-04 20:04:43 -0400
commitfca5e1b99aaa09f60c6f3f469fdfd23231f50c90 (patch)
tree4479f276325714033fcf52ecca0b21ee4feca102
parent4dc0af61c6ea5b1581aca0d15cfd9ffc0f525b10 (diff)
Added arrays to store packets on send/recv in net crypto.
Wrote down more of the protocol. Padding support has been added and implemented which will make it possible for us to pad packets to mitigate length related attacks.
-rw-r--r--docs/Tox_middle_level_network_protocol.txt31
-rw-r--r--toxcore/Messenger.c2
-rw-r--r--toxcore/net_crypto.c305
-rw-r--r--toxcore/net_crypto.h34
4 files changed, 332 insertions, 40 deletions
diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt
index 7b65db51..f9b03196 100644
--- a/docs/Tox_middle_level_network_protocol.txt
+++ b/docs/Tox_middle_level_network_protocol.txt
@@ -41,8 +41,8 @@ Detailed implementation details:
41cookie request packet: 41cookie request packet:
42[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 42[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24
43bytes)][Encrypted message containing: [Senders real public key (32 43bytes)][Encrypted message containing: [Senders real public key (32
44bytes)][Recievers real public key (32 bytes)][uint64_t number (must be sent back 44bytes)][Recievers real public key (32 bytes)][uint64_t number (must be sent
45untouched in cookie response)]] 45back untouched in cookie response)]]
46Encrypted message is encrypted with sender DHT private key, recievers DHT 46Encrypted message is encrypted with sender DHT private key, recievers DHT
47public key and the nonce. 47public key and the nonce.
48 48
@@ -88,9 +88,30 @@ in the handshake will be used to encrypt the first data packet sent, the nonce
88 88
89Data packets: 89Data packets:
90 90
91[uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce used 91[uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce
92to encrypt this][encrypted with the session key and a nonce:[data]] 92used to encrypt this][encrypted with the session key and a nonce:[plain data]]
93 93
94Data in the data packets: 94Plain data in the data packets:
95
96[uint32_t our recvbuffers buffer_start, (highest packet number handled +
971)][uint32_t packet number if lossless, our sendbuffer buffer_end if
98lossy][data]
99
100data ids:
1010: padding (skipped until we hit a non zero (data id) byte)
1021: packet request packet (lossy packet)
95... 103...
10416+: reserved for Messenger usage (lossless packets).
105
106packet request packet: [uint8_t (1)][uint8_t num][uint8_t num][uint8_t
107num]...[uint8_t num]
108
109the list of nums are a list of packet numbers the other is requesting.
110to get the real packet numbers from this list take the recvbuffers buffer_start
111from the packet, substract 1 to it and put it in packet_num then start from the
112beggining of the num list: if num is zero, add 255 to packet_num then do the
113next num. if num isn't zero, add its value to packet_num, note that the other
114has requested we send this packet again to them then continue to the next num in
115the list.
116
96 117
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 37feccf5..a84c391b 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -849,7 +849,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id,
849 if (length != 0) 849 if (length != 0)
850 memcpy(packet + 1, data, length); 850 memcpy(packet + 1, data, length);
851 851
852 return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); 852 return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1) != -1;
853} 853}
854 854
855/**********GROUP CHATS************/ 855/**********GROUP CHATS************/
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index d4922380..9f8048be 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -358,6 +358,138 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data,
358 return 0; 358 return 0;
359} 359}
360 360
361/** START: Array Related functions **/
362
363
364/* Return number of packets in array
365 * Note that holes are counted too.
366 */
367static uint32_t num_packets_array(Packets_Array *array)
368{
369 return array->buffer_end - array->buffer_start;
370}
371
372/* Add data with packet number to array.
373 *
374 * return -1 on failure.
375 * return 0 on success.
376 */
377static int add_data_to_buffer(Packets_Array *array, uint32_t number, Packet_Data *data)
378{
379 if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE)
380 return -1;
381
382 uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
383
384 if (array->buffer[num])
385 return -1;
386
387 Packet_Data *new_d = malloc(sizeof(Packet_Data));
388
389 if (new_d == NULL)
390 return -1;
391
392 memcpy(new_d, data, sizeof(Packet_Data));
393 array->buffer[num] = new_d;
394
395 if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start))
396 array->buffer_end = number + 1;
397
398 return 0;
399}
400
401/* Copy data with packet number to data.
402 *
403 * return -1 on failure.
404 * return 0 on success.
405 */
406static int copy_data_number(Packets_Array *array, Packet_Data *data, uint32_t number)
407{
408 uint32_t num_spots = array->buffer_end - array->buffer_start;
409
410 if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots)
411 return -1;
412
413 uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
414
415 if (!array->buffer[num])
416 return -1;
417
418 memcpy(data, array->buffer[num], sizeof(Packet_Data));
419 return 0;
420}
421
422/* Add data to end of array.
423 *
424 * return -1 on failure.
425 * return packet number on success.
426 */
427static int64_t add_data_end_of_buffer(Packets_Array *array, Packet_Data *data)
428{
429 if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE)
430 return -1;
431
432 Packet_Data *new_d = malloc(sizeof(Packet_Data));
433
434 if (new_d == NULL)
435 return -1;
436
437 memcpy(new_d, data, sizeof(Packet_Data));
438 uint32_t id = array->buffer_end;
439 array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d;
440 ++array->buffer_end;
441 return id;
442}
443
444/* Read data from begginning of array.
445 *
446 * return -1 on failure.
447 * return packet number on success.
448 */
449static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
450{
451 if (array->buffer_end == array->buffer_start)
452 return -1;
453
454 uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE;
455
456 if (!array->buffer[num])
457 return -1;
458
459 memcpy(data, array->buffer[num], sizeof(Packet_Data));
460 uint32_t id = array->buffer_start;
461 ++array->buffer_start;
462 return id;
463}
464
465/* Delete all packets in array before number (but not number)
466 *
467 * return -1 on failure.
468 * return 0 on success
469 */
470static int clear_buffer_until(Packets_Array *array, uint32_t number)
471{
472 uint32_t num_spots = array->buffer_end - array->buffer_start;
473
474 if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots)
475 return -1;
476
477 uint32_t i;
478
479 for (i = array->buffer_start; i != number; ++i) {
480 uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
481
482 if (array->buffer[num]) {
483 free(array->buffer[num]);
484 array->buffer[num] = NULL;
485 }
486 }
487
488 array->buffer_start = i;
489 return 0;
490}
491/** END: Array Related functions **/
492
361#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) 493#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES))
362 494
363static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) 495static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length)
@@ -383,6 +515,47 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat
383 return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); 515 return send_packet_to(c, crypt_connection_id, packet, sizeof(packet));
384} 516}
385 517
518static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num,
519 uint8_t *data, uint32_t length)
520{
521 num = htonl(num);
522 buffer_start = htonl(buffer_start);
523 uint8_t packet[sizeof(uint32_t) + sizeof(uint32_t) + length];
524 memcpy(packet, &buffer_start, sizeof(uint32_t));
525 memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t));
526 memcpy(packet + (sizeof(uint32_t) * 2), data, length);
527
528 return send_data_packet(c, crypt_connection_id, packet, sizeof(packet));
529}
530
531/* return -1 if data could not be put in packet queue.
532 * return positive packet number if data was put into the queue.
533 */
534static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
535{
536 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE)
537 return -1;
538
539 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
540
541 if (conn == 0)
542 return -1;
543
544 Packet_Data dt;
545 dt.time = current_time_monotonic();
546 dt.length = length;
547 memcpy(dt.data, data, length);
548 int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt);
549
550 if (packet_num == -1)
551 return -1;
552
553 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) != 0)
554 printf("send_data_packet failed\n");
555
556 return packet_num;
557}
558
386/* Get the lowest 2 bytes from the nonce and convert 559/* Get the lowest 2 bytes from the nonce and convert
387 * them to host byte format before returning them. 560 * them to host byte format before returning them.
388 */ 561 */
@@ -433,6 +606,7 @@ static int handle_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *d
433 return len; 606 return len;
434} 607}
435 608
609
436/* Add a new temp packet to send repeatedly. 610/* Add a new temp packet to send repeatedly.
437 * 611 *
438 * return -1 on failure. 612 * return -1 on failure.
@@ -536,6 +710,80 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t
536 return 0; 710 return 0;
537} 711}
538 712
713/* Handle a recieved data packet.
714 *
715 * return -1 on failure.
716 * return 0 on success.
717 */
718static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length)
719{
720 if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE)
721 return -1;
722
723 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
724
725 if (conn == 0)
726 return -1;
727
728 uint8_t data[MAX_DATA_DATA_PACKET_SIZE];
729 int len = handle_data_packet(c, crypt_connection_id, data, packet, length);
730
731 if (len <= (int)(sizeof(uint32_t) * 2))
732 return -1;
733
734 uint32_t buffer_start, num;
735 memcpy(&buffer_start, data, sizeof(uint32_t));
736 memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t));
737 buffer_start = ntohl(buffer_start);
738 num = ntohl(num);
739
740 if (buffer_start != conn->send_array.buffer_start && clear_buffer_until(&conn->send_array, buffer_start) != 0)
741 return -1;
742
743 uint8_t *real_data = data + (sizeof(uint32_t) * 2);
744 uint16_t real_length = len - (sizeof(uint32_t) * 2);
745
746 while (real_data[0] == 0) { /* Remove Padding */
747 ++real_data;
748 --real_length;
749
750 if (real_length == 0)
751 return -1;
752 }
753
754 if (real_data[0] == PACKET_ID_REQUEST) {
755 if (real_length <= 1)
756 return -1;
757
758
759 //TODO
760 } else {
761 Packet_Data dt;
762 dt.time = current_time_monotonic();
763 dt.length = real_length;
764 memcpy(dt.data, real_data, real_length);
765
766 if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0)
767 return -1;
768
769 while (read_data_beg_buffer(&conn->recv_array, &dt) != -1) {
770 if (conn->connection_data_callback)
771 conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data,
772 dt.length);
773 }
774 }
775
776 if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
777 if (conn->connection_status_callback)
778 conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1);
779
780 clear_temp_packet(c, crypt_connection_id);
781 conn->status = CRYPTO_CONN_ESTABLISHED;
782 }
783
784 return 0;
785}
786
539/* Handle a packet that was recieved for the connection. 787/* Handle a packet that was recieved for the connection.
540 * 788 *
541 * return -1 on failure. 789 * return -1 on failure.
@@ -598,24 +846,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint
598 846
599 case NET_PACKET_CRYPTO_DATA: { 847 case NET_PACKET_CRYPTO_DATA: {
600 if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { 848 if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) {
601 uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; 849 return handle_data_packet_helper(c, crypt_connection_id, packet, length);
602 int len = handle_data_packet(c, crypt_connection_id, data, packet, length);
603
604 if (len == -1)
605 return -1;
606
607 if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
608 if (conn->connection_status_callback)
609 conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1);
610
611 clear_temp_packet(c, crypt_connection_id);
612 conn->status = CRYPTO_CONN_ESTABLISHED;
613 }
614
615 if (conn->connection_data_callback)
616 conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, data, len);
617
618 //TODO add buffers and packet requesting.
619 } else { 850 } else {
620 return -1; 851 return -1;
621 } 852 }
@@ -1053,8 +1284,8 @@ static void send_crypto_packets(Net_Crypto *c)
1053 1284
1054 if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED 1285 if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED
1055 && (500ULL + conn->last_data_packet_sent) < temp_time) {//TODO remove this. 1286 && (500ULL + conn->last_data_packet_sent) < temp_time) {//TODO remove this.
1056 uint8_t data[4] = {}; 1287 uint8_t data[4] = {5, 2};
1057 send_data_packet(c, i, data, 4); 1288 send_lossless_packet(c, i, data, 4);
1058 } 1289 }
1059 } 1290 }
1060} 1291}
@@ -1065,20 +1296,38 @@ static void send_crypto_packets(Net_Crypto *c)
1065 */ 1296 */
1066uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) 1297uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id)
1067{ 1298{
1299 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1300
1301 if (conn == 0)
1302 return 0;
1303
1068 //TODO 1304 //TODO
1069 return 0; 1305 return CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array);
1070} 1306}
1071 1307
1072/* return 0 if data could not be put in packet queue. 1308
1073 * return 1 if data was put into the queue. 1309
1310
1311/* return -1 if data could not be put in packet queue.
1312 * return positive packet number if data was put into the queue.
1074 */ 1313 */
1075int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) 1314int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
1076{ 1315{
1077 //TODO 1316 if (length == 0)
1078 if (send_data_packet(c, crypt_connection_id, data, length) == 0) 1317 return -1;
1079 return 1;
1080 1318
1081 return 0; 1319 if (data[0] < CRYPTO_RESERVED_PACKETS)
1320 return -1;
1321
1322 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1323
1324 if (conn == 0)
1325 return -1;
1326
1327 if (conn->status != CRYPTO_CONN_ESTABLISHED)
1328 return -1;
1329
1330 return send_lossless_packet(c, crypt_connection_id, data, length);
1082} 1331}
1083 1332
1084/* Kill a crypto connection. 1333/* Kill a crypto connection.
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index 0389f283..7c090aaa 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -35,18 +35,37 @@
35#define CRYPTO_CONN_ESTABLISHED 4 35#define CRYPTO_CONN_ESTABLISHED 4
36#define CRYPTO_CONN_TIMED_OUT 5 36#define CRYPTO_CONN_TIMED_OUT 5
37 37
38#define CRYPTO_PACKET_BUFFER_SIZE 64 38#define CRYPTO_PACKET_BUFFER_SIZE 64 /* Must be a power of 2 */
39 39
40#define MAX_CRYPTO_PACKET_SIZE 1400 40#define MAX_CRYPTO_PACKET_SIZE 1400
41 41
42#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + crypto_box_MACBYTES)
43
42/* Max size of data in packets TODO*/ 44/* Max size of data in packets TODO*/
43#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) 45#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
44 46
45/* Interval in ms between sending cookie request/handshake packets. */ 47/* Interval in ms between sending cookie request/handshake packets. */
46#define CRYPTO_SEND_PACKET_INTERVAL 500 48#define CRYPTO_SEND_PACKET_INTERVAL 500
47/* The maximum number of times we try to send the cookie request and handshake 49/* The maximum number of times we try to send the cookie request and handshake
48 before giving up. */ 50 before giving up. */
49#define MAX_NUM_SENDPACKET_TRIES 10 51#define MAX_NUM_SENDPACKET_TRIES 8
52
53#define PACKET_ID_PADDING 0
54#define PACKET_ID_REQUEST 1
55
56#define CRYPTO_RESERVED_PACKETS 16
57
58typedef struct {
59 uint64_t time;
60 uint16_t length;
61 uint8_t data[MAX_CRYPTO_DATA_SIZE];
62} Packet_Data;
63
64typedef struct {
65 Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE];
66 uint32_t buffer_start;
67 uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
68} Packets_Array;
50 69
51typedef struct { 70typedef struct {
52 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ 71 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
@@ -74,6 +93,8 @@ typedef struct {
74 IP_Port ip_port; /* The ip and port to contact this guy directly.*/ 93 IP_Port ip_port; /* The ip and port to contact this guy directly.*/
75 uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */ 94 uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */
76 95
96 Packets_Array send_array;
97 Packets_Array recv_array;
77 98
78 int (*connection_status_callback)(void *object, int id, uint8_t status); 99 int (*connection_status_callback)(void *object, int id, uint8_t status);
79 void *connection_status_callback_object; 100 void *connection_status_callback_object;
@@ -99,6 +120,7 @@ typedef struct {
99 DHT *dht; 120 DHT *dht;
100 121
101 Crypto_Connection *crypto_connections; 122 Crypto_Connection *crypto_connections;
123 //TCP_Client_Connection *tcp_connections;
102 124
103 uint32_t crypto_connections_length; /* Length of connections array. */ 125 uint32_t crypto_connections_length; /* Length of connections array. */
104 126
@@ -182,10 +204,10 @@ int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connec
182 */ 204 */
183uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id); 205uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id);
184 206
185/* return 0 if data could not be put in packet queue. 207/* return -1 if data could not be put in packet queue.
186 * return 1 if data was put into the queue. 208 * return positive packet number if data was put into the queue.
187 */ 209 */
188int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); 210int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length);
189 211
190 212
191/* Kill a crypto connection. 213/* Kill a crypto connection.