diff options
-rw-r--r-- | toxcore/net_crypto.c | 216 | ||||
-rw-r--r-- | toxcore/net_crypto.h | 7 |
2 files changed, 218 insertions, 5 deletions
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 71959c46..3f74cf04 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -46,6 +46,8 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection | |||
46 | #define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + sizeof(uint64_t) + crypto_box_MACBYTES) | 46 | #define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + sizeof(uint64_t) + crypto_box_MACBYTES) |
47 | 47 | ||
48 | /* Create a cookie request packet and put it in packet. | 48 | /* Create a cookie request packet and put it in packet. |
49 | * dht_public_key is the dht public key of the other | ||
50 | * real_public_key is the real public key of the other. | ||
49 | * | 51 | * |
50 | * packet must be of size COOKIE_REQUEST_LENGTH or bigger. | 52 | * packet must be of size COOKIE_REQUEST_LENGTH or bigger. |
51 | * | 53 | * |
@@ -426,7 +428,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint | |||
426 | 428 | ||
427 | switch (packet[0]) { | 429 | switch (packet[0]) { |
428 | case NET_PACKET_COOKIE_RESPONSE: { | 430 | case NET_PACKET_COOKIE_RESPONSE: { |
429 | if (conn->status != CRYPTO_CONN_COOKIE_REQUESTED) | 431 | if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) |
430 | return -1; | 432 | return -1; |
431 | 433 | ||
432 | uint8_t cookie[COOKIE_LENGTH]; | 434 | uint8_t cookie[COOKIE_LENGTH]; |
@@ -453,7 +455,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint | |||
453 | } | 455 | } |
454 | 456 | ||
455 | case NET_PACKET_CRYPTO_HS: { | 457 | case NET_PACKET_CRYPTO_HS: { |
456 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTED || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { | 458 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { |
457 | uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; | 459 | uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; |
458 | uint8_t cookie[COOKIE_LENGTH]; | 460 | uint8_t cookie[COOKIE_LENGTH]; |
459 | 461 | ||
@@ -489,6 +491,95 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint | |||
489 | return 0; | 491 | return 0; |
490 | } | 492 | } |
491 | 493 | ||
494 | /* Set the size of the friend list to numfriends. | ||
495 | * | ||
496 | * return -1 if realloc fails. | ||
497 | * return 0 if it succeeds. | ||
498 | */ | ||
499 | static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) | ||
500 | { | ||
501 | if (num == 0) { | ||
502 | free(c->crypto_connections); | ||
503 | c->crypto_connections = NULL; | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection)); | ||
508 | |||
509 | if (newcrypto_connections == NULL) | ||
510 | return -1; | ||
511 | |||
512 | c->crypto_connections = newcrypto_connections; | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | |||
517 | /* Create a new empty crypto connection. | ||
518 | * | ||
519 | * return -1 on failure. | ||
520 | * return connection id on success. | ||
521 | */ | ||
522 | static int create_crypto_connection(Net_Crypto *c) | ||
523 | { | ||
524 | uint32_t i; | ||
525 | |||
526 | for (i = 0; i <= c->crypto_connections_length; ++i) { | ||
527 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) | ||
528 | return i; | ||
529 | } | ||
530 | |||
531 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) | ||
532 | return -1; | ||
533 | |||
534 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | ||
535 | int id = c->crypto_connections_length; | ||
536 | ++c->crypto_connections_length; | ||
537 | return id; | ||
538 | } | ||
539 | |||
540 | /* Wipe a crypto connection. | ||
541 | * | ||
542 | * return -1 on failure. | ||
543 | * return 0 on success. | ||
544 | */ | ||
545 | static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) | ||
546 | { | ||
547 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
548 | return -1; | ||
549 | |||
550 | uint32_t i; | ||
551 | memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); | ||
552 | |||
553 | for (i = c->crypto_connections_length; i != 0; --i) { | ||
554 | if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) | ||
555 | break; | ||
556 | } | ||
557 | |||
558 | if (c->crypto_connections_length != i) { | ||
559 | c->crypto_connections_length = i; | ||
560 | realloc_cryptoconnection(c, c->crypto_connections_length); | ||
561 | } | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | /* Get crypto connection id from public key of peer. | ||
567 | * | ||
568 | * return -1 if there are no connections like we are looking for. | ||
569 | * return id if it found it. | ||
570 | */ | ||
571 | static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) | ||
572 | { | ||
573 | uint32_t i; | ||
574 | |||
575 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
576 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) | ||
577 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
578 | return i; | ||
579 | } | ||
580 | |||
581 | return -1; | ||
582 | } | ||
492 | 583 | ||
493 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), | 584 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), |
494 | void *object) | 585 | void *object) |
@@ -497,17 +588,136 @@ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void * | |||
497 | c->new_connection_callback_object = object; | 588 | c->new_connection_callback_object = object; |
498 | } | 589 | } |
499 | 590 | ||
500 | static int handle_new_connection_handshake(Net_Crypto *c, uint8_t *data, uint16_t length) | 591 | /* Handle a handshake packet by someone who wants to initiate a new connection with us. |
592 | * This calls the callback set by new_connection_handler() if the handshake is ok. | ||
593 | * | ||
594 | * return -1 on failure. | ||
595 | * return 0 on success. | ||
596 | */ | ||
597 | static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_t *data, uint16_t length) | ||
501 | { | 598 | { |
599 | New_Connection n_c; | ||
600 | n_c.cookie = malloc(COOKIE_LENGTH); | ||
502 | 601 | ||
602 | if (n_c.cookie == NULL) | ||
603 | return -1; | ||
604 | |||
605 | n_c.source = source; | ||
606 | n_c.cookie_length = COOKIE_LENGTH; | ||
607 | |||
608 | 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) | ||
610 | return -1; | ||
503 | 611 | ||
612 | return c->new_connection_callback(c->new_connection_callback_object, &n_c); | ||
504 | } | 613 | } |
505 | 614 | ||
615 | /* Accept a crypto connection. | ||
616 | * | ||
617 | * return -1 on failure. | ||
618 | * return connection id on success. | ||
619 | */ | ||
506 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) | 620 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) |
507 | { | 621 | { |
622 | //TODO: do something with n_c->source. | ||
623 | if (getcryptconnection_id(c, n_c->public_key) != -1) | ||
624 | return -1; | ||
625 | |||
626 | int crypt_connection_id = create_crypto_connection(c); | ||
627 | |||
628 | if (crypt_connection_id == -1) | ||
629 | return -1; | ||
630 | |||
631 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
632 | |||
633 | if (conn == 0) | ||
634 | return -1; | ||
635 | |||
636 | memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES); | ||
637 | memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES); | ||
638 | memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, crypto_box_PUBLICKEYBYTES); | ||
639 | random_nonce(conn->sent_nonce); | ||
640 | crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); | ||
641 | encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); | ||
642 | |||
643 | if (n_c->cookie_length != COOKIE_LENGTH) | ||
644 | return -1; | ||
645 | |||
646 | uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; | ||
647 | |||
648 | if (create_crypto_handshake(c, handshake_packet, n_c->cookie, conn->sent_nonce, conn->sessionpublic_key, | ||
649 | conn->public_key) != sizeof(handshake_packet)) | ||
650 | return -1; | ||
651 | |||
652 | if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) | ||
653 | return -1; | ||
654 | |||
655 | send_temp_packet(c, crypt_connection_id); | ||
656 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; | ||
657 | return crypt_connection_id; | ||
658 | } | ||
659 | |||
660 | /* Create a crypto connection. | ||
661 | * If one to that real public key already exists, return it. | ||
662 | * | ||
663 | * return -1 on failure. | ||
664 | * return connection id on success. | ||
665 | */ | ||
666 | int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) | ||
667 | { | ||
668 | int crypt_connection_id = getcryptconnection_id(c, real_public_key); | ||
669 | |||
670 | if (crypt_connection_id != -1) | ||
671 | return crypt_connection_id; | ||
672 | |||
673 | crypt_connection_id = create_crypto_connection(c); | ||
674 | |||
675 | if (crypt_connection_id == -1) | ||
676 | return -1; | ||
677 | |||
678 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
679 | |||
680 | if (conn == 0) | ||
681 | return -1; | ||
682 | |||
683 | memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES); | ||
684 | random_nonce(conn->sent_nonce); | ||
685 | crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); | ||
686 | conn->status = CRYPTO_CONN_COOKIE_REQUESTING; | ||
687 | return crypt_connection_id; | ||
688 | } | ||
689 | |||
690 | /* Set the DHT public key of the crypto connection. | ||
691 | * If one to that real public key already exists, return it. | ||
692 | * | ||
693 | * return -1 on failure. | ||
694 | * return 0 on success. | ||
695 | */ | ||
696 | int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) | ||
697 | { | ||
698 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
508 | 699 | ||
700 | if (conn == 0) | ||
701 | return -1; | ||
509 | 702 | ||
703 | memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); | ||
704 | conn->dht_public_key_set = 1; | ||
705 | |||
706 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { | ||
707 | conn->cookie_request_number = random_64b(); | ||
708 | uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; | ||
709 | |||
710 | if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->public_key, | ||
711 | conn->cookie_request_number) != sizeof(cookie_request)) | ||
712 | return -1; | ||
713 | |||
714 | if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) | ||
715 | return -1; | ||
716 | }//TODO | ||
717 | |||
718 | return 0; | ||
510 | } | 719 | } |
720 | |||
511 | /* return 0 if there is no received data in the buffer. | 721 | /* return 0 if there is no received data in the buffer. |
512 | * return -1 if the packet was discarded. | 722 | * return -1 if the packet was discarded. |
513 | * return length of received data if successful. | 723 | * return length of received data if successful. |
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 8dac937e..0d27ae4d 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h | |||
@@ -30,7 +30,7 @@ | |||
30 | #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) | 30 | #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) |
31 | 31 | ||
32 | #define CRYPTO_CONN_NO_CONNECTION 0 | 32 | #define CRYPTO_CONN_NO_CONNECTION 0 |
33 | #define CRYPTO_CONN_COOKIE_REQUESTED 1 //send cookie request packets | 33 | #define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets |
34 | #define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets | 34 | #define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets |
35 | #define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets | 35 | #define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets |
36 | #define CRYPTO_CONN_ESTABLISHED 4 | 36 | #define CRYPTO_CONN_ESTABLISHED 4 |
@@ -39,7 +39,7 @@ | |||
39 | #define CRYPTO_PACKET_BUFFER_SIZE 64 | 39 | #define CRYPTO_PACKET_BUFFER_SIZE 64 |
40 | 40 | ||
41 | #define MAX_CRYPTO_PACKET_SIZE 1400 | 41 | #define MAX_CRYPTO_PACKET_SIZE 1400 |
42 | 42 | #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) | |
43 | typedef struct { | 43 | typedef struct { |
44 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ | 44 | 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. */ | 45 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ |
@@ -58,6 +58,8 @@ typedef struct { | |||
58 | uint64_t timeout; | 58 | uint64_t timeout; |
59 | 59 | ||
60 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ | 60 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ |
61 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ | ||
62 | uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ | ||
61 | 63 | ||
62 | uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ | 64 | uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ |
63 | uint16_t temp_packet_length; | 65 | uint16_t temp_packet_length; |
@@ -65,6 +67,7 @@ typedef struct { | |||
65 | } Crypto_Connection; | 67 | } Crypto_Connection; |
66 | 68 | ||
67 | typedef struct { | 69 | typedef struct { |
70 | IP_Port source; | ||
68 | 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. */ |
69 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ | 72 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ |
70 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ | 73 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ |