Added CFB mode to aes, twofish and cast5. Unified the CBC, CFB and
authorPekka Riikonen <priikone@silcnet.org>
Sat, 14 Jul 2007 10:53:43 +0000 (10:53 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 14 Jul 2007 10:53:43 +0000 (10:53 +0000)
CTR mode APIs.

12 files changed:
CHANGES.CRYPTO
lib/silccrypt/aes.c
lib/silccrypt/cast5.c
lib/silccrypt/ciphers_def.h
lib/silccrypt/rijndael_internal.h
lib/silccrypt/silccipher.c
lib/silccrypt/silccipher.h
lib/silccrypt/silccipher_i.h
lib/silccrypt/tests/test_aes.c
lib/silccrypt/tests/test_cast5.c
lib/silccrypt/tests/test_twofish.c
lib/silccrypt/twofish.c

index 92d9a8103e1d4022eda6e4944f8918cfbab02fe1..e01fe574cfc580de7b2852a6b1b682e7c0b9f46e 100644 (file)
@@ -1,3 +1,9 @@
+Sat Jul 14 13:45:34 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added CFB mode to aes, twofish and cast5.  Unified the API
+         for CBC, CTR and CFB modes.  Affected files are in
+         lib/silccrypt/.
+
 Fri Jul 13 22:55:13 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Added CAST5 (CAST-128) algorithm.  Affected files are
index fc67504d91b362fcfc6962fd2803c62241899c5a..52d0397b917e0068fe3dbd27115936776e2784b7 100644 (file)
@@ -54,6 +54,7 @@ SILC_CIPHER_API_SET_KEY(aes)
     break;
 
   case SILC_CIPHER_MODE_CTR:
+  case SILC_CIPHER_MODE_CFB:
     aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
     break;
 
@@ -67,11 +68,22 @@ SILC_CIPHER_API_SET_KEY(aes)
 
 SILC_CIPHER_API_SET_IV(aes)
 {
-  if (cipher->mode == SILC_CIPHER_MODE_CTR) {
-    AesContext *aes = context;
+  AesContext *aes = context;
+
+  switch (cipher->mode) {
 
+  case SILC_CIPHER_MODE_CTR:
     /* Starts new block. */
     aes->u.enc.inf.b[2] = 0;
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    /* Starts new block. */
+    aes->u.enc.inf.b[2] = 16;
+    break;
+
+  default:
+    break;
   }
 }
 
@@ -88,7 +100,7 @@ SILC_CIPHER_API_CONTEXT_LEN(aes)
 SILC_CIPHER_API_ENCRYPT(aes)
 {
   AesContext *aes = context;
-  int i;
+  SilcUInt32 ctr[4];
 
   switch (cipher->mode) {
   case SILC_CIPHER_MODE_CBC:
@@ -113,42 +125,13 @@ SILC_CIPHER_API_ENCRYPT(aes)
     break;
 
   case SILC_CIPHER_MODE_CTR:
-    {
-      SilcUInt32 ctr[4];
-
-      SILC_GET32_MSB(ctr[0], iv);
-      SILC_GET32_MSB(ctr[1], iv + 4);
-      SILC_GET32_MSB(ctr[2], iv + 8);
-      SILC_GET32_MSB(ctr[3], iv + 12);
-
-      i = aes->u.enc.inf.b[2];
-      if (!i)
-       i = 16;
-
-      while (len-- > 0) {
-       if (i == 16) {
-         if (++ctr[3] == 0)
-           if (++ctr[2] == 0)
-             if (++ctr[1] == 0)
-               ++ctr[0];
-
-         SILC_PUT32_MSB(ctr[0], iv);
-         SILC_PUT32_MSB(ctr[1], iv + 4);
-         SILC_PUT32_MSB(ctr[2], iv + 8);
-         SILC_PUT32_MSB(ctr[3], iv + 12);
-
-         aes_encrypt(iv, iv, &aes->u.enc);
-         i = 0;
-       }
-       *dst++ = *src++ ^ iv[i++];
-      }
-      aes->u.enc.inf.b[2] = i;
+    SILC_CTR_MSB_128_8(iv, ctr, iv, aes->u.enc.inf.b[2], src, dst,
+                      aes_encrypt(iv, iv, &aes->u.enc));
+    break;
 
-      SILC_PUT32_MSB(ctr[0], iv);
-      SILC_PUT32_MSB(ctr[1], iv + 4);
-      SILC_PUT32_MSB(ctr[2], iv + 8);
-      SILC_PUT32_MSB(ctr[3], iv + 12);
-    }
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_ENC_MSB_128_8(iv, aes->u.enc.inf.b[2], src, dst,
+                          aes_encrypt(iv, iv, &aes->u.enc));
     break;
 
   default:
@@ -163,6 +146,8 @@ SILC_CIPHER_API_ENCRYPT(aes)
 
 SILC_CIPHER_API_DECRYPT(aes)
 {
+  AesContext *aes = context;
+
   switch (cipher->mode) {
   case SILC_CIPHER_MODE_CBC:
     {
@@ -174,7 +159,7 @@ SILC_CIPHER_API_DECRYPT(aes)
 
       while(nb--) {
        memcpy(tmp, src, 16);
-       aes_decrypt(src, dst, &((AesContext *)context)->u.dec);
+       aes_decrypt(src, dst, &aes->u.dec);
        lp32(dst)[0] ^= lp32(iv)[0];
        lp32(dst)[1] ^= lp32(iv)[1];
        lp32(dst)[2] ^= lp32(iv)[2];
@@ -190,6 +175,11 @@ SILC_CIPHER_API_DECRYPT(aes)
     return silc_aes_encrypt(cipher, context, src, dst, len, iv);
     break;
 
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_DEC_MSB_128_8(iv, aes->u.enc.inf.b[2], src, dst,
+                          aes_encrypt(iv, iv, &aes->u.enc));
+    break;
+
   default:
     return FALSE;
   }
@@ -244,7 +234,6 @@ AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1])
     ke4(cx->ks, 6);  ke4(cx->ks, 7);
     ke4(cx->ks, 8);
     ke4(cx->ks, 9);
-    cx->inf.l = 0;
     cx->inf.b[0] = 10 * 16;
 }
 
@@ -276,7 +265,6 @@ AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1])
     ke6(cx->ks, 4);  ke6(cx->ks, 5);
     ke6(cx->ks, 6);
     kef6(cx->ks, 7);
-    cx->inf.l = 0;
     cx->inf.b[0] = 12 * 16;
 }
 
@@ -311,7 +299,6 @@ AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1])
     ke8(cx->ks, 2); ke8(cx->ks, 3);
     ke8(cx->ks, 4); ke8(cx->ks, 5);
     kef8(cx->ks, 6);
-    cx->inf.l = 0;
     cx->inf.b[0] = 14 * 16;
 }
 
@@ -377,7 +364,6 @@ AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1])
      kd4(cx->ks, 4);  kd4(cx->ks, 5);
      kd4(cx->ks, 6);  kd4(cx->ks, 7);
      kd4(cx->ks, 8); kdl4(cx->ks, 9);
-    cx->inf.l = 0;
     cx->inf.b[0] = 10 * 16;
 }
 
@@ -436,7 +422,6 @@ AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1])
     kd6(cx->ks, 2);  kd6(cx->ks, 3);
     kd6(cx->ks, 4);  kd6(cx->ks, 5);
     kd6(cx->ks, 6); kdl6(cx->ks, 7);
-    cx->inf.l = 0;
     cx->inf.b[0] = 12 * 16;
 }
 
@@ -504,7 +489,6 @@ AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])
     kd8(cx->ks, 2);  kd8(cx->ks, 3);
     kd8(cx->ks, 4);  kd8(cx->ks, 5);
     kdl8(cx->ks, 6);
-    cx->inf.l = 0;
     cx->inf.b[0] = 14 * 16;
 }
 
