/* Sets the key for the cipher. */
-SILC_CIPHER_API_SET_KEY(twofish_cbc)
+SILC_CIPHER_API_SET_KEY(twofish)
{
SilcUInt32 k[8];
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(twofish)
+{
+ 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. */
-SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc)
+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(twofish_cbc)
+SILC_CIPHER_API_ENCRYPT(twofish)
{
- SilcUInt32 tiv[4];
+ TwofishContext *twofish = context;
+ SilcUInt32 tmp[4], ctr[4];
int i;
- SILC_ASSERT((len & (16 - 1)) == 0);
- if (len & (16 - 1))
- return FALSE;
- 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;
+
+ case SILC_CIPHER_MODE_CFB:
+ SILC_CFB_ENC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+ twofish_encrypt(twofish, tmp, tmp));
+ break;
- SILC_CBC_PUT_IV(tiv, iv);
+ 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(twofish_cbc)
+SILC_CIPHER_API_DECRYPT(twofish)
{
+ TwofishContext *twofish = context;
SilcUInt32 tmp[4], tmp2[4], tiv[4];
int i;
- if (len & (16 - 1))
- return FALSE;
+ switch (cipher->mode) {
- SILC_CBC_GET_IV(tiv, iv);
+ 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;
- SILC_CBC_PUT_IV(tiv, iv);
+ default:
+ return FALSE;
+ }
return TRUE;
}
a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2];
a4 = qt2[n][a3]; b4 = qt3[n][b3];
return (b4 << 4) | a4;
-};
+}
#ifdef Q_TABLES
q(0,i) = qp(0, (u1byte)i);
q(1,i) = qp(1, (u1byte)i);
}
-};
+}
#else
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
#endif
}
}
-};
+}
# ifdef ONE_STEP
# define g0_fun(x) ( mk_tab[0][byte(x,0)] ^ mk_tab[1][byte(x,1)] \
}
return p1;
-};
+}
/* initialise the key schedule from the user supplied key */
#endif
return l_key;
-};
+}
/* encrypt a block of text */
out_blk[1] = blk[3] ^ l_key[5];
out_blk[2] = blk[0] ^ l_key[6];
out_blk[3] = blk[1] ^ l_key[7];
-};
+}
/* decrypt a block of text */
out_blk[1] = blk[3] ^ l_key[1];
out_blk[2] = blk[0] ^ l_key[2];
out_blk[3] = blk[1] ^ l_key[3];
-};
+}