Major restructuring of the internals of SILC Cipher API
authorPekka Riikonen <priikone@silcnet.org>
Sat, 23 Feb 2008 13:59:32 +0000 (15:59 +0200)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 23 Feb 2008 13:59:32 +0000 (15:59 +0200)
The API now has two new operation functions init and uninit, and the
old context_len operation is removed.  The init is called in
silc_cipher_alloc and uninit is called in silc_cipher_free.  The init()
function must allocate and return the internal algorithm context.
Changed all supported ciphers to use the new API.

Fixed also CTR mode encryption of partial blocks.  Optimized also the CTR
mode especially on little endian systems.

Imported entirely new Twofish implementation from the public domain
library libtomcrypt.

Renamed rjindael_internal.h to aes_internal.h.

29 files changed:
configure.ad
lib/Makefile.ad
lib/silccrypt/aes.c
lib/silccrypt/aes.h
lib/silccrypt/aes_internal.h [moved from lib/silccrypt/rijndael_internal.h with 100% similarity]
lib/silccrypt/blowfish.c
lib/silccrypt/blowfish.h
lib/silccrypt/cast.c
lib/silccrypt/cast.h
lib/silccrypt/cast5.c
lib/silccrypt/cast5.h
lib/silccrypt/ciphers_def.h
lib/silccrypt/des.c
lib/silccrypt/des.h
lib/silccrypt/none.c
lib/silccrypt/none.h
lib/silccrypt/rc5.c
lib/silccrypt/rc5.h
lib/silccrypt/sha256.c
lib/silccrypt/silccipher.c
lib/silccrypt/silccipher.h
lib/silccrypt/silccipher_i.h
lib/silccrypt/tests/Makefile.am
lib/silccrypt/tests/test_aes.c
lib/silccrypt/tests/test_cipher.c [new file with mode: 0644]
lib/silccrypt/tests/test_twofish.c
lib/silccrypt/twofish.c
lib/silccrypt/twofish.h
lib/silccrypt/twofish_internal.h

index 7b0dfaf811e0551037ff4ea186f1abe9ff98ebd3..a45f57dd35bf4d95253cebaad9be043516688d76 100644 (file)
@@ -141,6 +141,9 @@ case "$host_cpu" in
 
   # Intel IA-64, 64-bit CPU (not x86_64 compatible)
   ia64)
+    AC_DEFINE([SILC_IA64], [], [SILC_IA64])
+    cpu_ia64=true
+
     # Check for specific CPU features
     SILC_CPU_FLAG(mmx, true, AC_DEFINE([SILC_CPU_MMX], [], [SILC_CPU_MMX]), [])
     SILC_CPU_FLAG(sse2, true, AC_DEFINE([SILC_CPU_SSE2], [], [SILC_CPU_SSE2]), [])
@@ -151,6 +154,8 @@ case "$host_cpu" in
 
   # AMD/Intel x86_64, 64-bit CPU
   x86_64)
+    cpu_x86_64=true
+
     # Check for specific CPU features
     SILC_CPU_FLAG(mmx, true, AC_DEFINE([SILC_CPU_MMX], [], [SILC_CPU_MMX]), [])
     SILC_CPU_FLAG(sse2, true, AC_DEFINE([SILC_CPU_SSE2], [], [SILC_CPU_SSE2]), [])
@@ -161,6 +166,7 @@ case "$host_cpu" in
 
   # PowerPC, 32-bit and 64-bit CPUs
   powerpc*)
+    cpu_ppc=true
     ;;
 esac
 AM_CONDITIONAL(SILC_I386, test x$cpu_i386 = xtrue)
@@ -176,17 +182,15 @@ if test x$want_cpu_optimizations = xtrue; then
   # Set some compiler options based on CPU
   if test "x$CC" = "xicc"; then
     # ICC flags
-    if test x$x_have_cpu_sse2 = xtrue; then
-      SILC_ADD_CFLAGS(-axW)
-    fi
-    if test x$x_have_cpu_sse3 = xtrue; then
-      SILC_ADD_CFLAGS(-axP)
+    if test x$x_have_cpu_sse4 = xtrue; then
+      SILC_ADD_CFLAGS(-axS)
     fi
     if test x$x_have_cpu_ssse3 = xtrue; then
       SILC_ADD_CFLAGS(-axT)
-    fi
-    if test x$x_have_cpu_sse4 = xtrue; then
-      SILC_ADD_CFLAGS(-axS)
+    elif test x$x_have_cpu_pni = xtrue; then
+      SILC_ADD_CFLAGS(-axP)
+    elif test x$x_have_cpu_sse2 = xtrue; then
+      SILC_ADD_CFLAGS(-axW)
     fi
   else
     # Other compilers
@@ -491,6 +495,9 @@ SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcssh"
 #ifdef SILC_DIST_PGP
 SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcpgp"
 #endif SILC_DIST_PGP
+#ifdef SILC_DIST_PKIX
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcpkix"
+#endif SILC_DIST_PKIX
 
 # SILC Runtime Toolkit checking
 AC_ARG_WITH(srt-includes,
@@ -660,6 +667,10 @@ lib/silcssh/tests/Makefile
 lib/silcpgp/Makefile
 lib/silcpgp/tests/Makefile
 #endif SILC_DIST_PGP
+#ifdef SILC_DIST_PKIX
+lib/silcpkix/Makefile
+lib/silcpkix/tests/Makefile
+#endif SILC_DIST_PKIX
 lib/silcskr/Makefile
 lib/silcskr/tests/Makefile
 lib/silcmath/Makefile
index 0191e8472121438165085ced5c59bc8e8afda384..286f821391d5259760ad47f4669536758d1290e2 100644 (file)
@@ -30,6 +30,9 @@ CRYPTO_DIRS =                 \
 #ifdef SILC_DIST_PGP
        silcpgp         \
 #endif SILC_DIST_PGP
+#ifdef SILC_DIST_PKIX
+       silcpkix
+#endif SILC_DIST_PKIX
 
 if SILC_ENABLE_SHARED
 if SILC_WIN32
index 27a47cc95b43731f69c3f5fd33697fcf9811f8d3..f60f395226978acba8f984369b174b2ca916a121 100644 (file)
@@ -34,7 +34,7 @@
 */
 
 #include "silccrypto.h"
-#include "rijndael_internal.h"
+#include "aes_internal.h"
 #include "aes.h"
 
 /*
 
 SILC_CIPHER_API_SET_KEY(aes)
 {
-  switch (cipher->mode) {
+  switch (ops->mode) {
+  case SILC_CIPHER_MODE_CTR:
+  case SILC_CIPHER_MODE_CFB:
+    aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
+    break;
+
   case SILC_CIPHER_MODE_CBC:
+  case SILC_CIPHER_MODE_ECB:
     if (encryption)
       aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
     else
       aes_decrypt_key(key, keylen, &((AesContext *)context)->u.dec);
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-  case SILC_CIPHER_MODE_CFB:
-    aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
-    break;
-
   default:
     return FALSE;
   }
@@ -70,13 +71,9 @@ SILC_CIPHER_API_SET_IV(aes)
 {
   AesContext *aes = context;
 
-  switch (cipher->mode) {
+  switch (ops->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;
@@ -87,11 +84,22 @@ SILC_CIPHER_API_SET_IV(aes)
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
+
+SILC_CIPHER_API_INIT(aes)
+{
+  AesContext *aes = silc_calloc(1, sizeof(AesContext));
+  if (aes)
+    aes->u.enc.inf.b[2] = 16;
+}
+
+/* Unnitialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(aes)
+SILC_CIPHER_API_UNINIT(aes)
 {
-  return sizeof(AesContext);
+  AesContext *aes = context;
+  memset(aes, 0, sizeof(*aes));
+  silc_free(aes);
 }
 
 /* Encrypts with the cipher. Source and destination buffers maybe one and
@@ -100,12 +108,29 @@ SILC_CIPHER_API_CONTEXT_LEN(aes)
 SILC_CIPHER_API_ENCRYPT(aes)
 {
   AesContext *aes = context;
-  SilcUInt32 ctr[4];
+  int i;
+
+  switch (ops->mode) {
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_MSB_128_8(iv, cipher->block, aes->u.enc.inf.b[2], src, dst,
+                      aes_encrypt(iv, cipher->block, &aes->u.enc));
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 4;
+
+      while (nb--) {
+       aes_encrypt(src, dst, &aes->u.enc);
+       src += 16;
+       dst += 16;
+      }
+    }
+    break;
 
-  switch (cipher->mode) {
   case SILC_CIPHER_MODE_CBC:
     {
-      int nb = len >> 4;
+      SilcUInt32 nb = len >> 4;
 
       SILC_ASSERT((len & (16 - 1)) == 0);
       if (len & (16 - 1))
@@ -124,11 +149,6 @@ SILC_CIPHER_API_ENCRYPT(aes)
     }
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    SILC_CTR_MSB_128_8(iv, ctr, iv, aes->u.enc.inf.b[2], src, dst,
-                      aes_encrypt(iv, iv, &aes->u.enc));
-    break;
-
   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));
@@ -148,11 +168,27 @@ SILC_CIPHER_API_DECRYPT(aes)
 {
   AesContext *aes = context;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+  case SILC_CIPHER_MODE_CTR:
+    return silc_aes_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 4;
+
+      while (nb--) {
+       aes_decrypt(src, dst, &aes->u.dec);
+       src += 16;
+       dst += 16;
+      }
+    }
+    break;
+
   case SILC_CIPHER_MODE_CBC:
     {
       unsigned char tmp[16];
-      int nb = len >> 4;
+      SilcUInt32 nb = len >> 4;
 
       if (len & (16 - 1))
        return FALSE;
@@ -171,10 +207,6 @@ SILC_CIPHER_API_DECRYPT(aes)
     }
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    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));
index 008b3d1a462b6cfb08d43d17cb73e1dc7e3bb434..f573638b2c003a57d01a0e1922e5ed4b3b70c6db 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2007 Pekka Riikonen
+  Copyright (C) 1997 - 2008 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
@@ -28,6 +28,7 @@ SILC_CIPHER_API_SET_KEY(aes);
 SILC_CIPHER_API_SET_IV(aes);
 SILC_CIPHER_API_ENCRYPT(aes);
 SILC_CIPHER_API_DECRYPT(aes);
-SILC_CIPHER_API_CONTEXT_LEN(aes);
+SILC_CIPHER_API_INIT(aes);
+SILC_CIPHER_API_UNINIT(aes);
 
 #endif
index 067a8fb701fa1364a56c4223c19932442aa9210b..862f1c2015f0ac980b90998d542bbaf92a1bdf44 100644 (file)
@@ -56,11 +56,20 @@ SILC_CIPHER_API_SET_IV(blowfish_cbc)
 
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(blowfish_cbc)
+SILC_CIPHER_API_INIT(blowfish_cbc)
 {
-  return sizeof(BlowfishContext);
+  return silc_calloc(1, sizeof(BlowfishContext));
+}
+
+/* Unnitialize */
+
+SILC_CIPHER_API_UNINIT(blowfish_cbc)
+{
+  BlowfishContext *b = context;
+  memset(b, 0, sizeof(*b));
+  silc_free(b);
 }
 
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
index 996f7fe97f10e96506e9548e23aae9add826bbae..ece02a38b9cf3731a9eefe4ba421579cadb72f64 100644 (file)
@@ -26,7 +26,8 @@
 
 SILC_CIPHER_API_SET_KEY(blowfish_cbc);
 SILC_CIPHER_API_SET_IV(blowfish_cbc);
-SILC_CIPHER_API_CONTEXT_LEN(blowfish_cbc);
+SILC_CIPHER_API_INIT(blowfish_cbc);
+SILC_CIPHER_API_UNINIT(blowfish_cbc);
 SILC_CIPHER_API_ENCRYPT(blowfish_cbc);
 SILC_CIPHER_API_DECRYPT(blowfish_cbc);
 
index dbf27e716d94dc6a3a28c7a5f334784c71997965..ac8aa770b50d60daff1474a079c66ee258335102 100644 (file)
@@ -87,11 +87,20 @@ SILC_CIPHER_API_SET_IV(cast_cbc)
 
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(cast_cbc)
+SILC_CIPHER_API_INIT(cast_cbc)
 {
-  return sizeof(CastContext);
+  return silc_calloc(1, sizeof(CastContext));
+}
+
+/* Uninitialize */
+
+SILC_CIPHER_API_UNINIT(cast_cbc)
+{
+  CastContext *cast = context;
+  memset(cast, 0, sizeof(*cast));
+  silc_free(cast);
 }
 
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
index 383b9fdde207472484f1f93a158cdd824e638d65..8a06bfad58a687d9ad7c330dd48ec556f0910224 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1999 - 2000, 2006, 2007 Pekka Riikonen
+  Copyright (C) 1999 - 2008 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
@@ -26,7 +26,8 @@
 
 SILC_CIPHER_API_SET_KEY(cast_cbc);
 SILC_CIPHER_API_SET_IV(cast_cbc);
-SILC_CIPHER_API_CONTEXT_LEN(cast_cbc);
+SILC_CIPHER_API_INIT(cast_cbc);
+SILC_CIPHER_API_UNINIT(cast_cbc);
 SILC_CIPHER_API_ENCRYPT(cast_cbc);
 SILC_CIPHER_API_DECRYPT(cast_cbc);
 
index dc1774eb620bed45819aa15783828a1d399f6f01..2d5cf2206c62ccc5f353f6c4a739a7e06bb57df7 100644 (file)
@@ -24,13 +24,9 @@ SILC_CIPHER_API_SET_IV(cast5)
 {
   cast5_key *cast5 = context;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    /* Starts new block. */
-    cast5->padlen = 0;
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     /* Starts new block. */
     cast5->padlen = 8;
@@ -41,31 +37,58 @@ SILC_CIPHER_API_SET_IV(cast5)
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(cast5)
+SILC_CIPHER_API_INIT(cast5)
 {
-  return sizeof(cast5_key);
+  cast5_key *cast5 = silc_calloc(1, sizeof(cast5_key));
+  if (cast5)
+    cast5->padlen = 8;
+}
+
+/* Uninitialize */
+
+SILC_CIPHER_API_UNINIT(cast5)
+{
+  cast5_key *cast5 = context;
+  memset(cast5, 0, sizeof(*cast5));
+  silc_free(cast5);
 }
 
 SILC_CIPHER_API_ENCRYPT(cast5)
 {
   cast5_key *cast5 = context;
-  SilcUInt32 tmp[2], ctr[2];
+  SilcUInt32 tmp[2];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_MSB_64_32(iv, tmp, cipher->block, cast5->padlen, src, dst,
+                      cast5_encrypt(cast5, tmp, tmp));
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_MSB(tmp[0], src);
+        SILC_GET32_MSB(tmp[1], src + 4);
+        cast5_encrypt(cast5, tmp, tmp);
+        SILC_PUT32_MSB(tmp[0], dst);
+        SILC_PUT32_MSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
+    }
+    break;
 
   case SILC_CIPHER_MODE_CBC:
     SILC_CBC_ENC_MSB_64_32(len, iv, tmp, src, dst, i,
                           cast5_encrypt(cast5, tmp, tmp));
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    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));
@@ -84,17 +107,33 @@ SILC_CIPHER_API_DECRYPT(cast5)
   SilcUInt32 tmp[2], tmp2[2], tiv[2];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    return silc_cast5_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_LSB(tmp[0], src);
