diff options
-rw-r--r-- | src/cadet/gnunet-service-cadet_tunnel.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/src/cadet/gnunet-service-cadet_tunnel.c b/src/cadet/gnunet-service-cadet_tunnel.c index 9740e41d9..3a826a98c 100644 --- a/src/cadet/gnunet-service-cadet_tunnel.c +++ b/src/cadet/gnunet-service-cadet_tunnel.c | |||
@@ -104,7 +104,22 @@ struct CadetTunnelKXCtx | |||
104 | struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old; | 104 | struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old; |
105 | 105 | ||
106 | /** | 106 | /** |
107 | * Challenge to send in a ping and expect in the pong. | 107 | * Same as @c e_key_old, for the case of two simultaneous KX. |
108 | * This can happen if cadet decides to start a re-key while the peer has also | ||
109 | * started its re-key (due to network delay this is impossible to avoid). | ||
110 | * In this case, the key material generated with the peer's old ephemeral | ||
111 | * *might* (but doesn't have to) be incorrect. | ||
112 | * Since no more than two re-keys can happen simultaneously, this is enough. | ||
113 | */ | ||
114 | struct GNUNET_CRYPTO_SymmetricSessionKey e_key_old2; | ||
115 | |||
116 | /** | ||
117 | * Same as @c d_key_old, for the case described in @c e_key_old2. | ||
118 | */ | ||
119 | struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old2; | ||
120 | |||
121 | /** | ||
122 | * Challenge to send and expect in the PONG. | ||
108 | */ | 123 | */ |
109 | uint32_t challenge; | 124 | uint32_t challenge; |
110 | 125 | ||
@@ -799,27 +814,34 @@ t_decrypt_and_validate (struct CadetTunnel *t, | |||
799 | if (0 == memcmp (msg_hmac, &hmac, sizeof (hmac))) | 814 | if (0 == memcmp (msg_hmac, &hmac, sizeof (hmac))) |
800 | return decrypted_size; | 815 | return decrypted_size; |
801 | 816 | ||
802 | /* If no key exchange is going on, we just failed */ | 817 | /* If no key exchange is going on, we just failed. */ |
803 | if (NULL == t->kx_ctx) | 818 | if (NULL == t->kx_ctx) |
804 | { | 819 | { |
805 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 820 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
806 | "Failed checksum validation on tunnel %s with no KX\n", | 821 | "Failed checksum validation on tunnel %s with no KX\n", |
807 | GCT_2s (t)); | 822 | GCT_2s (t)); |
808 | GNUNET_STATISTICS_update (stats, "# wrong HMAC", 1, GNUNET_NO); | 823 | GNUNET_STATISTICS_update (stats, "# wrong HMAC no KX", 1, GNUNET_NO); |
809 | return -1; | 824 | return -1; |
810 | } | 825 | } |
811 | 826 | ||
812 | /* Try secondary (from previous KX period) key */ | 827 | /* Try secondary key, from previous KX period. */ |
813 | key = &t->kx_ctx->d_key_old; | 828 | key = &t->kx_ctx->d_key_old; |
814 | decrypted_size = decrypt (key, dst, src, size, iv); | 829 | decrypted_size = decrypt (key, dst, src, size, iv); |
815 | t_hmac (src, size, iv, key, &hmac); | 830 | t_hmac (src, size, iv, key, &hmac); |
816 | if (0 == memcmp (msg_hmac, &hmac, sizeof (hmac))) | 831 | if (0 == memcmp (msg_hmac, &hmac, sizeof (hmac))) |
817 | return decrypted_size; | 832 | return decrypted_size; |
818 | 833 | ||
819 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 834 | /* Hail Mary, try tertiary, key, in case of parallel re-keys. */ |
835 | key = &t->kx_ctx->d_key_old2; | ||
836 | decrypted_size = decrypt (key, dst, src, size, iv); | ||
837 | t_hmac (src, size, iv, key, &hmac); | ||
838 | if (0 == memcmp (msg_hmac, &hmac, sizeof (hmac))) | ||
839 | return decrypted_size; | ||
840 | |||
841 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
820 | "Failed checksum validation on tunnel %s with KX\n", | 842 | "Failed checksum validation on tunnel %s with KX\n", |
821 | GCT_2s (t)); | 843 | GCT_2s (t)); |
822 | GNUNET_STATISTICS_update (stats, "# wrong HMAC", 1, GNUNET_NO); | 844 | GNUNET_STATISTICS_update (stats, "# wrong HMAC with KX", 1, GNUNET_NO); |
823 | return -1; | 845 | return -1; |
824 | } | 846 | } |
825 | 847 | ||