return NULL;
}
+ SILC_LOG_DEBUG(("Created packet stream %p", ps));
+
return ps;
}
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);
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);
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);
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))) {
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);
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);
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) {
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);
}
}
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);
}
}
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);
}
}
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);
}
}
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;
}