From: Pekka Riikonen Date: Mon, 5 Nov 2007 20:36:19 +0000 (+0000) Subject: Fixed CTR mode rekey. Fixsed IV Included CTR mode encryption/ X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=d4698528ed84c05aad3be8c2b18a343d2dc2b521 Fixed CTR mode rekey. Fixsed IV Included CTR mode encryption/ decryption in packet engine. --- diff --git a/CHANGES.TOOLKIT b/CHANGES.TOOLKIT index 64cfe8c2..65844e8f 100644 --- a/CHANGES.TOOLKIT +++ b/CHANGES.TOOLKIT @@ -1,3 +1,10 @@ +Mon Nov 5 22:24:25 EET 2007 Pekka Riikonen + + * Fixed CTR mode rekey. Affected file is lib/silcske/silcske.c. + + * Rewrote the IV Included CTR mode encryption/decryption in + packet engine. Affected file is lib/silccore/silcpacket.c. + Sun Aug 26 12:28:49 EEST 2007 Pekka Riikonen * Fixed TIMEOUT handling in user info resolving during JOINing, diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index c8fd4b12..17aee8d4 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -786,6 +786,8 @@ SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine, return NULL; } + SILC_LOG_DEBUG(("Created packet stream %p", ps)); + return ps; } @@ -888,6 +890,8 @@ void silc_packet_stream_destroy(SilcPacketStream stream) if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) { stream->destroyed = TRUE; + SILC_LOG_DEBUG(("Marking packet stream %p destroyed", stream)); + /* Close the underlaying stream */ if (!stream->udp && stream->stream) silc_stream_close(stream->stream); @@ -1468,14 +1472,6 @@ static inline void silc_packet_send_ctr_increment(SilcPacketStream stream, unsigned char *iv = silc_cipher_get_iv(cipher); SilcUInt32 pc1, pc2; - /* Increment 64-bit packet counter */ - SILC_GET32_MSB(pc1, iv + 4); - SILC_GET32_MSB(pc2, iv + 8); - if (++pc2 == 0) - ++pc1; - SILC_PUT32_MSB(pc1, iv + 4); - SILC_PUT32_MSB(pc2, iv + 8); - /* Reset block counter */ memset(iv + 12, 0, 4); @@ -1486,11 +1482,24 @@ static inline void silc_packet_send_ctr_increment(SilcPacketStream stream, ret_iv[1] = ret_iv[0] + iv[4]; ret_iv[2] = ret_iv[0] ^ ret_iv[1]; ret_iv[3] = ret_iv[0] + ret_iv[2]; - SILC_PUT32_MSB(pc2, ret_iv + 4); + + /* Increment 32-bit packet counter */ + SILC_GET32_MSB(pc1, iv + 8); + pc1++; + SILC_PUT32_MSB(pc1, ret_iv + 4); + SILC_LOG_HEXDUMP(("IV"), ret_iv, 8); /* Set new nonce to counter block */ - memcpy(iv + 4, ret_iv, 4); + memcpy(iv + 4, ret_iv, 8); + } else { + /* Increment 64-bit packet counter */ + SILC_GET32_MSB(pc1, iv + 4); + SILC_GET32_MSB(pc2, iv + 8); + if (++pc2 == 0) + ++pc1; + SILC_PUT32_MSB(pc1, iv + 4); + SILC_PUT32_MSB(pc2, iv + 8); } SILC_LOG_HEXDUMP(("Counter Block"), iv, 16); @@ -1605,6 +1614,12 @@ static inline SilcBool silc_packet_send_raw(SilcPacketStream stream, silc_mutex_lock(stream->lock); + if (silc_unlikely(stream->destroyed)) { + SILC_LOG_DEBUG(("Stream %p is destroyed, cannot send packet", stream)); + silc_mutex_unlock(stream->lock); + return FALSE; + } + /* Get packet pointer from the outgoing buffer */ if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen, hmac, &packet))) { diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index f8f41cb8..3d4ca10d 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -402,6 +402,12 @@ const char *silc_packet_error_string(SilcPacketError error); * Returns list of packet streams added to the packet engine. The caller * must free the list with silc_packet_engine_free_streams_list. * + * NOTES + * + * This function may also return disconnected and destroyed streams. The + * caller should use silc_packet_stream_is_valid to check if the stream + * is valid. + * ***/ SilcDList silc_packet_engine_get_streams(SilcPacketEngine engine); diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 02d0961c..65835628 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -1881,7 +1881,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_failure) SilcSKE ske = fsm_context; SilcUInt32 error = SILC_SKE_STATUS_ERROR; - if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) { + if (ske->packet && ske->packet->type == SILC_PACKET_FAILURE && + silc_buffer_len(&ske->packet->buffer) == 4) { SILC_GET32_MSB(error, ske->packet->buffer.data); ske->status = error; silc_packet_free(ske->packet); @@ -2470,7 +2471,8 @@ SILC_FSM_STATE(silc_ske_st_responder_failure) SILC_LOG_DEBUG(("Key exchange protocol failed")); - if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) { + if (ske->packet && ske->packet->type == SILC_PACKET_FAILURE && + silc_buffer_len(&ske->packet->buffer) == 4) { SILC_GET32_MSB(error, ske->packet->buffer.data); ske->status = error; silc_packet_free(ske->packet); @@ -3416,6 +3418,12 @@ SilcBool silc_ske_set_keys(SilcSKE ske, return FALSE; } + /* Allocate hash */ + if (ret_hash) { + if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash)) + return FALSE; + } + /* Set key material */ memset(iv, 0, sizeof(iv)); if (ske->responder) { @@ -3424,10 +3432,22 @@ SilcBool silc_ske_set_keys(SilcSKE ske, keymat->enc_key_len, TRUE); if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) { - memcpy(iv, ske->hash, 4); - memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8); + /* Counter mode */ + if (!ske->rekeying) { + /* Set IV. */ + memcpy(iv, ske->hash, 4); + if (!iv_included) + memcpy(iv + 4, keymat->receive_iv, 8); + } else { + /* Rekey, recompute the truncated hash value. */ + silc_hash_make(prop->hash, keymat->receive_iv, 8, iv); + if (!iv_included) + memcpy(iv + 4, keymat->receive_iv, 8); + } + silc_cipher_set_iv(*ret_send_key, iv); } else { + /* Other modes */ silc_cipher_set_iv(*ret_send_key, keymat->receive_iv); } } @@ -3436,10 +3456,22 @@ SilcBool silc_ske_set_keys(SilcSKE ske, keymat->enc_key_len, FALSE); if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) { - memcpy(iv, ske->hash, 4); - memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8); + /* Counter mode */ + if (!ske->rekeying) { + /* Set IV. */ + memcpy(iv, ske->hash, 4); + if (!iv_included) + memcpy(iv + 4, keymat->send_iv, 8); + } else { + /* Rekey, recompute the truncated hash value. */ + silc_hash_make(prop->hash, keymat->send_iv, 8, iv); + if (!iv_included) + memcpy(iv + 4, keymat->send_iv, 8); + } + silc_cipher_set_iv(*ret_receive_key, iv); } else { + /* Other modes */ silc_cipher_set_iv(*ret_receive_key, keymat->send_iv); } } @@ -3455,10 +3487,22 @@ SilcBool silc_ske_set_keys(SilcSKE ske, keymat->enc_key_len, TRUE); if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) { - memcpy(iv, ske->hash, 4); - memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8); + /* Counter mode */ + if (!ske->rekeying) { + /* Set IV. */ + memcpy(iv, ske->hash, 4); + if (!iv_included) + memcpy(iv + 4, keymat->send_iv, 8); + } else { + /* Rekey, recompute the truncated hash value. */ + silc_hash_make(prop->hash, keymat->send_iv, 8, iv); + if (!iv_included) + memcpy(iv + 4, keymat->send_iv, 8); + } + silc_cipher_set_iv(*ret_send_key, iv); } else { + /* Other modes */ silc_cipher_set_iv(*ret_send_key, keymat->send_iv); } } @@ -3467,10 +3511,23 @@ SilcBool silc_ske_set_keys(SilcSKE ske, keymat->enc_key_len, FALSE); if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) { - memcpy(iv, ske->hash, 4); - memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8); + /* Counter mode */ + if (!ske->rekeying) { + /* Set IV. If IV Included flag was negotiated we only set the + truncated hash value. */ + memcpy(iv, ske->hash, 4); + if (!iv_included) + memcpy(iv + 4, keymat->receive_iv, 8); + } else { + /* Rekey, recompute the truncated hash value. */ + silc_hash_make(prop->hash, keymat->receive_iv, 8, iv); + if (!iv_included) + memcpy(iv + 4, keymat->receive_iv, 8); + } + silc_cipher_set_iv(*ret_receive_key, iv); } else { + /* Other modes */ silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv); } } @@ -3482,12 +3539,6 @@ SilcBool silc_ske_set_keys(SilcSKE ske, keymat->hmac_key_len); } - /* Allocate hash */ - if (ret_hash) { - if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash)) - return FALSE; - } - return TRUE; }