summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-05-01 19:20:28 -0400
committerirungentoo <irungentoo@gmail.com>2014-05-01 19:20:28 -0400
commit47aa53a3840f81b42e0f78dea03a57ebd7c3ebb5 (patch)
treef5c00a5ab3269b00e3d111bf136850f3f4ea5e60 /toxcore
parent19a4b1e443f015e38d04decbe8e042acb17d8ae8 (diff)
Protocol implementation is starting to look ok.
Still need to decide exactly how data packets will work though.
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/crypto_core.c2
-rw-r--r--toxcore/crypto_core.h2
-rw-r--r--toxcore/net_crypto.c267
-rw-r--r--toxcore/net_crypto.h8
4 files changed, 267 insertions, 12 deletions
diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c
index 3f3e7b48..0b1971e7 100644
--- a/toxcore/crypto_core.c
+++ b/toxcore/crypto_core.c
@@ -33,7 +33,7 @@
33/* Use this instead of memcmp; not vulnerable to timing attacks. 33/* Use this instead of memcmp; not vulnerable to timing attacks.
34 returns 0 if both mem locations of length are equal, 34 returns 0 if both mem locations of length are equal,
35 return -1 if they are not. */ 35 return -1 if they are not. */
36unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) 36int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length)
37{ 37{
38 if (length == 16) { 38 if (length == 16) {
39 return crypto_verify_16(mem1, mem2); 39 return crypto_verify_16(mem1, mem2);
diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h
index 7ee5f59e..c5969453 100644
--- a/toxcore/crypto_core.h
+++ b/toxcore/crypto_core.h
@@ -43,7 +43,7 @@
43/* Use this instead of memcmp; not vulnerable to timing attacks. 43/* Use this instead of memcmp; not vulnerable to timing attacks.
44 returns 0 if both mem locations of length are equal, 44 returns 0 if both mem locations of length are equal,
45 return -1 if they are not. */ 45 return -1 if they are not. */
46unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); 46int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length);
47 47
48/* Encrypts plain of length length to encrypted of length + 16 using the 48/* Encrypts plain of length length to encrypted of length + 16 using the
49 * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. 49 * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce.
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 */
41static 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 */
57static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key, 72static 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 */
207static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, 221static 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 */
333static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) 347static 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
363static 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 */
388uint16_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 */
404static 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 */
687static 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 */
584void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), 710void 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 */
620int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) 770int 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 */
875int 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 */
895static 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 */
918static 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
948static 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
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index 0d27ae4d..736d3070 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -40,6 +40,10 @@
40 40
41#define MAX_CRYPTO_PACKET_SIZE 1400 41#define MAX_CRYPTO_PACKET_SIZE 1400
42#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) 42#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES))
43
44/* Interval in ms between sending cookie request/handshake packets. */
45#define CRYPTO_SEND_PACKET_INTERVAL 500
46
43typedef struct { 47typedef struct {
44 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ 48 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
45 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ 49 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
@@ -64,6 +68,10 @@ typedef struct {
64 uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ 68 uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
65 uint16_t temp_packet_length; 69 uint16_t temp_packet_length;
66 uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ 70 uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
71
72 IP_Port ip_port; /* The ip and port to contact this guy directly.*/
73 uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */
74
67} Crypto_Connection; 75} Crypto_Connection;
68 76
69typedef struct { 77typedef struct {