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);
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;
}