X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccrypt%2Ftwofish.c;h=87d443c7fc91f67e4b8fc1140aa82b6e7040e0d4;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=08d3d510aaab371ed459a214cb75add7d4eda4ef;hpb=62f89b2886bbe9df82d9b2fdabfe707509d9e0fc;p=silc.git diff --git a/lib/silccrypt/twofish.c b/lib/silccrypt/twofish.c index 08d3d510..87d443c7 100644 --- a/lib/silccrypt/twofish.c +++ b/lib/silccrypt/twofish.c @@ -39,10 +39,11 @@ 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 */ @@ -50,24 +51,35 @@ Mean: 378 cycles = 67.8 mbits/sec SILC_CIPHER_API_SET_KEY(twofish) { - 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) { - /* unsigned char key[md5_hash_len]; - SilcMarsContext *ctx = (SilcMarsContext *)context; + TwofishContext *twofish = context; + + switch (cipher->mode) { - make_md5_hash(string, &key); - memcpy(&ctx->key, mars_set_key(&key, keylen), keylen); - memset(&key, 'F', sizeoof(key)); - */ + case SILC_CIPHER_MODE_CTR: + /* Starts new block. */ + twofish->padlen = 0; + break; - return 1; + case SILC_CIPHER_MODE_CFB: + /* Starts new block. */ + twofish->padlen = 16; + break; + + default: + break; + } } /* Returns the size of the cipher context. */ @@ -77,92 +89,66 @@ SILC_CIPHER_API_CONTEXT_LEN(twofish) 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) { - unsigned int *in, *out, *tiv; - unsigned int tmp[4]; + TwofishContext *twofish = context; + SilcUInt32 tmp[4], ctr[4]; int i; - in = (unsigned int *)src; - out = (unsigned int *)dst; - tiv = (unsigned int *)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; - - 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; - } + switch (cipher->mode) { - tiv[0] = out[0 - 4]; - tiv[1] = out[1 - 4]; - tiv[2] = out[2 - 4]; - tiv[3] = out[3 - 4]; + case SILC_CIPHER_MODE_CBC: + SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i, + twofish_encrypt(twofish, tmp, tmp)); + break; + + case SILC_CIPHER_MODE_CTR: + SILC_CTR_LSB_128_32(iv, ctr, tmp, twofish->padlen, src, dst, + twofish_encrypt(twofish, tmp, tmp)); + break; + + 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) { - unsigned int *tiv, *in, *out; - unsigned int tmp[4], tmp2[4]; + TwofishContext *twofish = context; + 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; - - 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; - } + 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)); + + case SILC_CIPHER_MODE_CTR: + return silc_twofish_encrypt(cipher, context, src, dst, len, iv); + break; - tiv[0] = tmp[0]; - tiv[1] = tmp[1]; - tiv[2] = tmp[2]; - tiv[3] = tmp[3]; + 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; + } return TRUE; } @@ -189,26 +175,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 +204,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 +217,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 +236,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 +247,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 +326,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 +364,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 +377,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 +390,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 +423,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 +450,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 +522,7 @@ u4byte *twofish_set_key(TwofishContext *ctx, #endif return l_key; -}; +} /* encrypt a block of text */ @@ -550,7 +536,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 +552,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 +567,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 +583,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]; +}