index 227cae11418a2adc0fff01adac507036979ae423..995fc09bfd2e823bff82c9a0e07b70e2953b9675 100644 (file)
@@ -22,11 +22,22 @@ SILC_CIPHER_API_SET_KEY(cast5)
 
 SILC_CIPHER_API_SET_IV(cast5)
 {
-  if (cipher->mode == SILC_CIPHER_MODE_CTR) {
-    cast5_key *cast5 = context;
+  cast5_key *cast5 = context;
+
+  switch (cipher->mode) {
 
-    /* Starts new block */
+  case SILC_CIPHER_MODE_CTR:
+    /* Starts new block. */
     cast5->padlen = 0;
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    /* Starts new block. */
+    cast5->padlen = 8;
+    break;
+
+  default:
+    break;
   }
 }
 
@@ -46,49 +57,18 @@ SILC_CIPHER_API_ENCRYPT(cast5)
   switch (cipher->mode) {
 
   case SILC_CIPHER_MODE_CBC:
-    SILC_ASSERT((len & (8 - 1)) == 0);
-    if (len & (8 - 1))
-      return FALSE;
-    SILC_CBC_MSB_GET_IV(tmp, iv, 8);
-
-    SILC_CBC_MSB_ENC_PRE(tmp, src, 8);
-    cast5_encrypt(cast5, tmp, tmp);
-    SILC_CBC_MSB_ENC_POST(tmp, dst, src, 8);
-
-    for (i = 8; i < len; i += 8) {
-      SILC_CBC_MSB_ENC_PRE(tmp, src, 8);
-      cast5_encrypt(cast5, tmp, tmp);
-      SILC_CBC_MSB_ENC_POST(tmp, dst, src, 8);
-    }
-
-    SILC_CBC_MSB_PUT_IV(tmp, iv, 8);
+    SILC_CBC_ENC_MSB_64_32(len, iv, tmp, src, dst, i,
+                          cast5_encrypt(cast5, tmp, tmp));
     break;
 
   case SILC_CIPHER_MODE_CTR:
-    SILC_GET32_MSB(ctr[0], iv);
-    SILC_GET32_MSB(ctr[1], iv + 4);
-
-    i = cast5->padlen;
-    if (!i)
-      i = 8;
-
-    while (len-- > 0) {
-      if (i == 8) {
-       if (++ctr[1] == 0)
-         ++ctr[0];
-
-       cast5_encrypt(cast5, ctr, tmp);
-
-       SILC_PUT32_MSB(tmp[0], iv);
-       SILC_PUT32_MSB(tmp[1], iv + 4);
-       i = 0;
-      }
-      *dst++ = *src++ ^ iv[i++];
-    }
-    cast5->padlen = i;
-
-    SILC_PUT32_MSB(ctr[0], iv);
-    SILC_PUT32_MSB(ctr[1], iv + 4);
+    SILC_CTR_MSB_64_32(iv, ctr, tmp, cast5->padlen, src, dst,
+                      cast5_encrypt(cast5, ctr, tmp));
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_ENC_MSB_64_32(iv, tmp, cast5->padlen, src, dst,
+                          cast5_encrypt(cast5, tmp, tmp));
     break;
 
   default:
@@ -100,34 +80,26 @@ SILC_CIPHER_API_ENCRYPT(cast5)
 
 SILC_CIPHER_API_DECRYPT(cast5)
 {
+  cast5_key *cast5 = context;
   SilcUInt32 tmp[2], tmp2[2], tiv[2];
   int i;
 
   switch (cipher->mode) {
 
   case SILC_CIPHER_MODE_CBC:
-    if (len & (8 - 1))
-      return FALSE;
-
-    SILC_CBC_MSB_GET_IV(tiv, iv, 8);
-
-    SILC_CBC_MSB_DEC_PRE(tmp, src, 8);
-    cast5_decrypt((cast5_key *)context, tmp, tmp2);
-    SILC_CBC_MSB_DEC_POST(tmp2, dst, src, tmp, tiv, 8);
-
-    for (i = 8; i < len; i += 8) {
-      SILC_CBC_MSB_DEC_PRE(tmp, src, 8);
-      cast5_decrypt((cast5_key *)context, tmp, tmp2);
-      SILC_CBC_MSB_DEC_POST(tmp2, dst, src, tmp, tiv, 8);
-    }
-
-    SILC_CBC_MSB_PUT_IV(tiv, iv, 8);
+    SILC_CBC_DEC_MSB_64_32(len, iv, tiv, tmp, tmp2, src, dst, i,
+                          cast5_decrypt(cast5, tmp, tmp2));
     break;
 
   case SILC_CIPHER_MODE_CTR:
     return silc_cast5_encrypt(cipher, context, src, dst, len, iv);
     break;
 
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_DEC_MSB_64_32(iv, tmp, cast5->padlen, src, dst,
+                          cast5_encrypt(cast5, tmp, tmp));
+    break;
+
   default:
     return FALSE;
   }
index d755a9f3b64c724473e097f3b6451b7d9c7deda3..19716f4805f6802ec99e0b7579a9b07b088af17d 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1999 - 2006 Pekka Riikonen
+  Copyright (C) 1999 - 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
@@ -39,152 +39,557 @@ do {                                              \
     SILC_GET32_LSB(d[_i], s + (_i * 4));       \
 } while(0);
 
-/* CBC mode macros (LSB). */
+/* CBC mode 128-bit block, LSB, 32-bit block argument must be encrypted */
 
-#define SILC_CBC_GET_IV(d, s)                  \
-do {                                           \
-  SILC_GET32_LSB(d[0], &s[0]);                 \
-  SILC_GET32_LSB(d[1], &s[4]);                 \
-  SILC_GET32_LSB(d[2], &s[8]);                 \
-  SILC_GET32_LSB(d[3], &s[12]);                        \
-} while(0);
+#define SILC_CBC_ENC_LSB_128_32(len, iv, block, src, dst, i, enc)      \
+do {                                                                   \
+  SILC_ASSERT((len & (16 - 1)) == 0);                                  \
+  if (len & (16 - 1))                                                  \
+    return FALSE;                                                      \
+                                                                       \
+  SILC_GET32_LSB(block[0], &iv[0]);                                    \
+  SILC_GET32_LSB(block[1], &iv[4]);                                    \
+  SILC_GET32_LSB(block[2], &iv[8]);                                    \
+  SILC_GET32_LSB(block[3], &iv[12]);                                   \
+                                                                       \
+  for (i = 0; i < len; i += 16) {                                      \
+    SILC_GET32_X_LSB(block[0], &src[0]);                               \
+    SILC_GET32_X_LSB(block[1], &src[4]);                               \
+    SILC_GET32_X_LSB(block[2], &src[8]);                               \
+    SILC_GET32_X_LSB(block[3], &src[12]);                              \
+                                                                       \
+    enc;                                                               \
+                                                                       \
+    SILC_PUT32_LSB(block[0], &dst[0]);                                 \
+    SILC_PUT32_LSB(block[1], &dst[4]);                                 \
+    SILC_PUT32_LSB(block[2], &dst[8]);                                 \
+    SILC_PUT32_LSB(block[3], &dst[12]);                                        \
+                                                                       \
+    dst += 16;                                                         \
+    src += 16;                                                         \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_LSB(block[0], &iv[0]);                                    \
+  SILC_PUT32_LSB(block[1], &iv[4]);                                    \
+  SILC_PUT32_LSB(block[2], &iv[8]);                                    \
+  SILC_PUT32_LSB(block[3], &iv[12]);                                   \
+} while(0)
 
-#define SILC_CBC_PUT_IV(s, d)                  \
-do {                                           \
-  SILC_PUT32_LSB(s[0], &d[0]);                 \
-  SILC_PUT32_LSB(s[1], &d[4]);                 \
-  SILC_PUT32_LSB(s[2], &d[8]);                 \
-  SILC_PUT32_LSB(s[3], &d[12]);                        \
-} while(0);
+/* CBC mode 128-bit block, LSB, decrypt block to block_dec. */
 
-#define SILC_CBC_ENC_PRE(d, s)                 \
-do {                                           \
-  SILC_GET32_X_LSB(d[0], &s[0]);               \
-  SILC_GET32_X_LSB(d[1], &s[4]);               \
-  SILC_GET32_X_LSB(d[2], &s[8]);               \
-  SILC_GET32_X_LSB(d[3], &s[12]);              \
-} while(0);
+#define SILC_CBC_DEC_LSB_128_32(len, iv, block_prev, block,            \
+                               block_dec, src, dst, i, dec)            \
+do {                                                                   \
+  if (len & (16 - 1))                                                  \
+    return FALSE;                                                      \
+                                                                       \
+  SILC_GET32_LSB(block_prev[0], &iv[0]);                               \
+  SILC_GET32_LSB(block_prev[1], &iv[4]);                               \
+  SILC_GET32_LSB(block_prev[2], &iv[8]);                               \
+  SILC_GET32_LSB(block_prev[3], &iv[12]);                              \
+                                                                       \
+  for (i = 0; i < len; i += 16) {                                      \
+    SILC_GET32_LSB(block[0], &src[0]);                                 \
+    SILC_GET32_LSB(block[1], &src[4]);                                 \
+    SILC_GET32_LSB(block[2], &src[8]);                                 \
+    SILC_GET32_LSB(block[3], &src[12]);                                        \
+                                                                       \
+    dec;                                                               \
+                                                                       \
+    block_dec[0] ^= block_prev[0];                                     \
+    block_dec[1] ^= block_prev[1];                                     \
+    block_dec[2] ^= block_prev[2];                                     \
+    block_dec[3] ^= block_prev[3];                                     \
+                                                                       \
+    SILC_PUT32_LSB(block_dec[0], &dst[0]);                             \
+    SILC_PUT32_LSB(block_dec[1], &dst[4]);                             \
+    SILC_PUT32_LSB(block_dec[2], &dst[8]);                             \
+    SILC_PUT32_LSB(block_dec[3], &dst[12]);                            \
+                                                                       \
+    block_prev[0] = block[0];                                          \
+    block_prev[1] = block[1];                                          \
+    block_prev[2] = block[2];                                          \
+    block_prev[3] = block[3];                                          \
+                                                                       \
+    dst += 16;                                                         \
+    src += 16;                                                         \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_LSB(block[0], &iv[0]);                                    \
+  SILC_PUT32_LSB(block[1], &iv[4]);                                    \
+  SILC_PUT32_LSB(block[2], &iv[8]);                                    \
+  SILC_PUT32_LSB(block[3], &iv[12]);                                   \
+} while(0)
 
-#define SILC_CBC_ENC_POST(s, d, t)             \
-do {                                           \
-  SILC_PUT32_LSB(s[0], &d[0]);                 \
-  SILC_PUT32_LSB(s[1], &d[4]);                 \
-  SILC_PUT32_LSB(s[2], &d[8]);                 \
-  SILC_PUT32_LSB(s[3], &d[12]);                        \
-                                               \
-  d += 16;                                     \
-  t += 16;                                     \
-} while(0);
+/* CBC mode 128-bit block, MSB, 32-bit block argument must be encrypted */
 
-#define SILC_CBC_DEC_PRE(d, s)                 \
-do {                                           \
-  SILC_GET32_LSB(d[0], &s[0]);                 \
-  SILC_GET32_LSB(d[1], &s[4]);                 \
-  SILC_GET32_LSB(d[2], &s[8]);                 \
-  SILC_GET32_LSB(d[3], &s[12]);                        \
-} while(0);
+#define SILC_CBC_ENC_MSB_128_32(len, iv, block, src, dst, i, enc)      \
+do {                                                                   \
+  SILC_ASSERT((len & (16 - 1)) == 0);                                  \
+  if (len & (16 - 1))                                                  \
+    return FALSE;                                                      \
+                                                                       \
+  SILC_GET32_MSB(block[0], &iv[0]);                                    \
+  SILC_GET32_MSB(block[1], &iv[4]);                                    \
+  SILC_GET32_MSB(block[2], &iv[8]);                                    \
+  SILC_GET32_MSB(block[3], &iv[12]);                                   \
+                                                                       \
+  for (i = 0; i < len; i += 16) {                                      \
+    SILC_GET32_X_MSB(block[0], &src[0]);                               \
+    SILC_GET32_X_MSB(block[1], &src[4]);                               \
+    SILC_GET32_X_MSB(block[2], &src[8]);                               \
+    SILC_GET32_X_MSB(block[3], &src[12]);                              \
+                                                                       \
+    enc;                                                               \
+                                                                       \
+    SILC_PUT32_MSB(block[0], &dst[0]);                                 \
+    SILC_PUT32_MSB(block[1], &dst[4]);                                 \
+    SILC_PUT32_MSB(block[2], &dst[8]);                                 \
+    SILC_PUT32_MSB(block[3], &dst[12]);                                        \
+                                                                       \
+    dst += 16;                                                         \
+    src += 16;                                                         \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(block[0], &iv[0]);                                    \
+  SILC_PUT32_MSB(block[1], &iv[4]);                                    \
+  SILC_PUT32_MSB(block[2], &iv[8]);                                    \
+  SILC_PUT32_MSB(block[3], &iv[12]);                                   \
+} while(0)
 
-#define SILC_CBC_DEC_POST(s, d, p, t, siv)     \
-do {                                           \
-  s[0] ^= siv[0];                              \
-  s[1] ^= siv[1];                              \
-  s[2] ^= siv[2];                              \
-  s[3] ^= siv[3];                              \
-                                               \
-  SILC_PUT32_LSB(s[0], &d[0]);                 \
-  SILC_PUT32_LSB(s[1], &d[4]);                 \
-  SILC_PUT32_LSB(s[2], &d[8]);                 \
-  SILC_PUT32_LSB(s[3], &d[12]);                        \
-                                               \
-  siv[0] = t[0];                               \
-  siv[1] = t[1];                               \
-  siv[2] = t[2];                               \
-  siv[3] = t[3];                               \
-                                               \
-  d += 16;                                     \
-  p += 16;                                     \
-} while(0);
+/* CBC mode 128-bit block, MSB, decrypt block to block_dec. */
 
-/* CBC mode macros (MSB). */
+#define SILC_CBC_DEC_MSB_128_32(len, iv, block_prev, block,            \
+                               block_dec, src, dst, i, dec)            \
+do {                                                                   \
+  if (len & (16 - 1))                                                  \
+    return FALSE;                                                      \
+                                                                       \
+  SILC_GET32_MSB(block_prev[0], &iv[0]);                               \
+  SILC_GET32_MSB(block_prev[1], &iv[4]);                               \
+  SILC_GET32_MSB(block_prev[2], &iv[8]);                               \
+  SILC_GET32_MSB(block_prev[3], &iv[12]);                              \
+                                                                       \
+  for (i = 0; i < len; i += 16) {                                      \
+    SILC_GET32_MSB(block[0], &src[0]);                                 \
+    SILC_GET32_MSB(block[1], &src[4]);                                 \
+    SILC_GET32_MSB(block[2], &src[8]);                                 \
+    SILC_GET32_MSB(block[3], &src[12]);                                        \
+                                                                       \
+    dec;                                                               \
+                                                                       \
+    block_dec[0] ^= block_prev[0];                                     \
+    block_dec[1] ^= block_prev[1];                                     \
+    block_dec[2] ^= block_prev[2];                                     \
+    block_dec[3] ^= block_prev[3];                                     \
+                                                                       \
+    SILC_PUT32_MSB(block_dec[0], &dst[0]);                             \
+    SILC_PUT32_MSB(block_dec[1], &dst[4]);                             \
+    SILC_PUT32_MSB(block_dec[2], &dst[8]);                             \
+    SILC_PUT32_MSB(block_dec[3], &dst[12]);                            \
+                                                                       \
+    block_prev[0] = block[0];                                          \
+    block_prev[1] = block[1];                                          \
+    block_prev[2] = block[2];                                          \
+    block_prev[3] = block[3];                                          \
+                                                                       \
+    dst += 16;                                                         \
+    src += 16;                                                         \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(block[0], &iv[0]);                                    \
+  SILC_PUT32_MSB(block[1], &iv[4]);                                    \
+  SILC_PUT32_MSB(block[2], &iv[8]);                                    \
+  SILC_PUT32_MSB(block[3], &iv[12]);                                   \
+} while(0)
 
-#define SILC_CBC_MSB_GET_IV(d, s, l)           \
-do {                                           \
-  SILC_GET32_MSB(d[0], &s[0]);                 \
-  SILC_GET32_MSB(d[1], &s[4]);                 \
-  if (l > 8) {                                 \
-    SILC_GET32_MSB(d[2], &s[8]);               \
-    SILC_GET32_MSB(d[3], &s[12]);              \
-  }                                            \
-} while(0);
+/* CBC mode 64-bit block, MSB, 32-bit block argument must be encrypted */
 
-#define SILC_CBC_MSB_PUT_IV(s, d, l)           \
-do {                                           \
-  SILC_PUT32_MSB(s[0], &d[0]);                 \
-  SILC_PUT32_MSB(s[1], &d[4]);                 \
-  if (l > 8) {                                 \
-    SILC_PUT32_MSB(s[2], &d[8]);               \
-    SILC_PUT32_MSB(s[3], &d[12]);              \
-  }                                            \
-} while(0);
+#define SILC_CBC_ENC_MSB_64_32(len, iv, block, src, dst, i, enc)       \
+do {                                                                   \
+  SILC_ASSERT((len & (8 - 1)) == 0);                                   \
+  if (len & (8 - 1))                                                   \
+    return FALSE;                                                      \
+                                                                       \
+  SILC_GET32_MSB(block[0], &iv[0]);                                    \
+  SILC_GET32_MSB(block[1], &iv[4]);                                    \
+                                                                       \
+  for (i = 0; i < len; i += 8) {                                       \
+    SILC_GET32_X_MSB(block[0], &src[0]);                               \
+    SILC_GET32_X_MSB(block[1], &src[4]);                               \
+                                                                       \
+    enc;                                                               \
+                                                                       \
+    SILC_PUT32_MSB(block[0], &dst[0]);                                 \
+    SILC_PUT32_MSB(block[1], &dst[4]);                                 \
+                                                                       \
+    dst += 8;                                                          \
+    src += 8;                                                          \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(block[0], &iv[0]);                                    \
+  SILC_PUT32_MSB(block[1], &iv[4]);                                    \
+} while(0)
 
-#define SILC_CBC_MSB_ENC_PRE(d, s, l)          \
-do {                                           \
-  SILC_GET32_X_MSB(d[0], &s[0]);               \
-  SILC_GET32_X_MSB(d[1], &s[4]);               \
-  if (l > 8) {                                 \
-    SILC_GET32_X_MSB(d[2], &s[8]);             \
-    SILC_GET32_X_MSB(d[3], &s[12]);            \
-  }                                            \
-} while(0);
+/* CBC mode 64-bit block, MSB, decrypt block to block_dec. */
 
-#define SILC_CBC_MSB_ENC_POST(s, d, t, l)      \
-do {                                           \
-  SILC_PUT32_MSB(s[0], &d[0]);                 \
-  SILC_PUT32_MSB(s[1], &d[4]);                 \
-  if (l > 8) {                                 \
-    SILC_PUT32_MSB(s[2], &d[8]);               \
-    SILC_PUT32_MSB(s[3], &d[12]);              \
-  }                                            \
-                                               \
-  d += l;                                      \
-  t += l;                                      \
-} while(0);
+#define SILC_CBC_DEC_MSB_64_32(len, iv, block_prev, block,             \
+                              block_dec, src, dst, i, dec)             \
+do {                                                                   \
+  if (len & (8 - 1))                                                   \
+    return FALSE;                                                      \
+                                                                       \
+  SILC_GET32_MSB(block_prev[0], &iv[0]);                               \
+  SILC_GET32_MSB(block_prev[1], &iv[4]);                               \
+                                                                       \
+  for (i = 0; i < len; i += 8) {                                       \
+    SILC_GET32_MSB(block[0], &src[0]);                                 \
+    SILC_GET32_MSB(block[1], &src[4]);                                 \
+                                                                       \
+    dec;                                                               \
+                                                                       \
+    block_dec[0] ^= block_prev[0];                                     \
+    block_dec[1] ^= block_prev[1];                                     \
+                                                                       \
+    SILC_PUT32_MSB(block_dec[0], &dst[0]);                             \
+    SILC_PUT32_MSB(block_dec[1], &dst[4]);                             \
+                                                                       \
+    block_prev[0] = block[0];                                          \
+    block_prev[1] = block[1];                                          \
+                                                                       \
+    dst += 8;                                                          \
+    src += 8;                                                          \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(block[0], &iv[0]);                                    \
+  SILC_PUT32_MSB(block[1], &iv[4]);                                    \
+} while(0)
 
-#define SILC_CBC_MSB_DEC_PRE(d, s, l)          \
-do {                                           \
-  SILC_GET32_MSB(d[0], &s[0]);                 \
-  SILC_GET32_MSB(d[1], &s[4]);                 \
-  if (l > 8) {                                 \
-    SILC_GET32_MSB(d[2], &s[8]);               \
-    SILC_GET32_MSB(d[3], &s[12]);              \
-  }                                            \
-} while(0);
 
-#define SILC_CBC_MSB_DEC_POST(s, d, p, t, siv, l)      \
-do {                                                   \
-  s[0] ^= siv[0];                                      \
-  s[1] ^= siv[1];                                      \
-  if (l > 8) {                                         \
-    s[2] ^= siv[2];                                    \
-    s[3] ^= siv[3];                                    \
-  }                                                    \
-                                                       \
-  SILC_PUT32_MSB(s[0], &d[0]);                         \
-  SILC_PUT32_MSB(s[1], &d[4]);                         \
-  if (l > 8) {                                         \
-    SILC_PUT32_MSB(s[2], &d[8]);                       \
-    SILC_PUT32_MSB(s[3], &d[12]);                      \
-  }                                                    \
-                                                       \
-  siv[0] = t[0];                                       \
-  siv[1] = t[1];                                       \
-  if (l > 8) {                                         \
-    siv[2] = t[2];                                     \
-    siv[3] = t[3];                                     \
-  }                                                    \
-                                                       \
-  d += l;                                              \
-  p += l;                                              \
-} while(0);
+/* CTR mode 128-bit block, MSB, MSB counter, the 8-bit enc_ctr argument must
+   be encrypted */
+
+#define SILC_CTR_MSB_128_8(iv, ctr, enc_ctr, pad, src, dst, enc)       \
+do {                                                                   \
+  SILC_GET32_MSB(ctr[0], iv);                                          \
+  SILC_GET32_MSB(ctr[1], iv + 4);                                      \
+  SILC_GET32_MSB(ctr[2], iv + 8);                                      \
+  SILC_GET32_MSB(ctr[3], iv + 12);                                     \
+                                                                       \
+  if (pad == 0)                                                                \
+    pad = 16;                                                          \
+                                                                       \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      if (++ctr[3] == 0)                                               \
+       if (++ctr[2] == 0)                                              \
+         if (++ctr[1] == 0)                                            \
+           ++ctr[0];                                                   \
+                                                                       \
+      SILC_PUT32_MSB(ctr[0], enc_ctr);                                 \
+      SILC_PUT32_MSB(ctr[1], enc_ctr + 4);                             \
+      SILC_PUT32_MSB(ctr[2], enc_ctr + 8);                             \
+      SILC_PUT32_MSB(ctr[3], enc_ctr + 12);                            \
+                                                                       \
+      enc;                                                             \
+      pad = 0;                                                         \
+    }                                                                  \
+    *dst++ = *src++ ^ enc_ctr[pad++];                                  \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(ctr[0], iv);                                          \
+  SILC_PUT32_MSB(ctr[1], iv + 4);                                      \
+  SILC_PUT32_MSB(ctr[2], iv + 8);                                      \
+  SILC_PUT32_MSB(ctr[3], iv + 12);                                     \
+} while(0)
+
+/* CTR mode 128-bit block, MSB, MSB counter, the 32-bit ctr argument must
+   be encrypted to enc_ctr */
+
+#define SILC_CTR_MSB_128_32(iv, ctr, enc_ctr, pad, src, dst, enc)      \
+do {                                                                   \
+  SILC_GET32_MSB(ctr[0], iv);                                          \
+  SILC_GET32_MSB(ctr[1], iv + 4);                                      \
+  SILC_GET32_MSB(ctr[2], iv + 8);                                      \
+  SILC_GET32_MSB(ctr[3], iv + 12);                                     \
+                                                                       \
+  if (pad == 0)                                                                \
+    pad = 16;                                                          \
+                                                                       \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      if (++ctr[3] == 0)                                               \
+       if (++ctr[2] == 0)                                              \
+         if (++ctr[1] == 0)                                            \
+           ++ctr[0];                                                   \
+                                                                       \
+      enc;                                                             \
+      SILC_PUT32_MSB(enc_ctr[0], iv);                                  \
+      SILC_PUT32_MSB(enc_ctr[1], iv + 4);                              \
+      SILC_PUT32_MSB(enc_ctr[2], iv + 8);                              \
+      SILC_PUT32_MSB(enc_ctr[3], iv + 12);                             \
+      pad = 0;                                                         \
+    }                                                                  \
+    *dst++ = *src++ ^ enc_ctr[pad++];                                  \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(ctr[0], iv);                                          \
+  SILC_PUT32_MSB(ctr[1], iv + 4);                                      \
+  SILC_PUT32_MSB(ctr[2], iv + 8);                                      \
+  SILC_PUT32_MSB(ctr[3], iv + 12);                                     \
+} while(0)
+
+/* CTR mode 128-bit block, LSB, MSB counter, the 32-bit enc_ctr argument
+   must be encrypted */
+
+#define SILC_CTR_LSB_128_32(iv, ctr, enc_ctr, pad, src, dst, enc)      \
+do {                                                                   \
+  SILC_GET32_MSB(ctr[0], iv);                                          \
+  SILC_GET32_MSB(ctr[1], iv + 4);                                      \
+  SILC_GET32_MSB(ctr[2], iv + 8);                                      \
+  SILC_GET32_MSB(ctr[3], iv + 12);                                     \
+                                                                       \
+  if (pad == 0)                                                                \
+    pad = 16;                                                          \
+                                                                       \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      if (++ctr[3] == 0)                                               \
+       if (++ctr[2] == 0)                                              \
+         if (++ctr[1] == 0)                                            \
+           ++ctr[0];                                                   \
+                                                                       \
+      enc_ctr[0] = SILC_SWAB_32(ctr[0]);                               \
+      enc_ctr[1] = SILC_SWAB_32(ctr[1]);                               \
+      enc_ctr[2] = SILC_SWAB_32(ctr[2]);                               \
+      enc_ctr[3] = SILC_SWAB_32(ctr[3]);                               \
+                                                                       \
+      enc;                                                             \
+      SILC_PUT32_LSB(enc_ctr[0], iv);                                  \
+      SILC_PUT32_LSB(enc_ctr[1], iv + 4);                              \
+      SILC_PUT32_LSB(enc_ctr[2], iv + 8);                              \
+      SILC_PUT32_LSB(enc_ctr[3], iv + 12);                             \
+      pad = 0;                                                         \
+    }                                                                  \
+    *dst++ = *src++ ^ iv[pad++];                                       \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(ctr[0], iv);                                          \
+  SILC_PUT32_MSB(ctr[1], iv + 4);                                      \
+  SILC_PUT32_MSB(ctr[2], iv + 8);                                      \
+  SILC_PUT32_MSB(ctr[3], iv + 12);                                     \
+} while(0)
+
+/* CTR mode 64-bit block, MSB, MSB counter, the 32-bit ctr argument must
+   be encrypted to enc_ctr */
+
+#define SILC_CTR_MSB_64_32(iv, ctr, enc_ctr, pad, src, dst, enc)       \
+do {                                                                   \
+  SILC_GET32_MSB(ctr[0], iv);                                          \
+  SILC_GET32_MSB(ctr[1], iv + 4);                                      \
+                                                                       \
+  if (pad == 0)                                                                \
+    pad = 8;                                                           \
+                                                                       \
+  while (len-- > 0) {                                                  \
+    if (pad == 8) {                                                    \
+      if (++ctr[1] == 0)                                               \
+       ++ctr[0];                                                       \
+                                                                       \
+      enc;                                                             \
+      SILC_PUT32_MSB(enc_ctr[0], iv);                                  \
+      SILC_PUT32_MSB(enc_ctr[1], iv + 4);                              \
+      pad = 0;                                                         \
+    }                                                                  \
+    *dst++ = *src++ ^ iv[pad++];                                       \
+  }                                                                    \
+                                                                       \
+  SILC_PUT32_MSB(ctr[0], iv);                                          \
+  SILC_PUT32_MSB(ctr[1], iv + 4);                                      \
+} while(0)
+
+/* CFB 128-bit block, LSB, the 32-bit cfb argument must be encrypted. */
+
+#define SILC_CFB_ENC_LSB_128_32(iv, cfb, pad, src, dst, enc)           \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      SILC_GET32_LSB(cfb[0], iv);                                      \
+      SILC_GET32_LSB(cfb[1], iv + 4);                                  \
+      SILC_GET32_LSB(cfb[2], iv + 8);                                  \
+      SILC_GET32_LSB(cfb[3], iv + 12);                                 \
+                                                                       \
+      enc;                                                             \
+                                                                       \
+      SILC_PUT32_LSB(cfb[0], iv);                                      \
+      SILC_PUT32_LSB(cfb[1], iv + 4);                                  \
+      SILC_PUT32_LSB(cfb[2], iv + 8);                                  \
+      SILC_PUT32_LSB(cfb[3], iv + 12);                                 \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = (*dst = *src ^ iv[pad]);                                 \
+    dst++;                                                             \
+    src++;                                                             \
+    pad++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 128-bit block, LSB, the 32-bit cfb argument must be decrypted. */
+
+#define SILC_CFB_DEC_LSB_128_32(iv, cfb, pad, src, dst, dec)           \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      SILC_GET32_LSB(cfb[0], iv);                                      \
+      SILC_GET32_LSB(cfb[1], iv + 4);                                  \
+      SILC_GET32_LSB(cfb[2], iv + 8);                                  \
+      SILC_GET32_LSB(cfb[3], iv + 12);                                 \
+                                                                       \
+      dec;                                                             \
+                                                                       \
+      SILC_PUT32_LSB(cfb[0], iv);                                      \
+      SILC_PUT32_LSB(cfb[1], iv + 4);                                  \
+      SILC_PUT32_LSB(cfb[2], iv + 8);                                  \
+      SILC_PUT32_LSB(cfb[3], iv + 12);                                 \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = *src ^ iv[pad];                                          \
+    *dst = iv[pad];                                                    \
+    iv[pad++] = *src;                                                  \
+    dst++;                                                             \
+    src++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 32-bit cfb argument must be encrypted. */
+
+#define SILC_CFB_ENC_MSB_128_32(iv, cfb, pad, src, dst, enc)           \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      SILC_GET32_MSB(cfb[0], iv);                                      \
+      SILC_GET32_MSB(cfb[1], iv + 4);                                  \
+      SILC_GET32_MSB(cfb[2], iv + 8);                                  \
+      SILC_GET32_MSB(cfb[3], iv + 12);                                 \
+                                                                       \
+      enc;                                                             \
+                                                                       \
+      SILC_PUT32_MSB(cfb[0], iv);                                      \
+      SILC_PUT32_MSB(cfb[1], iv + 4);                                  \
+      SILC_PUT32_MSB(cfb[2], iv + 8);                                  \
+      SILC_PUT32_MSB(cfb[3], iv + 12);                                 \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = (*dst = *src ^ iv[pad]);                                 \
+    dst++;                                                             \
+    src++;                                                             \
+    pad++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 32-bit cfb argument must be decrypted. */
+
+#define SILC_CFB_DEC_MSB_128_32(iv, cfb, pad, src, dst, dec)           \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      SILC_GET32_MSB(cfb[0], iv);                                      \
+      SILC_GET32_MSB(cfb[1], iv + 4);                                  \
+      SILC_GET32_MSB(cfb[2], iv + 8);                                  \
+      SILC_GET32_MSB(cfb[3], iv + 12);                                 \
+                                                                       \
+      dec;                                                             \
+                                                                       \
+      SILC_PUT32_MSB(cfb[0], iv);                                      \
+      SILC_PUT32_MSB(cfb[1], iv + 4);                                  \
+      SILC_PUT32_MSB(cfb[2], iv + 8);                                  \
+      SILC_PUT32_MSB(cfb[3], iv + 12);                                 \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = *src ^ iv[pad];                                          \
+    *dst = iv[pad];                                                    \
+    iv[pad++] = *src;                                                  \
+    dst++;                                                             \
+    src++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 64-bit block, MSB, the 32-bit cfb argument must be encrypted. */
+
+#define SILC_CFB_ENC_MSB_64_32(iv, cfb, pad, src, dst, enc)            \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 8) {                                                    \
+      SILC_GET32_MSB(cfb[0], iv);                                      \
+      SILC_GET32_MSB(cfb[1], iv + 4);                                  \
+                                                                       \
+      enc;                                                             \
+                                                                       \
+      SILC_PUT32_MSB(cfb[0], iv);                                      \
+      SILC_PUT32_MSB(cfb[1], iv + 4);                                  \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = (*dst = *src ^ iv[pad]);                                 \
+    dst++;                                                             \
+    src++;                                                             \
+    pad++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 64-bit block, MSB, the 32-bit cfb argument must be decrypted. */
+
+#define SILC_CFB_DEC_MSB_64_32(iv, cfb, pad, src, dst, dec)            \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 8) {                                                    \
+      SILC_GET32_MSB(cfb[0], iv);                                      \
+      SILC_GET32_MSB(cfb[1], iv + 4);                                  \
+                                                                       \
+      dec;                                                             \
+                                                                       \
+      SILC_PUT32_MSB(cfb[0], iv);                                      \
+      SILC_PUT32_MSB(cfb[1], iv + 4);                                  \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = *src ^ iv[pad];                                          \
+    *dst = iv[pad];                                                    \
+    iv[pad++] = *src;                                                  \
+    dst++;                                                             \
+    src++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 8-bit iv argument must be encrypted. */
+
+#define SILC_CFB_ENC_MSB_128_8(iv, pad, src, dst, enc)                 \
+do {                                                                   \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      enc;                                                             \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = (*dst = *src ^ iv[pad]);                                 \
+    dst++;                                                             \
+    src++;                                                             \
+    pad++;                                                             \
+  }                                                                    \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 8-bit iv argument must be decrypted. */
+
+#define SILC_CFB_DEC_MSB_128_8(iv, pad, src, dst, dec)                 \
+ do {                                                                  \
+  while (len-- > 0) {                                                  \
+    if (pad == 16) {                                                   \
+      dec;                                                             \
+      pad = 0;                                                         \
+    }                                                                  \
+    iv[pad] = *src ^ iv[pad];                                          \
+    *dst = iv[pad];                                                    \
+    iv[pad++] = *src;                                                  \
+    dst++;                                                             \
+    src++;                                                             \
+  }                                                                    \
+} while(0)
 
 #endif
index e6dcb1c3a4a5fa9dca85a4d7bcbec681625581e6..c1dc7e80fc4e86eac4eb7832fa4bf79c0fd32b8a 100644 (file)
@@ -37,7 +37,6 @@
 #define KS_LENGTH       60
 
 typedef union {
-  uint_32t l;
   uint_8t b[4];
 } aes_inf;
 
index c783afb92eabd86951f8e2d1cee50b0d4283f085..b434fef5cf770554febe904e29bc512b1c318a82 100644 (file)
@@ -48,14 +48,21 @@ const SilcCipherObject silc_default_ciphers[] =
   SILC_CDEF("aes-256-cbc", aes, 256, 16, 16, SILC_CIPHER_MODE_CBC),
   SILC_CDEF("aes-192-cbc", aes, 192, 16, 16, SILC_CIPHER_MODE_CBC),
   SILC_CDEF("aes-128-cbc", aes, 128, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("aes-256-cfb", aes, 256, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("aes-192-cfb", aes, 192, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("aes-128-cfb", aes, 128, 16, 16, SILC_CIPHER_MODE_CFB),
   SILC_CDEF("twofish-256-ctr", twofish, 256, 16, 16, SILC_CIPHER_MODE_CTR),
   SILC_CDEF("twofish-192-ctr", twofish, 192, 16, 16, SILC_CIPHER_MODE_CTR),
   SILC_CDEF("twofish-128-ctr", twofish, 128, 16, 16, SILC_CIPHER_MODE_CTR),
   SILC_CDEF("twofish-256-cbc", twofish, 256, 16, 16, SILC_CIPHER_MODE_CBC),
   SILC_CDEF("twofish-192-cbc", twofish, 192, 16, 16, SILC_CIPHER_MODE_CBC),
   SILC_CDEF("twofish-128-cbc", twofish, 128, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("twofish-256-cfb", twofish, 256, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("twofish-192-cfb", twofish, 192, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("twofish-128-cfb", twofish, 128, 16, 16, SILC_CIPHER_MODE_CFB),
   SILC_CDEF("cast5-128-ctr", cast5, 128, 8, 8, SILC_CIPHER_MODE_CTR),
   SILC_CDEF("cast5-128-cbc", cast5, 128, 8, 8, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("cast5-128-cfb", cast5, 128, 8, 8, SILC_CIPHER_MODE_CFB),
 #ifdef SILC_DEBUG
   SILC_CDEF("none", none, 0, 0, 0, 0),
 #endif /* SILC_DEBUG */
@@ -341,7 +348,7 @@ void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
 {
   if (iv)
     memmove(&cipher->iv, iv, cipher->cipher->iv_len);
-  cipher->cipher->set_iv(cipher->cipher, cipher->context, iv);
+  cipher->cipher->set_iv(cipher->cipher, cipher->context, cipher->iv);
 }
 
 /* Returns the IV (initial vector) of the cipher. */
index 5981ce73caef15718e3e5b3171518998a6fb4e3e..b24a69697d987b682eb9e970385ed61d2903cf73 100644 (file)
@@ -57,7 +57,43 @@ typedef struct SilcCipherStruct *SilcCipher;
  *
  * DESCRIPTION
  *
- *    Cipher modes.
+ *    Cipher modes.  Notes about cipher modes and implementation:
+ *
+ *    SILC_CIPHER_MODE_CBC
+ *
+ *      The Cipher-block Chaining mode.  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.
+ *
+ *    SILC_CIPHER_MODE_CTR
+ *
+ *      The Counter mode.  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 counter
+ *      mode expects MSB first ordered counter.  Note also, the counter is
+ *      incremented when silc_cipher_encrypt is called for the first time,
+ *      before encrypting.
+ *
+ *    SILC_CIPHER_MODE_CFB
+ *
+ *      The Cipher Feedback mode.  The CFB mode is normal cipher feedback mode.
+ *      The CFB 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 stream are used next time silc_cipher_encrypt is
+ *      called.  If silc_cipher_set_iv is called it will reset the feedback
+ *      for a new block (discarding any remaining bits from previous stream).
+ *
+ *    SILC_CIPHER_MODE_OFB
+ *
+ *      The Output Feedback mode.
+ *
+ *    SILC_CIPHER_MODE_ECB
+ *
+ *      The Electronic Codebook mode.  This mode does not provide sufficient
+ *      security and should not be used.
  *
  * SOURCE
  */
@@ -169,19 +205,6 @@ SilcBool silc_cipher_unregister_all(void);
  *
  *    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 counter mode expects
- *    MSB first ordered counter.  Note also, the counter is incremented when
- *    silc_cipher_encrypt is called for the first time, before encrypting.
- *
- *    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);
 
index e5206b63d4bc6771c9422285b2548288e21b0f7a..a148d29113a60a305b0db272ea4b674db2eeb564 100644 (file)
                                 const unsigned char *key,              \
                                 SilcUInt32 keylen,                     \
                                 SilcBool encryption)
-#define SILC_CIPHER_API_SET_IV(name)                           \
+#define SILC_CIPHER_API_SET_IV(name)                                   \
   void silc_##name##_set_iv(struct SilcCipherObjectStruct *cipher,     \
-                           void *context,                      \
-                           const unsigned char *iv)
+                           void *context,                              \
+                           unsigned char *iv)
 #define SILC_CIPHER_API_ENCRYPT(name)                                  \
   SilcBool silc_##name##_encrypt(struct SilcCipherObjectStruct *cipher,        \
                                 void *context,                         \
@@ -67,7 +67,7 @@ struct SilcCipherObjectStruct {
   /* Set IV.  The upper layer (SilcCipher) maintains the IV.  If the algorithm
      needs to set the IV itself, this should be implemented. */
   void (*set_iv)(struct SilcCipherObjectStruct *cipher,
-                void *context, const unsigned char *iv);
+                void *context, unsigned char *iv);
 
   /* Encrypt.  The `src' and `dst' may be same pointer.  The `iv' may be
      edited inside this function. */
index 0a104598a4d215bb977993de7901e75d4290c56c..87073b30a42d262da58c06ec56a609a24adefb42 100644 (file)
@@ -45,6 +45,16 @@ const unsigned char p5[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C
 int p5_len = 36;
 const unsigned char c5[] = "\xEB\x6C\x52\x82\x1D\x0B\xBB\xF7\xCE\x75\x94\x46\x2A\xCA\x4F\xAA\xB4\x07\xDF\x86\x65\x69\xFD\x07\xF4\x8C\xC0\xB5\x83\xD6\x07\x1F\x1E\xC0\xE6\xB8";
 
+/* CFB */
+
+/* 36 bytes plaintext, 256 bits key */
+const unsigned char key6[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key6_len = 32 * 8;
+const unsigned char iv6[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p6[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p6_len = 36;
+const unsigned char c6[] = "\x7C\x4C\x1D\xB1\x25\x20\x76\x4E\x86\x57\x16\xEF\x82\x93\x53\x62\xE8\x99\x98\x11\xCB\x83\x1A\xEA\x61\x0D\xC7\xE3\x91\x19\x5F\x5D\xD8\xA6\x7B\xD5";
+
 int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
@@ -242,6 +252,47 @@ int main(int argc, char **argv)
   SILC_LOG_DEBUG(("Decrypt is successful"));
   silc_cipher_free(cipher2);
 
+
+  SILC_LOG_DEBUG(("Allocating aes-256-cfb cipher"));
+  if (!silc_cipher_alloc("aes-256-cfb", &cipher)) {
+    SILC_LOG_DEBUG(("Allocating aes-256-cfb cipher failed"));
+    goto err;
+  }
+  if (!silc_cipher_alloc("aes-256-cfb", &cipher2)) {
+    SILC_LOG_DEBUG(("Allocating aes-256-cfb cipher failed"));
+    goto err;
+  }
+
+  SILC_LOG_DEBUG(("CFB test vector"));
+  memset(dst, 0, sizeof(dst));
+  memset(pdst, 0, sizeof(pdst));
+  silc_cipher_set_iv(cipher, iv6);
+  assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
+  assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
+  assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
+  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+                silc_cipher_get_block_len(cipher),
+                silc_cipher_get_key_len(cipher),
+                silc_cipher_get_name(cipher)));
+  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
+  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
+  if (memcmp(dst, c6, p6_len)) {
+    SILC_LOG_DEBUG(("Encrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encrypt is successful"));
+  silc_cipher_set_iv(cipher2, iv6);
+  assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
+  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
+  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p6, p6_len);
+  if (memcmp(pdst, p6, p6_len)) {
+    SILC_LOG_DEBUG(("Decrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypt is successful"));
+  silc_cipher_free(cipher2);
+
   success = TRUE;
 
  err:
index 0954ae274d893abaf9530c7677ead43e1ccc114e..af76bced7e7a7550eefcba046e68c400188fdd6e 100644 (file)
@@ -16,7 +16,7 @@ const unsigned char p2[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c
 int p2_len = 32;
 const unsigned char c2[] = "\x23\xA5\xBD\xC5\x2A\x59\xD4\x06\x61\xBF\xF3\x47\x76\x4B\xC8\x41\x1C\x65\xE3\xE2\x1A\x1F\x42\x4B\xBD\x22\xDF\xEC\xD9\xC9\x52\x43";
 
-/* CTR test vectors from RFC3686. */
+/* CTR */
 
 /* 32 bytes plaintext, 128 bits key */
 const unsigned char key4[] = "\x7E\x24\x06\x78\x17\xFA\xE0\xD7\x43\xD6\xCE\x1F\x32\x53\x91\x63";
@@ -26,6 +26,16 @@ const unsigned char p4[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C
 int p4_len = 32;
 const unsigned char c4[] = "\xAA\x16\xEC\xEA\x77\x73\x12\xC1\x14\x0F\x10\x65\x06\x72\xF8\xE5\x89\xCF\x26\x2C\x84\xC6\x3A\x93\xEE\xC0\xB2\xBA\x92\xAD\x19\xCA";
 
+/* CFB */
+
+/* 36 bytes plaintext, 128 bits key */
+const unsigned char key6[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key6_len = 16 * 8;
+const unsigned char iv6[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p6[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p6_len = 36;
+const unsigned char c6[] = "\xE2\x30\xB2\x57\x12\x31\x04\x54\x37\xEC\xF1\x43\xC1\x3F\x20\x53\xA4\xDD\x99\x29\x3C\xCA\x4A\x7C\xCC\xEA\x12\xBF\xA8\x05\x37\x89\xA9\xB3\x3B\x15";
+
 int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
@@ -151,6 +161,47 @@ int main(int argc, char **argv)
   SILC_LOG_DEBUG(("Decrypt is successful"));
   silc_cipher_free(cipher);
 
+
+  SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher"));
+  if (!silc_cipher_alloc("cast5-128-cfb", &cipher)) {
+    SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher failed"));
+    goto err;
+  }
+  if (!silc_cipher_alloc("cast5-128-cfb", &cipher2)) {
+    SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher failed"));
+    goto err;
+  }
+
+  SILC_LOG_DEBUG(("CFB test vector"));
+  memset(dst, 0, sizeof(dst));
+  memset(pdst, 0, sizeof(pdst));
+  silc_cipher_set_iv(cipher, iv6);
+  assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
+  assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
+  assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
+  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+                silc_cipher_get_block_len(cipher),
+                silc_cipher_get_key_len(cipher),
+                silc_cipher_get_name(cipher)));
+  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
+  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
+  if (memcmp(dst, c6, p6_len)) {
+    SILC_LOG_DEBUG(("Encrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encrypt is successful"));
+  silc_cipher_set_iv(cipher2, iv6);
+  assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
+  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
+  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p6, p6_len);
+  if (memcmp(pdst, p6, p6_len)) {
+    SILC_LOG_DEBUG(("Decrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypt is successful"));
+  silc_cipher_free(cipher2);
+
   success = TRUE;
 
  err:
index 730b1a08db7eb1e4530cf87f96329425728b0241..89731328e9335e5d76d3dd3e756fa090c7192b1a 100644 (file)
@@ -45,6 +45,16 @@ const unsigned char p5[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C
 int p5_len = 36;
 const unsigned char c5[] = "\x71\x2F\x9C\xE1\x4F\xD5\x9E\xBF\x6A\x1E\x7D\x76\x0C\xBA\x70\xE9\x5E\xCE\x27\xAD\x5B\xE1\x38\xDB\x99\xEF\x46\x78\x4D\xCF\x99\x24\x63\x0E\x84\x58";
 
+/* CFB */
+
+/* 36 bytes plaintext, 256 bits key */
+const unsigned char key6[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key6_len = 32 * 8;
+const unsigned char iv6[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p6[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p6_len = 36;
+const unsigned char c6[] = "\x2C\x0E\x4D\xEF\xE4\x71\xEB\x2A\x4B\x03\x21\x96\xD1\xCD\x73\xD7\x3A\xA9\xEB\x08\x87\xB2\xAB\x66\x28\x3A\xC2\x99\xB7\x13\x8C\x92\xEA\xD6\xFD\x41";
+
 int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
@@ -142,7 +152,7 @@ int main(int argc, char **argv)
   }
 
   /* Third test vector */
-  SILC_LOG_DEBUG(("Third test vector"));
+  SILC_LOG_DEBUG(("CTR test vector"));
   memset(dst, 0, sizeof(dst));
   memset(pdst, 0, sizeof(pdst));
   silc_cipher_set_iv(cipher, iv3);
@@ -172,7 +182,7 @@ int main(int argc, char **argv)
 
 
   /* Fourth test vector */
-  SILC_LOG_DEBUG(("Fourth test vector"));
+  SILC_LOG_DEBUG(("CTR test vector"));
   memset(dst, 0, sizeof(dst));
   memset(pdst, 0, sizeof(pdst));
   silc_cipher_set_iv(cipher, iv4);
@@ -212,7 +222,7 @@ int main(int argc, char **argv)
   }
 
   /* Fifth test vector */
-  SILC_LOG_DEBUG(("Fifth test vector"));
+  SILC_LOG_DEBUG(("CTR test vector"));
   memset(dst, 0, sizeof(dst));
   memset(pdst, 0, sizeof(pdst));
   silc_cipher_set_iv(cipher, iv5);
@@ -242,6 +252,48 @@ int main(int argc, char **argv)
   SILC_LOG_DEBUG(("Decrypt is successful"));
   silc_cipher_free(cipher2);
 
+
+  SILC_LOG_DEBUG(("Allocating twofish-256-cfb cipher"));
+  if (!silc_cipher_alloc("twofish-256-cfb", &cipher)) {
+    SILC_LOG_DEBUG(("Allocating twofish-256-cfb cipher failed"));
+    goto err;
+  }
+  if (!silc_cipher_alloc("twofish-256-cfb", &cipher2)) {
+    SILC_LOG_DEBUG(("Allocating twofish-256-cfb cipher failed"));
+    goto err;
+  }
+
+  /* Fifth test vector */
+  SILC_LOG_DEBUG(("CFB test vector"));
+  memset(dst, 0, sizeof(dst));
+  memset(pdst, 0, sizeof(pdst));
+  silc_cipher_set_iv(cipher, iv6);
+  assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
+  assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
+  assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
+  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+                silc_cipher_get_block_len(cipher),
+                silc_cipher_get_key_len(cipher),
+                silc_cipher_get_name(cipher)));
+  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
+  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
+  if (memcmp(dst, c6, p6_len)) {
+    SILC_LOG_DEBUG(("Encrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encrypt is successful"));
+  silc_cipher_set_iv(cipher2, iv6);
+  assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
+  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
+  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p5, p6_len);
+  if (memcmp(pdst, p6, p6_len)) {
+    SILC_LOG_DEBUG(("Decrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypt is successful"));
+  silc_cipher_free(cipher2);
+
   success = TRUE;
 
  err:
index 53caed419f151b0d57e1931343b1579c40b7644d..87d443c7fc91f67e4b8fc1140aa82b6e7040e0d4 100644 (file)
@@ -63,11 +63,22 @@ SILC_CIPHER_API_SET_KEY(twofish)
 
 SILC_CIPHER_API_SET_IV(twofish)
 {
-  if (cipher->mode == SILC_CIPHER_MODE_CTR) {
-    TwofishContext *twofish = context;
+  TwofishContext *twofish = context;
+
+  switch (cipher->mode) {
 
+  case SILC_CIPHER_MODE_CTR:
     /* Starts new block. */
     twofish->padlen = 0;
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    /* Starts new block. */
+    twofish->padlen = 16;
+    break;
+
+  default:
+    break;
   }
 }
 
@@ -90,62 +101,18 @@ SILC_CIPHER_API_ENCRYPT(twofish)
   switch (cipher->mode) {
 
   case SILC_CIPHER_MODE_CBC:
-    SILC_ASSERT((len & (16 - 1)) == 0);
-    if (len & (16 - 1))
-      return FALSE;
-    SILC_CBC_GET_IV(tmp, iv);
-
-    SILC_CBC_ENC_PRE(tmp, src);
-    twofish_encrypt(twofish, tmp, tmp);
-    SILC_CBC_ENC_POST(tmp, dst, src);
-
-    for (i = 16; i < len; i += 16) {
-      SILC_CBC_ENC_PRE(tmp, src);
-      twofish_encrypt(twofish, tmp, tmp);
-      SILC_CBC_ENC_POST(tmp, dst, src);
-    }
-
-    SILC_CBC_PUT_IV(tmp, iv);
+    SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i,
+                           twofish_encrypt(twofish, tmp, tmp));
     break;
 
   case SILC_CIPHER_MODE_CTR:
-    SILC_GET32_MSB(ctr[0], iv);
-    SILC_GET32_MSB(ctr[1], iv + 4);
-    SILC_GET32_MSB(ctr[2], iv + 8);
-    SILC_GET32_MSB(ctr[3], iv + 12);
-
-    i = twofish->padlen;
-    if (!i)
-      i = 16;
-
-    while (len-- > 0) {
-      if (i == 16) {
-       if (++ctr[3] == 0)
-         if (++ctr[2] == 0)
-           if (++ctr[1] == 0)
-             ++ctr[0];
-
-       tmp[0] = SILC_SWAB_32(ctr[0]);
-       tmp[1] = SILC_SWAB_32(ctr[1]);
-       tmp[2] = SILC_SWAB_32(ctr[2]);
-       tmp[3] = SILC_SWAB_32(ctr[3]);
-
-       twofish_encrypt(twofish, tmp, tmp);
-
-       SILC_PUT32_LSB(tmp[0], iv);
-       SILC_PUT32_LSB(tmp[1], iv + 4);
-       SILC_PUT32_LSB(tmp[2], iv + 8);
-       SILC_PUT32_LSB(tmp[3], iv + 12);
-       i = 0;
-      }
-      *dst++ = *src++ ^ iv[i++];
-    }
-    twofish->padlen = i;
+    SILC_CTR_LSB_128_32(iv, ctr, tmp, twofish->padlen, src, dst,
+                       twofish_encrypt(twofish, tmp, tmp));
+    break;
 
-    SILC_PUT32_MSB(ctr[0], iv);
-    SILC_PUT32_MSB(ctr[1], iv + 4);
-    SILC_PUT32_MSB(ctr[2], iv + 8);
-    SILC_PUT32_MSB(ctr[3], iv + 12);
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_ENC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+                           twofish_encrypt(twofish, tmp, tmp));
     break;
 
   default:
@@ -160,33 +127,25 @@ SILC_CIPHER_API_ENCRYPT(twofish)
 
 SILC_CIPHER_API_DECRYPT(twofish)
 {
+  TwofishContext *twofish = context;
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
 
   switch (cipher->mode) {
 
   case SILC_CIPHER_MODE_CBC:
-    if (len & (16 - 1))
-      return FALSE;
-
-    SILC_CBC_GET_IV(tiv, iv);
-
-    SILC_CBC_DEC_PRE(tmp, src);
-    twofish_decrypt((TwofishContext *)context, tmp, tmp2);
-    SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
-
-    for (i = 16; i < len; i += 16) {
-      SILC_CBC_DEC_PRE(tmp, src);
-      twofish_decrypt((TwofishContext *)context, tmp, tmp2);
-      SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
-    }
-
-    SILC_CBC_PUT_IV(tiv, iv);
+    SILC_CBC_DEC_LSB_128_32(len, iv, tiv, tmp, tmp2, src, dst, i,
+                           twofish_decrypt(twofish, tmp, tmp2));
 
   case SILC_CIPHER_MODE_CTR:
     return silc_twofish_encrypt(cipher, context, src, dst, len, iv);
     break;
 
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_DEC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+                           twofish_encrypt(twofish, tmp, tmp));
+    break;
+
   default:
     return FALSE;
   }