+        SILC_GET32_LSB(tmp[1], src + 4);
+        cast5_decrypt(cast5, tmp, tmp);
+        SILC_PUT32_LSB(tmp[0], dst);
+        SILC_PUT32_LSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
+    }
+    break;
 
   case SILC_CIPHER_MODE_CBC:
     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));
index 2860ab16531c510e88298a4190e27d013bf46e03..5e403ad737ed26c3ddd0e40ce973a7531b754bd3 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2007 Pekka Riikonen
+  Copyright (C) 2007 - 2008 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
@@ -26,7 +26,8 @@
 
 SILC_CIPHER_API_SET_KEY(cast5);
 SILC_CIPHER_API_SET_IV(cast5);
-SILC_CIPHER_API_CONTEXT_LEN(cast5);
+SILC_CIPHER_API_INIT(cast5);
+SILC_CIPHER_API_UNINIT(cast5);
 SILC_CIPHER_API_ENCRYPT(cast5);
 SILC_CIPHER_API_DECRYPT(cast5);
 
index d99da6df3539e7d147e892a379ec685445685250..ad00c9aa90246e39b518c491b81916c8a820ccf6 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1999 - 2007 Pekka Riikonen
+  Copyright (C) 1999 - 2008 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
@@ -20,6 +20,9 @@
 #ifndef CIPHERS_DEF_H
 #define CIPHERS_DEF_H
 
+
+#include "silclog.h"
+
 /* General definitions for algorithms */
 typedef unsigned char u1byte;
 typedef SilcUInt32 u4byte;
@@ -265,147 +268,103 @@ do {                                                                    \
   SILC_PUT32_MSB(block[1], &iv[4]);                                    \
 } while(0)
 
+#ifndef WORDS_BIGENDIAN
 
-/* CTR mode 128-bit block, MSB, MSB counter, the 8-bit enc_ctr argument must
-   be encrypted */
+/* CTR mode 128-bit block, MSB, MSB counter, the 8-bit ctr argument must
+   be encrypted to enc_ctr */
 
-#define SILC_CTR_MSB_128_8(iv, ctr, enc_ctr, pad, src, dst, enc)       \
+#define SILC_CTR_MSB_128_8(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) {                                                  \
+  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);                            \
+      for (i = 15; i >= 0; i--)                                                \
+       if (++ctr[i])                                                   \
+         break;                                                        \
                                                                        \
       enc;                                                             \
+                                                                       \
+      if (len >= 16) {                                                 \
+       *(SilcUInt64 *)dst = *(SilcUInt64 *)src ^ *(SilcUInt64 *)enc_ctr; \
+       *(SilcUInt64 *)(dst + 8) = *(SilcUInt64 *)(src + 8) ^           \
+         *(SilcUInt64 *)(enc_ctr + 8);                                 \
+       src += 16;                                                      \
+       dst += 16;                                                      \
+       len -= 16;                                                      \
+       silc_prefetch((void *)src, 0, 0);                               \
+       continue;                                                       \
+      }                                                                        \
       pad = 0;                                                         \
     }                                                                  \
     *dst++ = *src++ ^ enc_ctr[pad++];                                  \
+    len--;                                                             \
   }                                                                    \
-                                                                       \
-  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 */
+#else /* WORDS_BIGENDIAN */
 
-#define SILC_CTR_MSB_128_32(iv, ctr, enc_ctr, pad, src, dst, enc)      \
+#define SILC_CTR_MSB_128_8(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];                                                   \
+      for (i = 15; i >= 0; i--)                                                \
+       if (++ctr[i])                                                   \
+         break;                                                        \
                                                                        \
       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 */
+#endif /* !WORDS_BIGENDIAN */
+
+/* CTR mode 128-bit block, LSB, MSB counter, the 32-bit tmp argument
+   must be encrypted, enc_ctr must have the encrypted data too.  */
 
-#define SILC_CTR_LSB_128_32(iv, ctr, enc_ctr, pad, src, dst, enc)      \
+#define SILC_CTR_LSB_128_32(ctr, tmp, 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]);                               \
+      for (i = 15; i >= 0; i--)                                                \
+       if (++ctr[i])                                                   \
+         break;                                                        \
                                                                        \
+      SILC_GET32_LSB(tmp[0], ctr);                                     \
+      SILC_GET32_LSB(tmp[1], ctr + 4);                                 \
+      SILC_GET32_LSB(tmp[2], ctr + 8);                                 \
+      SILC_GET32_LSB(tmp[3], ctr + 12);                                        \
       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);                             \
+      SILC_PUT32_LSB(tmp[0], enc_ctr);                                 \
+      SILC_PUT32_LSB(tmp[1], enc_ctr + 4);                             \
+      SILC_PUT32_LSB(tmp[2], enc_ctr + 8);                             \
+      SILC_PUT32_LSB(tmp[3], enc_ctr + 12);                            \
       pad = 0;                                                         \
     }                                                                  \
-    *dst++ = *src++ ^ iv[pad++];                                       \
+    *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 64-bit block, MSB, MSB counter, the 32-bit ctr argument must
-   be encrypted to enc_ctr */
+/* CTR mode 128-bit block, LSB, MSB counter, the 32-bit tmp argument
+   must be encrypted, enc_ctr must have the encrypted data too.  */
 
-#define SILC_CTR_MSB_64_32(iv, ctr, enc_ctr, pad, src, dst, enc)       \
+#define SILC_CTR_MSB_64_32(ctr, tmp, 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];                                                       \
+      for (i = 7; i >= 0; i--)                                         \
+       if (++ctr[i])                                                   \
+         break;                                                        \
                                                                        \
+      SILC_GET32_MSB(tmp[0], ctr);                                     \
+      SILC_GET32_MSB(tmp[1], ctr + 4);                                 \
       enc;                                                             \
-      SILC_PUT32_MSB(enc_ctr[0], iv);                                  \
-      SILC_PUT32_MSB(enc_ctr[1], iv + 4);                              \
+      SILC_PUT32_MSB(tmp[0], enc_ctr);                                 \
+      SILC_PUT32_MSB(tmp[1], enc_ctr + 4);                             \
       pad = 0;                                                         \
     }                                                                  \
