diff options
Diffstat (limited to 'toxcore/net_crypto.c')
-rw-r--r-- | toxcore/net_crypto.c | 267 |
1 files changed, 257 insertions, 10 deletions
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 3bc2ce33..ad41ce78 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -35,6 +35,21 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection | |||
35 | return (uint32_t)crypt_connection_id >= c->crypto_connections_length; | 35 | return (uint32_t)crypt_connection_id >= c->crypto_connections_length; |
36 | } | 36 | } |
37 | 37 | ||
38 | /* return 0 if connection is dead. | ||
39 | * return 1 if connection is alive. | ||
40 | */ | ||
41 | static int is_alive(uint8_t status) | ||
42 | { | ||
43 | if (status == CRYPTO_CONN_COOKIE_REQUESTING || | ||
44 | status == CRYPTO_CONN_HANDSHAKE_SENT || | ||
45 | status == CRYPTO_CONN_NOT_CONFIRMED || | ||
46 | status == CRYPTO_CONN_ESTABLISHED) { | ||
47 | return 1; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
38 | /* cookie timeout in seconds */ | 53 | /* cookie timeout in seconds */ |
39 | #define COOKIE_TIMEOUT 10 | 54 | #define COOKIE_TIMEOUT 10 |
40 | #define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) | 55 | #define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) |
@@ -55,7 +70,7 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection | |||
55 | * return COOKIE_REQUEST_LENGTH on success. | 70 | * return COOKIE_REQUEST_LENGTH on success. |
56 | */ | 71 | */ |
57 | static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key, | 72 | static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key, |
58 | uint64_t number) | 73 | uint64_t number, uint8_t *shared_key) |
59 | { | 74 | { |
60 | uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; | 75 | uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; |
61 | 76 | ||
@@ -63,7 +78,6 @@ static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_pu | |||
63 | memcpy(plain + crypto_box_PUBLICKEYBYTES, real_public_key, crypto_box_PUBLICKEYBYTES); | 78 | memcpy(plain + crypto_box_PUBLICKEYBYTES, real_public_key, crypto_box_PUBLICKEYBYTES); |
64 | memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); | 79 | memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); |
65 | 80 | ||
66 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | ||
67 | DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); | 81 | DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); |
68 | uint8_t nonce[crypto_box_NONCEBYTES]; | 82 | uint8_t nonce[crypto_box_NONCEBYTES]; |
69 | new_nonce(nonce); | 83 | new_nonce(nonce); |
@@ -204,7 +218,7 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack | |||
204 | * return -1 on failure. | 218 | * return -1 on failure. |
205 | * return COOKIE_LENGTH on success. | 219 | * return COOKIE_LENGTH on success. |
206 | */ | 220 | */ |
207 | static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, | 221 | static int handle_cookie_response(uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, |
208 | uint8_t *shared_key) | 222 | uint8_t *shared_key) |
209 | { | 223 | { |
210 | if (length != COOKIE_RESPONSE_LENGTH) | 224 | if (length != COOKIE_RESPONSE_LENGTH) |
@@ -332,9 +346,90 @@ static Crypto_Connection *get_crypto_connection(Net_Crypto *c, int crypt_connect | |||
332 | */ | 346 | */ |
333 | static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) | 347 | static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) |
334 | { | 348 | { |
335 | //TODO | 349 | //TODO TCP, etc... |
350 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
351 | |||
352 | if (conn == 0) | ||
353 | return -1; | ||
354 | |||
355 | if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) != length) | ||
356 | return -1; | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | #define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) | ||
362 | |||
363 | static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) | ||
364 | { | ||
365 | if (length == 0 || length + (1 + sizeof(uint16_t) + crypto_box_MACBYTES) > MAX_CRYPTO_PACKET_SIZE) | ||
366 | return -1; | ||
367 | |||
368 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
369 | |||
370 | if (conn == 0) | ||
371 | return -1; | ||
336 | 372 | ||
373 | uint8_t packet[1 + sizeof(uint16_t) + length + crypto_box_MACBYTES]; | ||
374 | packet[0] = NET_PACKET_CRYPTO_DATA; | ||
375 | memcpy(packet + 1, conn->sent_nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); | ||
376 | int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); | ||
337 | 377 | ||
378 | if (len + 1 + sizeof(uint16_t) != sizeof(packet)) | ||
379 | return -1; | ||
380 | |||
381 | increment_nonce(conn->sent_nonce); | ||
382 | return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); | ||
383 | } | ||
384 | |||
385 | /* Get the lowest 2 bytes from the nonce and convert | ||
386 | * them to host byte format before returning them. | ||
387 | */ | ||
388 | uint16_t get_nonce_uint16(uint8_t *nonce) | ||
389 | { | ||
390 | uint16_t num; | ||
391 | memcpy(&num, nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); | ||
392 | return ntohs(num); | ||
393 | } | ||
394 | |||
395 | #define DATA_NUM_THRESHOLD 21845 | ||
396 | |||
397 | /* Handle a data packet. | ||
398 | * Decrypt packet of length and put it into data. | ||
399 | * data must be at least MAX_DATA_DATA_PACKET_SIZE big. | ||
400 | * | ||
401 | * return -1 on failure. | ||
402 | * return length of data on success. | ||
403 | */ | ||
404 | static int handle_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint8_t *packet, uint16_t length) | ||
405 | { | ||
406 | if (length <= (1 + sizeof(uint16_t) + crypto_box_MACBYTES) || length > MAX_CRYPTO_PACKET_SIZE) | ||
407 | return -1; | ||
408 | |||
409 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
410 | |||
411 | if (conn == 0) | ||
412 | return -1; | ||
413 | |||
414 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
415 | memcpy(nonce, conn->recv_nonce, crypto_box_NONCEBYTES); | ||
416 | uint16_t num_cur_nonce = get_nonce_uint16(nonce); | ||
417 | uint16_t num; | ||
418 | memcpy(&num, packet + 1, sizeof(uint16_t)); | ||
419 | num = ntohs(num); | ||
420 | uint16_t diff = num - num_cur_nonce; | ||
421 | increment_nonce_number(nonce, diff); | ||
422 | int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), | ||
423 | length - (1 + sizeof(uint16_t)), data); | ||
424 | |||
425 | if ((unsigned int)len != length - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) | ||
426 | return -1; | ||
427 | |||
428 | if (diff > DATA_NUM_THRESHOLD * 2) { | ||
429 | increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD); | ||
430 | } | ||
431 | |||
432 | return len; | ||
338 | } | 433 | } |
339 | 434 | ||
340 | /* Add a new temp packet to send repeatedly. | 435 | /* Add a new temp packet to send repeatedly. |
@@ -434,7 +529,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint | |||
434 | uint8_t cookie[COOKIE_LENGTH]; | 529 | uint8_t cookie[COOKIE_LENGTH]; |
435 | uint64_t number; | 530 | uint64_t number; |
436 | 531 | ||
437 | if (handle_cookie_response(c, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) | 532 | if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) |
438 | return -1; | 533 | return -1; |
439 | 534 | ||
440 | if (number != conn->cookie_request_number) | 535 | if (number != conn->cookie_request_number) |
@@ -581,6 +676,37 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) | |||
581 | return -1; | 676 | return -1; |
582 | } | 677 | } |
583 | 678 | ||
679 | /* Add a source to the crypto connection. | ||
680 | * This is to be used only when we have recieved a packet from that source. | ||
681 | * | ||
682 | * return -1 on failure. | ||
683 | * return positive number on success. | ||
684 | * 0 if source was a direct UDP connection. | ||
685 | * TODO | ||
686 | */ | ||
687 | static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, IP_Port source) | ||
688 | { | ||
689 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
690 | |||
691 | if (conn == 0) | ||
692 | return -1; | ||
693 | |||
694 | if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { | ||
695 | conn->ip_port = source; | ||
696 | conn->direct_lastrecv_time = current_time(); | ||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | return -1; | ||
701 | } | ||
702 | |||
703 | |||
704 | /* Set function to be called when someone requests a new connection to us. | ||
705 | * | ||
706 | * The set function should return -1 on failure and 0 on success. | ||
707 | * | ||
708 | * n_c is only valid for the duration of this function. | ||
709 | */ | ||
584 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), | 710 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), |
585 | void *object) | 711 | void *object) |
586 | { | 712 | { |
@@ -606,10 +732,34 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ | |||
606 | n_c.cookie_length = COOKIE_LENGTH; | 732 | n_c.cookie_length = COOKIE_LENGTH; |
607 | 733 | ||
608 | if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.cookie, data, length, | 734 | if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.cookie, data, length, |
609 | 0) != 0) | 735 | 0) != 0) { |
736 | free(n_c.cookie); | ||
610 | return -1; | 737 | return -1; |
738 | } | ||
611 | 739 | ||
612 | return c->new_connection_callback(c->new_connection_callback_object, &n_c); | 740 | int crypt_connection_id = getcryptconnection_id(c, n_c.public_key); |
741 | |||
742 | if (crypt_connection_id != -1) { | ||
743 | int ret = -1; | ||
744 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
745 | |||
746 | if (conn != 0 && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) { | ||
747 | memcpy(conn->recv_nonce, n_c.recv_nonce, crypto_box_NONCEBYTES); | ||
748 | memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, crypto_box_PUBLICKEYBYTES); | ||
749 | encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); | ||
750 | |||
751 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; | ||
752 | crypto_connection_add_source(c, crypt_connection_id, source); | ||
753 | ret = 0; | ||
754 | } | ||
755 | |||
756 | free(n_c.cookie); | ||
757 | return ret; | ||
758 | } | ||
759 | |||
760 | int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c); | ||
761 | free(n_c.cookie); | ||
762 | return ret; | ||
613 | } | 763 | } |
614 | 764 | ||
615 | /* Accept a crypto connection. | 765 | /* Accept a crypto connection. |
@@ -619,7 +769,6 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ | |||
619 | */ | 769 | */ |
620 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) | 770 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) |
621 | { | 771 | { |
622 | //TODO: do something with n_c->source. | ||
623 | if (getcryptconnection_id(c, n_c->public_key) != -1) | 772 | if (getcryptconnection_id(c, n_c->public_key) != -1) |
624 | return -1; | 773 | return -1; |
625 | 774 | ||
@@ -654,6 +803,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) | |||
654 | 803 | ||
655 | send_temp_packet(c, crypt_connection_id); | 804 | send_temp_packet(c, crypt_connection_id); |
656 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; | 805 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; |
806 | crypto_connection_add_source(c, crypt_connection_id, n_c->source); | ||
657 | return crypt_connection_id; | 807 | return crypt_connection_id; |
658 | } | 808 | } |
659 | 809 | ||
@@ -688,7 +838,6 @@ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) | |||
688 | } | 838 | } |
689 | 839 | ||
690 | /* Set the DHT public key of the crypto connection. | 840 | /* Set the DHT public key of the crypto connection. |
691 | * If one to that real public key already exists, return it. | ||
692 | * | 841 | * |
693 | * return -1 on failure. | 842 | * return -1 on failure. |
694 | * return 0 on success. | 843 | * return 0 on success. |
@@ -708,7 +857,7 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t | |||
708 | uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; | 857 | uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; |
709 | 858 | ||
710 | if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->public_key, | 859 | if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->public_key, |
711 | conn->cookie_request_number) != sizeof(cookie_request)) | 860 | conn->cookie_request_number, conn->shared_key) != sizeof(cookie_request)) |
712 | return -1; | 861 | return -1; |
713 | 862 | ||
714 | if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) | 863 | if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) |
@@ -718,6 +867,101 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t | |||
718 | return 0; | 867 | return 0; |
719 | } | 868 | } |
720 | 869 | ||
870 | /* Set the direct ip of the crypto connection. | ||
871 | * | ||
872 | * return -1 on failure. | ||
873 | * return 0 on success. | ||
874 | */ | ||
875 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) | ||
876 | { | ||
877 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
878 | |||
879 | if (conn == 0) | ||
880 | return -1; | ||
881 | |||
882 | if (!ipport_equal(&ip_port, &conn->ip_port)) { | ||
883 | conn->ip_port = ip_port; | ||
884 | conn->direct_lastrecv_time = 0; | ||
885 | } | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | /* Get the crypto connection id from the ip_port. | ||
891 | * | ||
892 | * return -1 on failure. | ||
893 | * return connection id on success. | ||
894 | */ | ||
895 | static int crypto_id_ip_port(Net_Crypto *c, IP_Port ip_port) | ||
896 | { | ||
897 | uint32_t i; | ||
898 | |||
899 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
900 | if (is_alive(c->crypto_connections[i].status)) | ||
901 | if (ipport_equal(&ip_port, &c->crypto_connections[i].ip_port)) | ||
902 | return i; | ||
903 | } | ||
904 | |||
905 | return -1; | ||
906 | } | ||
907 | |||
908 | #define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + crypto_box_MACBYTES) | ||
909 | |||
910 | /* Handle raw UDP packets coming directly from the socket. | ||
911 | * | ||
912 | * Handles: | ||
913 | * Cookie response packets. | ||
914 | * Crypto handshake packets. | ||
915 | * Crypto data packets. | ||
916 | * | ||
917 | */ | ||
918 | static int udp_handle_packet(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
919 | { | ||
920 | if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) | ||
921 | return 1; | ||
922 | |||
923 | Net_Crypto *c = object; | ||
924 | int crypt_connection_id = crypto_id_ip_port(c, source); | ||
925 | |||
926 | if (crypt_connection_id == -1) { | ||
927 | if (packet[0] != NET_PACKET_CRYPTO_HS) | ||
928 | return 1; | ||
929 | |||
930 | if (handle_new_connection_handshake(c, source, packet, length) != 0) | ||
931 | return 1; | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | if (handle_packet_connection(c, crypt_connection_id, packet, length) != 0) | ||
937 | return 1; | ||
938 | |||
939 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
940 | |||
941 | if (conn == 0) | ||
942 | return -1; | ||
943 | |||
944 | conn->direct_lastrecv_time = current_time(); | ||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | static void send_crypto_packets(Net_Crypto *c) | ||
949 | { | ||
950 | uint32_t i; | ||
951 | uint64_t temp_time = current_time(); | ||
952 | |||
953 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
954 | Crypto_Connection *conn = get_crypto_connection(c, i); | ||
955 | |||
956 | if (conn == 0) | ||
957 | return; | ||
958 | |||
959 | if ((CRYPTO_SEND_PACKET_INTERVAL * 1000UL) + conn->temp_packet_sent_time < temp_time) { | ||
960 | send_temp_packet(c, i); | ||
961 | } | ||
962 | } | ||
963 | } | ||
964 | |||
721 | /* return 0 if there is no received data in the buffer. | 965 | /* return 0 if there is no received data in the buffer. |
722 | * return -1 if the packet was discarded. | 966 | * return -1 if the packet was discarded. |
723 | * return length of received data if successful. | 967 | * return length of received data if successful. |
@@ -1196,6 +1440,9 @@ Net_Crypto *new_net_crypto(DHT *dht) | |||
1196 | new_symmetric_key(temp->secret_symmetric_key); | 1440 | new_symmetric_key(temp->secret_symmetric_key); |
1197 | 1441 | ||
1198 | networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp); | 1442 | networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp); |
1443 | networking_registerhandler(dht->net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp); | ||
1444 | networking_registerhandler(dht->net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp); | ||
1445 | networking_registerhandler(dht->net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp); | ||
1199 | return temp; | 1446 | return temp; |
1200 | } | 1447 | } |
1201 | 1448 | ||