*/
-#include "silcincludes.h"
+#include "silc.h"
#include "twofish_internal.h"
#include "twofish.h"
-/*
+/*
* SILC Crypto API for Twofish
*/
SILC_CIPHER_API_SET_KEY(twofish)
{
- uint32 k[8];
+ SilcUInt32 k[8];
SILC_GET_WORD_KEY(key, k, keylen);
twofish_set_key((TwofishContext *)context, k, keylen);
return TRUE;
}
-/* Sets the string as a new key for the cipher. The string is first
- hashed and then used as a new key. */
+/* Sets IV for the cipher. */
-SILC_CIPHER_API_SET_KEY_WITH_STRING(twofish)
+SILC_CIPHER_API_SET_IV(twofish)
{
- return FALSE;
+ TwofishContext *twofish = context;
+
+ switch (cipher->mode) {
+
+ case SILC_CIPHER_MODE_CTR:
+ /* Starts new block. */
+ twofish->padlen = 0;
+ break;
+
+ case SILC_CIPHER_MODE_CFB:
+ /* Starts new block. */
+ twofish->padlen = 16;
+ break;
+
+ default:
+ break;
+ }
}
/* Returns the size of the cipher context. */
return sizeof(TwofishContext);
}
-/* Encrypts with the cipher in CBC mode. Source and destination buffers
- maybe one and same. */
+/* Encrypts with the cipher. Source and destination buffers maybe one
+ and same. */
-SILC_CIPHER_API_ENCRYPT_CBC(twofish)
+SILC_CIPHER_API_ENCRYPT(twofish)
{
- uint32 tiv[4];
+ TwofishContext *twofish = context;
+ SilcUInt32 tmp[4], ctr[4];
int i;
- SILC_CBC_GET_IV(tiv, iv);
+ switch (cipher->mode) {
- SILC_CBC_ENC_PRE(tiv, src);
- twofish_encrypt((TwofishContext *)context, tiv, tiv);
- SILC_CBC_ENC_POST(tiv, dst, src);
+ case SILC_CIPHER_MODE_CBC:
+ SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i,
+ twofish_encrypt(twofish, tmp, tmp));
+ break;
- for (i = 16; i < len; i += 16) {
- SILC_CBC_ENC_PRE(tiv, src);
- twofish_encrypt((TwofishContext *)context, tiv, tiv);
- SILC_CBC_ENC_POST(tiv, dst, src);
- }
+ case SILC_CIPHER_MODE_CTR:
+ SILC_CTR_LSB_128_32(iv, ctr, tmp, twofish->padlen, src, dst,
+ twofish_encrypt(twofish, tmp, tmp));
+ break;
- SILC_CBC_PUT_IV(tiv, iv);
+ case SILC_CIPHER_MODE_CFB:
+ SILC_CFB_ENC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+ twofish_encrypt(twofish, tmp, tmp));
+ break;
+
+ default:
+ return FALSE;
+ }
return TRUE;
}
-/* Decrypts with the cipher in CBC mode. Source and destination buffers
- maybe one and same. */
+/* Decrypts with the cipher. Source and destination buffers maybe one
+ and same. */
-SILC_CIPHER_API_DECRYPT_CBC(twofish)
+SILC_CIPHER_API_DECRYPT(twofish)
{
- uint32 tmp[4], tmp2[4], tiv[4];
+ TwofishContext *twofish = context;
+ SilcUInt32 tmp[4], tmp2[4], tiv[4];
int i;
- SILC_CBC_GET_IV(tiv, iv);
+ 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));
- SILC_CBC_DEC_PRE(tmp, src);
- twofish_decrypt((TwofishContext *)context, tmp, tmp2);
- SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
+ case SILC_CIPHER_MODE_CTR:
+ return silc_twofish_encrypt(cipher, context, src, dst, len, iv);
+ break;
- for (i = 16; i < len; i += 16) {
- SILC_CBC_DEC_PRE(tmp, src);
- twofish_decrypt((TwofishContext *)context, tmp, tmp2);
- SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
+ case SILC_CIPHER_MODE_CFB:
+ SILC_CFB_DEC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+ twofish_encrypt(twofish, tmp, tmp));
+ break;
+
+ default:
+ return FALSE;
}
-
- SILC_CBC_PUT_IV(tiv, iv);
-
+
return TRUE;
}
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 };
-u1byte qt0[2][16] =
+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 }
};
u1byte qt1[2][16] =
-{ { 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 },
+{ { 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 }
};
-u1byte qt2[2][16] =
+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 }
};
-u1byte qt3[2][16] =
+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 }
};
-
+
u1byte qp(const u4byte n, const u1byte x)
{ u1byte a0, a1, a2, a3, a4, b0, b1, b2, b3, b4;
a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2];
a4 = qt2[n][a3]; b4 = qt3[n][b3];
return (b4 << 4) | a4;
-};
+}
#ifdef Q_TABLES
{ u4byte i;
for(i = 0; i < 256; ++i)
- {
+ {
q(0,i) = qp(0, (u1byte)i);
q(1,i) = qp(1, (u1byte)i);
}
-};
+}
#else
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[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
}
-};
+}
#define mds(n,x) m_tab[n][x]
return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24);
#endif
-};
+}
#ifdef MK_TABLE
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[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;
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[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;
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[0][i] = q40(by); sb[1][i] = q41(by);
sb[2][i] = q42(by); sb[3][i] = q43(by);
#endif
}
}
-};
+}
# ifdef ONE_STEP
# define g0_fun(x) ( mk_tab[0][byte(x,0)] ^ mk_tab[1][byte(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.
+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
+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
+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.
*/
for(i = 0; i < 8; ++i)
{
t = p1 >> 24; /* get most significant coefficient */
-
+
p1 = (p1 << 8) | (p0 >> 24); p0 <<= 8; /* shift others up */
-
+
/* multiply t by a (the primitive element - i.e. left shift) */
- u = (t << 1);
-
+ u = (t << 1);
+
if(t & 0x80) /* subtract modular polynomial on overflow */
-
- u ^= G_MOD;
+
+ u ^= G_MOD;
p1 ^= t ^ (u << 16); /* remove t * (a * x^2 + 1) */
u ^= (t >> 1); /* form u = a * t + t / a = t * (a + 1 / a); */
-
+
if(t & 0x01) /* add the modular polynomial on underflow */
-
+
u ^= G_MOD >> 1;
p1 ^= (u << 24) | (u << 8); /* remove t * (a + 1/a) * (x^3 + x) */
}
return p1;
-};
+}
/* initialise the key schedule from the user supplied key */
u4byte *twofish_set_key(TwofishContext *ctx,
const u4byte in_key[], const u4byte key_len)
-{
+{
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)
{
#endif
return l_key;
-};
+}
/* encrypt a block of text */
void twofish_encrypt(TwofishContext *ctx,
const u4byte in_blk[4], u4byte out_blk[])
-{
+{
u4byte t0, t1, blk[4];
u4byte *l_key = ctx->l_key;
u4byte *s_key = ctx->s_key;
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];
-};
+ out_blk[3] = blk[1] ^ l_key[7];
+}
/* decrypt a block of text */
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;
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];
-};
+ out_blk[3] = blk[1] ^ l_key[3];
+}