summaryrefslogtreecommitdiff
path: root/toxcore/net_crypto.c
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 /toxcore/net_crypto.c
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.
Diffstat (limited to 'toxcore/net_crypto.c')
-rw-r--r--toxcore/net_crypto.c305
1 files changed, 277 insertions, 28 deletions
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.