CTR mode APIs.
+Sat Jul 14 13:45:34 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added CFB mode to aes, twofish and cast5. Unified the API
+ for CBC, CTR and CFB modes. Affected files are in
+ lib/silccrypt/.
+
Fri Jul 13 22:55:13 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
* Added CAST5 (CAST-128) algorithm. Affected files are
break;
case SILC_CIPHER_MODE_CTR:
+ case SILC_CIPHER_MODE_CFB:
aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
break;
SILC_CIPHER_API_SET_IV(aes)
{
- if (cipher->mode == SILC_CIPHER_MODE_CTR) {
- AesContext *aes = context;
+ AesContext *aes = context;
+
+ switch (cipher->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;
+ break;
+
+ default:
+ break;
}
}
SILC_CIPHER_API_ENCRYPT(aes)
{
AesContext *aes = context;
- int i;
+ SilcUInt32 ctr[4];
switch (cipher->mode) {
case SILC_CIPHER_MODE_CBC:
break;
case SILC_CIPHER_MODE_CTR:
- {
- SilcUInt32 ctr[4];
-
- 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);
-
- i = aes->u.enc.inf.b[2];
- if (!i)
- i = 16;
-
- while (len-- > 0) {
- if (i == 16) {
- if (++ctr[3] == 0)
- if (++ctr[2] == 0)
- if (++ctr[1] == 0)
- ++ctr[0];
-
- 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);
-
- aes_encrypt(iv, iv, &aes->u.enc);
- i = 0;
- }
- *dst++ = *src++ ^ iv[i++];
- }
- aes->u.enc.inf.b[2] = i;
+ SILC_CTR_MSB_128_8(iv, ctr, iv, aes->u.enc.inf.b[2], src, dst,
+ aes_encrypt(iv, iv, &aes->u.enc));
+ break;
- 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);
- }
+ 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));
break;
default:
SILC_CIPHER_API_DECRYPT(aes)
{
+ AesContext *aes = context;
+
switch (cipher->mode) {
case SILC_CIPHER_MODE_CBC:
{
while(nb--) {
memcpy(tmp, src, 16);
- aes_decrypt(src, dst, &((AesContext *)context)->u.dec);
+ aes_decrypt(src, dst, &aes->u.dec);
lp32(dst)[0] ^= lp32(iv)[0];
lp32(dst)[1] ^= lp32(iv)[1];
lp32(dst)[2] ^= lp32(iv)[2];
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));
+ break;
+
default:
return FALSE;
}
ke4(cx->ks, 6); ke4(cx->ks, 7);
ke4(cx->ks, 8);
ke4(cx->ks, 9);
- cx->inf.l = 0;
cx->inf.b[0] = 10 * 16;
}
ke6(cx->ks, 4); ke6(cx->ks, 5);
ke6(cx->ks, 6);
kef6(cx->ks, 7);
- cx->inf.l = 0;
cx->inf.b[0] = 12 * 16;
}
ke8(cx->ks, 2); ke8(cx->ks, 3);
ke8(cx->ks, 4); ke8(cx->ks, 5);
kef8(cx->ks, 6);
- cx->inf.l = 0;
cx->inf.b[0] = 14 * 16;
}
kd4(cx->ks, 4); kd4(cx->ks, 5);
kd4(cx->ks, 6); kd4(cx->ks, 7);
kd4(cx->ks, 8); kdl4(cx->ks, 9);
- cx->inf.l = 0;
cx->inf.b[0] = 10 * 16;
}
kd6(cx->ks, 2); kd6(cx->ks, 3);
kd6(cx->ks, 4); kd6(cx->ks, 5);
kd6(cx->ks, 6); kdl6(cx->ks, 7);
- cx->inf.l = 0;
cx->inf.b[0] = 12 * 16;
}
kd8(cx->ks, 2); kd8(cx->ks, 3);
kd8(cx->ks, 4); kd8(cx->ks, 5);
kdl8(cx->ks, 6);
- cx->inf.l = 0;
cx->inf.b[0] = 14 * 16;
}
SILC_CIPHER_API_SET_IV(cast5)
{
- if (cipher->mode == SILC_CIPHER_MODE_CTR) {
- cast5_key *cast5 = context;
+ cast5_key *cast5 = context;
+
+ switch (cipher->mode) {
- /* Starts new block */
+ case SILC_CIPHER_MODE_CTR:
+ /* Starts new block. */
cast5->padlen = 0;
+ break;
+
+ case SILC_CIPHER_MODE_CFB:
+ /* Starts new block. */
+ cast5->padlen = 8;
+ break;
+
+ default:
+ break;
}
}
switch (cipher->mode) {
case SILC_CIPHER_MODE_CBC:
- SILC_ASSERT((len & (8 - 1)) == 0);
- if (len & (8 - 1))
- return FALSE;
- SILC_CBC_MSB_GET_IV(tmp, iv, 8);
-
- SILC_CBC_MSB_ENC_PRE(tmp, src, 8);
- cast5_encrypt(cast5, tmp, tmp);
- SILC_CBC_MSB_ENC_POST(tmp, dst, src, 8);
-
- for (i = 8; i < len; i += 8) {
- SILC_CBC_MSB_ENC_PRE(tmp, src, 8);
- cast5_encrypt(cast5, tmp, tmp);
- SILC_CBC_MSB_ENC_POST(tmp, dst, src, 8);
- }
-
- SILC_CBC_MSB_PUT_IV(tmp, iv, 8);
+ SILC_CBC_ENC_MSB_64_32(len, iv, tmp, src, dst, i,
+ cast5_encrypt(cast5, tmp, tmp));
break;
case SILC_CIPHER_MODE_CTR:
- SILC_GET32_MSB(ctr[0], iv);
- SILC_GET32_MSB(ctr[1], iv + 4);
-
- i = cast5->padlen;
- if (!i)
- i = 8;
-
- while (len-- > 0) {
- if (i == 8) {
- if (++ctr[1] == 0)
- ++ctr[0];
-
- cast5_encrypt(cast5, ctr, tmp);
-
- SILC_PUT32_MSB(tmp[0], iv);
- SILC_PUT32_MSB(tmp[1], iv + 4);
- i = 0;
- }
- *dst++ = *src++ ^ iv[i++];
- }
- cast5->padlen = i;
-
- SILC_PUT32_MSB(ctr[0], iv);
- SILC_PUT32_MSB(ctr[1], iv + 4);
+ 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));
break;
default:
SILC_CIPHER_API_DECRYPT(cast5)
{
+ cast5_key *cast5 = context;
SilcUInt32 tmp[2], tmp2[2], tiv[2];
int i;
switch (cipher->mode) {
case SILC_CIPHER_MODE_CBC:
- if (len & (8 - 1))
- return FALSE;
-
- SILC_CBC_MSB_GET_IV(tiv, iv, 8);
-
- SILC_CBC_MSB_DEC_PRE(tmp, src, 8);
- cast5_decrypt((cast5_key *)context, tmp, tmp2);
- SILC_CBC_MSB_DEC_POST(tmp2, dst, src, tmp, tiv, 8);
-
- for (i = 8; i < len; i += 8) {
- SILC_CBC_MSB_DEC_PRE(tmp, src, 8);
- cast5_decrypt((cast5_key *)context, tmp, tmp2);
- SILC_CBC_MSB_DEC_POST(tmp2, dst, src, tmp, tiv, 8);
- }
-
- SILC_CBC_MSB_PUT_IV(tiv, iv, 8);
+ 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));
+ break;
+
default:
return FALSE;
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1999 - 2006 Pekka Riikonen
+ Copyright (C) 1999 - 2007 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
SILC_GET32_LSB(d[_i], s + (_i * 4)); \
} while(0);
-/* CBC mode macros (LSB). */
+/* CBC mode 128-bit block, LSB, 32-bit block argument must be encrypted */
-#define SILC_CBC_GET_IV(d, s) \
-do { \
- SILC_GET32_LSB(d[0], &s[0]); \
- SILC_GET32_LSB(d[1], &s[4]); \
- SILC_GET32_LSB(d[2], &s[8]); \
- SILC_GET32_LSB(d[3], &s[12]); \
-} while(0);
+#define SILC_CBC_ENC_LSB_128_32(len, iv, block, src, dst, i, enc) \
+do { \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ SILC_GET32_LSB(block[0], &iv[0]); \
+ SILC_GET32_LSB(block[1], &iv[4]); \
+ SILC_GET32_LSB(block[2], &iv[8]); \
+ SILC_GET32_LSB(block[3], &iv[12]); \
+ \
+ for (i = 0; i < len; i += 16) { \
+ SILC_GET32_X_LSB(block[0], &src[0]); \
+ SILC_GET32_X_LSB(block[1], &src[4]); \
+ SILC_GET32_X_LSB(block[2], &src[8]); \
+ SILC_GET32_X_LSB(block[3], &src[12]); \
+ \
+ enc; \
+ \
+ SILC_PUT32_LSB(block[0], &dst[0]); \
+ SILC_PUT32_LSB(block[1], &dst[4]); \
+ SILC_PUT32_LSB(block[2], &dst[8]); \
+ SILC_PUT32_LSB(block[3], &dst[12]); \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+ \
+ SILC_PUT32_LSB(block[0], &iv[0]); \
+ SILC_PUT32_LSB(block[1], &iv[4]); \
+ SILC_PUT32_LSB(block[2], &iv[8]); \
+ SILC_PUT32_LSB(block[3], &iv[12]); \
+} while(0)
-#define SILC_CBC_PUT_IV(s, d) \
-do { \
- SILC_PUT32_LSB(s[0], &d[0]); \
- SILC_PUT32_LSB(s[1], &d[4]); \
- SILC_PUT32_LSB(s[2], &d[8]); \
- SILC_PUT32_LSB(s[3], &d[12]); \
-} while(0);
+/* CBC mode 128-bit block, LSB, decrypt block to block_dec. */
-#define SILC_CBC_ENC_PRE(d, s) \
-do { \
- SILC_GET32_X_LSB(d[0], &s[0]); \
- SILC_GET32_X_LSB(d[1], &s[4]); \
- SILC_GET32_X_LSB(d[2], &s[8]); \
- SILC_GET32_X_LSB(d[3], &s[12]); \
-} while(0);
+#define SILC_CBC_DEC_LSB_128_32(len, iv, block_prev, block, \
+ block_dec, src, dst, i, dec) \
+do { \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ SILC_GET32_LSB(block_prev[0], &iv[0]); \
+ SILC_GET32_LSB(block_prev[1], &iv[4]); \
+ SILC_GET32_LSB(block_prev[2], &iv[8]); \
+ SILC_GET32_LSB(block_prev[3], &iv[12]); \
+ \
+ for (i = 0; i < len; i += 16) { \
+ SILC_GET32_LSB(block[0], &src[0]); \
+ SILC_GET32_LSB(block[1], &src[4]); \
+ SILC_GET32_LSB(block[2], &src[8]); \
+ SILC_GET32_LSB(block[3], &src[12]); \
+ \
+ dec; \
+ \
+ block_dec[0] ^= block_prev[0]; \
+ block_dec[1] ^= block_prev[1]; \
+ block_dec[2] ^= block_prev[2]; \
+ block_dec[3] ^= block_prev[3]; \
+ \
+ SILC_PUT32_LSB(block_dec[0], &dst[0]); \
+ SILC_PUT32_LSB(block_dec[1], &dst[4]); \
+ SILC_PUT32_LSB(block_dec[2], &dst[8]); \
+ SILC_PUT32_LSB(block_dec[3], &dst[12]); \
+ \
+ block_prev[0] = block[0]; \
+ block_prev[1] = block[1]; \
+ block_prev[2] = block[2]; \
+ block_prev[3] = block[3]; \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+ \
+ SILC_PUT32_LSB(block[0], &iv[0]); \
+ SILC_PUT32_LSB(block[1], &iv[4]); \
+ SILC_PUT32_LSB(block[2], &iv[8]); \
+ SILC_PUT32_LSB(block[3], &iv[12]); \
+} while(0)
-#define SILC_CBC_ENC_POST(s, d, t) \
-do { \
- SILC_PUT32_LSB(s[0], &d[0]); \
- SILC_PUT32_LSB(s[1], &d[4]); \
- SILC_PUT32_LSB(s[2], &d[8]); \
- SILC_PUT32_LSB(s[3], &d[12]); \
- \
- d += 16; \
- t += 16; \
-} while(0);
+/* CBC mode 128-bit block, MSB, 32-bit block argument must be encrypted */
-#define SILC_CBC_DEC_PRE(d, s) \
-do { \
- SILC_GET32_LSB(d[0], &s[0]); \
- SILC_GET32_LSB(d[1], &s[4]); \
- SILC_GET32_LSB(d[2], &s[8]); \
- SILC_GET32_LSB(d[3], &s[12]); \
-} while(0);
+#define SILC_CBC_ENC_MSB_128_32(len, iv, block, src, dst, i, enc) \
+do { \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ SILC_GET32_MSB(block[0], &iv[0]); \
+ SILC_GET32_MSB(block[1], &iv[4]); \
+ SILC_GET32_MSB(block[2], &iv[8]); \
+ SILC_GET32_MSB(block[3], &iv[12]); \
+ \
+ for (i = 0; i < len; i += 16) { \
+ SILC_GET32_X_MSB(block[0], &src[0]); \
+ SILC_GET32_X_MSB(block[1], &src[4]); \
+ SILC_GET32_X_MSB(block[2], &src[8]); \
+ SILC_GET32_X_MSB(block[3], &src[12]); \
+ \
+ enc; \
+ \
+ SILC_PUT32_MSB(block[0], &dst[0]); \
+ SILC_PUT32_MSB(block[1], &dst[4]); \
+ SILC_PUT32_MSB(block[2], &dst[8]); \
+ SILC_PUT32_MSB(block[3], &dst[12]); \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+ \
+ SILC_PUT32_MSB(block[0], &iv[0]); \
+ SILC_PUT32_MSB(block[1], &iv[4]); \
+ SILC_PUT32_MSB(block[2], &iv[8]); \
+ SILC_PUT32_MSB(block[3], &iv[12]); \
+} while(0)
-#define SILC_CBC_DEC_POST(s, d, p, t, siv) \
-do { \
- s[0] ^= siv[0]; \
- s[1] ^= siv[1]; \
- s[2] ^= siv[2]; \
- s[3] ^= siv[3]; \
- \
- SILC_PUT32_LSB(s[0], &d[0]); \
- SILC_PUT32_LSB(s[1], &d[4]); \
- SILC_PUT32_LSB(s[2], &d[8]); \
- SILC_PUT32_LSB(s[3], &d[12]); \
- \
- siv[0] = t[0]; \
- siv[1] = t[1]; \
- siv[2] = t[2]; \
- siv[3] = t[3]; \
- \
- d += 16; \
- p += 16; \
-} while(0);
+/* CBC mode 128-bit block, MSB, decrypt block to block_dec. */
-/* CBC mode macros (MSB). */
+#define SILC_CBC_DEC_MSB_128_32(len, iv, block_prev, block, \
+ block_dec, src, dst, i, dec) \
+do { \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ SILC_GET32_MSB(block_prev[0], &iv[0]); \
+ SILC_GET32_MSB(block_prev[1], &iv[4]); \
+ SILC_GET32_MSB(block_prev[2], &iv[8]); \
+ SILC_GET32_MSB(block_prev[3], &iv[12]); \
+ \
+ for (i = 0; i < len; i += 16) { \
+ SILC_GET32_MSB(block[0], &src[0]); \
+ SILC_GET32_MSB(block[1], &src[4]); \
+ SILC_GET32_MSB(block[2], &src[8]); \
+ SILC_GET32_MSB(block[3], &src[12]); \
+ \
+ dec; \
+ \
+ block_dec[0] ^= block_prev[0]; \
+ block_dec[1] ^= block_prev[1]; \
+ block_dec[2] ^= block_prev[2]; \
+ block_dec[3] ^= block_prev[3]; \
+ \
+ SILC_PUT32_MSB(block_dec[0], &dst[0]); \
+ SILC_PUT32_MSB(block_dec[1], &dst[4]); \
+ SILC_PUT32_MSB(block_dec[2], &dst[8]); \
+ SILC_PUT32_MSB(block_dec[3], &dst[12]); \
+ \
+ block_prev[0] = block[0]; \
+ block_prev[1] = block[1]; \
+ block_prev[2] = block[2]; \
+ block_prev[3] = block[3]; \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+ \
+ SILC_PUT32_MSB(block[0], &iv[0]); \
+ SILC_PUT32_MSB(block[1], &iv[4]); \
+ SILC_PUT32_MSB(block[2], &iv[8]); \
+ SILC_PUT32_MSB(block[3], &iv[12]); \
+} while(0)
-#define SILC_CBC_MSB_GET_IV(d, s, l) \
-do { \
- SILC_GET32_MSB(d[0], &s[0]); \
- SILC_GET32_MSB(d[1], &s[4]); \
- if (l > 8) { \
- SILC_GET32_MSB(d[2], &s[8]); \
- SILC_GET32_MSB(d[3], &s[12]); \
- } \
-} while(0);
+/* CBC mode 64-bit block, MSB, 32-bit block argument must be encrypted */
-#define SILC_CBC_MSB_PUT_IV(s, d, l) \
-do { \
- SILC_PUT32_MSB(s[0], &d[0]); \
- SILC_PUT32_MSB(s[1], &d[4]); \
- if (l > 8) { \
- SILC_PUT32_MSB(s[2], &d[8]); \
- SILC_PUT32_MSB(s[3], &d[12]); \
- } \
-} while(0);
+#define SILC_CBC_ENC_MSB_64_32(len, iv, block, src, dst, i, enc) \
+do { \
+ SILC_ASSERT((len & (8 - 1)) == 0); \
+ if (len & (8 - 1)) \
+ return FALSE; \
+ \
+ SILC_GET32_MSB(block[0], &iv[0]); \
+ SILC_GET32_MSB(block[1], &iv[4]); \
+ \
+ for (i = 0; i < len; i += 8) { \
+ SILC_GET32_X_MSB(block[0], &src[0]); \
+ SILC_GET32_X_MSB(block[1], &src[4]); \
+ \
+ enc; \
+ \
+ SILC_PUT32_MSB(block[0], &dst[0]); \
+ SILC_PUT32_MSB(block[1], &dst[4]); \
+ \
+ dst += 8; \
+ src += 8; \
+ } \
+ \
+ SILC_PUT32_MSB(block[0], &iv[0]); \
+ SILC_PUT32_MSB(block[1], &iv[4]); \
+} while(0)
-#define SILC_CBC_MSB_ENC_PRE(d, s, l) \
-do { \
- SILC_GET32_X_MSB(d[0], &s[0]); \
- SILC_GET32_X_MSB(d[1], &s[4]); \
- if (l > 8) { \
- SILC_GET32_X_MSB(d[2], &s[8]); \
- SILC_GET32_X_MSB(d[3], &s[12]); \
- } \
-} while(0);
+/* CBC mode 64-bit block, MSB, decrypt block to block_dec. */
-#define SILC_CBC_MSB_ENC_POST(s, d, t, l) \
-do { \
- SILC_PUT32_MSB(s[0], &d[0]); \
- SILC_PUT32_MSB(s[1], &d[4]); \
- if (l > 8) { \
- SILC_PUT32_MSB(s[2], &d[8]); \
- SILC_PUT32_MSB(s[3], &d[12]); \
- } \
- \
- d += l; \
- t += l; \
-} while(0);
+#define SILC_CBC_DEC_MSB_64_32(len, iv, block_prev, block, \
+ block_dec, src, dst, i, dec) \
+do { \
+ if (len & (8 - 1)) \
+ return FALSE; \
+ \
+ SILC_GET32_MSB(block_prev[0], &iv[0]); \
+ SILC_GET32_MSB(block_prev[1], &iv[4]); \
+ \
+ for (i = 0; i < len; i += 8) { \
+ SILC_GET32_MSB(block[0], &src[0]); \
+ SILC_GET32_MSB(block[1], &src[4]); \
+ \
+ dec; \
+ \
+ block_dec[0] ^= block_prev[0]; \
+ block_dec[1] ^= block_prev[1]; \
+ \
+ SILC_PUT32_MSB(block_dec[0], &dst[0]); \
+ SILC_PUT32_MSB(block_dec[1], &dst[4]); \
+ \
+ block_prev[0] = block[0]; \
+ block_prev[1] = block[1]; \
+ \
+ dst += 8; \
+ src += 8; \
+ } \
+ \
+ SILC_PUT32_MSB(block[0], &iv[0]); \
+ SILC_PUT32_MSB(block[1], &iv[4]); \
+} while(0)
-#define SILC_CBC_MSB_DEC_PRE(d, s, l) \
-do { \
- SILC_GET32_MSB(d[0], &s[0]); \
- SILC_GET32_MSB(d[1], &s[4]); \
- if (l > 8) { \
- SILC_GET32_MSB(d[2], &s[8]); \
- SILC_GET32_MSB(d[3], &s[12]); \
- } \
-} while(0);
-#define SILC_CBC_MSB_DEC_POST(s, d, p, t, siv, l) \
-do { \
- s[0] ^= siv[0]; \
- s[1] ^= siv[1]; \
- if (l > 8) { \
- s[2] ^= siv[2]; \
- s[3] ^= siv[3]; \
- } \
- \
- SILC_PUT32_MSB(s[0], &d[0]); \
- SILC_PUT32_MSB(s[1], &d[4]); \
- if (l > 8) { \
- SILC_PUT32_MSB(s[2], &d[8]); \
- SILC_PUT32_MSB(s[3], &d[12]); \
- } \
- \
- siv[0] = t[0]; \
- siv[1] = t[1]; \
- if (l > 8) { \
- siv[2] = t[2]; \
- siv[3] = t[3]; \
- } \
- \
- d += l; \
- p += l; \
-} while(0);
+/* CTR mode 128-bit block, MSB, MSB counter, the 8-bit enc_ctr argument must
+ be encrypted */
+
+#define SILC_CTR_MSB_128_8(iv, 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]; \
+ \
+ 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); \
+ \
+ enc; \
+ 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, MSB, MSB counter, the 32-bit ctr argument must
+ be encrypted to enc_ctr */
+
+#define SILC_CTR_MSB_128_32(iv, 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]; \
+ \
+ 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 */
+
+#define SILC_CTR_LSB_128_32(iv, 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]; \
+ \
+ 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]); \
+ \
+ 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); \
+ pad = 0; \
+ } \
+ *dst++ = *src++ ^ iv[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 */
+
+#define SILC_CTR_MSB_64_32(iv, ctr, 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]; \
+ \
+ enc; \
+ SILC_PUT32_MSB(enc_ctr[0], iv); \
+ SILC_PUT32_MSB(enc_ctr[1], iv + 4); \
+ pad = 0; \
+ } \
+ *dst++ = *src++ ^ iv[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. */
+
+#define SILC_CFB_ENC_LSB_128_32(iv, cfb, pad, src, dst, enc) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 16) { \
+ SILC_GET32_LSB(cfb[0], iv); \
+ SILC_GET32_LSB(cfb[1], iv + 4); \
+ SILC_GET32_LSB(cfb[2], iv + 8); \
+ SILC_GET32_LSB(cfb[3], iv + 12); \
+ \
+ enc; \
+ \
+ SILC_PUT32_LSB(cfb[0], iv); \
+ SILC_PUT32_LSB(cfb[1], iv + 4); \
+ SILC_PUT32_LSB(cfb[2], iv + 8); \
+ SILC_PUT32_LSB(cfb[3], iv + 12); \
+ pad = 0; \
+ } \
+ iv[pad] = (*dst = *src ^ iv[pad]); \
+ dst++; \
+ src++; \
+ pad++; \
+ } \
+} while(0)
+
+/* CFB 128-bit block, LSB, the 32-bit cfb argument must be decrypted. */
+
+#define SILC_CFB_DEC_LSB_128_32(iv, cfb, pad, src, dst, dec) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 16) { \
+ SILC_GET32_LSB(cfb[0], iv); \
+ SILC_GET32_LSB(cfb[1], iv + 4); \
+ SILC_GET32_LSB(cfb[2], iv + 8); \
+ SILC_GET32_LSB(cfb[3], iv + 12); \
+ \
+ dec; \
+ \
+ SILC_PUT32_LSB(cfb[0], iv); \
+ SILC_PUT32_LSB(cfb[1], iv + 4); \
+ SILC_PUT32_LSB(cfb[2], iv + 8); \
+ SILC_PUT32_LSB(cfb[3], iv + 12); \
+ pad = 0; \
+ } \
+ iv[pad] = *src ^ iv[pad]; \
+ *dst = iv[pad]; \
+ iv[pad++] = *src; \
+ dst++; \
+ src++; \
+ } \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 32-bit cfb argument must be encrypted. */
+
+#define SILC_CFB_ENC_MSB_128_32(iv, cfb, pad, src, dst, enc) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 16) { \
+ SILC_GET32_MSB(cfb[0], iv); \
+ SILC_GET32_MSB(cfb[1], iv + 4); \
+ SILC_GET32_MSB(cfb[2], iv + 8); \
+ SILC_GET32_MSB(cfb[3], iv + 12); \
+ \
+ enc; \
+ \
+ SILC_PUT32_MSB(cfb[0], iv); \
+ SILC_PUT32_MSB(cfb[1], iv + 4); \
+ SILC_PUT32_MSB(cfb[2], iv + 8); \
+ SILC_PUT32_MSB(cfb[3], iv + 12); \
+ pad = 0; \
+ } \
+ iv[pad] = (*dst = *src ^ iv[pad]); \
+ dst++; \
+ src++; \
+ pad++; \
+ } \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 32-bit cfb argument must be decrypted. */
+
+#define SILC_CFB_DEC_MSB_128_32(iv, cfb, pad, src, dst, dec) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 16) { \
+ SILC_GET32_MSB(cfb[0], iv); \
+ SILC_GET32_MSB(cfb[1], iv + 4); \
+ SILC_GET32_MSB(cfb[2], iv + 8); \
+ SILC_GET32_MSB(cfb[3], iv + 12); \
+ \
+ dec; \
+ \
+ SILC_PUT32_MSB(cfb[0], iv); \
+ SILC_PUT32_MSB(cfb[1], iv + 4); \
+ SILC_PUT32_MSB(cfb[2], iv + 8); \
+ SILC_PUT32_MSB(cfb[3], iv + 12); \
+ pad = 0; \
+ } \
+ iv[pad] = *src ^ iv[pad]; \
+ *dst = iv[pad]; \
+ iv[pad++] = *src; \
+ dst++; \
+ src++; \
+ } \
+} while(0)
+
+/* CFB 64-bit block, MSB, the 32-bit cfb argument must be encrypted. */
+
+#define SILC_CFB_ENC_MSB_64_32(iv, cfb, pad, src, dst, enc) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 8) { \
+ SILC_GET32_MSB(cfb[0], iv); \
+ SILC_GET32_MSB(cfb[1], iv + 4); \
+ \
+ enc; \
+ \
+ SILC_PUT32_MSB(cfb[0], iv); \
+ SILC_PUT32_MSB(cfb[1], iv + 4); \
+ pad = 0; \
+ } \
+ iv[pad] = (*dst = *src ^ iv[pad]); \
+ dst++; \
+ src++; \
+ pad++; \
+ } \
+} while(0)
+
+/* CFB 64-bit block, MSB, the 32-bit cfb argument must be decrypted. */
+
+#define SILC_CFB_DEC_MSB_64_32(iv, cfb, pad, src, dst, dec) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 8) { \
+ SILC_GET32_MSB(cfb[0], iv); \
+ SILC_GET32_MSB(cfb[1], iv + 4); \
+ \
+ dec; \
+ \
+ SILC_PUT32_MSB(cfb[0], iv); \
+ SILC_PUT32_MSB(cfb[1], iv + 4); \
+ pad = 0; \
+ } \
+ iv[pad] = *src ^ iv[pad]; \
+ *dst = iv[pad]; \
+ iv[pad++] = *src; \
+ dst++; \
+ src++; \
+ } \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 8-bit iv argument must be encrypted. */
+
+#define SILC_CFB_ENC_MSB_128_8(iv, pad, src, dst, enc) \
+do { \
+ while (len-- > 0) { \
+ if (pad == 16) { \
+ enc; \
+ pad = 0; \
+ } \
+ iv[pad] = (*dst = *src ^ iv[pad]); \
+ dst++; \
+ src++; \
+ pad++; \
+ } \
+} while(0)
+
+/* CFB 128-bit block, MSB, the 8-bit iv argument must be decrypted. */
+
+#define SILC_CFB_DEC_MSB_128_8(iv, pad, src, dst, dec) \
+ do { \
+ while (len-- > 0) { \
+ if (pad == 16) { \
+ dec; \
+ pad = 0; \
+ } \
+ iv[pad] = *src ^ iv[pad]; \
+ *dst = iv[pad]; \
+ iv[pad++] = *src; \
+ dst++; \
+ src++; \
+ } \
+} while(0)
#endif
#define KS_LENGTH 60
typedef union {
- uint_32t l;
uint_8t b[4];
} aes_inf;
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),
#ifdef SILC_DEBUG
SILC_CDEF("none", none, 0, 0, 0, 0),
#endif /* SILC_DEBUG */
{
if (iv)
memmove(&cipher->iv, iv, cipher->cipher->iv_len);
- cipher->cipher->set_iv(cipher->cipher, cipher->context, iv);
+ cipher->cipher->set_iv(cipher->cipher, cipher->context, cipher->iv);
}
/* Returns the IV (initial vector) of the cipher. */
*
* DESCRIPTION
*
- * Cipher modes.
+ * Cipher modes. Notes about cipher modes and implementation:
+ *
+ * SILC_CIPHER_MODE_CBC
+ *
+ * The Cipher-block Chaining mode. The CBC is mode is a standard CBC
+ * mode. The plaintext length must be multiple by the cipher block size.
+ * If it isn't the plaintext must be padded.
+ *
+ * SILC_CIPHER_MODE_CTR
+ *
+ * The Counter mode. The CTR is normal counter mode. The CTR mode does
+ * not require the plaintext length to be multiple by the cipher block
+ * size. If the last plaintext block is shorter the remaining bits of
+ * the key stream are used next time silc_cipher_encrypt is called. If
+ * silc_cipher_set_iv is called it will reset the counter for a new block
+ * (discarding any remaining bits from previous key stream). The counter
+ * mode expects MSB first ordered counter. Note also, the counter is
+ * incremented when silc_cipher_encrypt is called for the first time,
+ * before encrypting.
+ *
+ * SILC_CIPHER_MODE_CFB
+ *
+ * The Cipher Feedback mode. The CFB mode is normal cipher feedback mode.
+ * The CFB mode does not require the plaintext length to be multiple by
+ * the cipher block size. If the last plaintext block is shorter the
+ * remaining bits of the stream are used next time silc_cipher_encrypt is
+ * called. If silc_cipher_set_iv is called it will reset the feedback
+ * for a new block (discarding any remaining bits from previous stream).
+ *
+ * SILC_CIPHER_MODE_OFB
+ *
+ * The Output Feedback mode.
+ *
+ * SILC_CIPHER_MODE_ECB
+ *
+ * The Electronic Codebook mode. This mode does not provide sufficient
+ * security and should not be used.
*
* SOURCE
*/
*
* Notes about modes:
*
- * The CTR is normal counter mode. The CTR mode does not require the
- * plaintext length to be multiple by the cipher block size. If the last
- * plaintext block is shorter the remaining bits of the key stream are
- * used next time silc_cipher_encrypt is called. If silc_cipher_set_iv
- * is called it will reset the counter for a new block (discarding any
- * remaining bits from previous key stream). The counter mode expects
- * MSB first ordered counter. Note also, the counter is incremented when
- * silc_cipher_encrypt is called for the first time, before encrypting.
- *
- * The CBC is mode is a standard CBC mode. The plaintext length must be
- * multiple by the cipher block size. If it isn't the plaintext must be
- * padded.
- *
***/
SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher);
const unsigned char *key, \
SilcUInt32 keylen, \
SilcBool encryption)
-#define SILC_CIPHER_API_SET_IV(name) \
+#define SILC_CIPHER_API_SET_IV(name) \
void silc_##name##_set_iv(struct SilcCipherObjectStruct *cipher, \
- void *context, \
- const unsigned char *iv)
+ void *context, \
+ unsigned char *iv)
#define SILC_CIPHER_API_ENCRYPT(name) \
SilcBool silc_##name##_encrypt(struct SilcCipherObjectStruct *cipher, \
void *context, \
/* 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 *context, const unsigned char *iv);
+ void *context, unsigned char *iv);
/* Encrypt. The `src' and `dst' may be same pointer. The `iv' may be
edited inside this function. */
int p5_len = 36;
const unsigned char c5[] = "\xEB\x6C\x52\x82\x1D\x0B\xBB\xF7\xCE\x75\x94\x46\x2A\xCA\x4F\xAA\xB4\x07\xDF\x86\x65\x69\xFD\x07\xF4\x8C\xC0\xB5\x83\xD6\x07\x1F\x1E\xC0\xE6\xB8";
+/* CFB */
+
+/* 36 bytes plaintext, 256 bits key */
+const unsigned char key6[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key6_len = 32 * 8;
+const unsigned char iv6[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p6[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p6_len = 36;
+const unsigned char c6[] = "\x7C\x4C\x1D\xB1\x25\x20\x76\x4E\x86\x57\x16\xEF\x82\x93\x53\x62\xE8\x99\x98\x11\xCB\x83\x1A\xEA\x61\x0D\xC7\xE3\x91\x19\x5F\x5D\xD8\xA6\x7B\xD5";
+
int main(int argc, char **argv)
{
SilcBool success = FALSE;
SILC_LOG_DEBUG(("Decrypt is successful"));
silc_cipher_free(cipher2);
+
+ SILC_LOG_DEBUG(("Allocating aes-256-cfb cipher"));
+ if (!silc_cipher_alloc("aes-256-cfb", &cipher)) {
+ SILC_LOG_DEBUG(("Allocating aes-256-cfb cipher failed"));
+ goto err;
+ }
+ if (!silc_cipher_alloc("aes-256-cfb", &cipher2)) {
+ SILC_LOG_DEBUG(("Allocating aes-256-cfb cipher failed"));
+ goto err;
+ }
+
+ SILC_LOG_DEBUG(("CFB test vector"));
+ memset(dst, 0, sizeof(dst));
+ memset(pdst, 0, sizeof(pdst));
+ silc_cipher_set_iv(cipher, iv6);
+ assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
+ assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
+ assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
+ SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+ silc_cipher_get_block_len(cipher),
+ silc_cipher_get_key_len(cipher),
+ silc_cipher_get_name(cipher)));
+ SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
+ SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
+ SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
+ if (memcmp(dst, c6, p6_len)) {
+ SILC_LOG_DEBUG(("Encrypt failed"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("Encrypt is successful"));
+ silc_cipher_set_iv(cipher2, iv6);
+ assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
+ SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
+ SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p6, p6_len);
+ if (memcmp(pdst, p6, p6_len)) {
+ SILC_LOG_DEBUG(("Decrypt failed"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("Decrypt is successful"));
+ silc_cipher_free(cipher2);
+
success = TRUE;
err:
int p2_len = 32;
const unsigned char c2[] = "\x23\xA5\xBD\xC5\x2A\x59\xD4\x06\x61\xBF\xF3\x47\x76\x4B\xC8\x41\x1C\x65\xE3\xE2\x1A\x1F\x42\x4B\xBD\x22\xDF\xEC\xD9\xC9\x52\x43";
-/* CTR test vectors from RFC3686. */
+/* CTR */
/* 32 bytes plaintext, 128 bits key */
const unsigned char key4[] = "\x7E\x24\x06\x78\x17\xFA\xE0\xD7\x43\xD6\xCE\x1F\x32\x53\x91\x63";
int p4_len = 32;
const unsigned char c4[] = "\xAA\x16\xEC\xEA\x77\x73\x12\xC1\x14\x0F\x10\x65\x06\x72\xF8\xE5\x89\xCF\x26\x2C\x84\xC6\x3A\x93\xEE\xC0\xB2\xBA\x92\xAD\x19\xCA";
+/* CFB */
+
+/* 36 bytes plaintext, 128 bits key */
+const unsigned char key6[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key6_len = 16 * 8;
+const unsigned char iv6[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p6[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p6_len = 36;
+const unsigned char c6[] = "\xE2\x30\xB2\x57\x12\x31\x04\x54\x37\xEC\xF1\x43\xC1\x3F\x20\x53\xA4\xDD\x99\x29\x3C\xCA\x4A\x7C\xCC\xEA\x12\xBF\xA8\x05\x37\x89\xA9\xB3\x3B\x15";
+
int main(int argc, char **argv)
{
SilcBool success = FALSE;
SILC_LOG_DEBUG(("Decrypt is successful"));
silc_cipher_free(cipher);
+
+ SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher"));
+ if (!silc_cipher_alloc("cast5-128-cfb", &cipher)) {
+ SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher failed"));
+ goto err;
+ }
+ if (!silc_cipher_alloc("cast5-128-cfb", &cipher2)) {
+ SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher failed"));
+ goto err;
+ }
+
+ SILC_LOG_DEBUG(("CFB test vector"));
+ memset(dst, 0, sizeof(dst));
+ memset(pdst, 0, sizeof(pdst));
+ silc_cipher_set_iv(cipher, iv6);
+ assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
+ assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
+ assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
+ SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+ silc_cipher_get_block_len(cipher),
+ silc_cipher_get_key_len(cipher),
+ silc_cipher_get_name(cipher)));
+ SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
+ SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
+ SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
+ if (memcmp(dst, c6, p6_len)) {
+ SILC_LOG_DEBUG(("Encrypt failed"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("Encrypt is successful"));
+ silc_cipher_set_iv(cipher2, iv6);
+ assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
+ SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
+ SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p6, p6_len);
+ if (memcmp(pdst, p6, p6_len)) {
+ SILC_LOG_DEBUG(("Decrypt failed"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("Decrypt is successful"));
+ silc_cipher_free(cipher2);
+
success = TRUE;
err:
int p5_len = 36;
const unsigned char c5[] = "\x71\x2F\x9C\xE1\x4F\xD5\x9E\xBF\x6A\x1E\x7D\x76\x0C\xBA\x70\xE9\x5E\xCE\x27\xAD\x5B\xE1\x38\xDB\x99\xEF\x46\x78\x4D\xCF\x99\x24\x63\x0E\x84\x58";
+/* CFB */
+
+/* 36 bytes plaintext, 256 bits key */
+const unsigned char key6[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key6_len = 32 * 8;
+const unsigned char iv6[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p6[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p6_len = 36;
+const unsigned char c6[] = "\x2C\x0E\x4D\xEF\xE4\x71\xEB\x2A\x4B\x03\x21\x96\xD1\xCD\x73\xD7\x3A\xA9\xEB\x08\x87\xB2\xAB\x66\x28\x3A\xC2\x99\xB7\x13\x8C\x92\xEA\xD6\xFD\x41";
+
int main(int argc, char **argv)
{
SilcBool success = FALSE;
}
/* Third test vector */
- SILC_LOG_DEBUG(("Third test vector"));
+ SILC_LOG_DEBUG(("CTR test vector"));
memset(dst, 0, sizeof(dst));
memset(pdst, 0, sizeof(pdst));
silc_cipher_set_iv(cipher, iv3);
/* Fourth test vector */
- SILC_LOG_DEBUG(("Fourth test vector"));
+ SILC_LOG_DEBUG(("CTR test vector"));
memset(dst, 0, sizeof(dst));
memset(pdst, 0, sizeof(pdst));
silc_cipher_set_iv(cipher, iv4);
}
/* Fifth test vector */
- SILC_LOG_DEBUG(("Fifth test vector"));
+ SILC_LOG_DEBUG(("CTR test vector"));
memset(dst, 0, sizeof(dst));
memset(pdst, 0, sizeof(pdst));
silc_cipher_set_iv(cipher, iv5);
SILC_LOG_DEBUG(("Decrypt is successful"));
silc_cipher_free(cipher2);
+
+ SILC_LOG_DEBUG(("Allocating twofish-256-cfb cipher"));
+ if (!silc_cipher_alloc("twofish-256-cfb", &cipher)) {
+ SILC_LOG_DEBUG(("Allocating twofish-256-cfb cipher failed"));
+ goto err;
+ }
+ if (!silc_cipher_alloc("twofish-256-cfb", &cipher2)) {
+ SILC_LOG_DEBUG(("Allocating twofish-256-cfb cipher failed"));
+ goto err;
+ }
+
+ /* Fifth test vector */
+ SILC_LOG_DEBUG(("CFB test vector"));
+ memset(dst, 0, sizeof(dst));
+ memset(pdst, 0, sizeof(pdst));
+ silc_cipher_set_iv(cipher, iv6);
+ assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
+ assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
+ assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
+ SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+ silc_cipher_get_block_len(cipher),
+ silc_cipher_get_key_len(cipher),
+ silc_cipher_get_name(cipher)));
+ SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
+ SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
+ SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
+ if (memcmp(dst, c6, p6_len)) {
+ SILC_LOG_DEBUG(("Encrypt failed"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("Encrypt is successful"));
+ silc_cipher_set_iv(cipher2, iv6);
+ assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
+ SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
+ SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p5, p6_len);
+ if (memcmp(pdst, p6, p6_len)) {
+ SILC_LOG_DEBUG(("Decrypt failed"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("Decrypt is successful"));
+ silc_cipher_free(cipher2);
+
success = TRUE;
err:
SILC_CIPHER_API_SET_IV(twofish)
{
- if (cipher->mode == SILC_CIPHER_MODE_CTR) {
- TwofishContext *twofish = context;
+ 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;
}
}
switch (cipher->mode) {
case SILC_CIPHER_MODE_CBC:
- SILC_ASSERT((len & (16 - 1)) == 0);
- if (len & (16 - 1))
- return FALSE;
- SILC_CBC_GET_IV(tmp, iv);
-
- SILC_CBC_ENC_PRE(tmp, src);
- twofish_encrypt(twofish, tmp, tmp);
- SILC_CBC_ENC_POST(tmp, dst, src);
-
- for (i = 16; i < len; i += 16) {
- SILC_CBC_ENC_PRE(tmp, src);
- twofish_encrypt(twofish, tmp, tmp);
- SILC_CBC_ENC_POST(tmp, dst, src);
- }
-
- SILC_CBC_PUT_IV(tmp, iv);
+ SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i,
+ twofish_encrypt(twofish, tmp, tmp));
break;
case SILC_CIPHER_MODE_CTR:
- 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);
-
- i = twofish->padlen;
- if (!i)
- i = 16;
-
- while (len-- > 0) {
- if (i == 16) {
- if (++ctr[3] == 0)
- if (++ctr[2] == 0)
- if (++ctr[1] == 0)
- ++ctr[0];
-
- tmp[0] = SILC_SWAB_32(ctr[0]);
- tmp[1] = SILC_SWAB_32(ctr[1]);
- tmp[2] = SILC_SWAB_32(ctr[2]);
- tmp[3] = SILC_SWAB_32(ctr[3]);
-
- twofish_encrypt(twofish, tmp, tmp);
-
- SILC_PUT32_LSB(tmp[0], iv);
- SILC_PUT32_LSB(tmp[1], iv + 4);
- SILC_PUT32_LSB(tmp[2], iv + 8);
- SILC_PUT32_LSB(tmp[3], iv + 12);
- i = 0;
- }
- *dst++ = *src++ ^ iv[i++];
- }
- twofish->padlen = i;
+ SILC_CTR_LSB_128_32(iv, ctr, tmp, twofish->padlen, src, dst,
+ twofish_encrypt(twofish, tmp, tmp));
+ break;
- 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);
+ case SILC_CIPHER_MODE_CFB:
+ SILC_CFB_ENC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+ twofish_encrypt(twofish, tmp, tmp));
break;
default:
SILC_CIPHER_API_DECRYPT(twofish)
{
+ TwofishContext *twofish = context;
SilcUInt32 tmp[4], tmp2[4], tiv[4];
int i;
switch (cipher->mode) {
case SILC_CIPHER_MODE_CBC:
- 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) {
- SILC_CBC_DEC_PRE(tmp, src);
- twofish_decrypt((TwofishContext *)context, tmp, tmp2);
- SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
- }
-
- SILC_CBC_PUT_IV(tiv, iv);
+ 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;
+ 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;
}