-    *dst++ = *src++ ^ iv[pad++];                                       \
+    *dst++ = *src++ ^ enc_ctr[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. */
index 75c887eebc737b6fa9607ca6b8f88e0a7d117523..a61d92598612f529187bc3f12bda3ea61417803e 100644 (file)
@@ -24,13 +24,9 @@ SILC_CIPHER_API_SET_IV(des)
 {
   des_key *des = context;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    /* Starts new block. */
-    des->padlen = 0;
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     /* Starts new block. */
     des->padlen = 8;
@@ -41,31 +37,58 @@ SILC_CIPHER_API_SET_IV(des)
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(des)
+SILC_CIPHER_API_INIT(des)
 {
-  return sizeof(des_key);
+  des_key *des = silc_calloc(1, sizeof(des_key));
+  if (des)
+    des->padlen = 8;
+}
+
+/* Uninitialize */
+
+SILC_CIPHER_API_UNINIT(des)
+{
+  des_key *des = context;
+  memset(des, 0, sizeof(*des));
+  silc_free(des);
 }
 
 SILC_CIPHER_API_ENCRYPT(des)
 {
   des_key *des = context;
-  SilcUInt32 tmp[2], ctr[2];
+  SilcUInt32 tmp[2];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_MSB_64_32(iv, tmp, cipher->block, des->padlen, src, dst,
+                      des_encrypt(des, tmp, tmp));
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_MSB(tmp[0], src);
+        SILC_GET32_MSB(tmp[1], src + 4);
+        des_encrypt(des, tmp, tmp);
+        SILC_PUT32_MSB(tmp[0], dst);
+        SILC_PUT32_MSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
+    }
+    break;
 
   case SILC_CIPHER_MODE_CBC:
     SILC_CBC_ENC_MSB_64_32(len, iv, tmp, src, dst, i,
                           des_encrypt(des, tmp, tmp));
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    SILC_CTR_MSB_64_32(iv, ctr, tmp, des->padlen, src, dst,
-                      des_encrypt(des, ctr, tmp));
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     SILC_CFB_ENC_MSB_64_32(iv, tmp, des->padlen, src, dst,
                           des_encrypt(des, tmp, tmp));
@@ -84,17 +107,33 @@ SILC_CIPHER_API_DECRYPT(des)
   SilcUInt32 tmp[2], tmp2[2], tiv[2];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    return silc_des_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_MSB(tmp[0], src);
+        SILC_GET32_MSB(tmp[1], src + 4);
+        des_decrypt(des, tmp, tmp);
+        SILC_PUT32_MSB(tmp[0], dst);
+        SILC_PUT32_MSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
+    }
+    break;
 
   case SILC_CIPHER_MODE_CBC:
     SILC_CBC_DEC_MSB_64_32(len, iv, tiv, tmp, tmp2, src, dst, i,
                           des_decrypt(des, tmp, tmp2));
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    return silc_des_encrypt(cipher, context, src, dst, len, iv);
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     SILC_CFB_DEC_MSB_64_32(iv, tmp, des->padlen, src, dst,
                           des_encrypt(des, tmp, tmp));
@@ -120,13 +159,9 @@ SILC_CIPHER_API_SET_IV(3des)
 {
   des3_key *des = context;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    /* Starts new block. */
-    des->padlen = 0;
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     /* Starts new block. */
     des->padlen = 8;
@@ -137,31 +172,58 @@ SILC_CIPHER_API_SET_IV(3des)
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(3des)
+SILC_CIPHER_API_INIT(3des)
 {
-  return sizeof(des3_key);
+  des3_key *des = silc_calloc(1, sizeof(des3_key));
+  if (!des)
+    des->padlen = 8;
+}
+
+/* Uninitialize */
+
+SILC_CIPHER_API_UNINIT(3des)
+{
+  des3_key *des = context;
+  memset(des, 0, sizeof(*des));
+  silc_free(des);
 }
 
 SILC_CIPHER_API_ENCRYPT(3des)
 {
   des3_key *des = context;
-  SilcUInt32 tmp[2], ctr[2];
+  SilcUInt32 tmp[2];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_MSB_64_32(iv, tmp, cipher->block, des->padlen, src, dst,
+                      des3_encrypt(des, tmp, tmp));
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_MSB(tmp[0], src);
+        SILC_GET32_MSB(tmp[1], src + 4);
+        des3_encrypt(des, tmp, tmp);
+        SILC_PUT32_MSB(tmp[0], dst);
+        SILC_PUT32_MSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
+    }
+    break;
 
   case SILC_CIPHER_MODE_CBC:
     SILC_CBC_ENC_MSB_64_32(len, iv, tmp, src, dst, i,
                           des3_encrypt(des, tmp, tmp));
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    SILC_CTR_MSB_64_32(iv, ctr, tmp, des->padlen, src, dst,
-                      des3_encrypt(des, ctr, tmp));
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     SILC_CFB_ENC_MSB_64_32(iv, tmp, des->padlen, src, dst,
                           des3_encrypt(des, tmp, tmp));
@@ -180,17 +242,33 @@ SILC_CIPHER_API_DECRYPT(3des)
   SilcUInt32 tmp[2], tmp2[2], tiv[2];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    return silc_3des_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_MSB(tmp[0], src);
+        SILC_GET32_MSB(tmp[1], src + 4);
+        des3_decrypt(des, tmp, tmp);
+        SILC_PUT32_MSB(tmp[0], dst);
+        SILC_PUT32_MSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
+    }
+    break;
 
   case SILC_CIPHER_MODE_CBC:
     SILC_CBC_DEC_MSB_64_32(len, iv, tiv, tmp, tmp2, src, dst, i,
                           des3_decrypt(des, tmp, tmp2));
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    return silc_3des_encrypt(cipher, context, src, dst, len, iv);
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     SILC_CFB_DEC_MSB_64_32(iv, tmp, des->padlen, src, dst,
                           des3_encrypt(des, tmp, tmp));
@@ -212,7 +290,7 @@ SILC_CIPHER_API_DECRYPT(3des)
 #pragma intrinsic(_lrotr,_lrotl)
 #define RORc(x,n) _lrotr(x,n)
 #else
-#define RORc(x, y) silc_ror(x, y)
+#define RORc(x, y) silc_rorc(x, y)
 #endif /* _MSC_VER */
 
 static const SilcUInt32 bytebit[8] =
index ae187f284c81d81912409ac14273d68617ba3218..1a612f9307156b252dbc2f18b52abef231814901 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2007 Pekka Riikonen
+  Copyright (C) 2007 - 2008 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 SILC_CIPHER_API_SET_KEY(des);
 SILC_CIPHER_API_SET_IV(des);
-SILC_CIPHER_API_CONTEXT_LEN(des);
+SILC_CIPHER_API_INIT(des);
+SILC_CIPHER_API_UNINIT(des);
 SILC_CIPHER_API_ENCRYPT(des);
 SILC_CIPHER_API_DECRYPT(des);
 
 SILC_CIPHER_API_SET_KEY(3des);
 SILC_CIPHER_API_SET_IV(3des);
-SILC_CIPHER_API_CONTEXT_LEN(3des);
+SILC_CIPHER_API_INIT(3des);
+SILC_CIPHER_API_UNINIT(3des);
 SILC_CIPHER_API_ENCRYPT(3des);
 SILC_CIPHER_API_DECRYPT(3des);
 
index b31bcb8e4a8609aa0ca73422f4fa3b36cbaec2a0..1dfe483d3e158d0f21ad5e89f184a2c6397669ae 100644 (file)
@@ -34,9 +34,14 @@ SILC_CIPHER_API_SET_IV(none)
 
 }
 
-SILC_CIPHER_API_CONTEXT_LEN(none)
+SILC_CIPHER_API_INIT(none)
 {
-  return 1;
+  return (void *)0x01;
+}
+
+SILC_CIPHER_API_UNINIT(none)
+{
+
 }
 
 SILC_CIPHER_API_ENCRYPT(none)
index 555ffa293ddd99b70b68177124d2d212a1430ae0..c219a665df971887c2c02336304cc53adaa0bf39 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2008 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
@@ -26,7 +26,8 @@
 
 SILC_CIPHER_API_SET_KEY(none);
 SILC_CIPHER_API_SET_IV(none);
-SILC_CIPHER_API_CONTEXT_LEN(none);
+SILC_CIPHER_API_INIT(none);
+SILC_CIPHER_API_UNINIT(none);
 SILC_CIPHER_API_ENCRYPT(none);
 SILC_CIPHER_API_DECRYPT(none);
 
index b84289b2f99658c8d4af26814510d980af87371e..3e93da32c49c1b95aa5f5d27372043853f377d82 100644 (file)
@@ -65,11 +65,20 @@ SILC_CIPHER_API_SET_IV(rc5_cbc)
 
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(rc5_cbc)
+SILC_CIPHER_API_INIT(rc5_cbc)
 {
-  return sizeof(RC5Context);
+  return silc_calloc(1, sizeof(RC5Context));
+}
+
+/* Initialize */
+
+SILC_CIPHER_API_UNINIT(rc5_cbc)
+{
+  RC5Context *rc5 = context;
+  memset(rc5, 0, sizeof(*rc5));
+  silc_free(rc5);
 }
 
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
index 3adbee4cf75e9d871a05b7c865f07bb161b1ce25..835f771fe855b319776cf828b076cddd6913ecac 100644 (file)
@@ -26,7 +26,8 @@
 
 SILC_CIPHER_API_SET_KEY(rc5_cbc);
 SILC_CIPHER_API_SET_IV(rc5_cbc);
-SILC_CIPHER_API_CONTEXT_LEN(rc5_cbc);
+SILC_CIPHER_API_INIT(rc5_cbc);
+SILC_CIPHER_API_UNINIT(rc5_cbc);
 SILC_CIPHER_API_ENCRYPT(rc5_cbc);
 SILC_CIPHER_API_DECRYPT(rc5_cbc);
 
index 5c317d8c4a81a4e1cab1df27ea15189b3307116d..00df535284ae31d8bfb1b3b32d80d6990fdd9182 100644 (file)
@@ -40,7 +40,7 @@ SILC_HASH_API_CONTEXT_LEN(sha256)
 #pragma intrinsic(_lrotr,_lrotl)
 #define RORc(x,n) _lrotr(x,n)
 #else
-#define RORc(x, y) silc_ror(x, y)
+#define RORc(x, y) silc_rorc(x, y)
 #endif /* _MSC_VER */
 
 /* Various logical functions */
index ec80f8d0767198a864b754bb103bed7081cba95d..229cc22b91bdaf17306fba4dc6c6da7f03ac73ec 100644 (file)
 #include "silccrypto.h"
 #include "ciphers.h"           /* Includes cipher definitions */
 
-/* The SilcCipher context */
-struct SilcCipherStruct {
-  SilcCipherObject *cipher;
-  void *context;
-  unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
-};
-
 #ifndef SILC_SYMBIAN
 /* Dynamically registered list of ciphers. */
 SilcDList silc_cipher_list = NULL;
 #endif /* SILC_SYMBIAN */
 
 /* Macro to define cipher to cipher list */
