diff options
author | Bart Polot <bart.polot+voyager@gmail.com> | 2017-01-27 17:05:54 +0100 |
---|---|---|
committer | Bart Polot <bart.polot+voyager@gmail.com> | 2017-01-27 17:05:54 +0100 |
commit | 1310298005df1c914d6c5d36c5f66a78fc8ebee9 (patch) | |
tree | 1e124a2b60c8afcd28409cbc95c4053862ffd059 /src/cadet | |
parent | 263e1a188460cc89c1341422a7338aaf0645b190 (diff) | |
parent | c93c2a94d0967e8159a22fd03e3ac7498c4c2907 (diff) | |
download | gnunet-1310298005df1c914d6c5d36c5f66a78fc8ebee9.tar.gz gnunet-1310298005df1c914d6c5d36c5f66a78fc8ebee9.zip |
Merge branch 'master' of git+ssh://gnunet.org/gnunet
Diffstat (limited to 'src/cadet')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_tunnels.c | 312 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_tunnels.h | 2 |
2 files changed, 211 insertions, 103 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet-new_tunnels.c index 020564d8e..10ff2867d 100644 --- a/src/cadet/gnunet-service-cadet-new_tunnels.c +++ b/src/cadet/gnunet-service-cadet-new_tunnels.c | |||
@@ -49,6 +49,12 @@ | |||
49 | 49 | ||
50 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) | 50 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) |
51 | 51 | ||
52 | /** | ||
53 | * How often do we try to decrypt payload with unverified key | ||
54 | * material? Used to limit CPU increase upon receiving bogus | ||
55 | * KX. | ||
56 | */ | ||
57 | #define MAX_UNVERIFIED_ATTEMPTS 16 | ||
52 | 58 | ||
53 | /** | 59 | /** |
54 | * How long do we wait until tearing down an idle tunnel? | 60 | * How long do we wait until tearing down an idle tunnel? |
@@ -293,6 +299,15 @@ struct CadetTunnel | |||
293 | struct CadetTunnelAxolotl ax; | 299 | struct CadetTunnelAxolotl ax; |
294 | 300 | ||
295 | /** | 301 | /** |
302 | * Unverified Axolotl info, used only if we got a fresh KX (not a | ||
303 | * KX_AUTH) while our end of the tunnel was still up. In this case, | ||
304 | * we keep the fresh KX around but do not put it into action until | ||
305 | * we got encrypted payload that assures us of the authenticity of | ||
306 | * the KX. | ||
307 | */ | ||
308 | struct CadetTunnelAxolotl *unverified_ax; | ||
309 | |||
310 | /** | ||
296 | * Task scheduled if there are no more channels using the tunnel. | 311 | * Task scheduled if there are no more channels using the tunnel. |
297 | */ | 312 | */ |
298 | struct GNUNET_SCHEDULER_Task *destroy_task; | 313 | struct GNUNET_SCHEDULER_Task *destroy_task; |
@@ -369,6 +384,13 @@ struct CadetTunnel | |||
369 | unsigned int num_connections; | 384 | unsigned int num_connections; |
370 | 385 | ||
371 | /** | 386 | /** |
387 | * How often have we tried and failed to decrypt a message using | ||
388 | * the unverified KX material from @e unverified_ax? Used to | ||
389 | * stop trying after #MAX_UNVERIFIED_ATTEMPTS. | ||
390 | */ | ||
391 | unsigned int unverified_attempts; | ||
392 | |||
393 | /** | ||
372 | * Number of entries in the @e tq_head DLL. | 394 | * Number of entries in the @e tq_head DLL. |
373 | */ | 395 | */ |
374 | unsigned int tq_len; | 396 | unsigned int tq_len; |
@@ -538,20 +560,6 @@ GCT_get_estate (struct CadetTunnel *t) | |||
538 | 560 | ||
539 | 561 | ||
540 | /** | 562 | /** |
541 | * Create a new Axolotl ephemeral (ratchet) key. | ||
542 | * | ||
543 | * @param t Tunnel. | ||
544 | */ | ||
545 | static void | ||
546 | new_ephemeral (struct CadetTunnel *t) | ||
547 | { | ||
548 | GNUNET_free_non_null (t->ax.DHRs); | ||
549 | t->ax.DHRs = GNUNET_CRYPTO_ecdhe_key_create (); | ||
550 | } | ||
551 | |||
552 | |||
553 | |||
554 | /** | ||
555 | * Called when either we have a new connection, or a new message in the | 563 | * Called when either we have a new connection, or a new message in the |
556 | * queue, or some existing connection has transmission capacity. Looks | 564 | * queue, or some existing connection has transmission capacity. Looks |
557 | * at our message queue and if there is a message, picks a connection | 565 | * at our message queue and if there is a message, picks a connection |
@@ -567,6 +575,19 @@ trigger_transmissions (void *cls); | |||
567 | 575 | ||
568 | 576 | ||
569 | /** | 577 | /** |
578 | * Create a new Axolotl ephemeral (ratchet) key. | ||
579 | * | ||
580 | * @param ax key material to update | ||
581 | */ | ||
582 | static void | ||
583 | new_ephemeral (struct CadetTunnelAxolotl *ax) | ||
584 | { | ||
585 | GNUNET_free_non_null (ax->DHRs); | ||
586 | ax->DHRs = GNUNET_CRYPTO_ecdhe_key_create (); | ||
587 | } | ||
588 | |||
589 | |||
590 | /** | ||
570 | * Calculate HMAC. | 591 | * Calculate HMAC. |
571 | * | 592 | * |
572 | * @param plaintext Content to HMAC. | 593 | * @param plaintext Content to HMAC. |
@@ -663,23 +684,21 @@ t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | |||
663 | /** | 684 | /** |
664 | * Encrypt data with the axolotl tunnel key. | 685 | * Encrypt data with the axolotl tunnel key. |
665 | * | 686 | * |
666 | * @param t Tunnel whose key to use. | 687 | * @param ax key material to use. |
667 | * @param dst Destination with @a size bytes for the encrypted data. | 688 | * @param dst Destination with @a size bytes for the encrypted data. |
668 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes | 689 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes |
669 | * @param size Size of the buffers at @a src and @a dst | 690 | * @param size Size of the buffers at @a src and @a dst |
670 | */ | 691 | */ |
671 | static void | 692 | static void |
672 | t_ax_encrypt (struct CadetTunnel *t, | 693 | t_ax_encrypt (struct CadetTunnelAxolotl *ax, |
673 | void *dst, | 694 | void *dst, |
674 | const void *src, | 695 | const void *src, |
675 | size_t size) | 696 | size_t size) |
676 | { | 697 | { |
677 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | 698 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; |
678 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 699 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
679 | struct CadetTunnelAxolotl *ax; | ||
680 | size_t out_size; | 700 | size_t out_size; |
681 | 701 | ||
682 | ax = &t->ax; | ||
683 | ax->ratchet_counter++; | 702 | ax->ratchet_counter++; |
684 | if ( (GNUNET_YES == ax->ratchet_allowed) && | 703 | if ( (GNUNET_YES == ax->ratchet_allowed) && |
685 | ( (ratchet_messages <= ax->ratchet_counter) || | 704 | ( (ratchet_messages <= ax->ratchet_counter) || |
@@ -695,7 +714,7 @@ t_ax_encrypt (struct CadetTunnel *t, | |||
695 | struct GNUNET_HashCode hmac; | 714 | struct GNUNET_HashCode hmac; |
696 | static const char ctx[] = "axolotl ratchet"; | 715 | static const char ctx[] = "axolotl ratchet"; |
697 | 716 | ||
698 | new_ephemeral (t); | 717 | new_ephemeral (ax); |
699 | ax->HKs = ax->NHKs; | 718 | ax->HKs = ax->NHKs; |
700 | 719 | ||
701 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ | 720 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ |
@@ -749,23 +768,21 @@ t_ax_encrypt (struct CadetTunnel *t, | |||
749 | /** | 768 | /** |
750 | * Decrypt data with the axolotl tunnel key. | 769 | * Decrypt data with the axolotl tunnel key. |
751 | * | 770 | * |
752 | * @param t Tunnel whose key to use. | 771 | * @param ax key material to use. |
753 | * @param dst Destination for the decrypted data, must contain @a size bytes. | 772 | * @param dst Destination for the decrypted data, must contain @a size bytes. |
754 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. | 773 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. |
755 | * @param size Size of the @a src and @a dst buffers | 774 | * @param size Size of the @a src and @a dst buffers |
756 | */ | 775 | */ |
757 | static void | 776 | static void |
758 | t_ax_decrypt (struct CadetTunnel *t, | 777 | t_ax_decrypt (struct CadetTunnelAxolotl *ax, |
759 | void *dst, | 778 | void *dst, |
760 | const void *src, | 779 | const void *src, |
761 | size_t size) | 780 | size_t size) |
762 | { | 781 | { |
763 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | 782 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; |
764 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 783 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
765 | struct CadetTunnelAxolotl *ax; | ||
766 | size_t out_size; | 784 | size_t out_size; |
767 | 785 | ||
768 | ax = &t->ax; | ||
769 | t_hmac_derive_key (&ax->CKr, | 786 | t_hmac_derive_key (&ax->CKr, |
770 | &MK, | 787 | &MK, |
771 | "0", | 788 | "0", |
@@ -791,18 +808,16 @@ t_ax_decrypt (struct CadetTunnel *t, | |||
791 | /** | 808 | /** |
792 | * Encrypt header with the axolotl header key. | 809 | * Encrypt header with the axolotl header key. |
793 | * | 810 | * |
794 | * @param t Tunnel whose key to use. | 811 | * @param ax key material to use. |
795 | * @param msg Message whose header to encrypt. | 812 | * @param msg Message whose header to encrypt. |
796 | */ | 813 | */ |
797 | static void | 814 | static void |
798 | t_h_encrypt (struct CadetTunnel *t, | 815 | t_h_encrypt (struct CadetTunnelAxolotl *ax, |
799 | struct GNUNET_CADET_TunnelEncryptedMessage *msg) | 816 | struct GNUNET_CADET_TunnelEncryptedMessage *msg) |
800 | { | 817 | { |
801 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 818 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
802 | struct CadetTunnelAxolotl *ax; | ||
803 | size_t out_size; | 819 | size_t out_size; |
804 | 820 | ||
805 | ax = &t->ax; | ||
806 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | 821 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, |
807 | &ax->HKs, | 822 | &ax->HKs, |
808 | NULL, 0, | 823 | NULL, 0, |
@@ -819,20 +834,18 @@ t_h_encrypt (struct CadetTunnel *t, | |||
819 | /** | 834 | /** |
820 | * Decrypt header with the current axolotl header key. | 835 | * Decrypt header with the current axolotl header key. |
821 | * | 836 | * |
822 | * @param t Tunnel whose current ax HK to use. | 837 | * @param ax key material to use. |
823 | * @param src Message whose header to decrypt. | 838 | * @param src Message whose header to decrypt. |
824 | * @param dst Where to decrypt header to. | 839 | * @param dst Where to decrypt header to. |
825 | */ | 840 | */ |
826 | static void | 841 | static void |
827 | t_h_decrypt (struct CadetTunnel *t, | 842 | t_h_decrypt (struct CadetTunnelAxolotl *ax, |
828 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | 843 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, |
829 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) | 844 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) |
830 | { | 845 | { |
831 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 846 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
832 | struct CadetTunnelAxolotl *ax; | ||
833 | size_t out_size; | 847 | size_t out_size; |
834 | 848 | ||
835 | ax = &t->ax; | ||
836 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | 849 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, |
837 | &ax->HKr, | 850 | &ax->HKr, |
838 | NULL, 0, | 851 | NULL, 0, |
@@ -849,18 +862,18 @@ t_h_decrypt (struct CadetTunnel *t, | |||
849 | /** | 862 | /** |
850 | * Delete a key from the list of skipped keys. | 863 | * Delete a key from the list of skipped keys. |
851 | * | 864 | * |
852 | * @param t Tunnel to delete from. | 865 | * @param ax key material to delete @a key from. |
853 | * @param key Key to delete. | 866 | * @param key Key to delete. |
854 | */ | 867 | */ |
855 | static void | 868 | static void |
856 | delete_skipped_key (struct CadetTunnel *t, | 869 | delete_skipped_key (struct CadetTunnelAxolotl *ax, |
857 | struct CadetTunnelSkippedKey *key) | 870 | struct CadetTunnelSkippedKey *key) |
858 | { | 871 | { |
859 | GNUNET_CONTAINER_DLL_remove (t->ax.skipped_head, | 872 | GNUNET_CONTAINER_DLL_remove (ax->skipped_head, |
860 | t->ax.skipped_tail, | 873 | ax->skipped_tail, |
861 | key); | 874 | key); |
862 | GNUNET_free (key); | 875 | GNUNET_free (key); |
863 | t->ax.skipped--; | 876 | ax->skipped--; |
864 | } | 877 | } |
865 | 878 | ||
866 | 879 | ||
@@ -868,14 +881,14 @@ delete_skipped_key (struct CadetTunnel *t, | |||
868 | * Decrypt and verify data with the appropriate tunnel key and verify that the | 881 | * Decrypt and verify data with the appropriate tunnel key and verify that the |
869 | * data has not been altered since it was sent by the remote peer. | 882 | * data has not been altered since it was sent by the remote peer. |
870 | * | 883 | * |
871 | * @param t Tunnel whose key to use. | 884 | * @param ax key material to use. |
872 | * @param dst Destination for the plaintext. | 885 | * @param dst Destination for the plaintext. |
873 | * @param src Source of the message. Can overlap with @c dst. | 886 | * @param src Source of the message. Can overlap with @c dst. |
874 | * @param size Size of the message. | 887 | * @param size Size of the message. |
875 | * @return Size of the decrypted data, -1 if an error was encountered. | 888 | * @return Size of the decrypted data, -1 if an error was encountered. |
876 | */ | 889 | */ |
877 | static ssize_t | 890 | static ssize_t |
878 | try_old_ax_keys (struct CadetTunnel *t, | 891 | try_old_ax_keys (struct CadetTunnelAxolotl *ax, |
879 | void *dst, | 892 | void *dst, |
880 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | 893 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, |
881 | size_t size) | 894 | size_t size) |
@@ -897,7 +910,7 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
897 | 910 | ||
898 | /* Find a correct Header Key */ | 911 | /* Find a correct Header Key */ |
899 | valid_HK = NULL; | 912 | valid_HK = NULL; |
900 | for (key = t->ax.skipped_head; NULL != key; key = key->next) | 913 | for (key = ax->skipped_head; NULL != key; key = key->next) |
901 | { | 914 | { |
902 | t_hmac (&src->ax_header, | 915 | t_hmac (&src->ax_header, |
903 | sizeof (struct GNUNET_CADET_AxHeader) + esize, | 916 | sizeof (struct GNUNET_CADET_AxHeader) + esize, |
@@ -954,7 +967,7 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
954 | &key->MK, | 967 | &key->MK, |
955 | &iv, | 968 | &iv, |
956 | dst); | 969 | dst); |
957 | delete_skipped_key (t, | 970 | delete_skipped_key (ax, |
958 | key); | 971 | key); |
959 | return res; | 972 | return res; |
960 | } | 973 | } |
@@ -963,32 +976,32 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
963 | /** | 976 | /** |
964 | * Delete a key from the list of skipped keys. | 977 | * Delete a key from the list of skipped keys. |
965 | * | 978 | * |
966 | * @param t Tunnel to delete from. | 979 | * @param ax key material to delete from. |
967 | * @param HKr Header Key to use. | 980 | * @param HKr Header Key to use. |
968 | */ | 981 | */ |
969 | static void | 982 | static void |
970 | store_skipped_key (struct CadetTunnel *t, | 983 | store_skipped_key (struct CadetTunnelAxolotl *ax, |
971 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) | 984 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) |
972 | { | 985 | { |
973 | struct CadetTunnelSkippedKey *key; | 986 | struct CadetTunnelSkippedKey *key; |
974 | 987 | ||
975 | key = GNUNET_new (struct CadetTunnelSkippedKey); | 988 | key = GNUNET_new (struct CadetTunnelSkippedKey); |
976 | key->timestamp = GNUNET_TIME_absolute_get (); | 989 | key->timestamp = GNUNET_TIME_absolute_get (); |
977 | key->Kn = t->ax.Nr; | 990 | key->Kn = ax->Nr; |
978 | key->HK = t->ax.HKr; | 991 | key->HK = ax->HKr; |
979 | t_hmac_derive_key (&t->ax.CKr, | 992 | t_hmac_derive_key (&ax->CKr, |
980 | &key->MK, | 993 | &key->MK, |
981 | "0", | 994 | "0", |
982 | 1); | 995 | 1); |
983 | t_hmac_derive_key (&t->ax.CKr, | 996 | t_hmac_derive_key (&ax->CKr, |
984 | &t->ax.CKr, | 997 | &ax->CKr, |
985 | "1", | 998 | "1", |
986 | 1); | 999 | 1); |
987 | GNUNET_CONTAINER_DLL_insert (t->ax.skipped_head, | 1000 | GNUNET_CONTAINER_DLL_insert (ax->skipped_head, |
988 | t->ax.skipped_tail, | 1001 | ax->skipped_tail, |
989 | key); | 1002 | key); |
990 | t->ax.skipped++; | 1003 | ax->skipped++; |
991 | t->ax.Nr++; | 1004 | ax->Nr++; |
992 | } | 1005 | } |
993 | 1006 | ||
994 | 1007 | ||
@@ -996,23 +1009,23 @@ store_skipped_key (struct CadetTunnel *t, | |||
996 | * Stage skipped AX keys and calculate the message key. | 1009 | * Stage skipped AX keys and calculate the message key. |
997 | * Stores each HK and MK for skipped messages. | 1010 | * Stores each HK and MK for skipped messages. |
998 | * | 1011 | * |
999 | * @param t Tunnel where to stage the keys. | 1012 | * @param ax key material to use |
1000 | * @param HKr Header key. | 1013 | * @param HKr Header key. |
1001 | * @param Np Received meesage number. | 1014 | * @param Np Received meesage number. |
1002 | * @return #GNUNET_OK if keys were stored. | 1015 | * @return #GNUNET_OK if keys were stored. |
1003 | * #GNUNET_SYSERR if an error ocurred (Np not expected). | 1016 | * #GNUNET_SYSERR if an error ocurred (Np not expected). |
1004 | */ | 1017 | */ |
1005 | static int | 1018 | static int |
1006 | store_ax_keys (struct CadetTunnel *t, | 1019 | store_ax_keys (struct CadetTunnelAxolotl *ax, |
1007 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | 1020 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, |
1008 | uint32_t Np) | 1021 | uint32_t Np) |
1009 | { | 1022 | { |
1010 | int gap; | 1023 | int gap; |
1011 | 1024 | ||
1012 | gap = Np - t->ax.Nr; | 1025 | gap = Np - ax->Nr; |
1013 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1026 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1014 | "Storing skipped keys [%u, %u)\n", | 1027 | "Storing skipped keys [%u, %u)\n", |
1015 | t->ax.Nr, | 1028 | ax->Nr, |
1016 | Np); | 1029 | Np); |
1017 | if (MAX_KEY_GAP < gap) | 1030 | if (MAX_KEY_GAP < gap) |
1018 | { | 1031 | { |
@@ -1022,7 +1035,7 @@ store_ax_keys (struct CadetTunnel *t, | |||
1022 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1035 | LOG (GNUNET_ERROR_TYPE_WARNING, |
1023 | "Got message %u, expected %u+\n", | 1036 | "Got message %u, expected %u+\n", |
1024 | Np, | 1037 | Np, |
1025 | t->ax.Nr); | 1038 | ax->Nr); |
1026 | return GNUNET_SYSERR; | 1039 | return GNUNET_SYSERR; |
1027 | } | 1040 | } |
1028 | if (0 > gap) | 1041 | if (0 > gap) |
@@ -1031,13 +1044,13 @@ store_ax_keys (struct CadetTunnel *t, | |||
1031 | return GNUNET_SYSERR; | 1044 | return GNUNET_SYSERR; |
1032 | } | 1045 | } |
1033 | 1046 | ||
1034 | while (t->ax.Nr < Np) | 1047 | while (ax->Nr < Np) |
1035 | store_skipped_key (t, | 1048 | store_skipped_key (ax, |
1036 | HKr); | 1049 | HKr); |
1037 | 1050 | ||
1038 | while (t->ax.skipped > MAX_SKIPPED_KEYS) | 1051 | while (ax->skipped > MAX_SKIPPED_KEYS) |
1039 | delete_skipped_key (t, | 1052 | delete_skipped_key (ax, |
1040 | t->ax.skipped_tail); | 1053 | ax->skipped_tail); |
1041 | return GNUNET_OK; | 1054 | return GNUNET_OK; |
1042 | } | 1055 | } |
1043 | 1056 | ||
@@ -1046,19 +1059,18 @@ store_ax_keys (struct CadetTunnel *t, | |||
1046 | * Decrypt and verify data with the appropriate tunnel key and verify that the | 1059 | * Decrypt and verify data with the appropriate tunnel key and verify that the |
1047 | * data has not been altered since it was sent by the remote peer. | 1060 | * data has not been altered since it was sent by the remote peer. |
1048 | * | 1061 | * |
1049 | * @param t Tunnel whose key to use. | 1062 | * @param ax key material to use |
1050 | * @param dst Destination for the plaintext. | 1063 | * @param dst Destination for the plaintext. |
1051 | * @param src Source of the message. Can overlap with @c dst. | 1064 | * @param src Source of the message. Can overlap with @c dst. |
1052 | * @param size Size of the message. | 1065 | * @param size Size of the message. |
1053 | * @return Size of the decrypted data, -1 if an error was encountered. | 1066 | * @return Size of the decrypted data, -1 if an error was encountered. |
1054 | */ | 1067 | */ |
1055 | static ssize_t | 1068 | static ssize_t |
1056 | t_ax_decrypt_and_validate (struct CadetTunnel *t, | 1069 | t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax, |
1057 | void *dst, | 1070 | void *dst, |
1058 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | 1071 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, |
1059 | size_t size) | 1072 | size_t size) |
1060 | { | 1073 | { |
1061 | struct CadetTunnelAxolotl *ax; | ||
1062 | struct GNUNET_ShortHashCode msg_hmac; | 1074 | struct GNUNET_ShortHashCode msg_hmac; |
1063 | struct GNUNET_HashCode hmac; | 1075 | struct GNUNET_HashCode hmac; |
1064 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | 1076 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; |
@@ -1067,7 +1079,6 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1067 | size_t esize; /* Size of encryped payload */ | 1079 | size_t esize; /* Size of encryped payload */ |
1068 | 1080 | ||
1069 | esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); | 1081 | esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); |
1070 | ax = &t->ax; | ||
1071 | 1082 | ||
1072 | /* Try current HK */ | 1083 | /* Try current HK */ |
1073 | t_hmac (&src->ax_header, | 1084 | t_hmac (&src->ax_header, |
@@ -1095,20 +1106,20 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1095 | sizeof (msg_hmac))) | 1106 | sizeof (msg_hmac))) |
1096 | { | 1107 | { |
1097 | /* Try the skipped keys, if that fails, we're out of luck. */ | 1108 | /* Try the skipped keys, if that fails, we're out of luck. */ |
1098 | return try_old_ax_keys (t, | 1109 | return try_old_ax_keys (ax, |
1099 | dst, | 1110 | dst, |
1100 | src, | 1111 | src, |
1101 | size); | 1112 | size); |
1102 | } | 1113 | } |
1103 | HK = ax->HKr; | 1114 | HK = ax->HKr; |
1104 | ax->HKr = ax->NHKr; | 1115 | ax->HKr = ax->NHKr; |
1105 | t_h_decrypt (t, | 1116 | t_h_decrypt (ax, |
1106 | src, | 1117 | src, |
1107 | &plaintext_header); | 1118 | &plaintext_header); |
1108 | Np = ntohl (plaintext_header.ax_header.Ns); | 1119 | Np = ntohl (plaintext_header.ax_header.Ns); |
1109 | PNp = ntohl (plaintext_header.ax_header.PNs); | 1120 | PNp = ntohl (plaintext_header.ax_header.PNs); |
1110 | DHRp = &plaintext_header.ax_header.DHRs; | 1121 | DHRp = &plaintext_header.ax_header.DHRs; |
1111 | store_ax_keys (t, | 1122 | store_ax_keys (ax, |
1112 | &HK, | 1123 | &HK, |
1113 | PNp); | 1124 | PNp); |
1114 | 1125 | ||
@@ -1134,25 +1145,25 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1134 | } | 1145 | } |
1135 | else | 1146 | else |
1136 | { | 1147 | { |
1137 | t_h_decrypt (t, | 1148 | t_h_decrypt (ax, |
1138 | src, | 1149 | src, |
1139 | &plaintext_header); | 1150 | &plaintext_header); |
1140 | Np = ntohl (plaintext_header.ax_header.Ns); | 1151 | Np = ntohl (plaintext_header.ax_header.Ns); |
1141 | PNp = ntohl (plaintext_header.ax_header.PNs); | 1152 | PNp = ntohl (plaintext_header.ax_header.PNs); |
1142 | } | 1153 | } |
1143 | if ( (Np != ax->Nr) && | 1154 | if ( (Np != ax->Nr) && |
1144 | (GNUNET_OK != store_ax_keys (t, | 1155 | (GNUNET_OK != store_ax_keys (ax, |
1145 | &ax->HKr, | 1156 | &ax->HKr, |
1146 | Np)) ) | 1157 | Np)) ) |
1147 | { | 1158 | { |
1148 | /* Try the skipped keys, if that fails, we're out of luck. */ | 1159 | /* Try the skipped keys, if that fails, we're out of luck. */ |
1149 | return try_old_ax_keys (t, | 1160 | return try_old_ax_keys (ax, |
1150 | dst, | 1161 | dst, |
1151 | src, | 1162 | src, |
1152 | size); | 1163 | size); |
1153 | } | 1164 | } |
1154 | 1165 | ||
1155 | t_ax_decrypt (t, | 1166 | t_ax_decrypt (ax, |
1156 | dst, | 1167 | dst, |
1157 | &src[1], | 1168 | &src[1], |
1158 | esize); | 1169 | esize); |
@@ -1229,13 +1240,14 @@ GCT_change_estate (struct CadetTunnel *t, | |||
1229 | * FIXME: does not take care of sender-authentication yet! | 1240 | * FIXME: does not take care of sender-authentication yet! |
1230 | * | 1241 | * |
1231 | * @param t Tunnel on which to send it. | 1242 | * @param t Tunnel on which to send it. |
1243 | * @param ax axolotl key context to use | ||
1232 | * @param force_reply Force the other peer to reply with a KX message. | 1244 | * @param force_reply Force the other peer to reply with a KX message. |
1233 | */ | 1245 | */ |
1234 | static void | 1246 | static void |
1235 | send_kx (struct CadetTunnel *t, | 1247 | send_kx (struct CadetTunnel *t, |
1248 | struct CadetTunnelAxolotl *ax, | ||
1236 | int force_reply) | 1249 | int force_reply) |
1237 | { | 1250 | { |
1238 | struct CadetTunnelAxolotl *ax = &t->ax; | ||
1239 | struct CadetTConnection *ct; | 1251 | struct CadetTConnection *ct; |
1240 | struct CadetConnection *cc; | 1252 | struct CadetConnection *cc; |
1241 | struct GNUNET_MQ_Envelope *env; | 1253 | struct GNUNET_MQ_Envelope *env; |
@@ -1280,9 +1292,26 @@ send_kx (struct CadetTunnel *t, | |||
1280 | 1292 | ||
1281 | 1293 | ||
1282 | /** | 1294 | /** |
1283 | * Handle KX message. | 1295 | * Cleanup state used by @a ax. |
1284 | * | 1296 | * |
1285 | * FIXME: sender-authentication in KX is missing! | 1297 | * @param ax state to free, but not memory of @a ax itself |
1298 | */ | ||
1299 | static void | ||
1300 | cleanup_ax (struct CadetTunnelAxolotl *ax) | ||
1301 | { | ||
1302 | while (NULL != ax->skipped_head) | ||
1303 | delete_skipped_key (ax, | ||
1304 | ax->skipped_head); | ||
1305 | GNUNET_assert (0 == ax->skipped); | ||
1306 | GNUNET_free_non_null (ax->kx_0); | ||
1307 | GNUNET_free_non_null (ax->DHRs); | ||
1308 | } | ||
1309 | |||
1310 | |||
1311 | /** | ||
1312 | * Handle KX message that lacks authentication (and which will thus | ||
1313 | * only be considered authenticated after we respond with our own | ||
1314 | * KX_AUTH and finally successfully decrypt payload). | ||
1286 | * | 1315 | * |
1287 | * @param ct connection/tunnel combo that received encrypted message | 1316 | * @param ct connection/tunnel combo that received encrypted message |
1288 | * @param msg the key exchange message | 1317 | * @param msg the key exchange message |
@@ -1292,13 +1321,36 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1292 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 1321 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) |
1293 | { | 1322 | { |
1294 | struct CadetTunnel *t = ct->t; | 1323 | struct CadetTunnel *t = ct->t; |
1295 | struct CadetTunnelAxolotl *ax = &t->ax; | 1324 | struct CadetTunnelAxolotl *ax; |
1296 | struct GNUNET_HashCode key_material[3]; | 1325 | struct GNUNET_HashCode key_material[3]; |
1297 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; | 1326 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; |
1298 | const char salt[] = "CADET Axolotl salt"; | 1327 | const char salt[] = "CADET Axolotl salt"; |
1299 | const struct GNUNET_PeerIdentity *pid; | 1328 | const struct GNUNET_PeerIdentity *pid; |
1300 | int am_I_alice; | 1329 | int am_I_alice; |
1301 | 1330 | ||
1331 | /* We only keep ONE unverified KX around, so if there is an existing one, | ||
1332 | clean it up. */ | ||
1333 | if (NULL != t->unverified_ax) | ||
1334 | { | ||
1335 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1336 | "Dropping old unverified KX state, got a fresh one.\n", | ||
1337 | t->unverified_attempts); | ||
1338 | cleanup_ax (t->unverified_ax); | ||
1339 | memset (t->unverified_ax, | ||
1340 | 0, | ||
1341 | sizeof (struct CadetTunnelAxolotl)); | ||
1342 | new_ephemeral (t->unverified_ax); | ||
1343 | t->unverified_ax->kx_0 = GNUNET_CRYPTO_ecdhe_key_create (); | ||
1344 | } | ||
1345 | else | ||
1346 | { | ||
1347 | t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl); | ||
1348 | new_ephemeral (t->unverified_ax); | ||
1349 | t->unverified_ax->kx_0 = GNUNET_CRYPTO_ecdhe_key_create (); | ||
1350 | } | ||
1351 | t->unverified_attempts = 0; | ||
1352 | ax = t->unverified_ax; | ||
1353 | |||
1302 | pid = GCP_get_id (t->destination); | 1354 | pid = GCP_get_id (t->destination); |
1303 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, | 1355 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, |
1304 | pid)) | 1356 | pid)) |
@@ -1320,6 +1372,7 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1320 | t->kx_task = NULL; | 1372 | t->kx_task = NULL; |
1321 | } | 1373 | } |
1322 | send_kx (t, | 1374 | send_kx (t, |
1375 | ax, | ||
1323 | GNUNET_NO); | 1376 | GNUNET_NO); |
1324 | } | 1377 | } |
1325 | 1378 | ||
@@ -1585,12 +1638,12 @@ destroy_tunnel (void *cls) | |||
1585 | } | 1638 | } |
1586 | GNUNET_MST_destroy (t->mst); | 1639 | GNUNET_MST_destroy (t->mst); |
1587 | GNUNET_MQ_destroy (t->mq); | 1640 | GNUNET_MQ_destroy (t->mq); |
1588 | while (NULL != t->ax.skipped_head) | 1641 | cleanup_ax (&t->ax); |
1589 | delete_skipped_key (t, | 1642 | if (NULL != t->unverified_ax) |
1590 | t->ax.skipped_head); | 1643 | { |
1591 | GNUNET_assert (0 == t->ax.skipped); | 1644 | cleanup_ax (t->unverified_ax); |
1592 | GNUNET_free_non_null (t->ax.kx_0); | 1645 | GNUNET_free (t->unverified_ax); |
1593 | GNUNET_free_non_null (t->ax.DHRs); | 1646 | } |
1594 | GNUNET_free (t); | 1647 | GNUNET_free (t); |
1595 | } | 1648 | } |
1596 | 1649 | ||
@@ -1680,6 +1733,7 @@ retry_kx (void *cls) | |||
1680 | 1733 | ||
1681 | t->kx_task = NULL; | 1734 | t->kx_task = NULL; |
1682 | send_kx (t, | 1735 | send_kx (t, |
1736 | &t->ax, | ||
1683 | ( (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || | 1737 | ( (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || |
1684 | (CADET_TUNNEL_KEY_SENT == t->estate) ) | 1738 | (CADET_TUNNEL_KEY_SENT == t->estate) ) |
1685 | ? GNUNET_YES | 1739 | ? GNUNET_YES |
@@ -1765,6 +1819,7 @@ connection_ready_cb (void *cls, | |||
1765 | { | 1819 | { |
1766 | case CADET_TUNNEL_KEY_UNINITIALIZED: | 1820 | case CADET_TUNNEL_KEY_UNINITIALIZED: |
1767 | send_kx (t, | 1821 | send_kx (t, |
1822 | &t->ax, | ||
1768 | GNUNET_YES); | 1823 | GNUNET_YES); |
1769 | break; | 1824 | break; |
1770 | case CADET_TUNNEL_KEY_SENT: | 1825 | case CADET_TUNNEL_KEY_SENT: |
@@ -1784,6 +1839,7 @@ connection_ready_cb (void *cls, | |||
1784 | break; | 1839 | break; |
1785 | case CADET_TUNNEL_KEY_REKEY: | 1840 | case CADET_TUNNEL_KEY_REKEY: |
1786 | send_kx (t, | 1841 | send_kx (t, |
1842 | &t->ax, | ||
1787 | GNUNET_NO); | 1843 | GNUNET_NO); |
1788 | t->estate = CADET_TUNNEL_KEY_OK; | 1844 | t->estate = CADET_TUNNEL_KEY_OK; |
1789 | break; | 1845 | break; |
@@ -2276,7 +2332,7 @@ GCT_create_tunnel (struct CadetPeer *destination) | |||
2276 | GNUNET_MQ_handler_end () | 2332 | GNUNET_MQ_handler_end () |
2277 | }; | 2333 | }; |
2278 | 2334 | ||
2279 | new_ephemeral (t); | 2335 | new_ephemeral (&t->ax); |
2280 | t->ax.kx_0 = GNUNET_CRYPTO_ecdhe_key_create (); | 2336 | t->ax.kx_0 = GNUNET_CRYPTO_ecdhe_key_create (); |
2281 | t->destination = destination; | 2337 | t->destination = destination; |
2282 | t->channels = GNUNET_CONTAINER_multihashmap32_create (8); | 2338 | t->channels = GNUNET_CONTAINER_multihashmap32_create (8); |
@@ -2397,13 +2453,70 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
2397 | "# received encrypted", | 2453 | "# received encrypted", |
2398 | 1, | 2454 | 1, |
2399 | GNUNET_NO); | 2455 | GNUNET_NO); |
2400 | decrypted_size = t_ax_decrypt_and_validate (t, | 2456 | decrypted_size = -1; |
2401 | cbuf, | 2457 | if ( (CADET_TUNNEL_KEY_OK == t->estate) || |
2402 | msg, | 2458 | (CADET_TUNNEL_KEY_REKEY == t->estate) ) |
2403 | size); | 2459 | { |
2460 | /* We have well-established key material available, | ||
2461 | try that. (This is the common case.) */ | ||
2462 | decrypted_size = t_ax_decrypt_and_validate (&t->ax, | ||
2463 | cbuf, | ||
2464 | msg, | ||
2465 | size); | ||
2466 | } | ||
2467 | |||
2468 | if ( (-1 == decrypted_size) && | ||
2469 | (NULL != t->unverified_ax) ) | ||
2470 | { | ||
2471 | /* We have un-authenticated KX material available. We should try | ||
2472 | this as a back-up option, in case the sender crashed and | ||
2473 | switched keys. */ | ||
2474 | decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax, | ||
2475 | cbuf, | ||
2476 | msg, | ||
2477 | size); | ||
2478 | if (-1 != decrypted_size) | ||
2479 | { | ||
2480 | /* It worked! Treat this as authentication of the AX data! */ | ||
2481 | cleanup_ax (&t->ax); | ||
2482 | t->ax = *t->unverified_ax; | ||
2483 | GNUNET_free (t->unverified_ax); | ||
2484 | t->unverified_ax = NULL; | ||
2485 | } | ||
2486 | if (CADET_TUNNEL_KEY_PING == t->estate) | ||
2487 | { | ||
2488 | /* First time it worked, move tunnel into production! */ | ||
2489 | GCT_change_estate (t, | ||
2490 | CADET_TUNNEL_KEY_OK); | ||
2491 | if (NULL != t->send_task) | ||
2492 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
2493 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
2494 | t); | ||
2495 | } | ||
2496 | } | ||
2497 | if (NULL != t->unverified_ax) | ||
2498 | { | ||
2499 | /* We had unverified KX material that was useless; so increment | ||
2500 | counter and eventually move to ignore it. Note that we even do | ||
2501 | this increment if we successfully decrypted with the old KX | ||
2502 | material and thus didn't even both with the new one. This is | ||
2503 | the ideal case, as a malicious injection of bogus KX data | ||
2504 | basically only causes us to increment a counter a few times. */ | ||
2505 | t->unverified_attempts++; | ||
2506 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2507 | "Failed to decrypt message with unverified KX data %u times\n", | ||
2508 | t->unverified_attempts); | ||
2509 | if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS) | ||
2510 | { | ||
2511 | cleanup_ax (t->unverified_ax); | ||
2512 | GNUNET_free (t->unverified_ax); | ||
2513 | t->unverified_ax = NULL; | ||
2514 | } | ||
2515 | } | ||
2404 | 2516 | ||
2405 | if (-1 == decrypted_size) | 2517 | if (-1 == decrypted_size) |
2406 | { | 2518 | { |
2519 | /* Decryption failed for good, complain. */ | ||
2407 | GNUNET_break_op (0); | 2520 | GNUNET_break_op (0); |
2408 | LOG (GNUNET_ERROR_TYPE_WARNING, | 2521 | LOG (GNUNET_ERROR_TYPE_WARNING, |
2409 | "Tunnel %s failed to decrypt and validate encrypted data\n", | 2522 | "Tunnel %s failed to decrypt and validate encrypted data\n", |
@@ -2414,15 +2527,7 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
2414 | GNUNET_NO); | 2527 | GNUNET_NO); |
2415 | return; | 2528 | return; |
2416 | } | 2529 | } |
2417 | if (CADET_TUNNEL_KEY_PING == t->estate) | 2530 | |
2418 | { | ||
2419 | GCT_change_estate (t, | ||
2420 | CADET_TUNNEL_KEY_OK); | ||
2421 | if (NULL != t->send_task) | ||
2422 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
2423 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
2424 | t); | ||
2425 | } | ||
2426 | /* The MST will ultimately call #handle_decrypted() on each message. */ | 2531 | /* The MST will ultimately call #handle_decrypted() on each message. */ |
2427 | GNUNET_break_op (GNUNET_OK == | 2532 | GNUNET_break_op (GNUNET_OK == |
2428 | GNUNET_MST_from_buffer (t->mst, | 2533 | GNUNET_MST_from_buffer (t->mst, |
@@ -2441,7 +2546,7 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
2441 | * @param t Tunnel on which this message is transmitted. | 2546 | * @param t Tunnel on which this message is transmitted. |
2442 | * @param cont Continuation to call once message is really sent. | 2547 | * @param cont Continuation to call once message is really sent. |
2443 | * @param cont_cls Closure for @c cont. | 2548 | * @param cont_cls Closure for @c cont. |
2444 | * @return Handle to cancel message. NULL if @c cont is NULL. | 2549 | * @return Handle to cancel message |
2445 | */ | 2550 | */ |
2446 | struct CadetTunnelQueueEntry * | 2551 | struct CadetTunnelQueueEntry * |
2447 | GCT_send (struct CadetTunnel *t, | 2552 | GCT_send (struct CadetTunnel *t, |
@@ -2454,6 +2559,12 @@ GCT_send (struct CadetTunnel *t, | |||
2454 | struct GNUNET_MQ_Envelope *env; | 2559 | struct GNUNET_MQ_Envelope *env; |
2455 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; | 2560 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; |
2456 | 2561 | ||
2562 | if ( (CADET_TUNNEL_KEY_OK != t->estate) && | ||
2563 | (CADET_TUNNEL_KEY_REKEY != t->estate) ) | ||
2564 | { | ||
2565 | GNUNET_break (0); | ||
2566 | return NULL; | ||
2567 | } | ||
2457 | payload_size = ntohs (message->size); | 2568 | payload_size = ntohs (message->size); |
2458 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2569 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2459 | "Encrypting %u bytes for tunnel %s\n", | 2570 | "Encrypting %u bytes for tunnel %s\n", |
@@ -2462,7 +2573,7 @@ GCT_send (struct CadetTunnel *t, | |||
2462 | env = GNUNET_MQ_msg_extra (ax_msg, | 2573 | env = GNUNET_MQ_msg_extra (ax_msg, |
2463 | payload_size, | 2574 | payload_size, |
2464 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); | 2575 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); |
2465 | t_ax_encrypt (t, | 2576 | t_ax_encrypt (&t->ax, |
2466 | &ax_msg[1], | 2577 | &ax_msg[1], |
2467 | message, | 2578 | message, |
2468 | payload_size); | 2579 | payload_size); |
@@ -2470,7 +2581,7 @@ GCT_send (struct CadetTunnel *t, | |||
2470 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); | 2581 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); |
2471 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs, | 2582 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs, |
2472 | &ax_msg->ax_header.DHRs); | 2583 | &ax_msg->ax_header.DHRs); |
2473 | t_h_encrypt (t, | 2584 | t_h_encrypt (&t->ax, |
2474 | ax_msg); | 2585 | ax_msg); |
2475 | t_hmac (&ax_msg->ax_header, | 2586 | t_hmac (&ax_msg->ax_header, |
2476 | sizeof (struct GNUNET_CADET_AxHeader) + payload_size, | 2587 | sizeof (struct GNUNET_CADET_AxHeader) + payload_size, |
@@ -2649,9 +2760,6 @@ GCT_debug (const struct CadetTunnel *t, | |||
2649 | estate2s (t->estate), | 2760 | estate2s (t->estate), |
2650 | t->tq_len, | 2761 | t->tq_len, |
2651 | t->num_connections); | 2762 | t->num_connections); |
2652 | #if DUMP_KEYS_TO_STDERR | ||
2653 | ax_debug (t->ax, level); | ||
2654 | #endif | ||
2655 | LOG2 (level, | 2763 | LOG2 (level, |
2656 | "TTT channels:\n"); | 2764 | "TTT channels:\n"); |
2657 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | 2765 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, |
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.h b/src/cadet/gnunet-service-cadet-new_tunnels.h index 463780686..080de0fc3 100644 --- a/src/cadet/gnunet-service-cadet-new_tunnels.h +++ b/src/cadet/gnunet-service-cadet-new_tunnels.h | |||
@@ -200,7 +200,7 @@ GCT_send_channel_destroy (struct CadetTunnel *t, | |||
200 | * @param t Tunnel on which this message is transmitted. | 200 | * @param t Tunnel on which this message is transmitted. |
201 | * @param cont Continuation to call once message is really sent. | 201 | * @param cont Continuation to call once message is really sent. |
202 | * @param cont_cls Closure for @c cont. | 202 | * @param cont_cls Closure for @c cont. |
203 | * @return Handle to cancel message. NULL if @c cont is NULL. | 203 | * @return Handle to cancel message. |
204 | */ | 204 | */ |
205 | struct CadetTunnelQueueEntry * | 205 | struct CadetTunnelQueueEntry * |
206 | GCT_send (struct CadetTunnel *t, | 206 | GCT_send (struct CadetTunnel *t, |