The silc_cipher_set_iv in CTR mode now resets for a new block.
unsigned char *ret_iv)
{
unsigned char *iv = silc_cipher_get_iv(cipher);
- SilcUInt32 pc;
+ SilcUInt32 pc1, pc2;
- /* Increment packet counter */
- SILC_GET32_MSB(pc, iv + 8);
- pc++;
- SILC_PUT32_MSB(pc, iv + 8);
+ /* 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(pc, ret_iv + 4);
+ SILC_PUT32_MSB(pc2, ret_iv + 4);
SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
/* Set new nonce to counter block */
/* Encrypt the packet */
if (silc_likely(cipher)) {
SILC_LOG_DEBUG(("Encrypting packet"));
+ silc_cipher_set_iv(cipher, NULL);
if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
packet.data + ivlen, enclen,
NULL))) {
unsigned char *iv,
unsigned char *packet_iv)
{
- SilcUInt32 pc;
+ SilcUInt32 pc1, pc2;
/* If IV Included flag, set the IV from packet to block counter. */
if (stream->iv_included) {
memcpy(iv + 4, packet_iv, 8);
} else {
- /* Increment packet counter */
- SILC_GET32_MSB(pc, iv + 8);
- pc++;
- SILC_PUT32_MSB(pc, iv + 8);
+ /* 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 */
silc_packet_receive_ctr_increment(stream, iv, NULL);
}
- silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp,
- block_len, iv);
+ if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
+ silc_cipher_set_iv(cipher, NULL);
+ silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp, block_len, iv);
header = tmp;
if (stream->iv_included) {
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(aes_cbc)
+{
+
+}
+
/* Returns the size of the cipher context. */
SILC_CIPHER_API_CONTEXT_LEN(aes_cbc)
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(aes_ctr)
+{
+ AesContext *aes = context;
+
+ /* Starts new block. */
+ aes->u.enc.inf.b[2] = 0;
+}
+
/* Returns the size of the cipher context. */
SILC_CIPHER_API_CONTEXT_LEN(aes_ctr)
{
AesContext *aes = context;
SilcUInt32 ctr[4];
- int i;
+ int i = 16;
SILC_GET32_MSB(ctr[0], iv);
SILC_GET32_MSB(ctr[1], iv + 4);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
SILC_CIPHER_API_SET_KEY(aes_cbc);
+SILC_CIPHER_API_SET_IV(aes_cbc);
SILC_CIPHER_API_ENCRYPT(aes_cbc);
SILC_CIPHER_API_DECRYPT(aes_cbc);
SILC_CIPHER_API_CONTEXT_LEN(aes_cbc);
SILC_CIPHER_API_SET_KEY(aes_ctr);
+SILC_CIPHER_API_SET_IV(aes_ctr);
SILC_CIPHER_API_ENCRYPT(aes_ctr);
SILC_CIPHER_API_DECRYPT(aes_ctr);
SILC_CIPHER_API_CONTEXT_LEN(aes_ctr);
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(blowfish_cbc)
+{
+
+}
+
/* Returns the size of the cipher context. */
SILC_CIPHER_API_CONTEXT_LEN(blowfish_cbc)
*/
SILC_CIPHER_API_SET_KEY(blowfish_cbc);
+SILC_CIPHER_API_SET_IV(blowfish_cbc);
SILC_CIPHER_API_CONTEXT_LEN(blowfish_cbc);
SILC_CIPHER_API_ENCRYPT(blowfish_cbc);
SILC_CIPHER_API_DECRYPT(blowfish_cbc);
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(cast_cbc)
+{
+
+}
+
/* Returns the size of the cipher context. */
SILC_CIPHER_API_CONTEXT_LEN(cast_cbc)
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1999 - 2000, 2006 Pekka Riikonen
+ Copyright (C) 1999 - 2000, 2006, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
SILC_CIPHER_API_SET_KEY(cast_cbc);
+SILC_CIPHER_API_SET_IV(cast_cbc);
SILC_CIPHER_API_CONTEXT_LEN(cast_cbc);
SILC_CIPHER_API_ENCRYPT(cast_cbc);
SILC_CIPHER_API_DECRYPT(cast_cbc);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return TRUE;
}
+SILC_CIPHER_API_SET_IV(none)
+{
+
+}
+
SILC_CIPHER_API_CONTEXT_LEN(none)
{
return 1;
SILC_CIPHER_API_ENCRYPT(none)
{
- memcpy(dst, src, len);
+ memmove(dst, src, len);
return TRUE;
}
SILC_CIPHER_API_DECRYPT(none)
{
- memcpy(dst, src, len);
+ memmove(dst, src, len);
return TRUE;
}
*/
SILC_CIPHER_API_SET_KEY(none);
+SILC_CIPHER_API_SET_IV(none);
SILC_CIPHER_API_CONTEXT_LEN(none);
SILC_CIPHER_API_ENCRYPT(none);
SILC_CIPHER_API_DECRYPT(none);
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(rc5_cbc)
+{
+
+}
+
/* Returns the size of the cipher context. */
SILC_CIPHER_API_CONTEXT_LEN(rc5_cbc)
*/
SILC_CIPHER_API_SET_KEY(rc5_cbc);
+SILC_CIPHER_API_SET_IV(rc5_cbc);
SILC_CIPHER_API_CONTEXT_LEN(rc5_cbc);
SILC_CIPHER_API_ENCRYPT(rc5_cbc);
SILC_CIPHER_API_DECRYPT(rc5_cbc);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Macro to define cipher to cipher list */
#define SILC_CIPHER_API_DEF(name, cipher, keylen, blocklen, ivlen, mode) \
-{ name, silc_##cipher##_set_key, silc_##cipher##_encrypt, \
- silc_##cipher##_decrypt, silc_##cipher##_context_len, \
- keylen, blocklen, ivlen, mode }
+{ name, silc_##cipher##_set_key, silc_##cipher##_set_iv, \
+ silc_##cipher##_encrypt, silc_##cipher##_decrypt, \
+ silc_##cipher##_context_len, keylen, blocklen, ivlen, mode }
/* Static list of ciphers for silc_cipher_register_default(). */
const SilcCipherObject silc_default_ciphers[] =
new->block_len = cipher->block_len;
new->iv_len = cipher->iv_len;
new->set_key = cipher->set_key;
+ new->set_iv = cipher->set_iv;
new->encrypt = cipher->encrypt;
new->decrypt = cipher->decrypt;
new->context_len = cipher->context_len;
void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
{
- memcpy(&cipher->iv, iv, cipher->cipher->iv_len);
+ if (iv)
+ memmove(&cipher->iv, iv, cipher->cipher->iv_len);
+ cipher->cipher->set_iv(cipher->context, iv);
}
/* Returns the IV (initial vector) of the cipher. */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
typedef struct {
char *name;
SilcBool (*set_key)(void *, const unsigned char *, SilcUInt32, SilcBool);
+ void (*set_iv)(void *, const unsigned char *);
SilcBool (*encrypt)(void *, const unsigned char *, unsigned char *,
SilcUInt32, unsigned char *);
SilcBool (*decrypt)(void *, const unsigned char *, unsigned char *,
const unsigned char *key, \
SilcUInt32 keylen, \
SilcBool encryption)
+#define SILC_CIPHER_API_SET_IV(cipher) \
+void silc_##cipher##_set_iv(void *context, \
+ const unsigned char *iv)
#define SILC_CIPHER_API_ENCRYPT(cipher) \
SilcBool silc_##cipher##_encrypt(void *context, \
const unsigned char *src, \
* SYNOPSIS
*
* SilcBool silc_cipher_alloc(const unsigned char *name,
- * SilcCipher *new_cipher);
+ * SilcCipher *new_cipher);
*
* DESCRIPTION
*
* caller must set the key to the cipher after this function has returned
* by calling the ciphers set_key function.
*
+ * The following ciphers are supported:
+ *
+ * aes-256-ctr AES-256, Counter mode
+ * aes-192-ctr AES-192, Counter mode
+ * aes-128-ctr AES,128, Counter mode
+ * aes-256-cbc AES-256, Cipher block chaining mode
+ * aes-192-cbc AES-192, Cipher block chaining mode
+ * aes-128-cbc AES,128, Cipher block chaining mode
+ * twofish-256-cbc Twofish-256, Cipher block chaining mode
+ * twofish-192-cbc Twofish-192, Cipher block chaining mode
+ * twofish-128-cbc Twofish-128, Cipher block chaining mode
+ *
+ * Notes about modes:
+ *
+ * The CTR is normal counter mode. The CTR mode does not require the
+ * plaintext length to be multiple by the cipher block size. If the last
+ * plaintext block is shorter the remaining bits of the key stream are
+ * used next time silc_cipher_encrypt is called. If silc_cipher_set_iv
+ * is called it will reset the counter for a new block (discarding any
+ * remaining bits from previous key stream).
+ *
+ * The CBC is mode is a standard CBC mode. The plaintext length must be
+ * multiple by the cipher block size. If it isn't the plaintext must be
+ * padded.
+ *
***/
SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher);
* DESCRIPTION
*
* Sets the IV (initial vector) for the cipher. The `iv' must be
- * the size of the block size of the cipher.
+ * the size of the block size of the cipher. If `iv' is NULL this
+ * does not do anything.
+ *
+ * If the encryption mode is CTR (Counter mode) this also resets the
+ * the counter for a new block. This is done also if `iv' is NULL.
*
***/
void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv);
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(twofish_cbc)
+{
+
+}
+
/* Returns the size of the cipher context. */
SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc)
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
SILC_CIPHER_API_SET_KEY(twofish_cbc);
+SILC_CIPHER_API_SET_IV(twofish_cbc);
SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc);
SILC_CIPHER_API_ENCRYPT(twofish_cbc);
SILC_CIPHER_API_DECRYPT(twofish_cbc);
SilcHash *ret_hash)
{
unsigned char iv[32];
+ SilcBool iv_included = (prop->flags & SILC_SKE_SP_FLAG_IV_INCLUDED);
/* Allocate ciphers to be used in the communication */
if (ret_send_key) {
if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->receive_iv, 4);
+ memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8);
silc_cipher_set_iv(*ret_send_key, iv);
} else {
silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->send_iv, 4);
+ memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8);
silc_cipher_set_iv(*ret_receive_key, iv);
} else {
silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->send_iv, 4);
+ memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8);
silc_cipher_set_iv(*ret_send_key, iv);
} else {
silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->receive_iv, 4);
+ memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8);
silc_cipher_set_iv(*ret_receive_key, iv);
} else {
silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);