Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1999 - 2007 Pekka Riikonen
+ Copyright (C) 1999 - 2008 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
#ifndef CIPHERS_DEF_H
#define CIPHERS_DEF_H
+
+#include "silclog.h"
+
/* General definitions for algorithms */
typedef unsigned char u1byte;
typedef SilcUInt32 u4byte;
SILC_GET32_LSB(d[_i], s + (_i * 4)); \
} while(0);
-/* CBC mode 128-bit block, LSB, 32-bit block argument must be encrypted */
+/* CBC mode 128-bit block, LSB, 8-bit iv argument must be encrypted */
+
+#ifndef WORDS_BIGENDIAN
+#ifdef SILC_X86_64
+/* x86-64 */
+#define SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i, enc) \
+do { \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ for (i = 0; i < len; i += 16) { \
+ *(SilcUInt64 *)iv ^= *(SilcUInt64 *)src; \
+ *(SilcUInt64 *)(iv + 8) ^= *(SilcUInt64 *)(src + 8); \
+ \
+ enc; \
+ \
+ *(SilcUInt64 *)dst = *(SilcUInt64 *)iv; \
+ *(SilcUInt64 *)(dst + 8) = *(SilcUInt64 *)(iv + 8); \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+} while(0)
+#else /* !SILC_X86_64 */
+/* x86 */
+#define SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i, enc) \
+do { \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ for (i = 0; i < len; i += 16) { \
+ *(SilcUInt32 *)iv ^= *(SilcUInt32 *)src; \
+ *(SilcUInt32 *)(iv + 4) ^= *(SilcUInt32 *)(src + 4); \
+ *(SilcUInt32 *)(iv + 8) ^= *(SilcUInt32 *)(src + 8); \
+ *(SilcUInt32 *)(iv + 12) ^= *(SilcUInt32 *)(src + 12); \
+ \
+ enc; \
+ \
+ memcpy(dst, iv, 16); \
+ dst += 16; \
+ src += 16; \
+ } \
+} while(0)
+#endif /* SILC_X86_64 */
+#else /* WORDS_BIGENDIAN */
+/* big-endian machines */
+#define SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i, enc) \
+do { \
+ SilcUInt32 tmp[4], tmp2[4]; \
+ \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ for (i = 0; i < len; i += 16) { \
+ SILC_GET32_MSB(tmp[0], &iv[0]); \
+ SILC_GET32_MSB(tmp[1], &iv[4]); \
+ SILC_GET32_MSB(tmp[2], &iv[8]); \
+ SILC_GET32_MSB(tmp[3], &iv[12]); \
+ \
+ SILC_GET32_MSB(tmp2[0], &src[0]); \
+ SILC_GET32_MSB(tmp2[1], &src[4]); \
+ SILC_GET32_MSB(tmp2[2], &src[8]); \
+ SILC_GET32_MSB(tmp2[3], &src[12]); \
+ \
+ tmp[0] = tmp[0] ^ tmp2[0]; \
+ tmp[1] = tmp[1] ^ tmp2[1]; \
+ tmp[2] = tmp[2] ^ tmp2[2]; \
+ tmp[3] = tmp[3] ^ tmp2[3]; \
+ \
+ SILC_PUT32_MSB(tmp[0], &iv[0]); \
+ SILC_PUT32_MSB(tmp[1], &iv[4]); \
+ SILC_PUT32_MSB(tmp[2], &iv[8]); \
+ SILC_PUT32_MSB(tmp[3], &iv[12]); \
+ \
+ enc; \
+ \
+ memcpy(dst, iv, 16); \
+ dst += 16; \
+ src += 16; \
+ } \
+} while(0)
+#endif /* !WORDS_BIGENDIAN */
+
+/* CBC mode 128-bit block, MSB, 32-bit block argument must be encrypted */
#define SILC_CBC_ENC_LSB_128_32(len, iv, block, src, dst, i, enc) \
do { \
SILC_PUT32_MSB(block[3], &iv[12]); \
} while(0)
+/* CBC mode 128-bit block, LSB, 8-bit src argument must be decrypted
+ to dst. */
+
+#ifndef WORDS_BIGENDIAN
+#ifdef SILC_X86_64
+/* x86-64 */
+#define SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i, dec) \
+{ \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ for (i = 0; i < len; i += 16) { \
+ *(SilcUInt64 *)prev = *(SilcUInt64 *)src; \
+ *(SilcUInt64 *)(prev + 8) = *(SilcUInt64 *)(src + 8); \
+ \
+ dec; \
+ \
+ *(SilcUInt64 *)dst ^= *(SilcUInt64 *)iv; \
+ *(SilcUInt64 *)(dst + 8) ^= *(SilcUInt64 *)(iv + 8); \
+ *(SilcUInt64 *)iv = *(SilcUInt64 *)prev; \
+ *(SilcUInt64 *)(iv + 8) = *(SilcUInt64 *)(prev + 8); \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+} while(0)
+#else /* !SILC_X86_64 */
+/* x86 */
+#define SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i, dec) \
+do { \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ for (i = 0; i < len; i += 16) { \
+ memcpy(prev, src, 16); \
+ \
+ dec; \
+ \
+ *(SilcUInt32 *)dst ^= *(SilcUInt32 *)iv; \
+ *(SilcUInt32 *)(dst + 4) ^= *(SilcUInt32 *)(iv + 4); \
+ *(SilcUInt32 *)(dst + 8) ^= *(SilcUInt32 *)(iv + 8); \
+ *(SilcUInt32 *)(dst + 12) ^= *(SilcUInt32 *)(iv + 12); \
+ memcpy(iv, prev, 16); \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+} while(0)
+#endif /* SILC_X86_64 */
+#else /* WORDS_BIGENDIAN */
+/* big-endian machines */
+#define SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i, dec) \
+do { \
+ SilcUInt32 tmp2[4], tmp3[4]; \
+ \
+ SILC_ASSERT((len & (16 - 1)) == 0); \
+ if (len & (16 - 1)) \
+ return FALSE; \
+ \
+ for (i = 0; i < len; i += 16) { \
+ memcpy(prev, src, 16); \
+ \
+ dec; \
+ \
+ SILC_GET32_MSB(tmp2[0], &iv[0]); \
+ SILC_GET32_MSB(tmp2[1], &iv[4]); \
+ SILC_GET32_MSB(tmp2[2], &iv[8]); \
+ SILC_GET32_MSB(tmp2[3], &iv[12]); \
+ \
+ SILC_GET32_MSB(tmp3[0], &dst[0]); \
+ SILC_GET32_MSB(tmp3[1], &dst[4]); \
+ SILC_GET32_MSB(tmp3[2], &dst[8]); \
+ SILC_GET32_MSB(tmp3[3], &dst[12]); \
+ \
+ tmp2[0] = tmp3[0] ^ tmp2[0]; \
+ tmp2[1] = tmp3[1] ^ tmp2[1]; \
+ tmp2[2] = tmp3[2] ^ tmp2[2]; \
+ tmp2[3] = tmp3[3] ^ tmp2[3]; \
+ \
+ SILC_PUT32_MSB(tmp2[0], &dst[0]); \
+ SILC_PUT32_MSB(tmp2[1], &dst[4]); \
+ SILC_PUT32_MSB(tmp2[2], &dst[8]); \
+ SILC_PUT32_MSB(tmp2[3], &dst[12]); \
+ \
+ memcpy(iv, prev, 16); \
+ \
+ dst += 16; \
+ src += 16; \
+ } \
+} while(0)
+#endif /* !WORDS_BIGENDIAN */
+
/* CBC mode 128-bit block, MSB, decrypt block to block_dec. */
#define SILC_CBC_DEC_MSB_128_32(len, iv, block_prev, block, \
SILC_PUT32_MSB(block[1], &iv[4]); \
} while(0)
+#ifndef WORDS_BIGENDIAN
-/* CTR mode 128-bit block, MSB, MSB counter, the 8-bit enc_ctr argument must
- be encrypted */
+/* CTR mode 128-bit block, MSB, MSB counter, the 8-bit ctr argument must
+ be encrypted to enc_ctr */
-#define SILC_CTR_MSB_128_8(iv, ctr, enc_ctr, pad, src, dst, enc) \
+#define SILC_CTR_MSB_128_8(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) { \
+ 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); \
+ for (i = 15; i >= 0; i--) \
+ if (++ctr[i]) \
+ break; \
\
enc; \
+ \
+ if (len >= 16) { \
+ *(SilcUInt64 *)dst = *(SilcUInt64 *)src ^ *(SilcUInt64 *)enc_ctr; \
+ *(SilcUInt64 *)(dst + 8) = *(SilcUInt64 *)(src + 8) ^ \
+ *(SilcUInt64 *)(enc_ctr + 8); \
+ src += 16; \
+ dst += 16; \
+ len -= 16; \
+ silc_prefetch((void *)src, 0, 0); \
+ continue; \
+ } \
pad = 0; \
} \
*dst++ = *src++ ^ enc_ctr[pad++]; \
+ len--; \
} \
- \
- 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 */
+#else /* WORDS_BIGENDIAN */
-#define SILC_CTR_MSB_128_32(iv, ctr, enc_ctr, pad, src, dst, enc) \
+#define SILC_CTR_MSB_128_8(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]; \
+ for (i = 15; i >= 0; i--) \
+ if (++ctr[i]) \
+ break; \
\
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 */
+#endif /* !WORDS_BIGENDIAN */
+
+/* CTR mode 128-bit block, LSB, MSB counter, the 32-bit tmp argument
+ must be encrypted, enc_ctr must have the encrypted data too. */
-#define SILC_CTR_LSB_128_32(iv, ctr, enc_ctr, pad, src, dst, enc) \
+#define SILC_CTR_LSB_128_32(ctr, tmp, 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]); \
+ for (i = 15; i >= 0; i--) \
+ if (++ctr[i]) \
+ break; \
\
+ SILC_GET32_LSB(tmp[0], ctr); \
+ SILC_GET32_LSB(tmp[1], ctr + 4); \
+ SILC_GET32_LSB(tmp[2], ctr + 8); \
+ SILC_GET32_LSB(tmp[3], ctr + 12); \
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); \
+ SILC_PUT32_LSB(tmp[0], enc_ctr); \
+ SILC_PUT32_LSB(tmp[1], enc_ctr + 4); \
+ SILC_PUT32_LSB(tmp[2], enc_ctr + 8); \
+ SILC_PUT32_LSB(tmp[3], enc_ctr + 12); \
pad = 0; \
} \
- *dst++ = *src++ ^ iv[pad++]; \
+ *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 64-bit block, MSB, MSB counter, the 32-bit ctr argument must
- be encrypted to enc_ctr */
+/* CTR mode 128-bit block, LSB, MSB counter, the 32-bit tmp argument
+ must be encrypted, enc_ctr must have the encrypted data too. */
-#define SILC_CTR_MSB_64_32(iv, ctr, enc_ctr, pad, src, dst, enc) \
+#define SILC_CTR_MSB_64_32(ctr, tmp, 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]; \
+ for (i = 7; i >= 0; i--) \
+ if (++ctr[i]) \
+ break; \
\
+ SILC_GET32_MSB(tmp[0], ctr); \
+ SILC_GET32_MSB(tmp[1], ctr + 4); \
enc; \
- SILC_PUT32_MSB(enc_ctr[0], iv); \
- SILC_PUT32_MSB(enc_ctr[1], iv + 4); \
+ SILC_PUT32_MSB(tmp[0], enc_ctr); \
+ SILC_PUT32_MSB(tmp[1], enc_ctr + 4); \
pad = 0; \
} \
- *dst++ = *src++ ^ iv[pad++]; \
+ *dst++ = *src++ ^ enc_ctr[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. */