Added CFB mode to aes, twofish and cast5. Unified the CBC, CFB and
[silc.git] / lib / silccrypt / ciphers_def.h
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