From: Pekka Riikonen Date: Sat, 23 Feb 2008 13:59:32 +0000 (+0200) Subject: Major restructuring of the internals of SILC Cipher API X-Git-Tag: 1.2.beta1~10 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=9f20f0382b6229eca740925a73f96294f6dcedc6 Major restructuring of the internals of SILC Cipher API 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. --- diff --git a/configure.ad b/configure.ad index 7b0dfaf8..a45f57dd 100644 --- a/configure.ad +++ b/configure.ad @@ -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 diff --git a/lib/Makefile.ad b/lib/Makefile.ad index 0191e847..286f8213 100644 --- a/lib/Makefile.ad +++ b/lib/Makefile.ad @@ -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 diff --git a/lib/silccrypt/aes.c b/lib/silccrypt/aes.c index 27a47cc9..f60f3952 100644 --- a/lib/silccrypt/aes.c +++ b/lib/silccrypt/aes.c @@ -34,7 +34,7 @@ */ #include "silccrypto.h" -#include "rijndael_internal.h" +#include "aes_internal.h" #include "aes.h" /* @@ -45,19 +45,20 @@ 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)); diff --git a/lib/silccrypt/aes.h b/lib/silccrypt/aes.h index 008b3d1a..f573638b 100644 --- a/lib/silccrypt/aes.h +++ b/lib/silccrypt/aes.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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 diff --git a/lib/silccrypt/rijndael_internal.h b/lib/silccrypt/aes_internal.h similarity index 100% rename from lib/silccrypt/rijndael_internal.h rename to lib/silccrypt/aes_internal.h diff --git a/lib/silccrypt/blowfish.c b/lib/silccrypt/blowfish.c index 067a8fb7..862f1c20 100644 --- a/lib/silccrypt/blowfish.c +++ b/lib/silccrypt/blowfish.c @@ -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 diff --git a/lib/silccrypt/blowfish.h b/lib/silccrypt/blowfish.h index 996f7fe9..ece02a38 100644 --- a/lib/silccrypt/blowfish.h +++ b/lib/silccrypt/blowfish.h @@ -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); diff --git a/lib/silccrypt/cast.c b/lib/silccrypt/cast.c index dbf27e71..ac8aa770 100644 --- a/lib/silccrypt/cast.c +++ b/lib/silccrypt/cast.c @@ -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 diff --git a/lib/silccrypt/cast.h b/lib/silccrypt/cast.h index 383b9fdd..8a06bfad 100644 --- a/lib/silccrypt/cast.h +++ b/lib/silccrypt/cast.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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); diff --git a/lib/silccrypt/cast5.c b/lib/silccrypt/cast5.c index dc1774eb..2d5cf220 100644 --- a/lib/silccrypt/cast5.c +++ b/lib/silccrypt/cast5.c @@ -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)); diff --git a/lib/silccrypt/cast5.h b/lib/silccrypt/cast5.h index 2860ab16..5e403ad7 100644 --- a/lib/silccrypt/cast5.h +++ b/lib/silccrypt/cast5.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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); diff --git a/lib/silccrypt/ciphers_def.h b/lib/silccrypt/ciphers_def.h index d99da6df..ad00c9aa 100644 --- a/lib/silccrypt/ciphers_def.h +++ b/lib/silccrypt/ciphers_def.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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. */ diff --git a/lib/silccrypt/des.c b/lib/silccrypt/des.c index 75c887ee..a61d9259 100644 --- a/lib/silccrypt/des.c +++ b/lib/silccrypt/des.c @@ -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] = diff --git a/lib/silccrypt/des.h b/lib/silccrypt/des.h index ae187f28..1a612f93 100644 --- a/lib/silccrypt/des.h +++ b/lib/silccrypt/des.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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,13 +26,15 @@ 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); diff --git a/lib/silccrypt/none.c b/lib/silccrypt/none.c index b31bcb8e..1dfe483d 100644 --- a/lib/silccrypt/none.c +++ b/lib/silccrypt/none.c @@ -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) diff --git a/lib/silccrypt/none.h b/lib/silccrypt/none.h index 555ffa29..c219a665 100644 --- a/lib/silccrypt/none.h +++ b/lib/silccrypt/none.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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); diff --git a/lib/silccrypt/rc5.c b/lib/silccrypt/rc5.c index b84289b2..3e93da32 100644 --- a/lib/silccrypt/rc5.c +++ b/lib/silccrypt/rc5.c @@ -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 diff --git a/lib/silccrypt/rc5.h b/lib/silccrypt/rc5.h index 3adbee4c..835f771f 100644 --- a/lib/silccrypt/rc5.h +++ b/lib/silccrypt/rc5.h @@ -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); diff --git a/lib/silccrypt/sha256.c b/lib/silccrypt/sha256.c index 5c317d8c..00df5352 100644 --- a/lib/silccrypt/sha256.c +++ b/lib/silccrypt/sha256.c @@ -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 */ diff --git a/lib/silccrypt/silccipher.c b/lib/silccrypt/silccipher.c index ec80f8d0..229cc22b 100644 --- a/lib/silccrypt/silccipher.c +++ b/lib/silccrypt/silccipher.c @@ -20,58 +20,60 @@ #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) diff --git a/lib/silccrypt/silccipher.h b/lib/silccrypt/silccipher.h index 7011bdfd..e64e3149 100644 --- a/lib/silccrypt/silccipher.h +++ b/lib/silccrypt/silccipher.h @@ -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 diff --git a/lib/silccrypt/silccipher_i.h b/lib/silccrypt/silccipher_i.h index a148d291..e52d8f00 100644 --- a/lib/silccrypt/silccipher_i.h +++ b/lib/silccrypt/silccipher_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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 @@ -24,67 +24,88 @@ #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 */ diff --git a/lib/silccrypt/tests/Makefile.am b/lib/silccrypt/tests/Makefile.am index 443d1a9c..9e86175b 100644 --- a/lib/silccrypt/tests/Makefile.am +++ b/lib/silccrypt/tests/Makefile.am @@ -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 diff --git a/lib/silccrypt/tests/test_aes.c b/lib/silccrypt/tests/test_aes.c index 87073b30..7b5877a5 100644 --- a/lib/silccrypt/tests/test_aes.c +++ b/lib/silccrypt/tests/test_aes.c @@ -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 index 00000000..3041e6a6 --- /dev/null +++ b/lib/silccrypt/tests/test_cipher.c @@ -0,0 +1,82 @@ +/* + + test_cipher.c + + Author: 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 + 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; +} diff --git a/lib/silccrypt/tests/test_twofish.c b/lib/silccrypt/tests/test_twofish.c index 89731328..7c734df9 100644 --- a/lib/silccrypt/tests/test_twofish.c +++ b/lib/silccrypt/tests/test_twofish.c @@ -1,5 +1,5 @@ -#include "silc.h" +#include "silccrypto.h" /* CBC */ diff --git a/lib/silccrypt/twofish.c b/lib/silccrypt/twofish.c index 01e622de..f8d83456 100644 --- a/lib/silccrypt/twofish.c +++ b/lib/silccrypt/twofish.c @@ -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; } diff --git a/lib/silccrypt/twofish.h b/lib/silccrypt/twofish.h index 2e12b332..dd0e4562 100644 --- a/lib/silccrypt/twofish.h +++ b/lib/silccrypt/twofish.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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 */ diff --git a/lib/silccrypt/twofish_internal.h b/lib/silccrypt/twofish_internal.h index 2c205d8b..716e0edf 100644 --- a/lib/silccrypt/twofish_internal.h +++ b/lib/silccrypt/twofish_internal.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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 @@ -24,18 +24,17 @@ /* 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 */