summaryrefslogtreecommitdiff
path: root/toxcore/net_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/net_crypto.c')
-rw-r--r--toxcore/net_crypto.c216
1 files changed, 213 insertions, 3 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 */
499static 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 */
522static 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 */
545static 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 */
571static 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
493void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), 584void 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
500static 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 */
597static 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 */
506int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) 620int 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 */
666int 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 */
696int 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.