diff options
author | irungentoo <irungentoo@gmail.com> | 2014-05-04 20:04:43 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-05-04 20:04:43 -0400 |
commit | fca5e1b99aaa09f60c6f3f469fdfd23231f50c90 (patch) | |
tree | 4479f276325714033fcf52ecca0b21ee4feca102 /toxcore/net_crypto.c | |
parent | 4dc0af61c6ea5b1581aca0d15cfd9ffc0f525b10 (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.c | 305 |
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 | */ | ||
367 | static 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 | */ | ||
377 | static 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 | */ | ||
406 | static 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 | */ | ||
427 | static 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 | */ | ||
449 | static 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 | */ | ||
470 | static 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 | ||
363 | static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) | 495 | static 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 | ||
518 | static 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 | */ | ||
534 | static 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 | */ | ||
718 | static 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 | */ |
1066 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | 1297 | uint32_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 | */ |
1075 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | 1314 | int64_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. |