diff options
author | irungentoo <irungentoo@gmail.com> | 2014-04-30 20:53:43 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-04-30 20:53:43 -0400 |
commit | 5715e5016940abab7009f093a7c0785440dd2de8 (patch) | |
tree | c4b2a8ab6dc7de83d07312adc420da88188eccc5 /toxcore/net_crypto.c | |
parent | 0505df009bc01ef7db6e31ee6ea999aaa83b8bfc (diff) |
Some more code written for the middle level protocol stuff.
Diffstat (limited to 'toxcore/net_crypto.c')
-rw-r--r-- | toxcore/net_crypto.c | 216 |
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 | */ | ||
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. |