-#define SILC_CDEF(name, cipher, keylen, blocklen, ivlen, mode)         \
-{ name, silc_##cipher##_set_key, silc_##cipher##_set_iv,               \
+#define SILC_CDEF(name, alg_name, cipher, keylen, blocklen, ivlen, mode)\
+{ name, alg_name, silc_##cipher##_set_key, silc_##cipher##_set_iv,     \
   silc_##cipher##_encrypt, silc_##cipher##_decrypt,                    \
-  silc_##cipher##_context_len, keylen, blocklen, ivlen, mode }
+  silc_##cipher##_init, silc_##cipher##_uninit, keylen, blocklen, ivlen, mode }
 
 /* Static list of ciphers for silc_cipher_register_default(). */
 const SilcCipherObject silc_default_ciphers[] =
 {
-  SILC_CDEF("aes-256-ctr", aes, 256, 16, 16, SILC_CIPHER_MODE_CTR),
-  SILC_CDEF("aes-192-ctr", aes, 192, 16, 16, SILC_CIPHER_MODE_CTR),
-  SILC_CDEF("aes-128-ctr", aes, 128, 16, 16, SILC_CIPHER_MODE_CTR),
-  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),
-  SILC_CDEF("des-56-ctr", des, 56, 8, 8, SILC_CIPHER_MODE_CTR),
-  SILC_CDEF("des-56-cbc", des, 56, 8, 8, SILC_CIPHER_MODE_CBC),
-  SILC_CDEF("des-56-cfb", des, 56, 8, 8, SILC_CIPHER_MODE_CFB),
-  SILC_CDEF("3des-168-ctr", 3des, 168, 8, 8, SILC_CIPHER_MODE_CTR),
-  SILC_CDEF("3des-168-cbc", 3des, 168, 8, 8, SILC_CIPHER_MODE_CBC),
-  SILC_CDEF("3des-168-cfb", 3des, 168, 8, 8, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("aes-256-ctr", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("aes-192-ctr", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("aes-128-ctr", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("aes-256-cbc", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("aes-192-cbc", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("aes-128-cbc", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("aes-256-cfb", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("aes-192-cfb", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("aes-128-cfb", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("aes-256-ecb", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("aes-192-ecb", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("aes-128-ecb", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("twofish-256-ctr", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("twofish-192-ctr", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("twofish-128-ctr", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("twofish-256-cbc", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("twofish-192-cbc", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("twofish-128-cbc", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("twofish-256-cfb", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("twofish-192-cfb", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("twofish-128-cfb", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("twofish-256-ecb", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("twofish-192-ecb", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("twofish-128-ecb", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("cast5-128-ctr", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("cast5-128-cbc", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("cast5-128-cfb", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("cast5-128-ecb", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("des-56-ctr", "des", des, 56, 8, 8, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("des-56-cbc", "des", des, 56, 8, 8, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("des-56-cfb", "des", des, 56, 8, 8, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("des-56-ecb", "des", des, 56, 8, 8, SILC_CIPHER_MODE_ECB),
+  SILC_CDEF("3des-168-ctr", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_CTR),
+  SILC_CDEF("3des-168-cbc", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_CBC),
+  SILC_CDEF("3des-168-cfb", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_CFB),
+  SILC_CDEF("3des-168-ecb", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_ECB),
 #ifdef SILC_DEBUG
-  SILC_CDEF("none", none, 0, 0, 0, 0),
+  SILC_CDEF("none", "none", none, 0, 0, 0, 0),
 #endif /* SILC_DEBUG */
-  { NULL, NULL, 0, 0, 0, 0 }
+  { NULL, NULL, NULL, 0, 0, 0, 0 }
 };
 
 /* Register new cipher */
@@ -108,7 +110,8 @@ SilcBool silc_cipher_register(const SilcCipherObject *cipher)
   new->set_iv = cipher->set_iv;
   new->encrypt = cipher->encrypt;
   new->decrypt = cipher->decrypt;
-  new->context_len = cipher->context_len;
+  new->init = cipher->init;
+  new->uninit = cipher->uninit;
   new->mode = cipher->mode;
 
   /* Add to list */
@@ -218,7 +221,7 @@ SilcBool silc_cipher_alloc(const char *name, SilcCipher *new_cipher)
     if (!(*new_cipher))
       return FALSE;
     (*new_cipher)->cipher = entry;
-    (*new_cipher)->context = silc_calloc(1, entry->context_len());
+    (*new_cipher)->context = entry->init(entry);
     if (!(*new_cipher)->context) {
       silc_free(*new_cipher);
       return FALSE;
@@ -230,12 +233,47 @@ SilcBool silc_cipher_alloc(const char *name, SilcCipher *new_cipher)
   return FALSE;
 }
 
+/* Allocate cipher */
+
+SilcBool silc_cipher_alloc_full(const char *alg_name, SilcUInt32 key_len,
+                                SilcCipherMode mode, SilcCipher *new_cipher)
+{
+  char name[64];
+  const char *mode_name;
+
+  switch (mode) {
+  case SILC_CIPHER_MODE_ECB:
+    mode_name = "ecb";
+    break;
+  case SILC_CIPHER_MODE_CBC:
+    mode_name = "cbc";
+    break;
+  case SILC_CIPHER_MODE_CTR:
+    mode_name = "ctr";
+    break;
+  case SILC_CIPHER_MODE_CFB:
+    mode_name = "cfb";
+    break;
+  case SILC_CIPHER_MODE_OFB:
+    mode_name = "ofb";
+    break;
+  default:
+    return FALSE;
+    break;
+  }
+
+  silc_snprintf(name, sizeof(name), "%s-%d-%s", alg_name, key_len, mode_name);
+
+  return silc_cipher_alloc(name, new_cipher);
+}
+
 /* Free's the given cipher. */
 
 void silc_cipher_free(SilcCipher cipher)
 {
   if (cipher) {
-    silc_free(cipher->context);
+    cipher->cipher->uninit(cipher->cipher, cipher->context);
+    memset(cipher, 0, sizeof(*cipher));
     silc_free(cipher);
   }
 }
@@ -324,7 +362,8 @@ SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
                             unsigned char *dst, SilcUInt32 len,
                             unsigned char *iv)
 {
-  return cipher->cipher->encrypt(cipher->cipher, cipher->context, src, dst, len,
+  return cipher->cipher->encrypt(cipher, cipher->cipher,
+                                cipher->context, src, dst, len,
                                 iv ? iv : cipher->iv);
 }
 
@@ -334,7 +373,8 @@ SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
                             unsigned char *dst, SilcUInt32 len,
                             unsigned char *iv)
 {
-  return cipher->cipher->decrypt(cipher->cipher, cipher->context, src, dst, len,
+  return cipher->cipher->decrypt(cipher, cipher->cipher,
+                                cipher->context, src, dst, len,
                                 iv ? iv : cipher->iv);
 }
 
@@ -343,8 +383,8 @@ SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
                             SilcUInt32 keylen, SilcBool encryption)
 {
-  return cipher->cipher->set_key(cipher->cipher, cipher->context, key, keylen,
-                                encryption);
+  return cipher->cipher->set_key(cipher, cipher->cipher, cipher->context,
+                                (void *)key, keylen, encryption);
 }
 
 /* Sets the IV (initial vector) for the cipher. */
@@ -352,8 +392,8 @@ SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
 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, cipher->iv);
+    memmove(cipher->iv, iv, cipher->cipher->iv_len);
+  cipher->cipher->set_iv(cipher, cipher->cipher, cipher->context, cipher->iv);
 }
 
 /* Returns the IV (initial vector) of the cipher. */
@@ -391,6 +431,13 @@ const char *silc_cipher_get_name(SilcCipher cipher)
   return (const char *)cipher->cipher->name;
 }
 
+/* Returns the algorithm name of the cipher */
+
+const char *silc_cipher_get_alg_name(SilcCipher cipher)
+{
+  return (const char *)cipher->cipher->alg_name;
+}
+
 /* Returns cipher mode */
 
 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
index 7011bdfd40bbe375ae7e02b22efeb883fc87fe16..e64e3149359fac4f2b20d11bbc4f4d209532cc9f 100644 (file)
@@ -191,10 +191,10 @@ SilcBool silc_cipher_unregister_all(void);
  *
  * DESCRIPTION
  *
- *    Allocates a new SILC cipher object. Function returns 1 on succes and 0
- *    on error. The allocated cipher is returned in new_cipher argument. The
- *    caller must set the key to the cipher after this function has returned
- *    by calling the ciphers set_key function.
+ *    Allocates a new SILC cipher object. Function returns TRUE on succes 
+ *    and FALSE on error. The allocated cipher is returned in new_cipher
+ *    argument. The caller must set the key to the cipher after this
+ *    function has returned by calling the silc_cipher_set_key.
  *
  *    The following ciphers are supported:
  *
@@ -213,6 +213,23 @@ SilcBool silc_cipher_unregister_all(void);
  ***/
 SilcBool silc_cipher_alloc(const char *name, SilcCipher *new_cipher);
 
+/****f* silccrypt/SilcCipherAPI/silc_cipher_alloc
+ *
+ * SYNOPSIS
+ *
+ *    SilcBool silc_cipher_alloc_full(const char *alg_name,
+ *                                    SilcUInt32 key_len,
+ *                                    SilcCipherMode mode,
+ *                                    SilcCipher *new_cipher);
+ * DESCRIPTION
+ *
+ *    Same as silc_cipher_alloc but takes the cipher algorithm name,
+ *    key length and mode as separate arguments.  
+ *
+ ***/
+SilcBool silc_cipher_alloc_full(const char *alg_name, SilcUInt32 key_len,
+                               SilcCipherMode mode, SilcCipher *new_cipher);
+
 /****f* silccrypt/SilcCipherAPI/silc_cipher_free
  *
  * SYNOPSIS
@@ -396,11 +413,24 @@ SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher);
  *
  * DESCRIPTION
  *
- *    Returns the name of the cipher.
+ *    Returns the full name of the cipher (eg. 'aes-256-ctr').
  *
  ***/
 const char *silc_cipher_get_name(SilcCipher cipher);
 
+/****f* silccrypt/SilcCipherAPI/silc_cipher_get_alg_name
+ *
+ * SYNOPSIS
+ *
+ *    const char *silc_cipher_get_alg_name(SilcCipher cipher);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the algorithm name of the cipher (eg. 'aes').
+ *
+ ***/
+const char *silc_cipher_get_alg_name(SilcCipher cipher);
+
 /****f* silccrypt/SilcCipherAPI/silc_cipher_get_mode
  *
  * SYNOPSIS
index a148d29113a60a305b0db272ea4b674db2eeb564..e52d8f00196716e48da8b1515a76c4b99ced701d 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2007 Pekka Riikonen
+  Copyright (C) 2007 - 2008 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
 #error "Do not include this header directly"
 #endif
 
+/* The SilcCipher context.  This is not visible to application programmer.
+   It is accessible from the algorithm implementations. */
+struct SilcCipherStruct {
+  SilcCipherObject *cipher;                    /* Cipher operations */
+  void *context;                               /* Algorithm context */
+  unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];   /* IV */
+  unsigned char block[SILC_CIPHER_MAX_IV_SIZE];        /* Extra block for free use */
+};
+
 /* These macros can be used to implement the SILC Crypto API and to avoid
    errors in the API these macros should be used always. */
 #define SILC_CIPHER_API_SET_KEY(name)                                  \
-  SilcBool silc_##name##_set_key(struct SilcCipherObjectStruct *cipher,        \
-                                void *context,                         \
-                                const unsigned char *key,              \
+  SilcBool silc_##name##_set_key(SilcCipher cipher,                    \
+                                struct SilcCipherObjectStruct *ops,    \
+                                void *context, void *key,              \
                                 SilcUInt32 keylen,                     \
                                 SilcBool encryption)
 #define SILC_CIPHER_API_SET_IV(name)                                   \
-  void silc_##name##_set_iv(struct SilcCipherObjectStruct *cipher,     \
+  void silc_##name##_set_iv(SilcCipher cipher,                         \
+                           struct SilcCipherObjectStruct *ops,         \
                            void *context,                              \
                            unsigned char *iv)
 #define SILC_CIPHER_API_ENCRYPT(name)                                  \
-  SilcBool silc_##name##_encrypt(struct SilcCipherObjectStruct *cipher,        \
+  SilcBool silc_##name##_encrypt(SilcCipher cipher,                    \
+                                struct SilcCipherObjectStruct *ops,    \
                                 void *context,                         \
                                 const unsigned char *src,              \
                                 unsigned char *dst,                    \
                                 SilcUInt32 len,                        \
                                 unsigned char *iv)
 #define SILC_CIPHER_API_DECRYPT(name)                                  \
-  SilcBool silc_##name##_decrypt(struct SilcCipherObjectStruct *cipher,        \
+  SilcBool silc_##name##_decrypt(SilcCipher cipher,                    \
+                                struct SilcCipherObjectStruct *ops,    \
                                 void *context,                         \
                                 const unsigned char *src,              \
                                 unsigned char *dst,                    \
                                 SilcUInt32 len,                        \
                                 unsigned char *iv)
-#define SILC_CIPHER_API_CONTEXT_LEN(name)      \
-  SilcUInt32 silc_##name##_context_len()
+#define SILC_CIPHER_API_INIT(name)                                     \
+  void *silc_##name##_init(struct SilcCipherObjectStruct *ops)
+#define SILC_CIPHER_API_UNINIT(name)                                   \
+  void silc_##name##_uninit(struct SilcCipherObjectStruct *ops,                \
+                           void *context)
 
 /* Cipher object to represent a cipher algorithm. */
 struct SilcCipherObjectStruct {
   /* Cipher name */
   char *name;
+  char *alg_name;
 
   /* Set new key.  If `encryption' is TRUE the key is for encryption,
      FALSE for decryption.  The `keylen' is in bits. */
-  SilcBool (*set_key)(struct SilcCipherObjectStruct *cipher,
-                     void *context, const unsigned char *key,
-                     SilcUInt32 keylen, SilcBool encryption);
+  SilcBool (*set_key)(SilcCipher cipher, struct SilcCipherObjectStruct *ops,
+                     void *context, void *key, SilcUInt32 keylen,
+                     SilcBool encryption);
 
   /* 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 (*set_iv)(SilcCipher cipher, struct SilcCipherObjectStruct *ops,
                 void *context, unsigned char *iv);
 
   /* Encrypt.  The `src' and `dst' may be same pointer.  The `iv' may be
      edited inside this function. */
-  SilcBool (*encrypt)(struct SilcCipherObjectStruct *cipher,
+  SilcBool (*encrypt)(SilcCipher cipher, struct SilcCipherObjectStruct *ops,
                      void *context, const unsigned char *src,
                      unsigned char *dst, SilcUInt32 len,
                      unsigned char *iv);
 
   /* Decrypt.  The `src' and `dst' may be same pointer.  The `iv' may be
      edited inside this function. */
-  SilcBool (*decrypt)(struct SilcCipherObjectStruct *cipher,
+  SilcBool (*decrypt)(SilcCipher cipher, struct SilcCipherObjectStruct *ops,
                      void *context, const unsigned char *src,
                      unsigned char *dst, SilcUInt32 len,
                      unsigned char *iv);
 
-  /* Returns the length of the internal cipher context */
-  SilcUInt32 (*context_len)(void);
+  /* Initializes the cipher.  Returns internal cipher context.  The uninit()
+     will be called in silc_cipher_free to uninitialize the cipher and free
+     the context. */
+  void *(*init)(struct SilcCipherObjectStruct *ops);
+
+  /* Uninitialize cipher. */
+  void (*uninit)(struct SilcCipherObjectStruct *ops, void *context);
 
   unsigned int key_len   : 10;            /* Key length in bits */
   unsigned int block_len : 8;             /* Block size in bytes */
index 443d1a9cdd6332782ced577e68267d5394c70599..9e86175b65b87e75f8aa1c7fe6c4a23853c5a071 100644 (file)
@@ -29,7 +29,8 @@ bin_PROGRAMS =        test_sha1       \
                test_des        \
                test_silcpkcs   \
                test_dsa        \
-               test_hash
+               test_hash       \
+               test_cipher
 
 test_hash_SOURCES = test_hash.c
 test_sha1_SOURCES = test_sha1.c
@@ -39,6 +40,7 @@ test_hmacsha1_SOURCES = test_hmacsha1.c
 test_hmacsha256_SOURCES = test_hmacsha256.c
 test_hmacmd5_SOURCES = test_hmacmd5.c
 
+test_cipher_SOURCES = test_cipher.c
 test_aes_SOURCES = test_aes.c
 test_twofish_SOURCES = test_twofish.c
 test_cast5_SOURCES = test_cast5.c
index 87073b30a42d262da58c06ec56a609a24adefb42..7b5877a5a1073bc533a0b0a403422df0ea7b8d20 100644 (file)
@@ -1,5 +1,5 @@
 
-#include "silc.h"
+#include "silccrypto.h"
 
 /* Test vectors from RFC3602. */
 
diff --git a/lib/silccrypt/tests/test_cipher.c b/lib/silccrypt/tests/test_cipher.c
new file mode 100644 (file)
index 0000000..3041e6a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+
+  test_cipher.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2008 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
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+
+#include "silccrypto.h"
+
+#define ENC_LEN 0x00100000     /* enc data len (at least) */
+#define ENC_ROUND 512          /* enc rounds (at least) */
+#define ENC_MIN_TIME 3.0        /* seconds to run the test (at least) */
+
+SilcTimerStruct timer;
+SilcCipher cipher;
+
+int main(int argc, char **argv)
+{
+  SilcUInt64 sec;
+  SilcUInt32 usec;
+  double totsec;
+  unsigned char *data;
+  SilcUInt32 rounds;
+  SilcUInt32 i, k;
+
+  data = malloc(ENC_LEN * sizeof(*data));
+  if (!data)
+    exit(1);
+
+  for (i = 0; i < ENC_LEN; i++)
+    data[i] = i % 255;
+
+  silc_timer_synchronize(&timer);
+
+  for (i = 0; silc_default_ciphers[i].name; i++) {
+    if (!silc_cipher_alloc(silc_default_ciphers[i].name, &cipher)) {
+      fprintf(stderr, "Error allocating %s\n", silc_default_ciphers[i].name);
+      exit(1);
+    }
+
+    silc_cipher_set_key(cipher, data, silc_cipher_get_key_len(cipher), TRUE);
+    silc_cipher_set_iv(cipher, data);
+
+    rounds = ENC_ROUND;
+
+  retry:
+    silc_timer_start(&timer);
+    for (k = 0; k < rounds; k++)
+      silc_cipher_encrypt(cipher, data, data, ENC_LEN, NULL);
+    silc_timer_stop(&timer);
+
+    silc_timer_value(&timer, &sec, &usec);
+    totsec = (double)sec;
+    totsec += ((double)usec / (double)(1000 * 1000));
+    if (totsec < ENC_MIN_TIME) {
+      rounds += rounds;
+      goto retry;
+    }
+
+    printf("%s:\t%.2f KB (%.2f MB) / sec (total test time %.2f secs)\n",
+          silc_default_ciphers[i].name,
+          (((double)(ENC_LEN * rounds) / 1024.0) / totsec),
+          (((double)(ENC_LEN * rounds) / (1024.0 * 1024.0)) / totsec),
+          totsec);
+
+    silc_cipher_free(cipher);
+  }
+
+  return 0;
+}
index 89731328e9335e5d76d3dd3e756fa090c7192b1a..7c734df961a37cfdc8d015895013f6858d7139d1 100644 (file)
@@ -1,5 +1,5 @@
 
-#include "silc.h"
+#include "silccrypto.h"
 
 /* CBC */
 
index 01e622deee24aeaceb44d54171f6f3d6ff2a3dc0..f8d834569d2e2f5e130a25ef4e14324c274c3587 100644 (file)
@@ -1,43 +1,7 @@
-/* Modified for SILC. -Pekka */
-
-/* This is an independent implementation of the encryption algorithm:   */
-/*                                                                      */
-/*         Twofish by Bruce Schneier and colleagues                     */
-/*                                                                      */
-/* which is a candidate algorithm in the Advanced Encryption Standard   */
-/* programme of the US National Institute of Standards and Technology.  */
-/*                                                                      */
-/* Copyright in this implementation is held by Dr B R Gladman but I     */
-/* hereby give permission for its free direct or derivative use subject */
-/* to acknowledgment of its origin and compliance with any conditions   */
-/* that the originators of t he algorithm place on its exploitation.     */
-/*                                                                      */
-/* My thanks to Doug Whiting and Niels Ferguson for comments that led   */
-/* to improvements in this implementation.                              */
-/*                                                                      */
-/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999     */
-
-/* Timing data for Twofish (twofish.c)
-
-128 bit key:
-Key Setup:    8414 cycles
-Encrypt:       376 cycles =    68.1 mbits/sec
-Decrypt:       374 cycles =    68.4 mbits/sec
-Mean:          375 cycles =    68.3 mbits/sec
-
-192 bit key:
-Key Setup:   11628 cycles
-Encrypt:       376 cycles =    68.1 mbits/sec
-Decrypt:       374 cycles =    68.4 mbits/sec
-Mean:          375 cycles =    68.3 mbits/sec
-
-256 bit key:
-Key Setup:   15457 cycles
-Encrypt:       381 cycles =    67.2 mbits/sec
-Decrypt:       374 cycles =    68.4 mbits/sec
-Mean:          378 cycles =    67.8 mbits/sec
-
-*/
+/* Taken from public domain libtomcrypt library and the code and all changes
+   to it are in public domain. -Pekka */
+
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
 
 #include "silccrypto.h"
 #include "twofish_internal.h"
@@ -51,27 +15,19 @@ Mean:          378 cycles =    67.8 mbits/sec
 
 SILC_CIPHER_API_SET_KEY(twofish)
 {
-  SilcUInt32 k[8];
-
-  SILC_GET_WORD_KEY(key, k, keylen);
-  twofish_set_key((TwofishContext *)context, k, keylen);
-
-  return TRUE;
+  twofish_key *twofish = context;
+  return twofish_setup(key, keylen, 0, twofish);
 }
 
 /* Sets IV for the cipher. */
 
 SILC_CIPHER_API_SET_IV(twofish)
 {
-  TwofishContext *twofish = context;
+  twofish_key *twofish = context;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    /* Starts new block. */
-    twofish->padlen = 0;
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     /* Starts new block. */
     twofish->padlen = 16;
@@ -82,11 +38,22 @@ SILC_CIPHER_API_SET_IV(twofish)
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(twofish)
+SILC_CIPHER_API_INIT(twofish)
 {
-  return sizeof(TwofishContext);
+  twofish_key *twofish = silc_calloc(1, sizeof(twofish_key));
+  if (twofish)
+    twofish->padlen = 16;
+}
+
+/* Uninitialize */
+
+SILC_CIPHER_API_UNINIT(twofish)
+{
+  twofish_key *twofish = context;
+  memset(twofish, 0, sizeof(*twofish));
+  silc_free(twofish);
 }
 
 /* Encrypts with the cipher. Source and destination buffers maybe one
@@ -94,25 +61,46 @@ SILC_CIPHER_API_CONTEXT_LEN(twofish)
 
 SILC_CIPHER_API_ENCRYPT(twofish)
 {
-  TwofishContext *twofish = context;
-  SilcUInt32 tmp[4], ctr[4];
+  twofish_key *twofish = context;
+  SilcUInt32 tmp[4];
   int i;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
 
-  case SILC_CIPHER_MODE_CBC:
-    SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i,
-                           twofish_encrypt(twofish, tmp, tmp));
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_LSB_128_32(iv, tmp, cipher->block, twofish->padlen, src, dst,
+                       twofish_encrypt(tmp, tmp, twofish));
+    memset(tmp, 0, 16);
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    SILC_CTR_LSB_128_32(iv, ctr, tmp, twofish->padlen, src, dst,
-                       twofish_encrypt(twofish, tmp, tmp));
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 4;
+
+      while (nb--) {
+       SILC_GET32_LSB(tmp[0], src);
+       SILC_GET32_LSB(tmp[1], src + 4);
+       SILC_GET32_LSB(tmp[2], src + 8);
+       SILC_GET32_LSB(tmp[3], src + 12);
+       twofish_encrypt(tmp, tmp, twofish);
+       SILC_PUT32_LSB(tmp[0], dst);
+       SILC_PUT32_LSB(tmp[1], dst + 4);
+       SILC_PUT32_LSB(tmp[2], dst + 8);
+       SILC_PUT32_LSB(tmp[3], dst + 12);
+       src += 16;
+       dst += 16;
+      }
+    }
+    break;
+
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i,
+                           twofish_encrypt(tmp, tmp, twofish));
     break;
 
   case SILC_CIPHER_MODE_CFB:
     SILC_CFB_ENC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
-                           twofish_encrypt(twofish, tmp, tmp));
+                           twofish_encrypt(tmp, tmp, twofish));
     break;
 
   default:
@@ -127,23 +115,43 @@ SILC_CIPHER_API_ENCRYPT(twofish)
 
 SILC_CIPHER_API_DECRYPT(twofish)
 {
-  TwofishContext *twofish = context;
+  twofish_key *twofish = context;
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
 
-  switch (cipher->mode) {
-
-  case SILC_CIPHER_MODE_CBC:
-    SILC_CBC_DEC_LSB_128_32(len, iv, tiv, tmp, tmp2, src, dst, i,
-                           twofish_decrypt(twofish, tmp, tmp2));
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    return silc_twofish_encrypt(cipher, context, src, dst, len, iv);
+    return silc_twofish_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 4;
+
+      while (nb--) {
+       SILC_GET32_LSB(tmp[0], src);
+       SILC_GET32_LSB(tmp[1], src + 4);
+       SILC_GET32_LSB(tmp[2], src + 8);
+       SILC_GET32_LSB(tmp[3], src + 12);
+       twofish_decrypt(tmp, tmp, twofish);
+       SILC_PUT32_LSB(tmp[0], dst);
+       SILC_PUT32_LSB(tmp[1], dst + 4);
+       SILC_PUT32_LSB(tmp[2], dst + 8);
+       SILC_PUT32_LSB(tmp[3], dst + 12);
+       src += 16;
+       dst += 16;
+      }
+    }
     break;
 
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_DEC_LSB_128_32(len, iv, tiv, tmp, tmp2, src, dst, i,
+                           twofish_decrypt(tmp, tmp2, twofish));
+
   case SILC_CIPHER_MODE_CFB:
     SILC_CFB_DEC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
-                           twofish_encrypt(twofish, tmp, tmp));
+                           twofish_encrypt(tmp, tmp, twofish));
     break;
 
   default:
@@ -153,435 +161,754 @@ SILC_CIPHER_API_DECRYPT(twofish)
   return TRUE;
 }
 
-#if 0
-#define Q_TABLES
-#define M_TABLE
-#define MK_TABLE
-#define ONE_STEP
-#endif
-
-/* finite field arithmetic for GF(2**8) with the modular    */
-/* polynomial x^8 + x^6 + x^5 + x^3 + 1 (0x169)             */
-
-#define G_M 0x0169
-
-u1byte  tab_5b[4] = { 0, G_M >> 2, G_M >> 1, (G_M >> 1) ^ (G_M >> 2) };
-u1byte  tab_ef[4] = { 0, (G_M >> 1) ^ (G_M >> 2), G_M >> 1, G_M >> 2 };
-
-#define ffm_01(x)    (x)
-#define ffm_5b(x)   ((x) ^ ((x) >> 2) ^ tab_5b[(x) & 3])
-#define ffm_ef(x)   ((x) ^ ((x) >> 1) ^ ((x) >> 2) ^ tab_ef[(x) & 3])
+/****************************************************************************/
 
-u1byte ror4[16] = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 };
-u1byte ashx[16] = { 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 };
+/* the two polynomials */
+#define MDS_POLY          0x169
+#define RS_POLY           0x14D
 
-u1byte qt0[2][16] =
-{   { 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 },
-    { 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 }
+/* The 4x4 MDS Linear Transform */
+static const unsigned char MDS[4][4] = {
+  { 0x01, 0xEF, 0x5B, 0x5B },
+  { 0x5B, 0xEF, 0xEF, 0x01 },
+  { 0xEF, 0x5B, 0x01, 0xEF },
+  { 0xEF, 0x01, 0xEF, 0x5B }
 };
 
-u1byte qt1[2][16] =
-{   { 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 },
-    { 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 }
+/* The 4x8 RS Linear Transform */
+static const unsigned char RS[4][8] = {
+  { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E },
+  { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 },
+  { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 },
+  { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 }
 };
 
-u1byte qt2[2][16] =
-{   { 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 },
-    { 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 }
+/* sbox usage orderings */
+static const unsigned char qord[4][5] = {
+  { 1, 1, 0, 0, 1 },
+  { 0, 1, 1, 0, 0 },
+  { 0, 0, 0, 1, 1 },
+  { 1, 0, 1, 1, 0 }
 };
 
-u1byte qt3[2][16] =
-{   { 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 },
-    { 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 }
+/* pre generated 8x8 tables from the four 4x4s */
+static const unsigned char SBOX[2][256] = {
+  {
+    0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92,
+    0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98,
+    0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13,
+    0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23,
+    0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01,
+    0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe,
+    0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c,
+    0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
+    0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95,
+    0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5,
+    0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9,
+    0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8,
+    0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d,
+    0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11,
+    0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c,
+    0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
+    0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87,
+    0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f,
+    0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e,
+    0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02,
+    0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7,
+    0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12,
+    0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc,
+    0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
+    0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d,
+    0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0},
+  {
+    0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3,
+    0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd,
+    0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa,
+    0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d,
+    0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84,
+    0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54,
+    0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60,
+    0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
+    0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3,
+    0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff,
+    0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7,
+    0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9,
+    0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94,
+    0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c,
+    0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76,
+    0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
+    0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23,
+    0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e,
+    0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f,
+    0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5,
+    0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e,
+    0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34,
+    0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4,
+    0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
+    0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25,
+    0x86, 0x56, 0x55, 0x09, 0xbe, 0x91}
 };
 
-u1byte qp(const u4byte n, const u1byte x)
-{   u1byte  a0, a1, a2, a3, a4, b0, b1, b2, b3, b4;
-
-    a0 = x >> 4; b0 = x & 15;
-    a1 = a0 ^ b0; b1 = ror4[b0] ^ ashx[a0];
-    a2 = qt0[n][a1]; b2 = qt1[n][b1];
-    a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2];
-    a4 = qt2[n][a3]; b4 = qt3[n][b3];
-    return (b4 << 4) | a4;
-}
-
-#ifdef  Q_TABLES
-
-u4byte  qt_gen = 0;
-u1byte  q_tab[2][256];
-
-#define q(n,x)  q_tab[n][x]
-
-void gen_qtab(void)
-{   u4byte  i;
-
-    for(i = 0; i < 256; ++i)
-    {
-        q(0,i) = qp(0, (u1byte)i);
-        q(1,i) = qp(1, (u1byte)i);
-    }
+/* the 4x4 MDS in a nicer format */
+static const SilcUInt32 mds_tab[4][256] = {
+{
+  0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL,
+  0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL,
+  0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL,
+  0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL,
+  0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL,
+  0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL,
+  0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL,
+  0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL,
+  0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL,
+  0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL,
+  0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL,
+  0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL,
+  0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL,
+  0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL,
+  0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL,
+  0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL,
+  0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL,
+  0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL,
+  0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL,
+  0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL,
+  0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL,
+  0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL,
+  0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL,
+  0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL,
+  0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL,
+  0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL,
+  0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL,
+  0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL,
+  0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL,
+  0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL,
+  0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL,
+  0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL
+},
+{
+  0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL,
+  0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL,
+  0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL,
+  0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL,
+  0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL,
+  0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL,
+  0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL,
+  0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL,
+  0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL,
+  0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL,
+  0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL,
+  0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL,
+  0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL,
+  0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL,
+  0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL,
+  0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL,
+  0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL,
+  0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL,
+  0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL,
+  0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL,
+  0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL,
+  0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL,
+  0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL,
+  0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL,
+  0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL,
+  0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL,
+  0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL,
+  0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL,
+  0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL,
+  0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL,
+  0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL,
+  0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL
+},
+{
+  0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL,
+  0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL,
+  0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL,
+  0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL,
+  0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL,
+  0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL,
+  0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL,
+  0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL,
+  0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL,
+  0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL,
+  0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL,
+  0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL,
+  0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL,
+  0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL,
+  0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL,
+  0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL,
+  0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL,
+  0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL,
+  0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL,
+  0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL,
+  0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL,
+  0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL,
+  0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL,
+  0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL,
+  0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL,
+  0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL,
+  0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL,
+  0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL,
+  0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL,
+  0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL,
+  0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL,
+  0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL
+},
+{
+  0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL,
+  0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL,
+  0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL,
+  0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL,
+  0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL,
+  0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL,
+  0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL,
+  0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL,
+  0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL,
+  0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL,
+  0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL,
+  0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL,
+  0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL,
+  0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL,
+  0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL,
+  0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL,
+  0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL,
+  0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL,
+  0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL,
+  0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL,
+  0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL,
+  0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL,
+  0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL,
+  0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL,
+  0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL,
+  0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL,
+  0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL,
+  0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL,
+  0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL,
+  0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL,
+  0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL,
+  0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL
+}};
+
+/* the 4x8 RS transform */
+static const SilcUInt32 rs_tab0[256] = {
+  0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU,
+  0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU,
+  0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU,
+  0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU,
+  0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU,
+  0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU,
+  0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU,
+  0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU,
+  0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU,
+  0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU,
+  0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU,
+  0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU,
+  0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU,
+  0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU,
+  0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU,
+  0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU,
+  0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU,
+  0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU,
+  0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU,
+  0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU,
+  0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU,
+  0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU,
+  0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU,
+  0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU,
+  0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU,
+  0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU,
+  0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU,
+  0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU,
+  0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU,
+  0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU,
+  0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU,
+  0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU };
+
+static const SilcUInt32 rs_tab1[256] = {
+  0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU,
+  0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU,
+  0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU,
+  0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU,
+  0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU,
+  0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU,
+  0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU,
+  0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU,
+  0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU,
+  0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU,
+  0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU,
+  0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU,
+  0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU,
+  0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU,
+  0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU,
+  0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU,
+  0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU,
+  0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU,
+  0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU,
+  0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU,
+  0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU,
+  0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU,
+  0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU,
+  0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU,
+  0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU,
+  0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU,
+  0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU,
+  0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU,
+  0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU,
+  0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU,
+  0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU,
+  0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU };
+
+static const SilcUInt32 rs_tab2[256] = {
+  0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU,
+  0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU,
+  0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU,
+  0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU,
+  0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU,
+  0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU,
+  0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU,
+  0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU,
+  0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU,
+  0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU,
+  0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU,
+  0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU,
+  0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU,
+  0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU,
+  0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU,
+  0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU,
+  0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU,
+  0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU,
+  0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU,
+  0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU,
+  0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU,
+  0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU,
+  0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU,
+  0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU,
+  0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU,
+  0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU,
+  0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU,
+  0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU,
+  0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU,
+  0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU,
+  0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU,
+  0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU };
+
+static const SilcUInt32 rs_tab3[256] = {
+  0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU,
+  0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU,
+  0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU,
+  0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU,
+  0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU,
+  0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU,
+  0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU,
+  0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU,
+  0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU,
+  0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU,
+  0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU,
+  0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU,
+  0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU,
+  0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU,
+  0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU,
+  0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU,
+  0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU,
+  0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU,
+  0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU,
+  0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU,
+  0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU,
+  0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU,
+  0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU,
+  0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU,
+  0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU,
+  0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU,
+  0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU,
+  0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU,
+  0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU,
+  0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU,
+  0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU,
+  0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU };
+
+static const SilcUInt32 rs_tab4[256] = {
+  0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU,
+  0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU,
+  0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU,
+  0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU,
+  0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU,
+  0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU,
+  0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU,
+  0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU,
+  0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU,
+  0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU,
+  0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU,
+  0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU,
+  0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU,
+  0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU,
+  0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU,
+  0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU,
+  0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU,
+  0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU,
+  0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU,
+  0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU,
+  0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU,
+  0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU,
+  0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU,
+  0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU,
+  0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU,
+  0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU,
+  0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU,
+  0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU,
+  0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU,
+  0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU,
+  0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU,
+  0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU };
+
+static const SilcUInt32 rs_tab5[256] = {
+  0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU,
+  0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU,
+  0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU,
+  0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU,
+  0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU,
+  0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU,
+  0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU,
+  0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU,
+  0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU,
+  0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU,
+  0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU,
+  0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU,
+  0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU,
+  0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU,
+  0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU,
+  0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU,
+  0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU,
+  0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU,
+  0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU,
+  0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU,
+  0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU,
+  0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU,
+  0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU,
+  0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU,
+  0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU,
+  0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU,
+  0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU,
+  0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU,
+  0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU,
+  0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU,
+  0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU,
+  0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU };
+
+static const SilcUInt32 rs_tab6[256] = {
+  0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU,
+  0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU,
+  0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU,
+  0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU,
+  0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU,
+  0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU,
+  0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU,
+  0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU,
+  0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU,
+  0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU,
+  0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU,
+  0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU,
+  0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU,
+  0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU,
+  0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU,
+  0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU,
+  0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU,
+  0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU,
+  0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU,
+  0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU,
+  0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU,
+  0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU,
+  0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU,
+  0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU,
+  0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU,
+  0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU,
+  0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU,
+  0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU,
+  0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU,
+  0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU,
+  0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU,
+  0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU };
+
+static const SilcUInt32 rs_tab7[256] = {
+  0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU,
+  0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU,
+  0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU,
+  0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU,
+  0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU,
+  0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU,
+  0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU,
+  0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU,
+  0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU,
+  0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU,
+  0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU,
+  0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU,
+  0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU,
+  0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU,
+  0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU,
+  0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU,
+  0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU,
+  0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU,
+  0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU,
+  0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU,
+  0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU,
+  0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU,
+  0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU,
+  0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU,
+  0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU,
+  0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU,
+  0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU,
+  0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU,
+  0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU,
+  0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU,
+  0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU,
+  0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU };
+
+#define sbox(i, x) ((SilcUInt32)SBOX[i][(x)&255])
+#define mds_column_mult(x, i) mds_tab[i][x]
+
+/* computes ab mod p */
+static inline SilcUInt32 gf_mult(SilcUInt32 a, SilcUInt32 b, SilcUInt32 p)
+{
+  SilcUInt32 result, B[2], P[2];
+
+  P[1] = p;
+  B[1] = b;
+  result = P[0] = B[0] = 0;
+
+  /* unrolled branchless GF multiplier */
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1);
+  result ^= B[a&1];
+
+  return result;
 }
 
-#else
-
-#define q(n,x)  qp(n, x)
-
-#endif
-
-#ifdef  M_TABLE
-
-u4byte  mt_gen = 0;
-u4byte  m_tab[4][256];
-
-void gen_mtab(void)
-{   u4byte  i, f01, f5b, fef;
-
-    for(i = 0; i < 256; ++i)
-    {
-        f01 = q(1,i); f5b = ffm_5b(f01); fef = ffm_ef(f01);
-        m_tab[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24);
-        m_tab[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24);
-
-        f01 = q(0,i); f5b = ffm_5b(f01); fef = ffm_ef(f01);
-        m_tab[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
-        m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
-    }
+/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */
+static inline void mds_mult(const unsigned char *in, unsigned char *out)
+{
+  SilcUInt32 x, tmp;
+  for (tmp = x = 0; x < 4; x++) {
+    tmp ^= mds_column_mult(in[x], x);
+  }
+  SILC_PUT32_LSB(tmp, out);
 }
 
-#define mds(n,x)    m_tab[n][x]
-
-#else
-
-#define fm_00   ffm_01
-#define fm_10   ffm_5b
-#define fm_20   ffm_ef
-#define fm_30   ffm_ef
-#define q_0(x)  q(1,x)
-
-#define fm_01   ffm_ef
-#define fm_11   ffm_ef
-#define fm_21   ffm_5b
-#define fm_31   ffm_01
-#define q_1(x)  q(0,x)
-
-#define fm_02   ffm_5b
-#define fm_12   ffm_ef
-#define fm_22   ffm_01
-#define fm_32   ffm_ef
-#define q_2(x)  q(1,x)
-
-#define fm_03   ffm_5b
-#define fm_13   ffm_01
-#define fm_23   ffm_ef
-#define fm_33   ffm_5b
-#define q_3(x)  q(0,x)
-
-#define f_0(n,x)    ((u4byte)fm_0##n(x))
-#define f_1(n,x)    ((u4byte)fm_1##n(x) << 8)
-#define f_2(n,x)    ((u4byte)fm_2##n(x) << 16)
-#define f_3(n,x)    ((u4byte)fm_3##n(x) << 24)
-
-#define mds(n,x)    f_0(n,q_##n(x)) ^ f_1(n,q_##n(x)) ^ f_2(n,q_##n(x)) ^ f_3(n,q_##n(x))
-
-#endif
-
-u4byte h_fun(TwofishContext *ctx, const u4byte x, const u4byte key[])
-{   u4byte  b0, b1, b2, b3;
-
-#ifndef M_TABLE
-    u4byte  m5b_b0, m5b_b1, m5b_b2, m5b_b3;
-    u4byte  mef_b0, mef_b1, mef_b2, mef_b3;
-#endif
-
-    b0 = byte(x, 0); b1 = byte(x, 1); b2 = byte(x, 2); b3 = byte(x, 3);
-
-    switch(ctx->k_len)
-    {
-    case 4: b0 = q(1, b0) ^ byte(key[3],0);
-            b1 = q(0, b1) ^ byte(key[3],1);
-            b2 = q(0, b2) ^ byte(key[3],2);
-            b3 = q(1, b3) ^ byte(key[3],3);
-    case 3: b0 = q(1, b0) ^ byte(key[2],0);
-            b1 = q(1, b1) ^ byte(key[2],1);
-            b2 = q(0, b2) ^ byte(key[2],2);
-            b3 = q(0, b3) ^ byte(key[2],3);
-    case 2: b0 = q(0,q(0,b0) ^ byte(key[1],0)) ^ byte(key[0],0);
-            b1 = q(0,q(1,b1) ^ byte(key[1],1)) ^ byte(key[0],1);
-            b2 = q(1,q(0,b2) ^ byte(key[1],2)) ^ byte(key[0],2);
-            b3 = q(1,q(1,b3) ^ byte(key[1],3)) ^ byte(key[0],3);
-    }
-#ifdef  M_TABLE
-
-    return  mds(0, b0) ^ mds(1, b1) ^ mds(2, b2) ^ mds(3, b3);
-
-#else
-
-    b0 = q(1, b0); b1 = q(0, b1); b2 = q(1, b2); b3 = q(0, b3);
-    m5b_b0 = ffm_5b(b0); m5b_b1 = ffm_5b(b1); m5b_b2 = ffm_5b(b2); m5b_b3 = ffm_5b(b3);
-    mef_b0 = ffm_ef(b0); mef_b1 = ffm_ef(b1); mef_b2 = ffm_ef(b2); mef_b3 = ffm_ef(b3);
-    b0 ^= mef_b1 ^ m5b_b2 ^ m5b_b3; b3 ^= m5b_b0 ^ mef_b1 ^ mef_b2;
-    b2 ^= mef_b0 ^ m5b_b1 ^ mef_b3; b1 ^= mef_b0 ^ mef_b2 ^ m5b_b3;
-
-    return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24);
-
-#endif
+/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
+static inline void rs_mult(const unsigned char *in, unsigned char *out)
+{
+  SilcUInt32 tmp;
+  tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^
+    rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]];
+  SILC_PUT32_LSB(tmp, out);
 }
 
-#ifdef  MK_TABLE
-
-#ifdef  ONE_STEP
-u4byte  mk_tab[4][256];
-#else
-u1byte  sb[4][256];
-#endif
-
-#define q20(x)  q(0,q(0,x) ^ byte(key[1],0)) ^ byte(key[0],0)
-#define q21(x)  q(0,q(1,x) ^ byte(key[1],1)) ^ byte(key[0],1)
-#define q22(x)  q(1,q(0,x) ^ byte(key[1],2)) ^ byte(key[0],2)
-#define q23(x)  q(1,q(1,x) ^ byte(key[1],3)) ^ byte(key[0],3)
-
-#define q30(x)  q(0,q(0,q(1, x) ^ byte(key[2],0)) ^ byte(key[1],0)) ^ byte(key[0],0)
-#define q31(x)  q(0,q(1,q(1, x) ^ byte(key[2],1)) ^ byte(key[1],1)) ^ byte(key[0],1)
-#define q32(x)  q(1,q(0,q(0, x) ^ byte(key[2],2)) ^ byte(key[1],2)) ^ byte(key[0],2)
-#define q33(x)  q(1,q(1,q(0, x) ^ byte(key[2],3)) ^ byte(key[1],3)) ^ byte(key[0],3)
-
-#define q40(x)  q(0,q(0,q(1, q(1, x) ^ byte(key[3],0)) ^ byte(key[2],0)) ^ byte(key[1],0)) ^ byte(key[0],0)
-#define q41(x)  q(0,q(1,q(1, q(0, x) ^ byte(key[3],1)) ^ byte(key[2],1)) ^ byte(key[1],1)) ^ byte(key[0],1)
-#define q42(x)  q(1,q(0,q(0, q(0, x) ^ byte(key[3],2)) ^ byte(key[2],2)) ^ byte(key[1],2)) ^ byte(key[0],2)
-#define q43(x)  q(1,q(1,q(0, q(1, x) ^ byte(key[3],3)) ^ byte(key[2],3)) ^ byte(key[1],3)) ^ byte(key[0],3)
-
-void gen_mk_tab(TwofishContext *ctx, u4byte key[])
-{   u4byte  i;
-    u1byte  by;
-
-    switch(ctx->k_len)
-    {
-    case 2: for(i = 0; i < 256; ++i)
-            {
-                by = (u1byte)i;
-#ifdef ONE_STEP
-                mk_tab[0][i] = mds(0, q20(by)); mk_tab[1][i] = mds(1, q21(by));
-                mk_tab[2][i] = mds(2, q22(by)); mk_tab[3][i] = mds(3, q23(by));
-#else
-                sb[0][i] = q20(by); sb[1][i] = q21(by);
-                sb[2][i] = q22(by); sb[3][i] = q23(by);
-#endif
-            }
-            break;
-
-    case 3: for(i = 0; i < 256; ++i)
-            {
-                by = (u1byte)i;
-#ifdef ONE_STEP
-                mk_tab[0][i] = mds(0, q30(by)); mk_tab[1][i] = mds(1, q31(by));
-                mk_tab[2][i] = mds(2, q32(by)); mk_tab[3][i] = mds(3, q33(by));
-#else
-                sb[0][i] = q30(by); sb[1][i] = q31(by);
-                sb[2][i] = q32(by); sb[3][i] = q33(by);
-#endif
-            }
-            break;
-
-    case 4: for(i = 0; i < 256; ++i)
-            {
-                by = (u1byte)i;
-#ifdef ONE_STEP
-                mk_tab[0][i] = mds(0, q40(by)); mk_tab[1][i] = mds(1, q41(by));
-                mk_tab[2][i] = mds(2, q42(by)); mk_tab[3][i] = mds(3, q43(by));
-#else
-                sb[0][i] = q40(by); sb[1][i] = q41(by);
-                sb[2][i] = q42(by); sb[3][i] = q43(by);
-#endif
-            }
-    }
+/* computes h(x) */
+static void h_func(const unsigned char *in, unsigned char *out,
+                  unsigned char *M, int k, int offset)
+{
+  SilcUInt32 x;
+  unsigned char y[4];
+  for (x = 0; x < 4; x++) {
+    y[x] = in[x];
+  }
+  switch (k) {
+  case 4:
+    y[0] = (unsigned char)(sbox(1, (SilcUInt32)y[0]) ^ M[4 * (6 + offset) + 0]);
+    y[1] = (unsigned char)(sbox(0, (SilcUInt32)y[1]) ^ M[4 * (6 + offset) + 1]);
+    y[2] = (unsigned char)(sbox(0, (SilcUInt32)y[2]) ^ M[4 * (6 + offset) + 2]);
+    y[3] = (unsigned char)(sbox(1, (SilcUInt32)y[3]) ^ M[4 * (6 + offset) + 3]);
+  case 3:
+    y[0] = (unsigned char)(sbox(1, (SilcUInt32)y[0]) ^ M[4 * (4 + offset) + 0]);
+    y[1] = (unsigned char)(sbox(1, (SilcUInt32)y[1]) ^ M[4 * (4 + offset) + 1]);
+    y[2] = (unsigned char)(sbox(0, (SilcUInt32)y[2]) ^ M[4 * (4 + offset) + 2]);
+    y[3] = (unsigned char)(sbox(0, (SilcUInt32)y[3]) ^ M[4 * (4 + offset) + 3]);
+  case 2:
+    y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (SilcUInt32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0]));
+    y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (SilcUInt32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1]));
+    y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (SilcUInt32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2]));
+    y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (SilcUInt32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3]));
+  }
+  mds_mult(y, out);
 }
 
-#  ifdef ONE_STEP
-#    define g0_fun(x) ( mk_tab[0][byte(x,0)] ^ mk_tab[1][byte(x,1)] \
-                      ^ mk_tab[2][byte(x,2)] ^ mk_tab[3][byte(x,3)] )
-#    define g1_fun(x) ( mk_tab[0][byte(x,3)] ^ mk_tab[1][byte(x,0)] \
-                      ^ mk_tab[2][byte(x,1)] ^ mk_tab[3][byte(x,2)] )
-#  else
-#    define g0_fun(x) ( mds(0, sb[0][byte(x,0)]) ^ mds(1, sb[1][byte(x,1)]) \
-                      ^ mds(2, sb[2][byte(x,2)]) ^ mds(3, sb[3][byte(x,3)]) )
-#    define g1_fun(x) ( mds(0, sb[0][byte(x,3)]) ^ mds(1, sb[1][byte(x,0)]) \
-                      ^ mds(2, sb[2][byte(x,1)]) ^ mds(3, sb[3][byte(x,2)]) )
-#  endif
-
-#else
-
-#define g0_fun(x)   h_fun(ctx,x,s_key)
-#define g1_fun(x)   h_fun(ctx,rotl(x,8),s_key)
-
+/* for GCC we don't use pointer aliases */
+#if defined(__GNUC__)
+#define S1 skey->S[0]
+#define S2 skey->S[1]
+#define S3 skey->S[2]
+#define S4 skey->S[3]
 #endif
 
-/* The (12,8) Reed Soloman code has the generator polynomial
-
-  g(x) = x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1
-
-where the coefficients are in the finite field GF(2^8) with a
-modular polynomial a^8 + a^6 + a^3 + a^2 + 1. To generate the
-remainder we have to start with a 12th order polynomial with our
-eight input bytes as the coefficients of the 4th to 11th terms.
-That is:
-
-  m[7] * x^11 + m[6] * x^10 ... + m[0] * x^4 + 0 * x^3 +... + 0
-
-We then multiply the generator polynomial by m[7] * x^7 and subtract
-it - xor in GF(2^8) - from the above to eliminate the x^7 term (the
-artihmetic on the coefficients is done in GF(2^8). We then multiply
-the generator polynomial by x^6 * coeff(x^10) and use this to remove
-the x^10 term. We carry on in this way until the x^4 term is removed
-so that we are left with:
-
-  r[3] * x^3 + r[2] * x^2 + r[1] 8 x^1 + r[0]
-
-which give the resulting 4 bytes of the remainder. This is equivalent
-to the matrix multiplication in the Twofish description but much faster
-to implement.
-
-*/
+/* the G function */
+#define g_func(x, dum)  (S1[byte(x,0)] ^ S2[byte(x,1)] ^ S3[byte(x,2)] ^ S4[byte(x,3)])
+#define g1_func(x, dum) (S2[byte(x,0)] ^ S3[byte(x,1)] ^ S4[byte(x,2)] ^ S1[byte(x,3)])
 
-#define G_MOD   0x0000014d
-
-u4byte mds_rem(u4byte p0, u4byte p1)
-{   u4byte  i, t, u;
-
-    for(i = 0; i < 8; ++i)
-    {
-        t = p1 >> 24;   /* get most significant coefficient */
-
-        p1 = (p1 << 8) | (p0 >> 24); p0 <<= 8;  /* shift others up */
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds,
+                 twofish_key *skey)
+{
+  unsigned char S[4*4], tmpx0, tmpx1;
+  int k, x, y;
+  unsigned char tmp[4], tmp2[4], M[8*4];
+  SilcUInt32 A, B;
 
-        /* multiply t by a (the primitive element - i.e. left shift) */
+  if (keylen / 8 != 16 && keylen / 8 != 24 && keylen / 8 != 32)
+    return FALSE;
 
-        u = (t << 1);
+  k = keylen / 64;
 
-        if(t & 0x80)            /* subtract modular polynomial on overflow */
+  /* copy the key into M */
+  for (x = 0; x < keylen / 8; x++)
+    M[x] = key[x] & 255;
 
-            u ^= G_MOD;
+  /* create the S[..] words */
+  for (x = 0; x < k; x++)
+    rs_mult(M+(x*8), S+(x*4));
 
-        p1 ^= t ^ (u << 16);    /* remove t * (a * x^2 + 1) */
+  /* make subkeys */
+  for (x = 0; x < 20; x++) {
+    /* A = h(p * 2x, Me) */
+    for (y = 0; y < 4; y++) {
+      tmp[y] = x+x;
+    }
+    h_func(tmp, tmp2, M, k, 0);
+    SILC_GET32_LSB(A, tmp2);
 
-        u ^= (t >> 1);          /* form u = a * t + t / a = t * (a + 1 / a); */
+    /* B = ROL(h(p * (2x + 1), Mo), 8) */
+    for (y = 0; y < 4; y++) {
+      tmp[y] = (unsigned char)(x+x+1);
+    }
+    h_func(tmp, tmp2, M, k, 1);
+    SILC_GET32_LSB(B, tmp2);
+    B = silc_rolc(B, 8);
 
-        if(t & 0x01)            /* add the modular polynomial on underflow */
+    /* K[2i]   = A + B */
+    skey->K[x+x] = (A + B) & 0xFFFFFFFFUL;
 
-            u ^= G_MOD >> 1;
+    /* K[2i+1] = (A + 2B) <<< 9 */
+    skey->K[x+x+1] = silc_rolc(B + B + A, 9);
+  }
 
-        p1 ^= (u << 24) | (u << 8); /* remove t * (a + 1/a) * (x^3 + x) */
+  /* make the sboxes (large ram variant) */
+  if (k == 2) {
+    for (x = 0; x < 256; x++) {
+      tmpx0 = (unsigned char)sbox(0, x);
+      tmpx1 = (unsigned char)sbox(1, x);
+      skey->S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0);
+      skey->S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1);
+      skey->S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2);
+      skey->S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3);
+    }
+  } else if (k == 3) {
+    for (x = 0; x < 256; x++) {
+      tmpx0 = (unsigned char)sbox(0, x);
+      tmpx1 = (unsigned char)sbox(1, x);
+      skey->S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0);
+      skey->S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1);
+      skey->S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2);
+      skey->S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3);
     }
+  } else {
+    for (x = 0; x < 256; x++) {
+      tmpx0 = (unsigned char)sbox(0, x);
+      tmpx1 = (unsigned char)sbox(1, x);
+      skey->S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0);
+      skey->S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1);
+      skey->S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2);
+      skey->S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3);
+    }
+  }
 
-    return p1;
+  return TRUE;
 }
 
-/* initialise the key schedule from the user supplied key   */
-
-u4byte *twofish_set_key(TwofishContext *ctx,
-                       const u4byte in_key[], const u4byte key_len)
+int twofish_encrypt(const SilcUInt32 pt[4], SilcUInt32 ct[4],
+                   twofish_key *skey)
 {
-    u4byte  i, a, b, me_key[4], mo_key[4];
-    u4byte *l_key = ctx->l_key;
-    u4byte *s_key = ctx->s_key;
-
-#ifdef Q_TABLES
-    if(!qt_gen)
-    {
-        gen_qtab(); qt_gen = 1;
-    }
+  SilcUInt32 a,b,c,d,t1,t2, *k;
+  int r;
+#if !defined(__GNUC__)
+  SilcUInt32 *S1, *S2, *S3, *S4;
 #endif
 
-#ifdef M_TABLE
-    if(!mt_gen)
-    {
-        gen_mtab(); mt_gen = 1;
-    }
+#if !defined(__GNUC__)
+  S1 = skey->S[0];
+  S2 = skey->S[1];
+  S3 = skey->S[2];
+  S4 = skey->S[3];
 #endif
 
-    ctx->k_len = ctx->k_len = key_len / 64;   /* 2, 3 or 4 */
-
-    for(i = 0; i < ctx->k_len; ++i)
-    {
-        a = in_key[i + i];     me_key[i] = a;
-        b = in_key[i + i + 1]; mo_key[i] = b;
-        s_key[ctx->k_len - i - 1] = mds_rem(a, b);
-    }
-
-    for(i = 0; i < 40; i += 2)
-    {
-        a = 0x01010101 * i; b = a + 0x01010101;
-        a = h_fun(ctx,a, me_key);
-        b = rotl(h_fun(ctx,b, mo_key), 8);
-        l_key[i] = a + b;
-        l_key[i + 1] = rotl(a + 2 * b, 9);
-    }
+  a = pt[0] ^ skey->K[0];
+  b = pt[1] ^ skey->K[1];
+  c = pt[2] ^ skey->K[2];
+  d = pt[3] ^ skey->K[3];
+
+  k  = skey->K + 8;
+  for (r = 8; r != 0; --r) {
+    t2 = g1_func(b, skey);
+    t1 = g_func(a, skey) + t2;
+    c  = silc_rorc(c ^ (t1 + k[0]), 1);
+    d  = silc_rolc(d, 1) ^ (t2 + t1 + k[1]);
+
+    t2 = g1_func(d, skey);
+    t1 = g_func(c, skey) + t2;
+    a  = silc_rorc(a ^ (t1 + k[2]), 1);
+    b  = silc_rolc(b, 1) ^ (t2 + t1 + k[3]);
+    k += 4;
+  }
 
-#ifdef MK_TABLE
-    gen_mk_tab(ctx,s_key);
-#endif
+  /* output with "undo last swap" */
+  ct[0] = c ^ skey->K[4];
+  ct[1] = d ^ skey->K[5];
+  ct[2] = a ^ skey->K[6];
+  ct[3] = b ^ skey->K[7];
 
-    return l_key;
+  return TRUE;
 }
 
-/* encrypt a block of text  */
-
-#define f_rnd(i)                                                    \
-    t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]);                       \
-    blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1);      \
-    blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]);  \
-    t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]);                       \
-    blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1);     \
-    blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11])
-
-void twofish_encrypt(TwofishContext *ctx,
-                    const u4byte in_blk[4], u4byte out_blk[])
+int twofish_decrypt(const SilcUInt32 ct[4], SilcUInt32 pt[4],
+                   twofish_key *skey)
 {
-    u4byte  t0, t1, blk[4];
-    u4byte *l_key = ctx->l_key;
-    u4byte *s_key = ctx->s_key;
-
-    blk[0] = in_blk[0] ^ l_key[0];
-    blk[1] = in_blk[1] ^ l_key[1];
-    blk[2] = in_blk[2] ^ l_key[2];
-    blk[3] = in_blk[3] ^ l_key[3];
-
-    f_rnd(0); f_rnd(1); f_rnd(2); f_rnd(3);
-    f_rnd(4); f_rnd(5); f_rnd(6); f_rnd(7);
-
-    out_blk[0] = blk[2] ^ l_key[4];
-    out_blk[1] = blk[3] ^ l_key[5];
-    out_blk[2] = blk[0] ^ l_key[6];
-    out_blk[3] = blk[1] ^ l_key[7];
-}
+  SilcUInt32 a,b,c,d,t1,t2, *k;
+  int r;
+#if !defined(__GNUC__)
+  SilcUInt32 *S1, *S2, *S3, *S4;
+#endif
 
