X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccrypt%2Ftwofish.c;h=e8f3bd44d88dc0fc961dea93b21b029b3ebed6f2;hb=e9374395ec9747bddd3ea0bfd3e5a17717e97b31;hp=08d3d510aaab371ed459a214cb75add7d4eda4ef;hpb=62f89b2886bbe9df82d9b2fdabfe707509d9e0fc;p=silc.git diff --git a/lib/silccrypt/twofish.c b/lib/silccrypt/twofish.c index 08d3d510..e8f3bd44 100644 --- a/lib/silccrypt/twofish.c +++ b/lib/silccrypt/twofish.c @@ -39,40 +39,36 @@ Mean: 378 cycles = 67.8 mbits/sec */ -#include "silcincludes.h" +#include "silc.h" +#include "twofish_internal.h" #include "twofish.h" -/* +/* * SILC Crypto API for Twofish */ /* Sets the key for the cipher. */ -SILC_CIPHER_API_SET_KEY(twofish) +SILC_CIPHER_API_SET_KEY(twofish_cbc) { - twofish_set_key((TwofishContext *)context, (unsigned int *)key, keylen); - return 1; + 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_cbc) { - /* unsigned char key[md5_hash_len]; - SilcMarsContext *ctx = (SilcMarsContext *)context; - make_md5_hash(string, &key); - memcpy(&ctx->key, mars_set_key(&key, keylen), keylen); - memset(&key, 'F', sizeoof(key)); - */ - - return 1; } /* Returns the size of the cipher context. */ -SILC_CIPHER_API_CONTEXT_LEN(twofish) +SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc) { return sizeof(TwofishContext); } @@ -80,38 +76,27 @@ SILC_CIPHER_API_CONTEXT_LEN(twofish) /* Encrypts with the cipher in CBC mode. Source and destination buffers maybe one and same. */ -SILC_CIPHER_API_ENCRYPT_CBC(twofish) +SILC_CIPHER_API_ENCRYPT(twofish_cbc) { - unsigned int *in, *out, *tiv; - unsigned int tmp[4]; + SilcUInt32 tiv[4]; int i; - in = (unsigned int *)src; - out = (unsigned int *)dst; - tiv = (unsigned int *)iv; + SILC_ASSERT((len & (16 - 1)) == 0); + if (len & (16 - 1)) + return FALSE; + SILC_CBC_GET_IV(tiv, iv); - tmp[0] = in[0] ^ tiv[0]; - tmp[1] = in[1] ^ tiv[1]; - tmp[2] = in[2] ^ tiv[2]; - tmp[3] = in[3] ^ tiv[3]; - twofish_encrypt((TwofishContext *)context, tmp, out); - in += 4; - out += 4; + SILC_CBC_ENC_PRE(tiv, src); + twofish_encrypt((TwofishContext *)context, tiv, tiv); + SILC_CBC_ENC_POST(tiv, dst, src); for (i = 16; i < len; i += 16) { - tmp[0] = in[0] ^ out[0 - 4]; - tmp[1] = in[1] ^ out[1 - 4]; - tmp[2] = in[2] ^ out[2 - 4]; - tmp[3] = in[3] ^ out[3 - 4]; - twofish_encrypt((TwofishContext *)context, tmp, out); - in += 4; - out += 4; + SILC_CBC_ENC_PRE(tiv, src); + twofish_encrypt((TwofishContext *)context, tiv, tiv); + SILC_CBC_ENC_POST(tiv, dst, src); } - tiv[0] = out[0 - 4]; - tiv[1] = out[1 - 4]; - tiv[2] = out[2 - 4]; - tiv[3] = out[3 - 4]; + SILC_CBC_PUT_IV(tiv, iv); return TRUE; } @@ -119,50 +104,27 @@ SILC_CIPHER_API_ENCRYPT_CBC(twofish) /* Decrypts with the cipher in CBC mode. Source and destination buffers maybe one and same. */ -SILC_CIPHER_API_DECRYPT_CBC(twofish) +SILC_CIPHER_API_DECRYPT(twofish_cbc) { - unsigned int *tiv, *in, *out; - unsigned int tmp[4], tmp2[4]; + SilcUInt32 tmp[4], tmp2[4], tiv[4]; int i; - in = (unsigned int *)src; - out = (unsigned int *)dst; - tiv = (unsigned int *)iv; - - tmp[0] = in[0]; - tmp[1] = in[1]; - tmp[2] = in[2]; - tmp[3] = in[3]; - twofish_decrypt((TwofishContext *)context, in, out); - out[0] ^= tiv[0]; - out[1] ^= tiv[1]; - out[2] ^= tiv[2]; - out[3] ^= tiv[3]; - in += 4; - out += 4; + if (len & (16 - 1)) + return FALSE; + + SILC_CBC_GET_IV(tiv, iv); + + SILC_CBC_DEC_PRE(tmp, src); + twofish_decrypt((TwofishContext *)context, tmp, tmp2); + SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv); for (i = 16; i < len; i += 16) { - tmp2[0] = tmp[0]; - tmp2[1] = tmp[1]; - tmp2[2] = tmp[2]; - tmp2[3] = tmp[3]; - tmp[0] = in[0]; - tmp[1] = in[1]; - tmp[2] = in[2]; - tmp[3] = in[3]; - twofish_decrypt((TwofishContext *)context, in, out); - out[0] ^= tmp2[0]; - out[1] ^= tmp2[1]; - out[2] ^= tmp2[2]; - out[3] ^= tmp2[3]; - in += 4; - out += 4; + SILC_CBC_DEC_PRE(tmp, src); + twofish_decrypt((TwofishContext *)context, tmp, tmp2); + SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv); } - tiv[0] = tmp[0]; - tiv[1] = tmp[1]; - tiv[2] = tmp[2]; - tiv[3] = tmp[3]; + SILC_CBC_PUT_IV(tiv, iv); return TRUE; } @@ -189,26 +151,26 @@ u1byte tab_ef[4] = { 0, (G_M >> 1) ^ (G_M >> 2), G_M >> 1, G_M >> 2 }; 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; @@ -218,7 +180,7 @@ u1byte qp(const u4byte n, const u1byte x) a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2]; a4 = qt2[n][a3]; b4 = qt3[n][b3]; return (b4 << 4) | a4; -}; +} #ifdef Q_TABLES @@ -231,11 +193,11 @@ 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); } -}; +} #else @@ -250,7 +212,7 @@ 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); @@ -261,7 +223,7 @@ void gen_mtab(void) 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] @@ -340,7 +302,7 @@ u4byte h_fun(TwofishContext *ctx, const u4byte x, const u4byte key[]) return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24); #endif -}; +} #ifdef MK_TABLE @@ -378,12 +340,12 @@ void gen_mk_tab(TwofishContext *ctx, u4byte key[]) 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; @@ -391,12 +353,12 @@ void gen_mk_tab(TwofishContext *ctx, u4byte key[]) 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; @@ -404,12 +366,12 @@ void gen_mk_tab(TwofishContext *ctx, u4byte key[]) 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)] \ @@ -437,22 +399,22 @@ void gen_mk_tab(TwofishContext *ctx, u4byte key[]) 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. */ @@ -464,41 +426,41 @@ u4byte mds_rem(u4byte p0, u4byte p1) 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); - - if(t & 0x80) // subtract modular polynomial on overflow - - 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 - + 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); + + if(t & 0x80) /* subtract modular polynomial on overflow */ + + 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) + 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) { @@ -536,7 +498,7 @@ u4byte *twofish_set_key(TwofishContext *ctx, #endif return l_key; -}; +} /* encrypt a block of text */ @@ -550,7 +512,7 @@ u4byte *twofish_set_key(TwofishContext *ctx, 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; @@ -566,8 +528,8 @@ void twofish_encrypt(TwofishContext *ctx, 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 */ @@ -581,7 +543,7 @@ void twofish_encrypt(TwofishContext *ctx, 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; @@ -597,5 +559,5 @@ void twofish_decrypt(TwofishContext *ctx, 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]; +}