From c145f2f7712489b6530438b18bd71e5d1e6ec642 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sat, 14 Jul 2007 10:53:43 +0000 Subject: [PATCH] Added CFB mode to aes, twofish and cast5. Unified the CBC, CFB and CTR mode APIs. --- CHANGES.CRYPTO | 6 + lib/silccrypt/aes.c | 74 ++-- lib/silccrypt/cast5.c | 90 ++-- lib/silccrypt/ciphers_def.h | 675 +++++++++++++++++++++++------ lib/silccrypt/rijndael_internal.h | 1 - lib/silccrypt/silccipher.c | 9 +- lib/silccrypt/silccipher.h | 51 ++- lib/silccrypt/silccipher_i.h | 8 +- lib/silccrypt/tests/test_aes.c | 51 +++ lib/silccrypt/tests/test_cast5.c | 53 ++- lib/silccrypt/tests/test_twofish.c | 58 ++- lib/silccrypt/twofish.c | 99 ++--- 12 files changed, 842 insertions(+), 333 deletions(-) diff --git a/CHANGES.CRYPTO b/CHANGES.CRYPTO index 92d9a810..e01fe574 100644 --- a/CHANGES.CRYPTO +++ b/CHANGES.CRYPTO @@ -1,3 +1,9 @@ +Sat Jul 14 13:45:34 EEST 2007 Pekka Riikonen + + * 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 * Added CAST5 (CAST-128) algorithm. Affected files are diff --git a/lib/silccrypt/aes.c b/lib/silccrypt/aes.c index fc67504d..52d0397b 100644 --- a/lib/silccrypt/aes.c +++ b/lib/silccrypt/aes.c @@ -54,6 +54,7 @@ SILC_CIPHER_API_SET_KEY(aes) break; case SILC_CIPHER_MODE_CTR: + case SILC_CIPHER_MODE_CFB: aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc); break; @@ -67,11 +68,22 @@ SILC_CIPHER_API_SET_KEY(aes) 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; } } @@ -88,7 +100,7 @@ SILC_CIPHER_API_CONTEXT_LEN(aes) SILC_CIPHER_API_ENCRYPT(aes) { AesContext *aes = context; - int i; + SilcUInt32 ctr[4]; switch (cipher->mode) { case SILC_CIPHER_MODE_CBC: @@ -113,42 +125,13 @@ SILC_CIPHER_API_ENCRYPT(aes) 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: @@ -163,6 +146,8 @@ SILC_CIPHER_API_ENCRYPT(aes) SILC_CIPHER_API_DECRYPT(aes) { + AesContext *aes = context; + switch (cipher->mode) { case SILC_CIPHER_MODE_CBC: { @@ -174,7 +159,7 @@ SILC_CIPHER_API_DECRYPT(aes) 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]; @@ -190,6 +175,11 @@ SILC_CIPHER_API_DECRYPT(aes) 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; } @@ -244,7 +234,6 @@ AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) 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; } @@ -276,7 +265,6 @@ AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) 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; } @@ -311,7 +299,6 @@ AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) 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; } @@ -377,7 +364,6 @@ AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) 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; } @@ -436,7 +422,6 @@ AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) 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; } @@ -504,7 +489,6 @@ AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) 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; } diff --git a/lib/silccrypt/cast5.c b/lib/silccrypt/cast5.c index 227cae11..995fc09b 100644 --- a/lib/silccrypt/cast5.c +++ b/lib/silccrypt/cast5.c @@ -22,11 +22,22 @@ SILC_CIPHER_API_SET_KEY(cast5) 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; } } @@ -46,49 +57,18 @@ SILC_CIPHER_API_ENCRYPT(cast5) 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: @@ -100,34 +80,26 @@ SILC_CIPHER_API_ENCRYPT(cast5) 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; } diff --git a/lib/silccrypt/ciphers_def.h b/lib/silccrypt/ciphers_def.h index d755a9f3..19716f48 100644 --- a/lib/silccrypt/ciphers_def.h +++ b/lib/silccrypt/ciphers_def.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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 @@ -39,152 +39,557 @@ do { \ 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 diff --git a/lib/silccrypt/rijndael_internal.h b/lib/silccrypt/rijndael_internal.h index e6dcb1c3..c1dc7e80 100644 --- a/lib/silccrypt/rijndael_internal.h +++ b/lib/silccrypt/rijndael_internal.h @@ -37,7 +37,6 @@ #define KS_LENGTH 60 typedef union { - uint_32t l; uint_8t b[4]; } aes_inf; diff --git a/lib/silccrypt/silccipher.c b/lib/silccrypt/silccipher.c index c783afb9..b434fef5 100644 --- a/lib/silccrypt/silccipher.c +++ b/lib/silccrypt/silccipher.c @@ -48,14 +48,21 @@ const SilcCipherObject silc_default_ciphers[] = 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 */ @@ -341,7 +348,7 @@ void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv) { 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. */ diff --git a/lib/silccrypt/silccipher.h b/lib/silccrypt/silccipher.h index 5981ce73..b24a6969 100644 --- a/lib/silccrypt/silccipher.h +++ b/lib/silccrypt/silccipher.h @@ -57,7 +57,43 @@ typedef struct SilcCipherStruct *SilcCipher; * * 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 */ @@ -169,19 +205,6 @@ SilcBool silc_cipher_unregister_all(void); * * 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); diff --git a/lib/silccrypt/silccipher_i.h b/lib/silccrypt/silccipher_i.h index e5206b63..a148d291 100644 --- a/lib/silccrypt/silccipher_i.h +++ b/lib/silccrypt/silccipher_i.h @@ -32,10 +32,10 @@ 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, \ @@ -67,7 +67,7 @@ struct SilcCipherObjectStruct { /* 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. */ diff --git a/lib/silccrypt/tests/test_aes.c b/lib/silccrypt/tests/test_aes.c index 0a104598..87073b30 100644 --- a/lib/silccrypt/tests/test_aes.c +++ b/lib/silccrypt/tests/test_aes.c @@ -45,6 +45,16 @@ const unsigned char p5[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C 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; @@ -242,6 +252,47 @@ int main(int argc, char **argv) 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: diff --git a/lib/silccrypt/tests/test_cast5.c b/lib/silccrypt/tests/test_cast5.c index 0954ae27..af76bced 100644 --- a/lib/silccrypt/tests/test_cast5.c +++ b/lib/silccrypt/tests/test_cast5.c @@ -16,7 +16,7 @@ const unsigned char p2[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c 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"; @@ -26,6 +26,16 @@ const unsigned char p4[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C 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; @@ -151,6 +161,47 @@ int main(int argc, char **argv) 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: diff --git a/lib/silccrypt/tests/test_twofish.c b/lib/silccrypt/tests/test_twofish.c index 730b1a08..89731328 100644 --- a/lib/silccrypt/tests/test_twofish.c +++ b/lib/silccrypt/tests/test_twofish.c @@ -45,6 +45,16 @@ const unsigned char p5[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C 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; @@ -142,7 +152,7 @@ int main(int argc, char **argv) } /* 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); @@ -172,7 +182,7 @@ int main(int argc, char **argv) /* 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); @@ -212,7 +222,7 @@ int main(int argc, char **argv) } /* 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); @@ -242,6 +252,48 @@ int main(int argc, char **argv) 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: diff --git a/lib/silccrypt/twofish.c b/lib/silccrypt/twofish.c index 53caed41..87d443c7 100644 --- a/lib/silccrypt/twofish.c +++ b/lib/silccrypt/twofish.c @@ -63,11 +63,22 @@ SILC_CIPHER_API_SET_KEY(twofish) 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; } } @@ -90,62 +101,18 @@ SILC_CIPHER_API_ENCRYPT(twofish) 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: @@ -160,33 +127,25 @@ SILC_CIPHER_API_ENCRYPT(twofish) 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; } -- 2.24.0