-/* decrypt a block of text  */
+#if !defined(__GNUC__)
+  S1 = skey->S[0];
+  S2 = skey->S[1];
+  S3 = skey->S[2];
+  S4 = skey->S[3];
+#endif
 
-#define i_rnd(i)                                                        \
-        t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]);                       \
-        blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]);     \
-        blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); \
-        t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]);                       \
-        blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) +  8]);     \
-        blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) +  9]), 1)
+  /* undo undo final swap */
+  a = ct[2] ^ skey->K[6];
+  b = ct[3] ^ skey->K[7];
+  c = ct[0] ^ skey->K[4];
+  d = ct[1] ^ skey->K[5];
+
+  k = skey->K + 36;
+  for (r = 8; r != 0; --r) {
+    t2 = g1_func(d, skey);
+    t1 = g_func(c, skey) + t2;
+    a = silc_rolc(a, 1) ^ (t1 + k[2]);
+    b = silc_rorc(b ^ (t2 + t1 + k[3]), 1);
+
+    t2 = g1_func(b, skey);
+    t1 = g_func(a, skey) + t2;
+    c = silc_rolc(c, 1) ^ (t1 + k[0]);
+    d = silc_rorc(d ^ (t2 +  t1 + k[1]), 1);
+    k -= 4;
+  }
 
-void twofish_decrypt(TwofishContext *ctx,
-                    const u4byte in_blk[4], u4byte out_blk[4])
-{
-    u4byte  t0, t1, blk[4];
-    u4byte *l_key = ctx->l_key;
-    u4byte *s_key = ctx->s_key;
-
-    blk[0] = in_blk[0] ^ l_key[4];
-    blk[1] = in_blk[1] ^ l_key[5];
-    blk[2] = in_blk[2] ^ l_key[6];
-    blk[3] = in_blk[3] ^ l_key[7];
-
-    i_rnd(7); i_rnd(6); i_rnd(5); i_rnd(4);
-    i_rnd(3); i_rnd(2); i_rnd(1); i_rnd(0);
-
-    out_blk[0] = blk[2] ^ l_key[0];
-    out_blk[1] = blk[3] ^ l_key[1];
-    out_blk[2] = blk[0] ^ l_key[2];
-    out_blk[3] = blk[1] ^ l_key[3];
+  /* pre-white */
+  pt[0] = a ^ skey->K[0];
+  pt[1] = b ^ skey->K[1];
+  pt[2] = c ^ skey->K[2];
+  pt[3] = d ^ skey->K[3];
+
+  return TRUE;
 }
index 2e12b33216f9be0429d596aa07d499956cee9e5d..dd0e4562e090d1cd26b6782a963964183a05bbf2 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2007 Pekka Riikonen
+  Copyright (C) 2008 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
@@ -26,8 +26,9 @@
 
 SILC_CIPHER_API_SET_KEY(twofish);
 SILC_CIPHER_API_SET_IV(twofish);
