diff --git a/src/stream/rabbit/rabbit.c b/src/stream/rabbit/rabbit.c deleted file mode 100644 index 9d7e0dff2..000000000 --- a/src/stream/rabbit/rabbit.c +++ /dev/null @@ -1,457 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - */ - -/****************************************************************************** - * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission - * and should run on any conforming C implementation (C90 or later). - * - * This implementation supports any key length up to 128 bits (16 bytes) and - * works in increments of 8-bit bytes. Keys must be submitted as whole bytes - * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv - * may be any length up to 8 bytes and will be padded out to 8 bytes. - * - * The eSTREAM submission was rather picky about the calling sequence of - * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed - * calling ECRYPT_process_blocks() multiple times for a multiple of whole - * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls - * were supported correctly. This implementation handles the keystream - * differently and rabbit_crypt() may be called as many times as desired, - * crypting any number of bytes each time. - * - * http://www.ecrypt.eu.org/stream/e2-rabbit.html - * - * NB: One of the test vectors distributed by the eSTREAM site in the file - * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" - * in that ZIP file, the 3rd line in "out1" should be - * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". - * - * Here is the original legal notice accompanying the Rabbit submission - * to the EU eSTREAM competition. - *--------------------------------------------------------------------------- - * Copyright (C) Cryptico A/S. All rights reserved. - * - * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. - * - * This software is developed by Cryptico A/S and/or its suppliers. - * All title and intellectual property rights in and to the software, - * including but not limited to patent rights and copyrights, are owned - * by Cryptico A/S and/or its suppliers. - * - * The software may be used solely for non-commercial purposes - * without the prior written consent of Cryptico A/S. For further - * information on licensing terms and conditions please contact - * Cryptico A/S at info@cryptico.com - * - * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" - * are either trademarks or registered trademarks of Cryptico A/S. - * - * Cryptico A/S shall not in any way be liable for any use of this - * software. The software is provided "as is" without any express or - * implied warranty. - *--------------------------------------------------------------------------- - * On October 6, 2008, Rabbit was "released into the public domain and - * may be used freely for any purpose." - * http://www.ecrypt.eu.org/stream/rabbitpf.html - * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 - ******************************************************************************/ - - -#include "tomcrypt_private.h" - -#ifdef LTC_RABBIT - -/* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */ -static LTC_INLINE ulong32 _rabbit_g_func(ulong32 x); -static LTC_INLINE void _rabbit_next_state(rabbit_ctx *p_instance); -static LTC_INLINE void _rabbit_gen_1_block(rabbit_state* st, unsigned char *out); - -/* -------------------------------------------------------------------------- */ - -/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ -/* the upper 32 bits XOR the lower 32 bits */ -static LTC_INLINE ulong32 _rabbit_g_func(ulong32 x) -{ - ulong32 a, b, h, l; - - /* Construct high and low argument for squaring */ - a = x & 0xFFFF; - b = x >> 16; - - /* Calculate high and low result of squaring */ - h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b; - l = x * x; - - /* Return high XOR low */ - return (ulong32)(h^l); -} - -/* -------------------------------------------------------------------------- */ - -/* Calculate the next internal state */ -static LTC_INLINE void _rabbit_next_state(rabbit_ctx *p_instance) -{ - ulong32 g[8], c_old[8], i; - - /* Save old counter values */ - for (i=0; i<8; i++) { - c_old[i] = p_instance->c[i]; - } - - /* Calculate new counter values */ - p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry); - p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0])); - p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1])); - p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2])); - p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3])); - p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4])); - p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5])); - p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6])); - p_instance->carry = (p_instance->c[7] < c_old[7]); - - /* Calculate the g-values */ - for (i=0;i<8;i++) { - g[i] = _rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i])); - } - - /* Calculate new state values */ - p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16)); - p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]); - p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16)); - p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]); - p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16)); - p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]); - p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16)); - p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]); -} - -/* ------------------------------------------------------------------------- */ - -static LTC_INLINE void _rabbit_gen_1_block(rabbit_state* st, unsigned char *out) -{ - ulong32 *ptr; - - /* Iterate the work context once */ - _rabbit_next_state(&(st->work_ctx)); - - /* Generate 16 bytes of pseudo-random data */ - ptr = (ulong32*)&(st->work_ctx.x); - STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0); - STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4); - STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8); - STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12); -} - -/* -------------------------------------------------------------------------- */ - -/* Key setup */ -int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen) -{ - ulong32 k0, k1, k2, k3, i; - unsigned char tmpkey[16] = {0}; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen <= 16); - - /* init state */ - XMEMSET(st, 0, sizeof(rabbit_state)); - - /* pad key in tmpkey */ - XMEMCPY(tmpkey, key, keylen); - - /* Generate four subkeys */ - LOAD32L(k0, tmpkey+ 0); - LOAD32L(k1, tmpkey+ 4); - LOAD32L(k2, tmpkey+ 8); - LOAD32L(k3, tmpkey+12); - -#ifdef LTC_CLEAN_STACK - /* done with tmpkey, wipe it */ - zeromem(tmpkey, sizeof(tmpkey)); -#endif - - /* Generate initial state variables */ - st->master_ctx.x[0] = k0; - st->master_ctx.x[2] = k1; - st->master_ctx.x[4] = k2; - st->master_ctx.x[6] = k3; - st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16); - st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16); - st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16); - st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16); - - /* Generate initial counter values */ - st->master_ctx.c[0] = ROLc(k2, 16); - st->master_ctx.c[2] = ROLc(k3, 16); - st->master_ctx.c[4] = ROLc(k0, 16); - st->master_ctx.c[6] = ROLc(k1, 16); - st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); - st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); - st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); - st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); - - /* Clear carry bit */ - st->master_ctx.carry = 0; - - /* Iterate the master context four times */ - for (i=0; i<4; i++) { - _rabbit_next_state(&(st->master_ctx)); - } - - /* Modify the counters */ - for (i=0; i<8; i++) { - st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7]; - } - - /* Copy master instance to work instance */ - for (i=0; i<8; i++) { - st->work_ctx.x[i] = st->master_ctx.x[i]; - st->work_ctx.c[i] = st->master_ctx.c[i]; - } - st->work_ctx.carry = st->master_ctx.carry; - /* ...and prepare block for crypt() */ - XMEMSET(&(st->block), 0, sizeof(st->block)); - st->unused = 0; - - return CRYPT_OK; -} - -/* -------------------------------------------------------------------------- */ - -/* IV setup */ -int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen) -{ - ulong32 i0, i1, i2, i3, i; - unsigned char tmpiv[8] = {0}; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL || ivlen == 0); - LTC_ARGCHK(ivlen <= 8); - - /* pad iv in tmpiv */ - if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen); - - /* Generate four subvectors */ - LOAD32L(i0, tmpiv+0); - LOAD32L(i2, tmpiv+4); - i1 = (i0>>16) | (i2&0xFFFF0000); - i3 = (i2<<16) | (i0&0x0000FFFF); - - /* Modify counter values */ - st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0; - st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1; - st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2; - st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3; - st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0; - st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1; - st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2; - st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3; - - /* Copy state variables */ - for (i=0; i<8; i++) { - st->work_ctx.x[i] = st->master_ctx.x[i]; - } - st->work_ctx.carry = st->master_ctx.carry; - - /* Iterate the work context four times */ - for (i=0; i<4; i++) { - _rabbit_next_state(&(st->work_ctx)); - } - - /* reset keystream buffer and unused count */ - XMEMSET(&(st->block), 0, sizeof(st->block)); - st->unused = 0; - - return CRYPT_OK; -} - -/* ------------------------------------------------------------------------- */ - -/* Crypt a chunk of any size (encrypt/decrypt) */ -int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char buf[16]; - unsigned long i, j; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - if (st->unused > 0) { - j = MIN(st->unused, inlen); - for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused]; - inlen -= j; - if (inlen == 0) return CRYPT_OK; - out += j; - in += j; - } - for (;;) { - /* gen a block for buf */ - _rabbit_gen_1_block(st, buf); - if (inlen <= 16) { - /* XOR and send to out */ - for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; - st->unused = 16 - inlen; - /* copy remainder to block */ - for (i = inlen; i < 16; ++i) st->block[i] = buf[i]; - return CRYPT_OK; - } - /* XOR entire buf and send to out */ - for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i]; - inlen -= 16; - out += 16; - in += 16; - } -} - -/* ------------------------------------------------------------------------- */ - -int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - - LTC_ARGCHK(out != NULL); - - XMEMSET(out, 0, outlen); - return rabbit_crypt(st, out, outlen, out); -} - -/* -------------------------------------------------------------------------- */ - -int rabbit_done(rabbit_state *st) -{ - LTC_ARGCHK(st != NULL); - - zeromem(st, sizeof(rabbit_state)); - return CRYPT_OK; -} - -/* -------------------------------------------------------------------------- */ - -int rabbit_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - rabbit_state st; - int err; - unsigned char out[1000] = { 0 }; - { - /* all 3 tests use key and iv fm set 6, vector 3, the last vector in: - http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log - */ - - /* --- Test 1 (generate whole blocks) --------------------------------- */ - - { - unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, - 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; - unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; - char pt[64] = { 0 }; - unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, - 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, - 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, - 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, - 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C, - 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39, - 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D, - 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F }; - unsigned long ptlen = sizeof(pt); - - /* crypt 64 nulls */ - if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; - } - - /* --- Test 2 (generate unusual number of bytes each time) ------------ */ - - { - unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, - 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; - unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; - char pt[39] = { 0 }; - unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, - 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, - 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, - 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, - 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D }; - unsigned long ptlen = sizeof(pt); - - /* crypt piece by piece (hit at least one 16-byte boundary) */ - if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; - } - - /* --- Test 3 (use non-null data) ------------------------------------- */ - - { - unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, - 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; - unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; - char pt[] = "Kilroy was here, there, and everywhere!"; - unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd, - 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54, - 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60, - 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87, - 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac }; - unsigned long ptlen = strlen(pt); - unsigned char out2[1000] = { 0 }; - unsigned char nulls[1000] = { 0 }; - - /* crypt piece by piece */ - if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* --- Test 4 (crypt in a single call) ------------------------------------ */ - - if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv), - (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; - /* use 'out' (ciphertext) in the next decryption test */ - - /* --- Test 5 (decrypt ciphertext) ------------------------------------ */ - - /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */ - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err; - if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* --- Test 6 (wipe state, incl key) ---------------------------------- */ - - if ((err = rabbit_done(&st)) != CRYPT_OK) return err; - if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR; - - } - - return CRYPT_OK; - } -#endif -} - -/* -------------------------------------------------------------------------- */ - -#endif - -/* ref: $Format:%D$ */ -/* git commit: $Format:%H$ */ -/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_common.h b/src/stream/rabbit/rabbit_common.h new file mode 100644 index 000000000..388ecb0a1 --- /dev/null +++ b/src/stream/rabbit/rabbit_common.h @@ -0,0 +1,154 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + *--------------------------------------------------------------------------- + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 + ******************************************************************************/ + + +#ifdef LTC_RABBIT + +/* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */ +static LTC_INLINE ulong32 _rabbit_g_func(ulong32 x); +static LTC_INLINE void _rabbit_next_state(rabbit_ctx *p_instance); +static LTC_INLINE void _rabbit_gen_1_block(rabbit_state* st, unsigned char *out); + +/* -------------------------------------------------------------------------- */ + +/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ +/* the upper 32 bits XOR the lower 32 bits */ +static LTC_INLINE ulong32 _rabbit_g_func(ulong32 x) +{ + ulong32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x & 0xFFFF; + b = x >> 16; + + /* Calculate high and low result of squaring */ + h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b; + l = x * x; + + /* Return high XOR low */ + return (ulong32)(h^l); +} + +/* -------------------------------------------------------------------------- */ + +/* Calculate the next internal state */ +static LTC_INLINE void _rabbit_next_state(rabbit_ctx *p_instance) +{ + ulong32 g[8], c_old[8], i; + + /* Save old counter values */ + for (i=0; i<8; i++) { + c_old[i] = p_instance->c[i]; + } + + /* Calculate new counter values */ + p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry); + p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0])); + p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1])); + p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2])); + p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3])); + p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4])); + p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5])); + p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6])); + p_instance->carry = (p_instance->c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i=0;i<8;i++) { + g[i] = _rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i])); + } + + /* Calculate new state values */ + p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16)); + p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]); + p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16)); + p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]); + p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16)); + p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]); + p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16)); + p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]); +} + +/* ------------------------------------------------------------------------- */ + +static LTC_INLINE void _rabbit_gen_1_block(rabbit_state* st, unsigned char *out) +{ + ulong32 *ptr; + + /* Iterate the work context once */ + _rabbit_next_state(&(st->work_ctx)); + + /* Generate 16 bytes of pseudo-random data */ + ptr = (ulong32*)&(st->work_ctx.x); + STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0); + STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4); + STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8); + STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12); +} + +/* -------------------------------------------------------------------------- */ + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_crypt.c b/src/stream/rabbit/rabbit_crypt.c new file mode 100644 index 000000000..681b9984a --- /dev/null +++ b/src/stream/rabbit/rabbit_crypt.c @@ -0,0 +1,118 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + *--------------------------------------------------------------------------- + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +#include "rabbit_common.h" + +/* ------------------------------------------------------------------------- */ + +/* Crypt a chunk of any size (encrypt/decrypt) */ +int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[16]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (st->unused > 0) { + j = MIN(st->unused, inlen); + for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + /* gen a block for buf */ + _rabbit_gen_1_block(st, buf); + if (inlen <= 16) { + /* XOR and send to out */ + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->unused = 16 - inlen; + /* copy remainder to block */ + for (i = inlen; i < 16; ++i) st->block[i] = buf[i]; + return CRYPT_OK; + } + /* XOR entire buf and send to out */ + for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 16; + out += 16; + in += 16; + } +} + +/* -------------------------------------------------------------------------- */ + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_done.c b/src/stream/rabbit/rabbit_done.c new file mode 100644 index 000000000..365925ab2 --- /dev/null +++ b/src/stream/rabbit/rabbit_done.c @@ -0,0 +1,85 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called, no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * https://www.ietf.org/rfc/rfc4503.txt + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + *--------------------------------------------------------------------------- + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + * + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + * + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +int rabbit_done(rabbit_state *st) +{ + LTC_ARGCHK(st != NULL); + + zeromem(st, sizeof(rabbit_state)); + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_keystream.c b/src/stream/rabbit/rabbit_keystream.c new file mode 100644 index 000000000..9c53d72a7 --- /dev/null +++ b/src/stream/rabbit/rabbit_keystream.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called, no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * https://www.ietf.org/rfc/rfc4503.txt + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + *--------------------------------------------------------------------------- + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + * + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + * + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(out != NULL); + + XMEMSET(out, 0, outlen); + return rabbit_crypt(st, out, outlen, out); +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_setiv.c b/src/stream/rabbit/rabbit_setiv.c new file mode 100644 index 000000000..c366126c1 --- /dev/null +++ b/src/stream/rabbit/rabbit_setiv.c @@ -0,0 +1,126 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + *--------------------------------------------------------------------------- + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +#include "rabbit_common.h" + +/* -------------------------------------------------------------------------- */ + +/* IV setup */ +int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen) +{ + ulong32 i0, i1, i2, i3, i; + unsigned char tmpiv[8] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL || ivlen == 0); + LTC_ARGCHK(ivlen <= 8); + + /* pad iv in tmpiv */ + if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen); + + /* Generate four subvectors */ + LOAD32L(i0, tmpiv+0); + LOAD32L(i2, tmpiv+4); + i1 = (i0>>16) | (i2&0xFFFF0000); + i3 = (i2<<16) | (i0&0x0000FFFF); + + /* Modify counter values */ + st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0; + st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1; + st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2; + st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3; + st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0; + st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1; + st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2; + st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3; + + /* Copy state variables */ + for (i=0; i<8; i++) { + st->work_ctx.x[i] = st->master_ctx.x[i]; + } + st->work_ctx.carry = st->master_ctx.carry; + + /* Iterate the work context four times */ + for (i=0; i<4; i++) { + _rabbit_next_state(&(st->work_ctx)); + } + + /* reset keystream buffer and unused count */ + XMEMSET(&(st->block), 0, sizeof(st->block)); + st->unused = 0; + + return CRYPT_OK; +} + +/* ------------------------------------------------------------------------- */ + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_setup.c b/src/stream/rabbit/rabbit_setup.c new file mode 100644 index 000000000..72a9f07d3 --- /dev/null +++ b/src/stream/rabbit/rabbit_setup.c @@ -0,0 +1,152 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + *--------------------------------------------------------------------------- + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +#include "rabbit_common.h" + +/* -------------------------------------------------------------------------- */ + +/* Key setup */ +int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen) +{ + ulong32 k0, k1, k2, k3, i; + unsigned char tmpkey[16] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen <= 16); + + /* init state */ + XMEMSET(st, 0, sizeof(rabbit_state)); + + /* pad key in tmpkey */ + XMEMCPY(tmpkey, key, keylen); + + /* Generate four subkeys */ + LOAD32L(k0, tmpkey+ 0); + LOAD32L(k1, tmpkey+ 4); + LOAD32L(k2, tmpkey+ 8); + LOAD32L(k3, tmpkey+12); + +#ifdef LTC_CLEAN_STACK + /* done with tmpkey, wipe it */ + zeromem(tmpkey, sizeof(tmpkey)); +#endif + + /* Generate initial state variables */ + st->master_ctx.x[0] = k0; + st->master_ctx.x[2] = k1; + st->master_ctx.x[4] = k2; + st->master_ctx.x[6] = k3; + st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16); + st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16); + st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16); + st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16); + + /* Generate initial counter values */ + st->master_ctx.c[0] = ROLc(k2, 16); + st->master_ctx.c[2] = ROLc(k3, 16); + st->master_ctx.c[4] = ROLc(k0, 16); + st->master_ctx.c[6] = ROLc(k1, 16); + st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); + st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); + st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); + st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); + + /* Clear carry bit */ + st->master_ctx.carry = 0; + + /* Iterate the master context four times */ + for (i=0; i<4; i++) { + _rabbit_next_state(&(st->master_ctx)); + } + + /* Modify the counters */ + for (i=0; i<8; i++) { + st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7]; + } + + /* Copy master instance to work instance */ + for (i=0; i<8; i++) { + st->work_ctx.x[i] = st->master_ctx.x[i]; + st->work_ctx.c[i] = st->master_ctx.c[i]; + } + st->work_ctx.carry = st->master_ctx.carry; + /* ...and prepare block for crypt() */ + XMEMSET(&(st->block), 0, sizeof(st->block)); + st->unused = 0; + + return CRYPT_OK; +} + +/* -------------------------------------------------------------------------- */ + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rabbit/rabbit_test.c b/src/stream/rabbit/rabbit_test.c new file mode 100644 index 000000000..098c66971 --- /dev/null +++ b/src/stream/rabbit/rabbit_test.c @@ -0,0 +1,191 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called, no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * https://www.ietf.org/rfc/rfc4503.txt + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + *--------------------------------------------------------------------------- + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + * + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + * + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +int rabbit_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + rabbit_state st; + int err; + unsigned char out[1000] = { 0 }; + { + /* all 3 tests use key and iv fm set 6, vector 3, the last vector in: + http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log + */ + + /* --- Test 1 (generate whole blocks) --------------------------------- */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[64] = { 0 }; + unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, + 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, + 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, + 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, + 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C, + 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39, + 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D, + 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F }; + unsigned long ptlen = sizeof(pt); + + /* crypt 64 nulls */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + /* --- Test 2 (generate unusual number of bytes each time) ------------ */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[39] = { 0 }; + unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, + 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, + 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, + 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, + 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D }; + unsigned long ptlen = sizeof(pt); + + /* crypt piece by piece (hit at least one 16-byte boundary) */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + /* --- Test 3 (use non-null data) ------------------------------------- */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[] = "Kilroy was here, there, and everywhere!"; + unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd, + 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54, + 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60, + 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87, + 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac }; + unsigned long ptlen = strlen(pt); + unsigned char out2[1000] = { 0 }; + unsigned char nulls[1000] = { 0 }; + + /* crypt piece by piece */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* --- Test 4 (crypt in a single call) ------------------------------------ */ + + if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv), + (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + /* use 'out' (ciphertext) in the next decryption test */ + + /* --- Test 5 (decrypt ciphertext) ------------------------------------ */ + + /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */ + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err; + if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* --- Test 6 (wipe state, incl key) ---------------------------------- */ + + if ((err = rabbit_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR; + + } + + return CRYPT_OK; + } +#endif +} + +/* -------------------------------------------------------------------------- */ + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rc4/rc4_stream.c b/src/stream/rc4/rc4_stream.c deleted file mode 100644 index f1c225d01..000000000 --- a/src/stream/rc4/rc4_stream.c +++ /dev/null @@ -1,111 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_RC4_STREAM - -/** - Initialize an RC4 context (only the key) - @param st [out] The destination of the RC4 state - @param key The secret key - @param keylen The length of the secret key (8 - 256 bytes) - @return CRYPT_OK if successful -*/ -int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) -{ - unsigned char tmp, *s; - int x, y; - unsigned long j; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */ - - s = st->buf; - for (x = 0; x < 256; x++) { - s[x] = x; - } - - for (j = x = y = 0; x < 256; x++) { - y = (y + s[x] + key[j++]) & 255; - if (j == keylen) { - j = 0; - } - tmp = s[x]; s[x] = s[y]; s[y] = tmp; - } - st->x = 0; - st->y = 0; - - return CRYPT_OK; -} - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 - @param st The RC4 state - @param in The plaintext (or ciphertext) - @param inlen The length of the input (octets) - @param out [out] The ciphertext (or plaintext), length inlen - @return CRYPT_OK if successful -*/ -int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char x, y, *s, tmp; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - x = st->x; - y = st->y; - s = st->buf; - while (inlen--) { - x = (x + 1) & 255; - y = (y + s[x]) & 255; - tmp = s[x]; s[x] = s[y]; s[y] = tmp; - tmp = (s[x] + s[y]) & 255; - *out++ = *in++ ^ s[tmp]; - } - st->x = x; - st->y = y; - return CRYPT_OK; -} - -/** - Generate a stream of random bytes via RC4 - @param st The RC420 state - @param out [out] The output buffer - @param outlen The output length - @return CRYPT_OK on success - */ -int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return rc4_stream_crypt(st, out, outlen, out); -} - -/** - Terminate and clear RC4 state - @param st The RC4 state - @return CRYPT_OK on success -*/ -int rc4_stream_done(rc4_state *st) -{ - LTC_ARGCHK(st != NULL); - XMEMSET(st, 0, sizeof(rc4_state)); - return CRYPT_OK; -} - -#endif - -/* ref: $Format:%D$ */ -/* git commit: $Format:%H$ */ -/* commit time: $Format:%ai$ */ diff --git a/src/stream/rc4/rc4_stream_crypt.c b/src/stream/rc4/rc4_stream_crypt.c new file mode 100644 index 000000000..0170f63a2 --- /dev/null +++ b/src/stream/rc4/rc4_stream_crypt.c @@ -0,0 +1,49 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 + @param st The RC4 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char x, y, *s, tmp; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + x = st->x; + y = st->y; + s = st->buf; + while (inlen--) { + x = (x + 1) & 255; + y = (y + s[x]) & 255; + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + tmp = (s[x] + s[y]) & 255; + *out++ = *in++ ^ s[tmp]; + } + st->x = x; + st->y = y; + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rc4/rc4_stream_done.c b/src/stream/rc4/rc4_stream_done.c new file mode 100644 index 000000000..e0d5c30d8 --- /dev/null +++ b/src/stream/rc4/rc4_stream_done.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + + +/** + Terminate and clear RC4 state + @param st The RC4 state + @return CRYPT_OK on success +*/ +int rc4_stream_done(rc4_state *st) +{ + LTC_ARGCHK(st != NULL); + XMEMSET(st, 0, sizeof(rc4_state)); + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rc4/rc4_stream_keystream.c b/src/stream/rc4/rc4_stream_keystream.c new file mode 100644 index 000000000..e1ad78585 --- /dev/null +++ b/src/stream/rc4/rc4_stream_keystream.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + + +/** + Generate a stream of random bytes via RC4 + @param st The RC420 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return rc4_stream_crypt(st, out, outlen, out); +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/rc4/rc4_stream_setup.c b/src/stream/rc4/rc4_stream_setup.c new file mode 100644 index 000000000..0e0aafdab --- /dev/null +++ b/src/stream/rc4/rc4_stream_setup.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +/** + Initialize an RC4 context (only the key) + @param st [out] The destination of the RC4 state + @param key The secret key + @param keylen The length of the secret key (8 - 256 bytes) + @return CRYPT_OK if successful +*/ +int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) +{ + unsigned char tmp, *s; + int x, y; + unsigned long j; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */ + + s = st->buf; + for (x = 0; x < 256; x++) { + s[x] = x; + } + + for (j = x = y = 0; x < 256; x++) { + y = (y + s[x] + key[j++]) & 255; + if (j == keylen) { + j = 0; + } + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + } + st->x = 0; + st->y = 0; + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream.c b/src/stream/sober128/sober128_stream.c deleted file mode 100644 index 952d5622e..000000000 --- a/src/stream/sober128/sober128_stream.c +++ /dev/null @@ -1,343 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - */ -#include "tomcrypt_private.h" - -/** - @file sober128_stream.c - Implementation of SOBER-128 by Tom St Denis. - Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. -*/ - -#ifdef LTC_SOBER128 - -#define __LTC_SOBER128TAB_C__ -#include "sober128tab.c" - -/* don't change these... */ -#define N 17 -#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ -#define KEYP 15 /* where to insert key words */ -#define FOLDP 4 /* where to insert non-linear feedback */ - -static ulong32 BYTE2WORD(const unsigned char *b) -{ - ulong32 t; - LOAD32L(t, b); - return t; -} - -static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) -{ - ulong32 t; - LOAD32L(t, in); - t ^= w; - STORE32L(t, out); -} - -/* give correct offset for the current position of the register, - * where logically R[0] is at position "zero". - */ -#define OFF(zero, i) (((zero)+(i)) % N) - -/* step the LFSR */ -/* After stepping, "zero" moves right one place */ -#define STEP(R,z) \ - R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; - -static void cycle(ulong32 *R) -{ - ulong32 t; - int i; - - STEP(R,0); - t = R[0]; - for (i = 1; i < N; ++i) { - R[i-1] = R[i]; - } - R[N-1] = t; -} - -/* Return a non-linear function of some parts of the register. - */ -#define NLFUNC(st,z) \ -{ \ - t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \ - t ^= Sbox[(t >> 24) & 0xFF]; \ - t = RORc(t, 8); \ - t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \ - t ^= Sbox[(t >> 24) & 0xFF]; \ - t = t + st->R[OFF(z,13)]; \ -} - -static ulong32 nltap(const sober128_state *st) -{ - ulong32 t; - NLFUNC(st, 0); - return t; -} - -/* Save the current register state - */ -static void s128_savestate(sober128_state *st) -{ - int i; - for (i = 0; i < N; ++i) { - st->initR[i] = st->R[i]; - } -} - -/* initialise to previously saved register state - */ -static void s128_reloadstate(sober128_state *st) -{ - int i; - - for (i = 0; i < N; ++i) { - st->R[i] = st->initR[i]; - } -} - -/* Initialise "konst" - */ -static void s128_genkonst(sober128_state *st) -{ - ulong32 newkonst; - - do { - cycle(st->R); - newkonst = nltap(st); - } while ((newkonst & 0xFF000000) == 0); - st->konst = newkonst; -} - -/* Load key material into the register - */ -#define ADDKEY(k) \ - st->R[KEYP] += (k); - -#define XORNL(nl) \ - st->R[FOLDP] ^= (nl); - -/* nonlinear diffusion of register for key */ -#define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t; -static void s128_diffuse(sober128_state *st) -{ - ulong32 t; - /* relies on FOLD == N == 17! */ - DROUND(0); - DROUND(1); - DROUND(2); - DROUND(3); - DROUND(4); - DROUND(5); - DROUND(6); - DROUND(7); - DROUND(8); - DROUND(9); - DROUND(10); - DROUND(11); - DROUND(12); - DROUND(13); - DROUND(14); - DROUND(15); - DROUND(16); -} - -/** - Initialize an Sober128 context (only the key) - @param st [out] The destination of the Sober128 state - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen) -{ - ulong32 i, k; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen > 0); - - /* keylen must be multiple of 4 bytes */ - if ((keylen & 3) != 0) { - return CRYPT_INVALID_KEYSIZE; - } - - /* Register initialised to Fibonacci numbers */ - st->R[0] = 1; - st->R[1] = 1; - for (i = 2; i < N; ++i) { - st->R[i] = st->R[i-1] + st->R[i-2]; - } - st->konst = INITKONST; - - for (i = 0; i < keylen; i += 4) { - k = BYTE2WORD((unsigned char *)&key[i]); - ADDKEY(k); - cycle(st->R); - XORNL(nltap(st)); - } - - /* also fold in the length of the key */ - ADDKEY(keylen); - - /* now diffuse */ - s128_diffuse(st); - s128_genkonst(st); - s128_savestate(st); - st->nbuf = 0; - - return CRYPT_OK; -} - -/** - Set IV to the Sober128 state - @param st The Sober12820 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 12) - @return CRYPT_OK on success - */ -int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen) -{ - ulong32 i, k; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - LTC_ARGCHK(ivlen > 0); - - /* ok we are adding an IV then... */ - s128_reloadstate(st); - - /* ivlen must be multiple of 4 bytes */ - if ((ivlen & 3) != 0) { - return CRYPT_INVALID_KEYSIZE; - } - - for (i = 0; i < ivlen; i += 4) { - k = BYTE2WORD((unsigned char *)&iv[i]); - ADDKEY(k); - cycle(st->R); - XORNL(nltap(st)); - } - - /* also fold in the length of the key */ - ADDKEY(ivlen); - - /* now diffuse */ - s128_diffuse(st); - st->nbuf = 0; - - return CRYPT_OK; -} - -/* XOR pseudo-random bytes into buffer - */ -#define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 - @param st The Sober128 state - @param in The plaintext (or ciphertext) - @param inlen The length of the input (octets) - @param out [out] The ciphertext (or plaintext), length inlen - @return CRYPT_OK if successful -*/ -int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - ulong32 t; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(st != NULL); - - /* handle any previously buffered bytes */ - while (st->nbuf != 0 && inlen != 0) { - *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); - st->sbuf >>= 8; - st->nbuf -= 8; - --inlen; - } - -#ifndef LTC_SMALL_CODE - /* do lots at a time, if there's enough to do */ - while (inlen >= N*4) { - SROUND(0); - SROUND(1); - SROUND(2); - SROUND(3); - SROUND(4); - SROUND(5); - SROUND(6); - SROUND(7); - SROUND(8); - SROUND(9); - SROUND(10); - SROUND(11); - SROUND(12); - SROUND(13); - SROUND(14); - SROUND(15); - SROUND(16); - out += 4*N; - in += 4*N; - inlen -= 4*N; - } -#endif - - /* do small or odd size buffers the slow way */ - while (4 <= inlen) { - cycle(st->R); - t = nltap(st); - XORWORD(t, in, out); - out += 4; - in += 4; - inlen -= 4; - } - - /* handle any trailing bytes */ - if (inlen != 0) { - cycle(st->R); - st->sbuf = nltap(st); - st->nbuf = 32; - while (st->nbuf != 0 && inlen != 0) { - *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); - st->sbuf >>= 8; - st->nbuf -= 8; - --inlen; - } - } - - return CRYPT_OK; -} - -int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return sober128_stream_crypt(st, out, outlen, out); -} - -/** - Terminate and clear Sober128 state - @param st The Sober128 state - @return CRYPT_OK on success -*/ -int sober128_stream_done(sober128_state *st) -{ - LTC_ARGCHK(st != NULL); - XMEMSET(st, 0, sizeof(sober128_state)); - return CRYPT_OK; -} - -#endif - -/* ref: $Format:%D$ */ -/* git commit: $Format:%H$ */ -/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream_common.h b/src/stream/sober128/sober128_stream_common.h new file mode 100644 index 000000000..a61c52028 --- /dev/null +++ b/src/stream/sober128/sober128_stream_common.h @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + + +#if defined(LTC_SOBER128_STREAM_SETUP) || defined(LTC_SOBER128_STREAM_SETIV) + +/* local prototypes */ +static void s128_diffuse(sober128_state *st); + +#endif /* LTC_SOBER128_STREAM_SETUP || LTC_SOBER128_STREAM_SETIV */ + + +/* don't change these... */ +#define N 17 +#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ +#define KEYP 15 /* where to insert key words */ +#define FOLDP 4 /* where to insert non-linear feedback */ + + +/* give correct offset for the current position of the register, + * where logically R[0] is at position "zero". + */ +#define OFF(zero, i) (((zero)+(i)) % N) + +/* step the LFSR */ +/* After stepping, "zero" moves right one place */ +#define STEP(R,z) \ + R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; + +static void cycle(ulong32 *R) +{ + ulong32 t; + int i; + + STEP(R,0); + t = R[0]; + for (i = 1; i < N; ++i) { + R[i-1] = R[i]; + } + R[N-1] = t; +} + +/* Return a non-linear function of some parts of the register. + */ +#define NLFUNC(st,z) \ +{ \ + t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = RORc(t, 8); \ + t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = t + st->R[OFF(z,13)]; \ +} + +static ulong32 nltap(const sober128_state *st) +{ + ulong32 t; + NLFUNC(st, 0); + return t; +} + + +/* Load key material into the register + */ +#define ADDKEY(k) \ + st->R[KEYP] += (k); + +#define XORNL(nl) \ + st->R[FOLDP] ^= (nl); + + +#if defined(LTC_SOBER128_STREAM_SETUP) || defined(LTC_SOBER128_STREAM_SETIV) + +/* nonlinear diffusion of register for key */ +#define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t; + +/* s128_diffuse() used in sober128_stream_setup() and sober128_stream_setiv() */ +static void s128_diffuse(sober128_state *st) +{ + ulong32 t; + /* relies on FOLD == N == 17! */ + DROUND(0); + DROUND(1); + DROUND(2); + DROUND(3); + DROUND(4); + DROUND(5); + DROUND(6); + DROUND(7); + DROUND(8); + DROUND(9); + DROUND(10); + DROUND(11); + DROUND(12); + DROUND(13); + DROUND(14); + DROUND(15); + DROUND(16); +} + +#endif /* LTC_SOBER128_STREAM_SETUP || LTC_SOBER128_STREAM_SETIV */ + + +#endif /* LTC_SOBER128 */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream_crypt.c b/src/stream/sober128/sober128_stream_crypt.c new file mode 100644 index 000000000..5ab8cf95a --- /dev/null +++ b/src/stream/sober128/sober128_stream_crypt.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +#define __LTC_SOBER128TAB_C__ +#include "sober128tab.c" + +#include "sober128_stream_common.h" + + +static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) +{ + ulong32 t; + LOAD32L(t, in); + t ^= w; + STORE32L(t, out); +} + + +/* XOR pseudo-random bytes into buffer + */ +#define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 + @param st The Sober128 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + ulong32 t; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st != NULL); + + /* handle any previously buffered bytes */ + while (st->nbuf != 0 && inlen != 0) { + *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); + st->sbuf >>= 8; + st->nbuf -= 8; + --inlen; + } + +#ifndef LTC_SMALL_CODE + /* do lots at a time, if there's enough to do */ + while (inlen >= N*4) { + SROUND(0); + SROUND(1); + SROUND(2); + SROUND(3); + SROUND(4); + SROUND(5); + SROUND(6); + SROUND(7); + SROUND(8); + SROUND(9); + SROUND(10); + SROUND(11); + SROUND(12); + SROUND(13); + SROUND(14); + SROUND(15); + SROUND(16); + out += 4*N; + in += 4*N; + inlen -= 4*N; + } +#endif + + /* do small or odd size buffers the slow way */ + while (4 <= inlen) { + cycle(st->R); + t = nltap(st); + XORWORD(t, in, out); + out += 4; + in += 4; + inlen -= 4; + } + + /* handle any trailing bytes */ + if (inlen != 0) { + cycle(st->R); + st->sbuf = nltap(st); + st->nbuf = 32; + while (st->nbuf != 0 && inlen != 0) { + *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); + st->sbuf >>= 8; + st->nbuf -= 8; + --inlen; + } + } + + return CRYPT_OK; +} + + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream_done.c b/src/stream/sober128/sober128_stream_done.c new file mode 100644 index 000000000..515667309 --- /dev/null +++ b/src/stream/sober128/sober128_stream_done.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +/** + Terminate and clear Sober128 state + @param st The Sober128 state + @return CRYPT_OK on success +*/ +int sober128_stream_done(sober128_state *st) +{ + LTC_ARGCHK(st != NULL); + XMEMSET(st, 0, sizeof(sober128_state)); + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream_keystream.c b/src/stream/sober128/sober128_stream_keystream.c new file mode 100644 index 000000000..04f853e61 --- /dev/null +++ b/src/stream/sober128/sober128_stream_keystream.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return sober128_stream_crypt(st, out, outlen, out); +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream_setiv.c b/src/stream/sober128/sober128_stream_setiv.c new file mode 100644 index 000000000..4fb4c5427 --- /dev/null +++ b/src/stream/sober128/sober128_stream_setiv.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +#define __LTC_SOBER128TAB_C__ +#include "sober128tab.c" + +#define LTC_SOBER128_STREAM_SETIV +#include "sober128_stream_common.h" +#undef LTC_SOBER128_STREAM_SETIV + +/* don't change these... */ +#define N 17 +#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ +#define KEYP 15 /* where to insert key words */ +#define FOLDP 4 /* where to insert non-linear feedback */ + +/* initialise to previously saved register state + */ +static void s128_reloadstate(sober128_state *st) +{ + int i; + + for (i = 0; i < N; ++i) { + st->R[i] = st->initR[i]; + } +} + + +/** + Set IV to the Sober128 state + @param st The Sober12820 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12) + @return CRYPT_OK on success + */ +int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen) +{ + ulong32 i, k; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen > 0); + + /* ok we are adding an IV then... */ + s128_reloadstate(st); + + /* ivlen must be multiple of 4 bytes */ + if ((ivlen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + for (i = 0; i < ivlen; i += 4) { + LOAD32L(k, (unsigned char *)&iv[i]); + ADDKEY(k); + cycle(st->R); + XORNL(nltap(st)); + } + + /* also fold in the length of the key */ + ADDKEY(ivlen); + + /* now diffuse */ + s128_diffuse(st); + st->nbuf = 0; + + return CRYPT_OK; +} + + +#endif + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sober128/sober128_stream_setup.c b/src/stream/sober128/sober128_stream_setup.c new file mode 100644 index 000000000..1ef158c61 --- /dev/null +++ b/src/stream/sober128/sober128_stream_setup.c @@ -0,0 +1,110 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +#define __LTC_SOBER128TAB_C__ +#include "sober128tab.c" + +#define LTC_SOBER128_STREAM_SETUP +#include "sober128_stream_common.h" +#undef LTC_SOBER128_STREAM_SETUP + +/* don't change these... */ +#define N 17 +#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ +#define KEYP 15 /* where to insert key words */ +#define FOLDP 4 /* where to insert non-linear feedback */ + + +/* Save the current register state + */ +static void s128_savestate(sober128_state *st) +{ + int i; + for (i = 0; i < N; ++i) { + st->initR[i] = st->R[i]; + } +} + +/* Initialise "konst" + */ +static void s128_genkonst(sober128_state *st) +{ + ulong32 newkonst; + + do { + cycle(st->R); + newkonst = nltap(st); + } while ((newkonst & 0xFF000000) == 0); + st->konst = newkonst; +} + + +/** + Initialize an Sober128 context (only the key) + @param st [out] The destination of the Sober128 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen) +{ + ulong32 i, k; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen > 0); + + /* keylen must be multiple of 4 bytes */ + if ((keylen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + /* Register initialised to Fibonacci numbers */ + st->R[0] = 1; + st->R[1] = 1; + for (i = 2; i < N; ++i) { + st->R[i] = st->R[i-1] + st->R[i-2]; + } + st->konst = INITKONST; + + for (i = 0; i < keylen; i += 4) { + LOAD32L(k, (unsigned char *)&key[i]); + ADDKEY(k); + cycle(st->R); + XORNL(nltap(st)); + } + + /* also fold in the length of the key */ + ADDKEY(keylen); + + /* now diffuse */ + s128_diffuse(st); + s128_genkonst(st); + s128_savestate(st); + st->nbuf = 0; + + return CRYPT_OK; +} + + +#endif + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sosemanuk/sosemanuk_common.h b/src/stream/sosemanuk/sosemanuk_common.h new file mode 100644 index 000000000..7d87882b7 --- /dev/null +++ b/src/stream/sosemanuk/sosemanuk_common.h @@ -0,0 +1,187 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#ifdef LTC_SOSEMANUK + +/* + * this code is common to sosemanuk_setup(), sosemanuk_setiv(), sosemanuk_crypt() + */ + +/* ======================================================================== */ + +/* + * We want (and sometimes need) to perform explicit truncations to 32 bits. + */ +#define T32(x) ((x) & (ulong32)0xFFFFFFFF) + +/* + * Some of our functions will be tagged as "inline" to help the compiler + * optimize things. We use "inline" only if the compiler is advanced + * enough to understand it; C99 compilers, and pre-C99 versions of gcc, + * understand enough "inline" for our purposes. + */ + +/* ======================================================================== */ + +/* + * Serpent S-boxes, implemented in bitslice mode. These circuits have + * been published by Dag Arne Osvik ("Speeding up Serpent", published in + * the 3rd AES Candidate Conference) and work on five 32-bit registers: + * the four inputs, and a fifth scratch register. There are meant to be + * quite fast on Pentium-class processors. These are not the fastest + * published, but they are "fast enough" and they are unencumbered as + * far as intellectual property is concerned (note: these are rewritten + * from the article itself, and hence are not covered by the GPL on + * Dag's code, which was not used here). + * + * The output bits are permuted. Here is the correspondance: + * S0: 1420 + * S1: 2031 + * S2: 2314 + * S3: 1234 + * S4: 1403 + * S5: 1302 + * S6: 0142 + * S7: 4310 + * (for instance, the output of S0 is in "r1, r4, r2, r0"). + */ + +#define S0(r0, r1, r2, r3, r4) do { \ + r3 ^= r0; r4 = r1; \ + r1 &= r3; r4 ^= r2; \ + r1 ^= r0; r0 |= r3; \ + r0 ^= r4; r4 ^= r3; \ + r3 ^= r2; r2 |= r1; \ + r2 ^= r4; r4 = ~r4; \ + r4 |= r1; r1 ^= r3; \ + r1 ^= r4; r3 |= r0; \ + r1 ^= r3; r4 ^= r3; \ + } while (0) + +#define S1(r0, r1, r2, r3, r4) do { \ + r0 = ~r0; r2 = ~r2; \ + r4 = r0; r0 &= r1; \ + r2 ^= r0; r0 |= r3; \ + r3 ^= r2; r1 ^= r0; \ + r0 ^= r4; r4 |= r1; \ + r1 ^= r3; r2 |= r0; \ + r2 &= r4; r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; r0 &= r2; \ + r0 ^= r4; \ + } while (0) + +#define S2(r0, r1, r2, r3, r4) do { \ + r4 = r0; r0 &= r2; \ + r0 ^= r3; r2 ^= r1; \ + r2 ^= r0; r3 |= r4; \ + r3 ^= r1; r4 ^= r2; \ + r1 = r3; r3 |= r4; \ + r3 ^= r0; r0 &= r1; \ + r4 ^= r0; r1 ^= r3; \ + r1 ^= r4; r4 = ~r4; \ + } while (0) + +#define S3(r0, r1, r2, r3, r4) do { \ + r4 = r0; r0 |= r3; \ + r3 ^= r1; r1 &= r4; \ + r4 ^= r2; r2 ^= r3; \ + r3 &= r0; r4 |= r1; \ + r3 ^= r4; r0 ^= r1; \ + r4 &= r0; r1 ^= r3; \ + r4 ^= r2; r1 |= r0; \ + r1 ^= r2; r0 ^= r3; \ + r2 = r1; r1 |= r3; \ + r1 ^= r0; \ + } while (0) + +#define S4(r0, r1, r2, r3, r4) do { \ + r1 ^= r3; r3 = ~r3; \ + r2 ^= r3; r3 ^= r0; \ + r4 = r1; r1 &= r3; \ + r1 ^= r2; r4 ^= r3; \ + r0 ^= r4; r2 &= r4; \ + r2 ^= r0; r0 &= r1; \ + r3 ^= r0; r4 |= r1; \ + r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r2 &= r3; \ + r0 = ~r0; r4 ^= r2; \ + } while (0) + +#define S5(r0, r1, r2, r3, r4) do { \ + r0 ^= r1; r1 ^= r3; \ + r3 = ~r3; r4 = r1; \ + r1 &= r0; r2 ^= r3; \ + r1 ^= r2; r2 |= r4; \ + r4 ^= r3; r3 &= r1; \ + r3 ^= r0; r4 ^= r1; \ + r4 ^= r2; r2 ^= r0; \ + r0 &= r3; r2 = ~r2; \ + r0 ^= r4; r4 |= r3; \ + r2 ^= r4; \ + } while (0) + +#define S6(r0, r1, r2, r3, r4) do { \ + r2 = ~r2; r4 = r3; \ + r3 &= r0; r0 ^= r4; \ + r3 ^= r2; r2 |= r4; \ + r1 ^= r3; r2 ^= r0; \ + r0 |= r1; r2 ^= r1; \ + r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r4 ^= r3; \ + r4 ^= r0; r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ + } while (0) + +#define S7(r0, r1, r2, r3, r4) do { \ + r4 = r1; r1 |= r2; \ + r1 ^= r3; r4 ^= r2; \ + r2 ^= r1; r3 |= r4; \ + r3 &= r0; r4 ^= r2; \ + r3 ^= r1; r1 |= r4; \ + r1 ^= r0; r0 |= r4; \ + r0 ^= r2; r1 ^= r4; \ + r2 ^= r1; r1 &= r0; \ + r1 ^= r4; r2 = ~r2; \ + r2 |= r0; \ + r4 ^= r2; \ + } while (0) + +/* ======================================================================== */ + + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sosemanuk/sosemanuk.c b/src/stream/sosemanuk/sosemanuk_crypt.c similarity index 53% rename from src/stream/sosemanuk/sosemanuk.c rename to src/stream/sosemanuk/sosemanuk_crypt.c index 1c7cc27b5..de28dbe78 100644 --- a/src/stream/sosemanuk/sosemanuk.c +++ b/src/stream/sosemanuk/sosemanuk_crypt.c @@ -10,6 +10,12 @@ /* * This LTC implementation was adapted from: * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + * + * Sosemanuk specifications require: + * 1- a key of at least 128 bits (16 bytes), not exceeding 256 bits (32 bytes). + * 2- keys < 32 bytes are terminated with 0x01 followed by NULLs as needed. + * 3- an iv of 128 bits (16 bytes). + * See http://www.ecrypt.eu.org/stream/p3ciphers/sosemanuk/sosemanuk_p3.pdf */ /* @@ -34,411 +40,9 @@ #ifdef LTC_SOSEMANUK -/* ======================================================================== */ - -/* - * We want (and sometimes need) to perform explicit truncations to 32 bits. - */ -#define T32(x) ((x) & (ulong32)0xFFFFFFFF) - -/* - * Some of our functions will be tagged as "inline" to help the compiler - * optimize things. We use "inline" only if the compiler is advanced - * enough to understand it; C99 compilers, and pre-C99 versions of gcc, - * understand enough "inline" for our purposes. - */ - -/* ======================================================================== */ - -/* - * Serpent S-boxes, implemented in bitslice mode. These circuits have - * been published by Dag Arne Osvik ("Speeding up Serpent", published in - * the 3rd AES Candidate Conference) and work on five 32-bit registers: - * the four inputs, and a fifth scratch register. There are meant to be - * quite fast on Pentium-class processors. These are not the fastest - * published, but they are "fast enough" and they are unencumbered as - * far as intellectual property is concerned (note: these are rewritten - * from the article itself, and hence are not covered by the GPL on - * Dag's code, which was not used here). - * - * The output bits are permuted. Here is the correspondance: - * S0: 1420 - * S1: 2031 - * S2: 2314 - * S3: 1234 - * S4: 1403 - * S5: 1302 - * S6: 0142 - * S7: 4310 - * (for instance, the output of S0 is in "r1, r4, r2, r0"). - */ - -#define S0(r0, r1, r2, r3, r4) do { \ - r3 ^= r0; r4 = r1; \ - r1 &= r3; r4 ^= r2; \ - r1 ^= r0; r0 |= r3; \ - r0 ^= r4; r4 ^= r3; \ - r3 ^= r2; r2 |= r1; \ - r2 ^= r4; r4 = ~r4; \ - r4 |= r1; r1 ^= r3; \ - r1 ^= r4; r3 |= r0; \ - r1 ^= r3; r4 ^= r3; \ - } while (0) - -#define S1(r0, r1, r2, r3, r4) do { \ - r0 = ~r0; r2 = ~r2; \ - r4 = r0; r0 &= r1; \ - r2 ^= r0; r0 |= r3; \ - r3 ^= r2; r1 ^= r0; \ - r0 ^= r4; r4 |= r1; \ - r1 ^= r3; r2 |= r0; \ - r2 &= r4; r0 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; r0 &= r2; \ - r0 ^= r4; \ - } while (0) - -#define S2(r0, r1, r2, r3, r4) do { \ - r4 = r0; r0 &= r2; \ - r0 ^= r3; r2 ^= r1; \ - r2 ^= r0; r3 |= r4; \ - r3 ^= r1; r4 ^= r2; \ - r1 = r3; r3 |= r4; \ - r3 ^= r0; r0 &= r1; \ - r4 ^= r0; r1 ^= r3; \ - r1 ^= r4; r4 = ~r4; \ - } while (0) - -#define S3(r0, r1, r2, r3, r4) do { \ - r4 = r0; r0 |= r3; \ - r3 ^= r1; r1 &= r4; \ - r4 ^= r2; r2 ^= r3; \ - r3 &= r0; r4 |= r1; \ - r3 ^= r4; r0 ^= r1; \ - r4 &= r0; r1 ^= r3; \ - r4 ^= r2; r1 |= r0; \ - r1 ^= r2; r0 ^= r3; \ - r2 = r1; r1 |= r3; \ - r1 ^= r0; \ - } while (0) - -#define S4(r0, r1, r2, r3, r4) do { \ - r1 ^= r3; r3 = ~r3; \ - r2 ^= r3; r3 ^= r0; \ - r4 = r1; r1 &= r3; \ - r1 ^= r2; r4 ^= r3; \ - r0 ^= r4; r2 &= r4; \ - r2 ^= r0; r0 &= r1; \ - r3 ^= r0; r4 |= r1; \ - r4 ^= r0; r0 |= r3; \ - r0 ^= r2; r2 &= r3; \ - r0 = ~r0; r4 ^= r2; \ - } while (0) +#include "sosemanuk_common.h" -#define S5(r0, r1, r2, r3, r4) do { \ - r0 ^= r1; r1 ^= r3; \ - r3 = ~r3; r4 = r1; \ - r1 &= r0; r2 ^= r3; \ - r1 ^= r2; r2 |= r4; \ - r4 ^= r3; r3 &= r1; \ - r3 ^= r0; r4 ^= r1; \ - r4 ^= r2; r2 ^= r0; \ - r0 &= r3; r2 = ~r2; \ - r0 ^= r4; r4 |= r3; \ - r2 ^= r4; \ - } while (0) - -#define S6(r0, r1, r2, r3, r4) do { \ - r2 = ~r2; r4 = r3; \ - r3 &= r0; r0 ^= r4; \ - r3 ^= r2; r2 |= r4; \ - r1 ^= r3; r2 ^= r0; \ - r0 |= r1; r2 ^= r1; \ - r4 ^= r0; r0 |= r3; \ - r0 ^= r2; r4 ^= r3; \ - r4 ^= r0; r3 = ~r3; \ - r2 &= r4; \ - r2 ^= r3; \ - } while (0) - -#define S7(r0, r1, r2, r3, r4) do { \ - r4 = r1; r1 |= r2; \ - r1 ^= r3; r4 ^= r2; \ - r2 ^= r1; r3 |= r4; \ - r3 &= r0; r4 ^= r2; \ - r3 ^= r1; r1 |= r4; \ - r1 ^= r0; r0 |= r4; \ - r0 ^= r2; r1 ^= r4; \ - r2 ^= r1; r1 &= r0; \ - r1 ^= r4; r2 = ~r2; \ - r2 |= r0; \ - r4 ^= r2; \ - } while (0) - -/* - * The Serpent linear transform. - */ -#define SERPENT_LT(x0, x1, x2, x3) do { \ - x0 = ROLc(x0, 13); \ - x2 = ROLc(x2, 3); \ - x1 = x1 ^ x0 ^ x2; \ - x3 = x3 ^ x2 ^ T32(x0 << 3); \ - x1 = ROLc(x1, 1); \ - x3 = ROLc(x3, 7); \ - x0 = x0 ^ x1 ^ x3; \ - x2 = x2 ^ x3 ^ T32(x1 << 7); \ - x0 = ROLc(x0, 5); \ - x2 = ROLc(x2, 22); \ - } while (0) - -/* ======================================================================== */ - -/* - * Initialize Sosemanuk's state by providing a key. The key is an array of - * 1 to 32 bytes. - * @param st The Sosemanuk state - * @param key Key - * @param keylen Length of key in bytes - * @return CRYPT_OK on success - */ -int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen) -{ - /* - * This key schedule is actually a truncated Serpent key schedule. - * The key-derived words (w_i) are computed within the eight - * local variables w0 to w7, which are reused again and again. - */ - -#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \ - ulong32 r0, r1, r2, r3, r4; \ - r0 = w ## o0; \ - r1 = w ## o1; \ - r2 = w ## o2; \ - r3 = w ## o3; \ - S(r0, r1, r2, r3, r4); \ - st->kc[i ++] = r ## d0; \ - st->kc[i ++] = r ## d1; \ - st->kc[i ++] = r ## d2; \ - st->kc[i ++] = r ## d3; \ - } while (0) - -#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0) -#define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1) -#define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4) -#define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4) -#define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3) -#define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2) -#define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2) -#define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0) - -#define WUP(wi, wi5, wi3, wi1, cc) do { \ - ulong32 tt = (wi) ^ (wi5) ^ (wi3) \ - ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \ - (wi) = ROLc(tt, 11); \ - } while (0) - -#define WUP0(cc) do { \ - WUP(w0, w3, w5, w7, cc); \ - WUP(w1, w4, w6, w0, cc + 1); \ - WUP(w2, w5, w7, w1, cc + 2); \ - WUP(w3, w6, w0, w2, cc + 3); \ - } while (0) - -#define WUP1(cc) do { \ - WUP(w4, w7, w1, w3, cc); \ - WUP(w5, w0, w2, w4, cc + 1); \ - WUP(w6, w1, w3, w5, cc + 2); \ - WUP(w7, w2, w4, w6, cc + 3); \ - } while (0) - - unsigned char wbuf[32]; - ulong32 w0, w1, w2, w3, w4, w5, w6, w7; - int i = 0; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen > 0 && keylen <= 32); - - /* - * The key is copied into the wbuf[] buffer and padded to 256 bits - * as described in the Serpent specification. - */ - XMEMCPY(wbuf, key, keylen); - if (keylen < 32) { - wbuf[keylen] = 0x01; - if (keylen < 31) { - XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); - } - } - - LOAD32L(w0, wbuf); - LOAD32L(w1, wbuf + 4); - LOAD32L(w2, wbuf + 8); - LOAD32L(w3, wbuf + 12); - LOAD32L(w4, wbuf + 16); - LOAD32L(w5, wbuf + 20); - LOAD32L(w6, wbuf + 24); - LOAD32L(w7, wbuf + 28); - - WUP0(0); SKS3; - WUP1(4); SKS2; - WUP0(8); SKS1; - WUP1(12); SKS0; - WUP0(16); SKS7; - WUP1(20); SKS6; - WUP0(24); SKS5; - WUP1(28); SKS4; - WUP0(32); SKS3; - WUP1(36); SKS2; - WUP0(40); SKS1; - WUP1(44); SKS0; - WUP0(48); SKS7; - WUP1(52); SKS6; - WUP0(56); SKS5; - WUP1(60); SKS4; - WUP0(64); SKS3; - WUP1(68); SKS2; - WUP0(72); SKS1; - WUP1(76); SKS0; - WUP0(80); SKS7; - WUP1(84); SKS6; - WUP0(88); SKS5; - WUP1(92); SKS4; - WUP0(96); SKS3; - -#undef SKS -#undef SKS0 -#undef SKS1 -#undef SKS2 -#undef SKS3 -#undef SKS4 -#undef SKS5 -#undef SKS6 -#undef SKS7 -#undef WUP -#undef WUP0 -#undef WUP1 - - return CRYPT_OK; -} - - -/* - * Initialization continues by setting the IV. The IV length is up to 16 bytes. - * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple - * encryptions/decryptions are to be performed with the same key and - * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called - * to set the state. - * @param st The Sosemanuk state - * @param iv Initialization vector - * @param ivlen Length of iv in bytes - * @return CRYPT_OK on success - */ -int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen) -{ - - /* - * The Serpent key addition step. - */ -#define KA(zc, x0, x1, x2, x3) do { \ - x0 ^= st->kc[(zc)]; \ - x1 ^= st->kc[(zc) + 1]; \ - x2 ^= st->kc[(zc) + 2]; \ - x3 ^= st->kc[(zc) + 3]; \ - } while (0) - - /* - * One Serpent round. - * zc = current subkey counter - * S = S-box macro for this round - * i0 to i4 = input register numbers (the fifth is a scratch register) - * o0 to o3 = output register numbers - */ -#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ - KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ - S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ - SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ - } while (0) - - /* - * Last Serpent round. Contrary to the "true" Serpent, we keep - * the linear transformation for that last round. - */ -#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ - KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ - S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ - SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ - KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \ - } while (0) - - ulong32 r0, r1, r2, r3, r4; - unsigned char ivtmp[16] = {0}; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(ivlen <= 16); - LTC_ARGCHK(iv != NULL || ivlen == 0); - - if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); - - /* - * Decode IV into four 32-bit words (little-endian). - */ - LOAD32L(r0, ivtmp); - LOAD32L(r1, ivtmp + 4); - LOAD32L(r2, ivtmp + 8); - LOAD32L(r3, ivtmp + 12); - - /* - * Encrypt IV with Serpent24. Some values are extracted from the - * output of the twelfth, eighteenth and twenty-fourth rounds. - */ - FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0); - FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4); - FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3); - FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2); - FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2); - FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4); - FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1); - FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0); - FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4); - FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3); - FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0); - FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2); - st->s09 = r3; - st->s08 = r1; - st->s07 = r0; - st->s06 = r2; - - FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2); - FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3); - FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1); - FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4); - FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3); - FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0); - st->r1 = r2; - st->s04 = r1; - st->r2 = r3; - st->s05 = r0; - - FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4); - FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2); - FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2); - FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0); - FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1); - FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3); - st->s03 = r0; - st->s02 = r1; - st->s01 = r2; - st->s00 = r3; - - st->ptr = sizeof(st->buf); - -#undef KA -#undef FSS -#undef FSF - - return CRYPT_OK; -} +/* -------------------------------------------------------------------------- */ /* * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24] @@ -580,6 +184,7 @@ static const ulong32 mul_ia[] = { 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 }; +/* -------------------------------------------------------------------------- */ /* * Compute the next block of bits of output stream. This is equivalent @@ -717,6 +322,8 @@ static LTC_INLINE void _sosemanuk_internal(sosemanuk_state *st) st->r2 = r2; } +/* -------------------------------------------------------------------------- */ + /* * Combine buffers in1[] and in2[] by XOR, result in out[]. The length * is "datalen" (in bytes). Partial overlap of out[] with either in1[] @@ -726,11 +333,11 @@ static LTC_INLINE void _sosemanuk_internal(sosemanuk_state *st) static LTC_INLINE void _xorbuf(const unsigned char *in1, const unsigned char *in2, unsigned char *out, unsigned long datalen) { - while (datalen -- > 0) { + while (datalen -- > 0) *out ++ = *in1 ++ ^ *in2 ++; - } } +/* -------------------------------------------------------------------------- */ /* * Cipher operation, as a stream cipher: data is read from the "in" @@ -753,9 +360,8 @@ int sosemanuk_crypt(sosemanuk_state *st, if (st->ptr < (sizeof(st->buf))) { unsigned long rlen = (sizeof(st->buf)) - st->ptr; - if (rlen > inlen) { + if (rlen > inlen) rlen = inlen; - } _xorbuf(st->buf + st->ptr, in, out, rlen); in += rlen; out += rlen; @@ -778,37 +384,7 @@ int sosemanuk_crypt(sosemanuk_state *st, return CRYPT_OK; } - - -/* - * Cipher operation, as a PRNG: the provided output buffer is filled with - * pseudo-random bytes as output from the stream cipher. - * @param st The Sosemanuk state - * @param out Data out - * @param outlen Length of output in bytes - * @return CRYPT_OK on success - */ -int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return sosemanuk_crypt(st, out, outlen, out); -} - - -/* - * Terminate and clear Sosemanuk key context - * @param st The Sosemanuk state - * @return CRYPT_OK on success - */ -int sosemanuk_done(sosemanuk_state *st) -{ - LTC_ARGCHK(st != NULL); - XMEMSET(st, 0, sizeof(sosemanuk_state)); - return CRYPT_OK; -} - +/* -------------------------------------------------------------------------- */ #endif diff --git a/src/stream/sosemanuk/sosemanuk_done.c b/src/stream/sosemanuk/sosemanuk_done.c new file mode 100644 index 000000000..038fc971b --- /dev/null +++ b/src/stream/sosemanuk/sosemanuk_done.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + * + * Sosemanuk specifications require: + * 1- a key of at least 128 bits (16 bytes), not exceeding 256 bits (32 bytes). + * 2- keys < 32 bytes are terminated with 0x01 followed by NULLs as needed. + * 3- an iv of 128 bits (16 bytes). + * See http://www.ecrypt.eu.org/stream/p3ciphers/sosemanuk/sosemanuk_p3.pdf + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +/* + * Terminate and clear Sosemanuk key context + * @param st The Sosemanuk state + * @return CRYPT_OK on success + */ +int sosemanuk_done(sosemanuk_state *st) +{ + LTC_ARGCHK(st != NULL); + XMEMSET(st, 0, sizeof(sosemanuk_state)); + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sosemanuk/sosemanuk_keystream.c b/src/stream/sosemanuk/sosemanuk_keystream.c new file mode 100644 index 000000000..3d7a5ae67 --- /dev/null +++ b/src/stream/sosemanuk/sosemanuk_keystream.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + * + * Sosemanuk specifications require: + * 1- a key of at least 128 bits (16 bytes), not exceeding 256 bits (32 bytes). + * 2- keys < 32 bytes are terminated with 0x01 followed by NULLs as needed. + * 3- an iv of 128 bits (16 bytes). + * See http://www.ecrypt.eu.org/stream/p3ciphers/sosemanuk/sosemanuk_p3.pdf + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +/* + * Cipher operation, as a PRNG: the provided output buffer is filled with + * pseudo-random bytes as output from the stream cipher. + * @param st The Sosemanuk state + * @param out Data out + * @param outlen Length of output in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return sosemanuk_crypt(st, out, outlen, out); +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sosemanuk/sosemanuk_setiv.c b/src/stream/sosemanuk/sosemanuk_setiv.c new file mode 100644 index 000000000..951d0982c --- /dev/null +++ b/src/stream/sosemanuk/sosemanuk_setiv.c @@ -0,0 +1,181 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +#include "sosemanuk_common.h" + +/* ======================================================================== */ + +/* + * The Serpent linear transform. + */ +#define SERPENT_LT(x0, x1, x2, x3) do { \ + x0 = ROLc(x0, 13); \ + x2 = ROLc(x2, 3); \ + x1 = x1 ^ x0 ^ x2; \ + x3 = x3 ^ x2 ^ T32(x0 << 3); \ + x1 = ROLc(x1, 1); \ + x3 = ROLc(x3, 7); \ + x0 = x0 ^ x1 ^ x3; \ + x2 = x2 ^ x3 ^ T32(x1 << 7); \ + x0 = ROLc(x0, 5); \ + x2 = ROLc(x2, 22); \ + } while (0) + +/* ======================================================================== */ + +/* + * Initialization continues by setting the IV. The IV length is up to 16 bytes. + * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple + * encryptions/decryptions are to be performed with the same key and + * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called + * to set the state. + * @param st The Sosemanuk state + * @param iv Initialization vector + * @param ivlen Length of iv in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen) +{ + + /* + * The Serpent key addition step. + */ +#define KA(zc, x0, x1, x2, x3) do { \ + x0 ^= st->kc[(zc)]; \ + x1 ^= st->kc[(zc) + 1]; \ + x2 ^= st->kc[(zc) + 2]; \ + x3 ^= st->kc[(zc) + 3]; \ + } while (0) + + /* + * One Serpent round. + * zc = current subkey counter + * S = S-box macro for this round + * i0 to i4 = input register numbers (the fifth is a scratch register) + * o0 to o3 = output register numbers + */ +#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ + KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ + S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ + SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ + } while (0) + + /* + * Last Serpent round. Contrary to the "true" Serpent, we keep + * the linear transformation for that last round. + */ +#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ + KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ + S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ + SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ + KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \ + } while (0) + + ulong32 r0, r1, r2, r3, r4; + unsigned char ivtmp[16] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(ivlen <= 16); + LTC_ARGCHK(iv != NULL || ivlen == 0); + + if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); + + /* + * Decode IV into four 32-bit words (little-endian). + */ + LOAD32L(r0, ivtmp); + LOAD32L(r1, ivtmp + 4); + LOAD32L(r2, ivtmp + 8); + LOAD32L(r3, ivtmp + 12); + + /* + * Encrypt IV with Serpent24. Some values are extracted from the + * output of the twelfth, eighteenth and twenty-fourth rounds. + */ + FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0); + FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4); + FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3); + FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2); + FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2); + FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4); + FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1); + FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0); + FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4); + FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3); + FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0); + FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2); + st->s09 = r3; + st->s08 = r1; + st->s07 = r0; + st->s06 = r2; + + FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2); + FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3); + FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1); + FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4); + FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3); + FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0); + st->r1 = r2; + st->s04 = r1; + st->r2 = r3; + st->s05 = r0; + + FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4); + FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2); + FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2); + FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0); + FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1); + FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3); + st->s03 = r0; + st->s02 = r1; + st->s01 = r2; + st->s00 = r3; + + st->ptr = sizeof(st->buf); + +#undef KA +#undef FSS +#undef FSF + + return CRYPT_OK; +} + + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/stream/sosemanuk/sosemanuk_setup.c b/src/stream/sosemanuk/sosemanuk_setup.c new file mode 100644 index 000000000..e40f41cd5 --- /dev/null +++ b/src/stream/sosemanuk/sosemanuk_setup.c @@ -0,0 +1,176 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +#include "sosemanuk_common.h" + +/* ======================================================================== */ + +/* + * Initialize Sosemanuk's state by providing a key. The key is an array of + * 1 to 32 bytes. + * @param st The Sosemanuk state + * @param key Key + * @param keylen Length of key in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen) +{ + /* + * This key schedule is actually a truncated Serpent key schedule. + * The key-derived words (w_i) are computed within the eight + * local variables w0 to w7, which are reused again and again. + */ + +#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \ + ulong32 r0, r1, r2, r3, r4; \ + r0 = w ## o0; \ + r1 = w ## o1; \ + r2 = w ## o2; \ + r3 = w ## o3; \ + S(r0, r1, r2, r3, r4); \ + st->kc[i ++] = r ## d0; \ + st->kc[i ++] = r ## d1; \ + st->kc[i ++] = r ## d2; \ + st->kc[i ++] = r ## d3; \ + } while (0) + +#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0) +#define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1) +#define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4) +#define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4) +#define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3) +#define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2) +#define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2) +#define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0) + +#define WUP(wi, wi5, wi3, wi1, cc) do { \ + ulong32 tt = (wi) ^ (wi5) ^ (wi3) \ + ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \ + (wi) = ROLc(tt, 11); \ + } while (0) + +#define WUP0(cc) do { \ + WUP(w0, w3, w5, w7, cc); \ + WUP(w1, w4, w6, w0, cc + 1); \ + WUP(w2, w5, w7, w1, cc + 2); \ + WUP(w3, w6, w0, w2, cc + 3); \ + } while (0) + +#define WUP1(cc) do { \ + WUP(w4, w7, w1, w3, cc); \ + WUP(w5, w0, w2, w4, cc + 1); \ + WUP(w6, w1, w3, w5, cc + 2); \ + WUP(w7, w2, w4, w6, cc + 3); \ + } while (0) + + unsigned char wbuf[32]; + ulong32 w0, w1, w2, w3, w4, w5, w6, w7; + int i = 0; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen > 0 && keylen <= 32); + + /* + * The key is copied into the wbuf[] buffer and padded to 256 bits + * as described in the Serpent specification. + */ + XMEMCPY(wbuf, key, keylen); + if (keylen < 32) { + wbuf[keylen] = 0x01; + if (keylen < 31) { + XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); + } + } + + LOAD32L(w0, wbuf); + LOAD32L(w1, wbuf + 4); + LOAD32L(w2, wbuf + 8); + LOAD32L(w3, wbuf + 12); + LOAD32L(w4, wbuf + 16); + LOAD32L(w5, wbuf + 20); + LOAD32L(w6, wbuf + 24); + LOAD32L(w7, wbuf + 28); + + WUP0(0); SKS3; + WUP1(4); SKS2; + WUP0(8); SKS1; + WUP1(12); SKS0; + WUP0(16); SKS7; + WUP1(20); SKS6; + WUP0(24); SKS5; + WUP1(28); SKS4; + WUP0(32); SKS3; + WUP1(36); SKS2; + WUP0(40); SKS1; + WUP1(44); SKS0; + WUP0(48); SKS7; + WUP1(52); SKS6; + WUP0(56); SKS5; + WUP1(60); SKS4; + WUP0(64); SKS3; + WUP1(68); SKS2; + WUP0(72); SKS1; + WUP1(76); SKS0; + WUP0(80); SKS7; + WUP1(84); SKS6; + WUP0(88); SKS5; + WUP1(92); SKS4; + WUP0(96); SKS3; + +#undef SKS +#undef SKS0 +#undef SKS1 +#undef SKS2 +#undef SKS3 +#undef SKS4 +#undef SKS5 +#undef SKS6 +#undef SKS7 +#undef WUP +#undef WUP0 +#undef WUP1 + + return CRYPT_OK; +} + + + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */