diff options
Diffstat (limited to 'src/core/gnunet-service-core_kx.c')
-rw-r--r-- | src/core/gnunet-service-core_kx.c | 326 |
1 files changed, 249 insertions, 77 deletions
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c index c2acc6b..1fce2e5 100644 --- a/src/core/gnunet-service-core_kx.c +++ b/src/core/gnunet-service-core_kx.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -37,6 +37,12 @@ #include "gnunet_protocols.h" #include "core.h" + +/** + * Set to GNUNET_YES to perform some slightly expensive internal invariant checks. + */ +#define EXTRA_CHECKS GNUNET_YES + /** * How long do we wait for SET_KEY confirmation initially? */ @@ -48,6 +54,12 @@ #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** + * How often do we rekey? + */ +#define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 90) + + +/** * What is the maximum age of a message for us to consider processing * it? Note that this looks at the timestamp used by the other peer, * so clock skew between machines does come into play here. So this @@ -216,6 +228,8 @@ struct EncryptedMessage }; GNUNET_NETWORK_STRUCT_END + + /** * Number of bytes (at the beginning) of "struct EncryptedMessage" * that are NOT encrypted. @@ -253,7 +267,19 @@ enum KxStateMachine * encrypted with his session key (which we got). Key exchange * is done. */ - KX_STATE_UP + KX_STATE_UP, + + /** + * We're rekeying, so we have received the other peer's session + * key, but he didn't get ours yet. + */ + KX_STATE_REKEY, + + /** + * We're rekeying but have not yet received confirmation for our new + * key from the other peer. + */ + KX_STATE_REKEY_SENT }; @@ -391,7 +417,6 @@ struct GSC_KeyExchangeInfo }; - /** * Handle to peerinfo service. */ @@ -413,9 +438,45 @@ static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; static struct GNUNET_SERVER_MessageStreamTokenizer *mst; +#if EXTRA_CHECKS +/** + * Check internal invariants of the given KX record. + * + * @param kx record to check + * @param file filename for error reporting + * @param line line number for error reporting + */ +static void +check_kx_record (struct GSC_KeyExchangeInfo *kx, + const char *file, + int line) +{ + struct GNUNET_HashCode hc; + + if (NULL == kx->public_key) + return; + GNUNET_CRYPTO_hash (kx->public_key, sizeof (*kx->public_key), &hc); + GNUNET_assert_at (0 == memcmp (&hc, &kx->peer, sizeof (struct GNUNET_HashCode)), file, line); +} + + +/** + * Check internal invariants of the given KX record. + * + * @param kx record to check + */ +#define CHECK_KX(kx) check_kx_record(kx, __FILE__, __LINE__) +#else +#define CHECK_KX(kx) +#endif /** * Derive an authentication key from "set key" information + * + * @param akey authentication key to derive + * @param skey session key to use + * @param seed seed to use + * @param creation_time creation time to use */ static void derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, @@ -425,7 +486,6 @@ derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, static const char ctx[] = "authentication key"; struct GNUNET_TIME_AbsoluteNBO ctbe; - ctbe = GNUNET_TIME_absolute_hton (creation_time); GNUNET_CRYPTO_hmac_derive_key (akey, skey, &seed, sizeof (seed), &skey->key, sizeof (skey->key), &ctbe, sizeof (ctbe), ctx, @@ -435,6 +495,11 @@ derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, /** * Derive an IV from packet information + * + * @param iv initialization vector to initialize + * @param skey session key to use + * @param seed seed to use + * @param identity identity of the other peer to use */ static void derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv, @@ -449,8 +514,15 @@ derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv, sizeof (ctx), NULL); } + /** * Derive an IV from pong packet information + * + * @param iv initialization vector to initialize + * @param skey session key to use + * @param seed seed to use + * @param challenge nonce to use + * @param identity identity of the other peer to use */ static void derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv, @@ -492,7 +564,9 @@ do_encrypt (struct GSC_KeyExchangeInfo *kx, &kx->encrypt_key, iv, out)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes encrypted"), size, GNUNET_NO); -#if DEBUG_CORE > 2 + /* the following is too sensitive to write to log files by accident, + so we require manual intervention to get this one... */ +#if 0 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for `%4s' using key %u, IV %u\n", (unsigned int) size, GNUNET_i2s (&kx->peer), @@ -504,8 +578,6 @@ do_encrypt (struct GSC_KeyExchangeInfo *kx, } - - /** * Decrypt size bytes from in and write the result to out. Use the * key for inbound traffic of the given neighbour. This function does @@ -528,7 +600,9 @@ do_decrypt (struct GSC_KeyExchangeInfo *kx, GNUNET_break (0); return GNUNET_NO; } - if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP)) + if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && + (kx->status != KX_STATE_REKEY_SENT) && + (kx->status != KX_STATE_REKEY) ) { GNUNET_break_op (0); return GNUNET_SYSERR; @@ -542,7 +616,9 @@ do_decrypt (struct GSC_KeyExchangeInfo *kx, } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes decrypted"), size, GNUNET_NO); -#if DEBUG_CORE > 1 + /* the following is too sensitive to write to log files by accident, + so we require manual intervention to get this one... */ +#if 0 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypted %u bytes from `%4s' using key %u, IV %u\n", (unsigned int) size, GNUNET_i2s (&kx->peer), @@ -598,36 +674,40 @@ process_hello (void *cls, const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx = cls; struct SetKeyMessage *skm; - if (err_msg != NULL) + CHECK_KX (kx); + if (NULL != err_msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Error in communication with PEERINFO service\n")); kx->pitr = NULL; + if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) + GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); kx->retry_set_key_task = GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, &set_key_retry_task, kx); return; } - if (peer == NULL) + if (NULL == peer) { kx->pitr = NULL; - if (kx->public_key != NULL) + if (NULL != kx->public_key) return; /* done here */ -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n", GNUNET_i2s (&kx->peer)); -#endif GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# Delayed connecting due to lack of public key"), 1, GNUNET_NO); + if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) + GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); kx->retry_set_key_task = GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, &set_key_retry_task, kx); return; } - if (kx->public_key != NULL) + GNUNET_break (0 == memcmp (peer, &kx->peer, sizeof (struct GNUNET_PeerIdentity))); + if (NULL != kx->public_key) { /* already have public key, why are we here? */ GNUNET_break (0); @@ -641,8 +721,10 @@ process_hello (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_break (0); GNUNET_free (kx->public_key); kx->public_key = NULL; + CHECK_KX (kx); return; } + CHECK_KX (kx); send_key (kx); if (NULL != kx->skm_received) { @@ -665,10 +747,8 @@ GSC_KX_start (const struct GNUNET_PeerIdentity *pid) { struct GSC_KeyExchangeInfo *kx; -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initiating key exchange with `%s'\n", GNUNET_i2s (pid)); -#endif GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges initiated"), 1, GNUNET_NO); @@ -679,6 +759,7 @@ GSC_KX_start (const struct GNUNET_PeerIdentity *pid) GNUNET_PEERINFO_iterate (peerinfo, pid, GNUNET_TIME_UNIT_FOREVER_REL /* timeout? */ , &process_hello, kx); + CHECK_KX (kx); return kx; } @@ -693,7 +774,7 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges stopped"), 1, GNUNET_NO); - if (kx->pitr != NULL) + if (NULL != kx->pitr) { GNUNET_PEERINFO_iterate_cancel (kx->pitr); kx->pitr = NULL; @@ -735,7 +816,8 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, struct PongMessage *pong; enum KxStateMachine sender_status; uint16_t size; - + + CHECK_KX (kx); size = ntohs (msg->size); if (size != sizeof (struct SetKeyMessage)) { @@ -746,12 +828,10 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# session keys received"), 1, GNUNET_NO); -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' request from `%4s'.\n", "SET_KEY", GNUNET_i2s (&kx->peer)); -#endif - if (kx->public_key == NULL) + if (NULL == kx->public_key) { GNUNET_free_non_null (kx->skm_received); kx->skm_received = (struct SetKeyMessage *) GNUNET_copy_message (msg); @@ -776,6 +856,7 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, &m->signature, kx->public_key))) { /* invalid signature */ + CHECK_KX (kx); GNUNET_break_op (0); return; } @@ -796,16 +877,20 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k))) { /* failed to decrypt !? */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid key %x decrypted by %s from message %u (origin: %s)\n", + (unsigned int) GNUNET_CRYPTO_crc32_n (&k, sizeof (struct GNUNET_CRYPTO_AesSessionKey)), + GNUNET_i2s (&GSC_my_identity), + (unsigned int) GNUNET_CRYPTO_crc32_n (&m->encrypted_key, sizeof (struct GNUNET_CRYPTO_RsaEncryptedData)), + GNUNET_h2s (&kx->peer.hashPubKey)); GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# SET_KEY messages decrypted"), 1, GNUNET_NO); -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received SET_KEY from `%s'\n", GNUNET_i2s (&kx->peer)); -#endif kx->decrypt_key = k; if (kx->decrypt_key_created.abs_value != t.abs_value) { @@ -815,7 +900,6 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, kx->decrypt_key_created = t; } sender_status = (enum KxStateMachine) ntohl (m->sender_status); - switch (kx->status) { case KX_STATE_DOWN: @@ -829,7 +913,17 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, case KX_STATE_KEY_RECEIVED: /* we're not up, so we are already doing 'send_key' */ break; - case KX_STATE_UP: + case KX_STATE_UP: + if ((sender_status == KX_STATE_DOWN) || + (sender_status == KX_STATE_KEY_SENT)) + send_key (kx); /* we are up, but other peer is not! */ + break; + case KX_STATE_REKEY: + if ((sender_status == KX_STATE_DOWN) || + (sender_status == KX_STATE_KEY_SENT)) + send_key (kx); /* we are up, but other peer is not! */ + break; + case KX_STATE_REKEY_SENT: if ((sender_status == KX_STATE_DOWN) || (sender_status == KX_STATE_KEY_SENT)) send_key (kx); /* we are up, but other peer is not! */ @@ -838,14 +932,14 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, GNUNET_break (0); break; } - if (kx->ping_received != NULL) + if (NULL != kx->ping_received) { ping = kx->ping_received; kx->ping_received = NULL; GSC_KX_handle_ping (kx, &ping->header); GNUNET_free (ping); } - if (kx->pong_received != NULL) + if (NULL != kx->pong_received) { pong = kx->pong_received; kx->pong_received = NULL; @@ -882,7 +976,8 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO); - if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP)) + if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && + (kx->status != KX_STATE_REKEY_SENT)) { /* defer */ GNUNET_free_non_null (kx->ping_received); @@ -890,11 +985,9 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, return; } m = (const struct PingMessage *) msg; -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' request from `%4s'.\n", "PING", GNUNET_i2s (&kx->peer)); -#endif derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity); if (GNUNET_OK != do_decrypt (kx, &iv, &m->target, &t.target, @@ -919,10 +1012,8 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, GNUNET_break_op (0); return; } -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PING from `%s'\n", GNUNET_i2s (&kx->peer)); -#endif /* construct PONG */ tx.reserved = GNUNET_BANDWIDTH_VALUE_MAX; tx.challenge = t.challenge; @@ -966,12 +1057,20 @@ setup_fresh_setkey (struct GSC_KeyExchangeInfo *kx) skm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY); skm->creation_time = GNUNET_TIME_absolute_hton (kx->encrypt_key_created); skm->target = kx->peer; + CHECK_KX (kx); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_rsa_encrypt (&kx->encrypt_key, sizeof (struct GNUNET_CRYPTO_AesSessionKey), kx->public_key, &skm->encrypted_key)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Encrypting key %x for %s resulting in message %u (origin: %s)\n", + (unsigned int) GNUNET_CRYPTO_crc32_n (&kx->encrypt_key, sizeof (struct GNUNET_CRYPTO_AesSessionKey)), + GNUNET_i2s (&kx->peer), + (unsigned int) GNUNET_CRYPTO_crc32_n (&skm->encrypted_key, sizeof (struct GNUNET_CRYPTO_RsaEncryptedData)), + GNUNET_h2s (&GSC_my_identity.hashPubKey)); + GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_rsa_sign (my_private_key, &skm->purpose, &skm->signature)); @@ -1020,19 +1119,18 @@ send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; left = GNUNET_TIME_absolute_get_remaining (kx->timeout); - if (left.rel_value == 0) + if (0 == left.rel_value) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# sessions terminated by timeout"), 1, GNUNET_NO); GSC_SESSIONS_end (&kx->peer); kx->status = KX_STATE_DOWN; + send_key (kx); return; } -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending KEEPALIVE to `%s'\n", GNUNET_i2s (&kx->peer)); -#endif GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# keepalive messages sent"), 1, GNUNET_NO); @@ -1070,6 +1168,49 @@ update_timeout (struct GSC_KeyExchangeInfo *kx) /** + * Trigger rekeying event. + * + * @param cls the 'struct GSC_KeyExchangeInfo' + * @param tc schedule context (unused) + */ +static void +trigger_rekey (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GSC_KeyExchangeInfo *kx = cls; + + GNUNET_break (KX_STATE_UP == kx->status); + kx->status = KX_STATE_REKEY; + kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY; + kx->retry_set_key_task = + GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, + &set_key_retry_task, kx); +} + + +/** + * Schedule rekey operation. + * + * @param kx key exchange to schedule rekey for + */ +static void +schedule_rekey (struct GSC_KeyExchangeInfo *kx) +{ + struct GNUNET_TIME_Relative rdelay; + + if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) + GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); + rdelay = REKEY_FREQUENCY; + /* randomize rekey frequency by one minute to avoid synchronization */ + rdelay.rel_value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, + 60 * 1000); + kx->retry_set_key_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, + &trigger_rekey, + kx); +} + + +/** * We received a PONG message. Validate and update our status. * * @param kx key exchange context for the the PONG @@ -1086,7 +1227,7 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, uint16_t msize; msize = ntohs (msg->size); - if (msize != sizeof (struct PongMessage)) + if (sizeof (struct PongMessage) != msize) { GNUNET_break_op (0); return; @@ -1094,21 +1235,30 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO); - if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP)) + switch (kx->status) { - if (kx->status == KX_STATE_KEY_SENT) - { - GNUNET_free_non_null (kx->pong_received); - kx->pong_received = (struct PongMessage *) GNUNET_copy_message (msg); - } + case KX_STATE_DOWN: + return; + case KX_STATE_KEY_SENT: + GNUNET_free_non_null (kx->pong_received); + kx->pong_received = (struct PongMessage *) GNUNET_copy_message (msg); + return; + case KX_STATE_KEY_RECEIVED: + break; + case KX_STATE_UP: + break; + case KX_STATE_REKEY: + break; + case KX_STATE_REKEY_SENT: + break; + default: + GNUNET_break (0); return; } m = (const struct PongMessage *) msg; -#if DEBUG_HANDSHAKE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' response from `%4s'.\n", "PONG", GNUNET_i2s (&kx->peer)); -#endif /* mark as garbage, just to be sure */ memset (&t, 255, sizeof (t)); derive_pong_iv (&iv, &kx->decrypt_key, m->iv_seed, kx->ping_challenge, @@ -1128,7 +1278,6 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, || (kx->ping_challenge != t.challenge)) { /* PONG malformed */ -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received malformed `%s' wanted sender `%4s' with challenge %u\n", "PONG", GNUNET_i2s (&kx->peer), @@ -1136,13 +1285,10 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received malformed `%s' received from `%4s' with challenge %u\n", "PONG", GNUNET_i2s (&t.target), (unsigned int) t.challenge); -#endif return; } -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PONG from `%s'\n", GNUNET_i2s (&kx->peer)); -#endif switch (kx->status) { case KX_STATE_DOWN: @@ -1158,13 +1304,10 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, GNUNET_NO); kx->status = KX_STATE_UP; GSC_SESSIONS_create (&kx->peer, kx); - if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) - { - GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); - kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_assert (kx->keep_alive_task == GNUNET_SCHEDULER_NO_TASK); - if (kx->emsg_received != NULL) + CHECK_KX (kx); + schedule_rekey (kx); + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); + if (NULL != kx->emsg_received) { emsg = kx->emsg_received; kx->emsg_received = NULL; @@ -1177,6 +1320,18 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, case KX_STATE_UP: update_timeout (kx); break; + case KX_STATE_REKEY: + update_timeout (kx); + break; + case KX_STATE_REKEY_SENT: + GNUNET_STATISTICS_update (GSC_stats, + gettext_noop + ("# rekey operations confirmed via PONG"), 1, + GNUNET_NO); + kx->status = KX_STATE_UP; + schedule_rekey (kx); + update_timeout (kx); + break; default: GNUNET_break (0); break; @@ -1192,17 +1347,20 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, static void send_key (struct GSC_KeyExchangeInfo *kx) { - GNUNET_assert (kx->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK); + CHECK_KX (kx); + if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) + { + GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); + kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; + } if (KX_STATE_UP == kx->status) return; /* nothing to do */ - if (kx->public_key == NULL) + if (NULL == kx->public_key) { /* lookup public key, then try again */ -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to obtain public key for `%s'\n", GNUNET_i2s (&kx->peer)); -#endif kx->pitr = GNUNET_PEERINFO_iterate (peerinfo, &kx->peer, GNUNET_TIME_UNIT_FOREVER_REL /* timeout? */ , @@ -1230,17 +1388,33 @@ send_key (struct GSC_KeyExchangeInfo *kx) case KX_STATE_UP: GNUNET_break (0); return; + case KX_STATE_REKEY: + kx->status = KX_STATE_REKEY_SENT; + /* setup fresh SET KEY message */ + setup_fresh_setkey (kx); + setup_fresh_ping (kx); + GNUNET_STATISTICS_update (GSC_stats, + gettext_noop + ("# SET_KEY and PING messages created"), 1, + GNUNET_NO); + GNUNET_STATISTICS_update (GSC_stats, + gettext_noop + ("# REKEY operations performed"), 1, + GNUNET_NO); + break; + case KX_STATE_REKEY_SENT: + break; default: GNUNET_break (0); return; } /* always update sender status in SET KEY message */ - kx->skm.sender_status = htonl ((int32_t) kx->status); -#if DEBUG_CORE + /* Not sending rekey sent state to be compatible with GNUnet 0.9.2 */ + kx->skm.sender_status = htonl ((int32_t) ((kx->status == KX_STATE_REKEY_SENT) ? + KX_STATE_KEY_RECEIVED : kx->status)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SET_KEY and PING to `%s'\n", GNUNET_i2s (&kx->peer)); -#endif GSC_NEIGHBOURS_transmit (&kx->peer, &kx->skm.header, kx->set_key_retry_frequency); GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header, @@ -1288,10 +1462,8 @@ GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, do_encrypt (kx, &iv, &ph->sequence_number, &em->sequence_number, used - ENCRYPTED_HEADER_SIZE)); -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for %s\n", used - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer)); -#endif derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed, kx->encrypt_key_created); GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number, @@ -1348,7 +1520,7 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, struct GNUNET_CRYPTO_AuthKey auth_key; struct DeliverMessageContext dmc; uint16_t size = ntohs (msg->size); - char buf[size]; + char buf[size] GNUNET_ALIGN; if (size < sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader)) @@ -1357,7 +1529,8 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, return; } m = (const struct EncryptedMessage *) msg; - if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP)) + if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && + (kx->status != KX_STATE_REKEY_SENT) ) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop @@ -1365,10 +1538,10 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, 1, GNUNET_NO); return; } - if (kx->status == KX_STATE_KEY_RECEIVED) + if (KX_STATE_KEY_RECEIVED == kx->status) { /* defer */ - GNUNET_free_non_null (kx->ping_received); + GNUNET_free_non_null (kx->emsg_received); kx->emsg_received = (struct EncryptedMessage *) GNUNET_copy_message (msg); return; } @@ -1389,10 +1562,8 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, do_decrypt (kx, &iv, &m->sequence_number, &buf[ENCRYPTED_HEADER_SIZE], size - ENCRYPTED_HEADER_SIZE)) return; -#if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypted %u bytes from %s\n", size - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer)); -#endif pt = (struct EncryptedMessage *) buf; /* validate sequence number */ @@ -1487,7 +1658,7 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, * @param client who sent us the message (struct GSC_KeyExchangeInfo) * @param m the message */ -static void +static int deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m) { struct DeliverMessageContext *dmc = client; @@ -1497,7 +1668,7 @@ deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m) case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP: case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP: GSC_SESSIONS_set_typemap (dmc->peer, m); - return; + return GNUNET_OK; default: GSC_CLIENTS_deliver_message (dmc->peer, dmc->atsi, dmc->atsi_count, m, ntohs (m->size), @@ -1506,6 +1677,7 @@ deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m) sizeof (struct GNUNET_MessageHeader), GNUNET_CORE_OPTION_SEND_HDR_INBOUND); } + return GNUNET_OK; } @@ -1530,7 +1702,7 @@ GSC_KX_init () } my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); GNUNET_free (keyfile); - if (my_private_key == NULL) + if (NULL == my_private_key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Core service could not access hostkey. Exiting.\n")); @@ -1559,17 +1731,17 @@ GSC_KX_init () void GSC_KX_done () { - if (my_private_key != NULL) + if (NULL != my_private_key) { GNUNET_CRYPTO_rsa_key_free (my_private_key); my_private_key = NULL; } - if (peerinfo != NULL) + if (NULL != peerinfo) { GNUNET_PEERINFO_disconnect (peerinfo); peerinfo = NULL; } - if (mst != NULL) + if (NULL != mst) { GNUNET_SERVER_mst_destroy (mst); mst = NULL; |