-SILC_CIPHER_API_CONTEXT_LEN(twofish);
+SILC_CIPHER_API_INIT(twofish);
+SILC_CIPHER_API_UNINIT(twofish);
 SILC_CIPHER_API_ENCRYPT(twofish);
 SILC_CIPHER_API_DECRYPT(twofish);
 
-#endif
+#endif /* TWOFISH_H */
index 2c205d8b3b1aaf656e6245b7bf619d87a9f7a71b..716e0edf64927230cee6c13e3ffb39b9a2cee618 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2007 Pekka Riikonen
+  Copyright (C) 2008 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
 
 /* Cipher's context */
 typedef struct {
-  u4byte l_key[40];
-  u4byte s_key[4];
-  SilcUInt16 k_len;
-  SilcUInt16 padlen;
-} TwofishContext;
+  SilcUInt32 S[4][256];
+  SilcUInt32 K[40];
+  SilcUInt32 padlen;
+} twofish_key;
 
 /* Prototypes */
-u4byte *twofish_set_key(TwofishContext *ctx,
-                       const u4byte in_key[], const u4byte key_len);
-void twofish_encrypt(TwofishContext *ctx,
-                    const u4byte in_blk[4], u4byte out_blk[]);
-void twofish_decrypt(TwofishContext *ctx,
-                    const u4byte in_blk[4], u4byte out_blk[4]);
-
-#endif
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds,
+                 twofish_key *skey);
+int twofish_encrypt(const SilcUInt32 pt[4], SilcUInt32 ct[4],
+                   twofish_key *skey);
+int twofish_decrypt(const SilcUInt32 ct[4], SilcUInt32 pt[4],
+                   twofish_key *skey);
+
+#endif /* TWOFISH_INTERNAL_H */