diff options
author | lloyd <[email protected]> | 2009-09-15 12:39:44 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-09-15 12:39:44 +0000 |
commit | 467cfb8b8a31eecfaf63c30cfa13b69bef4cd566 (patch) | |
tree | aa6314c8afa6d2c5e0759a57fc52c91a36f43af1 /src/block | |
parent | 63fb872cb36a44a852ec33133de7c242bd44427e (diff) | |
parent | 18d1a6d4d11d40afb2d5a9d96b0437933bcaa472 (diff) |
propagate from branch 'net.randombit.botan.1_8' (head ef51dd2869ed38dae3aeb1c3b931ca9d595580e1)
to branch 'net.randombit.botan' (head fc1942640045423f411fd865cbd584090b28d7eb)
Diffstat (limited to 'src/block')
57 files changed, 2409 insertions, 1298 deletions
diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index 9072b507b..34698ae7f 100644 --- a/src/block/aes/aes.cpp +++ b/src/block/aes/aes.cpp @@ -1,6 +1,6 @@ /** * AES -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,163 +13,175 @@ namespace Botan { /** * AES Encryption */ -void AES::enc(const byte in[], byte out[]) const +void AES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* TE0 = TE; const u32bit* TE1 = TE + 256; const u32bit* TE2 = TE + 512; const u32bit* TE3 = TE + 768; - u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0]; - u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1]; - u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2]; - u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3]; - - u32bit B0, B1, B2, B3; - B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4]; - B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ - TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[5]; - B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ - TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[6]; - B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ - TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7]; - - for(u32bit j = 2; j != ROUNDS; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u32bit K0 = EK[4*j]; - const u32bit K1 = EK[4*j+1]; - const u32bit K2 = EK[4*j+2]; - const u32bit K3 = EK[4*j+3]; - - T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ - TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0; - T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ - TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1; - T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ - TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2; - T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ - TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3; - - const u32bit K4 = EK[4*(j+1)+0]; - const u32bit K5 = EK[4*(j+1)+1]; - const u32bit K6 = EK[4*(j+1)+2]; - const u32bit K7 = EK[4*(j+1)+3]; + u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0]; + u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1]; + u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2]; + u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3]; + u32bit B0, B1, B2, B3; B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ K4; + TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4]; B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ - TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ K5; + TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[5]; B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ - TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ K6; + TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[6]; B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ - TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ K7; - } + TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7]; + + for(u32bit j = 2; j != ROUNDS; j += 2) + { + const u32bit K0 = EK[4*j]; + const u32bit K1 = EK[4*j+1]; + const u32bit K2 = EK[4*j+2]; + const u32bit K3 = EK[4*j+3]; + + T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ + TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0; + T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ + TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1; + T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ + TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2; + T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ + TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3; + + const u32bit K4 = EK[4*(j+1)+0]; + const u32bit K5 = EK[4*(j+1)+1]; + const u32bit K6 = EK[4*(j+1)+2]; + const u32bit K7 = EK[4*(j+1)+3]; - /* - Joseph Bonneau and Ilya Mironov's paper - <a href = "http://icme2007.org/users/mironov/papers/aes-timing.pdf"> - Cache-Collision Timing Attacks Against AES</a> describes an attack - that can recover AES keys with as few as 2<sup>13</sup> samples. - - """In addition to OpenSSL v. 0.9.8.(a), which was used in our - experiments, the AES implementations of Crypto++ 5.2.1 and - LibTomCrypt 1.09 use the original Rijndael C implementation with - very few changes and are highly vulnerable. The AES implementations - in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but - use a smaller byte-wide final table which lessens the effectiveness - of the attacks.""" - */ - out[ 0] = SE[get_byte(0, B0)] ^ ME[0]; - out[ 1] = SE[get_byte(1, B1)] ^ ME[1]; - out[ 2] = SE[get_byte(2, B2)] ^ ME[2]; - out[ 3] = SE[get_byte(3, B3)] ^ ME[3]; - out[ 4] = SE[get_byte(0, B1)] ^ ME[4]; - out[ 5] = SE[get_byte(1, B2)] ^ ME[5]; - out[ 6] = SE[get_byte(2, B3)] ^ ME[6]; - out[ 7] = SE[get_byte(3, B0)] ^ ME[7]; - out[ 8] = SE[get_byte(0, B2)] ^ ME[8]; - out[ 9] = SE[get_byte(1, B3)] ^ ME[9]; - out[10] = SE[get_byte(2, B0)] ^ ME[10]; - out[11] = SE[get_byte(3, B1)] ^ ME[11]; - out[12] = SE[get_byte(0, B3)] ^ ME[12]; - out[13] = SE[get_byte(1, B0)] ^ ME[13]; - out[14] = SE[get_byte(2, B1)] ^ ME[14]; - out[15] = SE[get_byte(3, B2)] ^ ME[15]; + B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ + TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ K4; + B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ + TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ K5; + B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ + TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ K6; + B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ + TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ K7; + } + + /* + Joseph Bonneau and Ilya Mironov's paper + <a href = "http://icme2007.org/users/mironov/papers/aes-timing.pdf"> + Cache-Collision Timing Attacks Against AES</a> describes an attack + that can recover AES keys with as few as 2<sup>13</sup> samples. + + """In addition to OpenSSL v. 0.9.8.(a), which was used in our + experiments, the AES implementations of Crypto++ 5.2.1 and + LibTomCrypt 1.09 use the original Rijndael C implementation with + very few changes and are highly vulnerable. The AES implementations + in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but + use a smaller byte-wide final table which lessens the effectiveness + of the attacks.""" + */ + out[ 0] = SE[get_byte(0, B0)] ^ ME[0]; + out[ 1] = SE[get_byte(1, B1)] ^ ME[1]; + out[ 2] = SE[get_byte(2, B2)] ^ ME[2]; + out[ 3] = SE[get_byte(3, B3)] ^ ME[3]; + out[ 4] = SE[get_byte(0, B1)] ^ ME[4]; + out[ 5] = SE[get_byte(1, B2)] ^ ME[5]; + out[ 6] = SE[get_byte(2, B3)] ^ ME[6]; + out[ 7] = SE[get_byte(3, B0)] ^ ME[7]; + out[ 8] = SE[get_byte(0, B2)] ^ ME[8]; + out[ 9] = SE[get_byte(1, B3)] ^ ME[9]; + out[10] = SE[get_byte(2, B0)] ^ ME[10]; + out[11] = SE[get_byte(3, B1)] ^ ME[11]; + out[12] = SE[get_byte(0, B3)] ^ ME[12]; + out[13] = SE[get_byte(1, B0)] ^ ME[13]; + out[14] = SE[get_byte(2, B1)] ^ ME[14]; + out[15] = SE[get_byte(3, B2)] ^ ME[15]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /** * AES Decryption */ -void AES::dec(const byte in[], byte out[]) const +void AES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* TD0 = TD; const u32bit* TD1 = TD + 256; const u32bit* TD2 = TD + 512; const u32bit* TD3 = TD + 768; - u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0]; - u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1]; - u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2]; - u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3]; - - u32bit B0, B1, B2, B3; - B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[4]; - B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ - TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[5]; - B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[6]; - B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ - TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7]; - - for(u32bit j = 2; j != ROUNDS; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u32bit K0 = DK[4*j+0]; - const u32bit K1 = DK[4*j+1]; - const u32bit K2 = DK[4*j+2]; - const u32bit K3 = DK[4*j+3]; - - T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ - TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0; - T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ - TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1; - T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ - TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2; - T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ - TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3; - - const u32bit K4 = DK[4*(j+1)+0]; - const u32bit K5 = DK[4*(j+1)+1]; - const u32bit K6 = DK[4*(j+1)+2]; - const u32bit K7 = DK[4*(j+1)+3]; + u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0]; + u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1]; + u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2]; + u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3]; + u32bit B0, B1, B2, B3; B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ K4; + TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[4]; B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ - TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ K5; + TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[5]; B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ K6; + TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[6]; B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ - TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ K7; - } + TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7]; + + for(u32bit j = 2; j != ROUNDS; j += 2) + { + const u32bit K0 = DK[4*j+0]; + const u32bit K1 = DK[4*j+1]; + const u32bit K2 = DK[4*j+2]; + const u32bit K3 = DK[4*j+3]; + + T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ + TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0; + T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ + TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1; + T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ + TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2; + T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ + TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3; + + const u32bit K4 = DK[4*(j+1)+0]; + const u32bit K5 = DK[4*(j+1)+1]; + const u32bit K6 = DK[4*(j+1)+2]; + const u32bit K7 = DK[4*(j+1)+3]; - out[ 0] = SD[get_byte(0, B0)] ^ MD[0]; - out[ 1] = SD[get_byte(1, B3)] ^ MD[1]; - out[ 2] = SD[get_byte(2, B2)] ^ MD[2]; - out[ 3] = SD[get_byte(3, B1)] ^ MD[3]; - out[ 4] = SD[get_byte(0, B1)] ^ MD[4]; - out[ 5] = SD[get_byte(1, B0)] ^ MD[5]; - out[ 6] = SD[get_byte(2, B3)] ^ MD[6]; - out[ 7] = SD[get_byte(3, B2)] ^ MD[7]; - out[ 8] = SD[get_byte(0, B2)] ^ MD[8]; - out[ 9] = SD[get_byte(1, B1)] ^ MD[9]; - out[10] = SD[get_byte(2, B0)] ^ MD[10]; - out[11] = SD[get_byte(3, B3)] ^ MD[11]; - out[12] = SD[get_byte(0, B3)] ^ MD[12]; - out[13] = SD[get_byte(1, B2)] ^ MD[13]; - out[14] = SD[get_byte(2, B1)] ^ MD[14]; - out[15] = SD[get_byte(3, B0)] ^ MD[15]; + B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ + TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ K4; + B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ + TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ K5; + B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ + TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ K6; + B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ + TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ K7; + } + + out[ 0] = SD[get_byte(0, B0)] ^ MD[0]; + out[ 1] = SD[get_byte(1, B3)] ^ MD[1]; + out[ 2] = SD[get_byte(2, B2)] ^ MD[2]; + out[ 3] = SD[get_byte(3, B1)] ^ MD[3]; + out[ 4] = SD[get_byte(0, B1)] ^ MD[4]; + out[ 5] = SD[get_byte(1, B0)] ^ MD[5]; + out[ 6] = SD[get_byte(2, B3)] ^ MD[6]; + out[ 7] = SD[get_byte(3, B2)] ^ MD[7]; + out[ 8] = SD[get_byte(0, B2)] ^ MD[8]; + out[ 9] = SD[get_byte(1, B1)] ^ MD[9]; + out[10] = SD[get_byte(2, B0)] ^ MD[10]; + out[11] = SD[get_byte(3, B3)] ^ MD[11]; + out[12] = SD[get_byte(0, B3)] ^ MD[12]; + out[13] = SD[get_byte(1, B2)] ^ MD[13]; + out[14] = SD[get_byte(2, B1)] ^ MD[14]; + out[15] = SD[get_byte(3, B0)] ^ MD[15]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /** diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h index 05e2e3123..768bb09e7 100644 --- a/src/block/aes/aes.h +++ b/src/block/aes/aes.h @@ -1,6 +1,6 @@ /** * AES -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -18,14 +18,16 @@ namespace Botan { class BOTAN_DLL AES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "AES"; } BlockCipher* clone() const { return new AES; } + AES() : BlockCipher(16, 16, 32, 8) { ROUNDS = 14; } AES(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static u32bit S(u32bit); diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h index 01c45af04..a27609171 100644 --- a/src/block/block_cipher.h +++ b/src/block/block_cipher.h @@ -1,6 +1,6 @@ /** * Block Cipher Base Class -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -45,7 +45,8 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param out The byte array designated to hold the encrypted block. * Must be of length BLOCK_SIZE. */ - void encrypt(const byte in[], byte out[]) const { enc(in, out); } + void encrypt(const byte in[], byte out[]) const + { encrypt_n(in, out, 1); } /** * Decrypt a block. @@ -54,7 +55,8 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param out The byte array designated to hold the decrypted block. * Must be of length BLOCK_SIZE. */ - void decrypt(const byte in[], byte out[]) const { dec(in, out); } + void decrypt(const byte in[], byte out[]) const + { decrypt_n(in, out, 1); } /** * Encrypt a block. @@ -62,7 +64,7 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * Must be of length BLOCK_SIZE. Will hold the result when the function * has finished. */ - void encrypt(byte block[]) const { enc(block, block); } + void encrypt(byte block[]) const { encrypt_n(block, block, 1); } /** * Decrypt a block. @@ -70,7 +72,12 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * Must be of length BLOCK_SIZE. Will hold the result when the function * has finished. */ - void decrypt(byte block[]) const { dec(block, block); } + void decrypt(byte block[]) const { decrypt_n(block, block, 1); } + + virtual void encrypt_n(const byte in[], byte out[], + u32bit blocks) const = 0; + virtual void decrypt_n(const byte in[], byte out[], + u32bit blocks) const = 0; /** * Get a new object representing the same algorithm as *this @@ -90,9 +97,6 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm BLOCK_SIZE(block_size) {} virtual ~BlockCipher() {} - private: - virtual void enc(const byte[], byte[]) const = 0; - virtual void dec(const byte[], byte[]) const = 0; }; } diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp index b0599d6c5..312603c3a 100644 --- a/src/block/blowfish/blowfish.cpp +++ b/src/block/blowfish/blowfish.cpp @@ -1,6 +1,6 @@ /* * Blowfish -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,59 +13,71 @@ namespace Botan { /* * Blowfish Encryption */ -void Blowfish::enc(const byte in[], byte out[]) const +void Blowfish::encrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* S1 = S + 0; const u32bit* S2 = S + 256; const u32bit* S3 = S + 512; const u32bit* S4 = S + 768; - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - L ^= P[j]; - R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ - S3[get_byte(2, L)]) + S4[get_byte(3, L)]; + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); - R ^= P[j+1]; - L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ - S3[get_byte(2, R)]) + S4[get_byte(3, R)]; - } + for(u32bit j = 0; j != 16; j += 2) + { + L ^= P[j]; + R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ + S3[get_byte(2, L)]) + S4[get_byte(3, L)]; - L ^= P[16]; R ^= P[17]; + R ^= P[j+1]; + L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ + S3[get_byte(2, R)]) + S4[get_byte(3, R)]; + } + + L ^= P[16]; R ^= P[17]; - store_be(out, R, L); + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Blowfish Decryption */ -void Blowfish::dec(const byte in[], byte out[]) const +void Blowfish::decrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* S1 = S + 0; const u32bit* S2 = S + 256; const u32bit* S3 = S + 512; const u32bit* S4 = S + 768; - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - for(u32bit j = 17; j != 1; j -= 2) + for(u32bit i = 0; i != blocks; ++i) { - L ^= P[j]; - R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ - S3[get_byte(2, L)]) + S4[get_byte(3, L)]; + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); - R ^= P[j-1]; - L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ - S3[get_byte(2, R)]) + S4[get_byte(3, R)]; - } + for(u32bit j = 17; j != 1; j -= 2) + { + L ^= P[j]; + R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ + S3[get_byte(2, L)]) + S4[get_byte(3, L)]; - L ^= P[1]; R ^= P[0]; + R ^= P[j-1]; + L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ + S3[get_byte(2, R)]) + S4[get_byte(3, R)]; + } + + L ^= P[1]; R ^= P[0]; - store_be(out, R, L); + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h index f0f26418d..345c1ce49 100644 --- a/src/block/blowfish/blowfish.h +++ b/src/block/blowfish/blowfish.h @@ -1,6 +1,6 @@ /* * Blowfish -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Blowfish : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Blowfish"; } BlockCipher* clone() const { return new Blowfish; } + Blowfish() : BlockCipher(8, 1, 56) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void generate_sbox(u32bit[], u32bit, u32bit&, u32bit&) const; diff --git a/src/block/cast/cast128.cpp b/src/block/cast/cast128.cpp index 046638ab9..887dcf994 100644 --- a/src/block/cast/cast128.cpp +++ b/src/block/cast/cast128.cpp @@ -48,57 +48,69 @@ inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK) /* * CAST-128 Encryption */ -void CAST_128::enc(const byte in[], byte out[]) const +void CAST_128::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - R1(L, R, MK[ 0], RK[ 0]); - R2(R, L, MK[ 1], RK[ 1]); - R3(L, R, MK[ 2], RK[ 2]); - R1(R, L, MK[ 3], RK[ 3]); - R2(L, R, MK[ 4], RK[ 4]); - R3(R, L, MK[ 5], RK[ 5]); - R1(L, R, MK[ 6], RK[ 6]); - R2(R, L, MK[ 7], RK[ 7]); - R3(L, R, MK[ 8], RK[ 8]); - R1(R, L, MK[ 9], RK[ 9]); - R2(L, R, MK[10], RK[10]); - R3(R, L, MK[11], RK[11]); - R1(L, R, MK[12], RK[12]); - R2(R, L, MK[13], RK[13]); - R3(L, R, MK[14], RK[14]); - R1(R, L, MK[15], RK[15]); - - store_be(out, R, L); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); + + R1(L, R, MK[ 0], RK[ 0]); + R2(R, L, MK[ 1], RK[ 1]); + R3(L, R, MK[ 2], RK[ 2]); + R1(R, L, MK[ 3], RK[ 3]); + R2(L, R, MK[ 4], RK[ 4]); + R3(R, L, MK[ 5], RK[ 5]); + R1(L, R, MK[ 6], RK[ 6]); + R2(R, L, MK[ 7], RK[ 7]); + R3(L, R, MK[ 8], RK[ 8]); + R1(R, L, MK[ 9], RK[ 9]); + R2(L, R, MK[10], RK[10]); + R3(R, L, MK[11], RK[11]); + R1(L, R, MK[12], RK[12]); + R2(R, L, MK[13], RK[13]); + R3(L, R, MK[14], RK[14]); + R1(R, L, MK[15], RK[15]); + + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * CAST-128 Decryption */ -void CAST_128::dec(const byte in[], byte out[]) const +void CAST_128::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - R1(L, R, MK[15], RK[15]); - R3(R, L, MK[14], RK[14]); - R2(L, R, MK[13], RK[13]); - R1(R, L, MK[12], RK[12]); - R3(L, R, MK[11], RK[11]); - R2(R, L, MK[10], RK[10]); - R1(L, R, MK[ 9], RK[ 9]); - R3(R, L, MK[ 8], RK[ 8]); - R2(L, R, MK[ 7], RK[ 7]); - R1(R, L, MK[ 6], RK[ 6]); - R3(L, R, MK[ 5], RK[ 5]); - R2(R, L, MK[ 4], RK[ 4]); - R1(L, R, MK[ 3], RK[ 3]); - R3(R, L, MK[ 2], RK[ 2]); - R2(L, R, MK[ 1], RK[ 1]); - R1(R, L, MK[ 0], RK[ 0]); - - store_be(out, R, L); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); + + R1(L, R, MK[15], RK[15]); + R3(R, L, MK[14], RK[14]); + R2(L, R, MK[13], RK[13]); + R1(R, L, MK[12], RK[12]); + R3(L, R, MK[11], RK[11]); + R2(R, L, MK[10], RK[10]); + R1(L, R, MK[ 9], RK[ 9]); + R3(R, L, MK[ 8], RK[ 8]); + R2(L, R, MK[ 7], RK[ 7]); + R1(R, L, MK[ 6], RK[ 6]); + R3(L, R, MK[ 5], RK[ 5]); + R2(R, L, MK[ 4], RK[ 4]); + R1(L, R, MK[ 3], RK[ 3]); + R3(R, L, MK[ 2], RK[ 2]); + R2(L, R, MK[ 1], RK[ 1]); + R1(R, L, MK[ 0], RK[ 0]); + + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/cast/cast128.h b/src/block/cast/cast128.h index 680481482..864a4e47e 100644 --- a/src/block/cast/cast128.h +++ b/src/block/cast/cast128.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL CAST_128 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-128"; } BlockCipher* clone() const { return new CAST_128; } + CAST_128() : BlockCipher(8, 11, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void key_schedule(u32bit[16], u32bit[4]); diff --git a/src/block/cast/cast256.cpp b/src/block/cast/cast256.cpp index 22ff876fa..7a4a4e805 100644 --- a/src/block/cast/cast256.cpp +++ b/src/block/cast/cast256.cpp @@ -48,77 +48,89 @@ void round3(u32bit& out, u32bit in, u32bit mask, u32bit rot) /* * CAST-256 Encryption */ -void CAST_256::enc(const byte in[], byte out[]) const +void CAST_256::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_be<u32bit>(in, 0); - u32bit B = load_be<u32bit>(in, 1); - u32bit C = load_be<u32bit>(in, 2); - u32bit D = load_be<u32bit>(in, 3); - - round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]); - round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]); - round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]); - round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]); - round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]); - round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]); - round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]); - round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]); - round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]); - round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]); - round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]); - round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]); - round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]); - round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]); - round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]); - round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]); - round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]); - round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]); - round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]); - round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]); - round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]); - round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]); - round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]); - round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]); - - store_be(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_be<u32bit>(in, 0); + u32bit B = load_be<u32bit>(in, 1); + u32bit C = load_be<u32bit>(in, 2); + u32bit D = load_be<u32bit>(in, 3); + + round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]); + round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]); + round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]); + round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]); + round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]); + round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]); + round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]); + round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]); + round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]); + round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]); + round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]); + round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]); + round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]); + round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]); + round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]); + round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]); + round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]); + round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]); + round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]); + round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]); + round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]); + round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]); + round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]); + round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]); + + store_be(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * CAST-256 Decryption */ -void CAST_256::dec(const byte in[], byte out[]) const +void CAST_256::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_be<u32bit>(in, 0); - u32bit B = load_be<u32bit>(in, 1); - u32bit C = load_be<u32bit>(in, 2); - u32bit D = load_be<u32bit>(in, 3); - - round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]); - round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]); - round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]); - round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]); - round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]); - round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]); - round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]); - round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]); - round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]); - round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]); - round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]); - round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]); - round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]); - round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]); - round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]); - round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]); - round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]); - round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]); - round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]); - round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]); - round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]); - round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]); - round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]); - round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]); - - store_be(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_be<u32bit>(in, 0); + u32bit B = load_be<u32bit>(in, 1); + u32bit C = load_be<u32bit>(in, 2); + u32bit D = load_be<u32bit>(in, 3); + + round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]); + round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]); + round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]); + round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]); + round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]); + round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]); + round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]); + round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]); + round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]); + round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]); + round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]); + round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]); + round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]); + round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]); + round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]); + round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]); + round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]); + round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]); + round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]); + round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]); + round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]); + round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]); + round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]); + round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]); + + store_be(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/cast/cast256.h b/src/block/cast/cast256.h index cd48edd5e..1be7fa9cf 100644 --- a/src/block/cast/cast256.h +++ b/src/block/cast/cast256.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL CAST_256 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-256"; } BlockCipher* clone() const { return new CAST_256; } + CAST_256() : BlockCipher(16, 4, 32, 4) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const u32bit KEY_MASK[192]; diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp index 37520e0fc..1c9d37e6b 100644 --- a/src/block/des/des.cpp +++ b/src/block/des/des.cpp @@ -139,51 +139,63 @@ void des_decrypt(u32bit& L, u32bit& R, /* * DES Encryption */ -void DES::enc(const byte in[], byte out[]) const +void DES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_encrypt(L, R, round_key); - des_encrypt(L, R, round_key); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * DES Decryption */ -void DES::dec(const byte in[], byte out[]) const +void DES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_decrypt(L, R, round_key); - des_decrypt(L, R, round_key); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* @@ -197,55 +209,67 @@ void DES::key_schedule(const byte key[], u32bit) /* * TripleDES Encryption */ -void TripleDES::enc(const byte in[], byte out[]) const +void TripleDES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_encrypt(L, R, round_key); + des_decrypt(R, L, round_key + 32); + des_encrypt(L, R, round_key + 64); - des_encrypt(L, R, round_key); - des_decrypt(R, L, round_key + 32); - des_encrypt(L, R, round_key + 64); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * TripleDES Decryption */ -void TripleDES::dec(const byte in[], byte out[]) const +void TripleDES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_decrypt(L, R, round_key + 64); + des_encrypt(R, L, round_key + 32); + des_decrypt(L, R, round_key); - des_decrypt(L, R, round_key + 64); - des_encrypt(R, L, round_key + 32); - des_decrypt(L, R, round_key); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/des/des.h b/src/block/des/des.h index 6fa59de5e..856aaf60c 100644 --- a/src/block/des/des.h +++ b/src/block/des/des.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL DES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "DES"; } BlockCipher* clone() const { return new DES; } + DES() : BlockCipher(8, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 32> round_key; @@ -36,13 +38,15 @@ class BOTAN_DLL DES : public BlockCipher class BOTAN_DLL TripleDES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "TripleDES"; } BlockCipher* clone() const { return new TripleDES; } + TripleDES() : BlockCipher(8, 16, 24, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 96> round_key; diff --git a/src/block/des/desx.cpp b/src/block/des/desx.cpp index e557901d3..1fc1c47f2 100644 --- a/src/block/des/desx.cpp +++ b/src/block/des/desx.cpp @@ -13,21 +13,33 @@ namespace Botan { /* * DESX Encryption */ -void DESX::enc(const byte in[], byte out[]) const +void DESX::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - xor_buf(out, in, K1.begin(), BLOCK_SIZE); - des.encrypt(out); - xor_buf(out, K2.begin(), BLOCK_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(out, in, K1.begin(), BLOCK_SIZE); + des.encrypt(out); + xor_buf(out, K2.begin(), BLOCK_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * DESX Decryption */ -void DESX::dec(const byte in[], byte out[]) const +void DESX::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - xor_buf(out, in, K2.begin(), BLOCK_SIZE); - des.decrypt(out); - xor_buf(out, K1.begin(), BLOCK_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(out, in, K2.begin(), BLOCK_SIZE); + des.decrypt(out); + xor_buf(out, K1.begin(), BLOCK_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/des/desx.h b/src/block/des/desx.h index 49ecc2421..d22895296 100644 --- a/src/block/des/desx.h +++ b/src/block/des/desx.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL DESX : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { des.clear(); K1.clear(); K2.clear(); } std::string name() const { return "DESX"; } BlockCipher* clone() const { return new DESX; } + DESX() : BlockCipher(8, 24) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<byte, 8> K1, K2; DES des; diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp index bfd092c56..272f1bcab 100644 --- a/src/block/gost_28147/gost_28147.cpp +++ b/src/block/gost_28147/gost_28147.cpp @@ -84,47 +84,58 @@ GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : /* * GOST Encryption */ -void GOST_28147_89::enc(const byte in[], byte out[]) const +void GOST_28147_89::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - - for(size_t i = 0; i != 3; ++i) + for(u32bit i = 0; i != blocks; ++i) { - GOST_2ROUND(N1, N2, 0, 1); - GOST_2ROUND(N1, N2, 2, 3); - GOST_2ROUND(N1, N2, 4, 5); - GOST_2ROUND(N1, N2, 6, 7); - } + u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - GOST_2ROUND(N1, N2, 7, 6); - GOST_2ROUND(N1, N2, 5, 4); - GOST_2ROUND(N1, N2, 3, 2); - GOST_2ROUND(N1, N2, 1, 0); + for(size_t j = 0; j != 3; ++j) + { + GOST_2ROUND(N1, N2, 0, 1); + GOST_2ROUND(N1, N2, 2, 3); + GOST_2ROUND(N1, N2, 4, 5); + GOST_2ROUND(N1, N2, 6, 7); + } - store_le(out, N2, N1); + GOST_2ROUND(N1, N2, 7, 6); + GOST_2ROUND(N1, N2, 5, 4); + GOST_2ROUND(N1, N2, 3, 2); + GOST_2ROUND(N1, N2, 1, 0); + + store_le(out, N2, N1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * GOST Decryption */ -void GOST_28147_89::dec(const byte in[], byte out[]) const +void GOST_28147_89::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - GOST_2ROUND(N1, N2, 0, 1); - GOST_2ROUND(N1, N2, 2, 3); - GOST_2ROUND(N1, N2, 4, 5); - GOST_2ROUND(N1, N2, 6, 7); + GOST_2ROUND(N1, N2, 0, 1); + GOST_2ROUND(N1, N2, 2, 3); + GOST_2ROUND(N1, N2, 4, 5); + GOST_2ROUND(N1, N2, 6, 7); - for(size_t i = 0; i != 3; ++i) - { - GOST_2ROUND(N1, N2, 7, 6); - GOST_2ROUND(N1, N2, 5, 4); - GOST_2ROUND(N1, N2, 3, 2); - GOST_2ROUND(N1, N2, 1, 0); - } + for(size_t i = 0; i != 3; ++i) + { + GOST_2ROUND(N1, N2, 7, 6); + GOST_2ROUND(N1, N2, 5, 4); + GOST_2ROUND(N1, N2, 3, 2); + GOST_2ROUND(N1, N2, 1, 0); + } - store_le(out, N2, N1); + store_le(out, N2, N1); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h index 96d24c669..18c1d0a29 100644 --- a/src/block/gost_28147/gost_28147.h +++ b/src/block/gost_28147/gost_28147.h @@ -44,6 +44,9 @@ class GOST_28147_89_Params class BOTAN_DLL GOST_28147_89 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "GOST-28147-89"; } @@ -54,8 +57,6 @@ class BOTAN_DLL GOST_28147_89 : public BlockCipher GOST_28147_89(const SecureBuffer<u32bit, 1024>& other_SBOX) : BlockCipher(8, 32), SBOX(other_SBOX) {} - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 1024> SBOX; diff --git a/src/block/idea/idea.cpp b/src/block/idea/idea.cpp index 5bbe47087..fb5fe83f1 100644 --- a/src/block/idea/idea.cpp +++ b/src/block/idea/idea.cpp @@ -60,77 +60,89 @@ u16bit mul_inv(u16bit x) /* * IDEA Encryption */ -void IDEA::enc(const byte in[], byte out[]) const +void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit X1 = load_be<u16bit>(in, 0); - u16bit X2 = load_be<u16bit>(in, 1); - u16bit X3 = load_be<u16bit>(in, 2); - u16bit X4 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; ++j) + for(u32bit i = 0; i != blocks; ++i) { - X1 = mul(X1, EK[6*j+0]); - X2 += EK[6*j+1]; - X3 += EK[6*j+2]; - X4 = mul(X4, EK[6*j+3]); - - u16bit T0 = X3; - X3 = mul(X3 ^ X1, EK[6*j+4]); - - u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); - X3 += X2; - - X1 ^= X2; - X4 ^= X3; - X2 ^= T0; - X3 ^= T1; + u16bit X1 = load_be<u16bit>(in, 0); + u16bit X2 = load_be<u16bit>(in, 1); + u16bit X3 = load_be<u16bit>(in, 2); + u16bit X4 = load_be<u16bit>(in, 3); + + for(u32bit j = 0; j != 8; ++j) + { + X1 = mul(X1, EK[6*j+0]); + X2 += EK[6*j+1]; + X3 += EK[6*j+2]; + X4 = mul(X4, EK[6*j+3]); + + u16bit T0 = X3; + X3 = mul(X3 ^ X1, EK[6*j+4]); + + u16bit T1 = X2; + X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); + X3 += X2; + + X1 ^= X2; + X4 ^= X3; + X2 ^= T0; + X3 ^= T1; + } + + X1 = mul(X1, EK[48]); + X2 += EK[50]; + X3 += EK[49]; + X4 = mul(X4, EK[51]); + + store_be(out, X1, X3, X2, X4); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - X1 = mul(X1, EK[48]); - X2 += EK[50]; - X3 += EK[49]; - X4 = mul(X4, EK[51]); - - store_be(out, X1, X3, X2, X4); } /* * IDEA Decryption */ -void IDEA::dec(const byte in[], byte out[]) const +void IDEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit X1 = load_be<u16bit>(in, 0); - u16bit X2 = load_be<u16bit>(in, 1); - u16bit X3 = load_be<u16bit>(in, 2); - u16bit X4 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; ++j) + for(u32bit i = 0; i != blocks; ++i) { - X1 = mul(X1, DK[6*j+0]); - X2 += DK[6*j+1]; - X3 += DK[6*j+2]; - X4 = mul(X4, DK[6*j+3]); - - u16bit T0 = X3; - X3 = mul(X3 ^ X1, DK[6*j+4]); - - u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, DK[6*j+5]); - X3 += X2; - - X1 ^= X2; - X4 ^= X3; - X2 ^= T0; - X3 ^= T1; + u16bit X1 = load_be<u16bit>(in, 0); + u16bit X2 = load_be<u16bit>(in, 1); + u16bit X3 = load_be<u16bit>(in, 2); + u16bit X4 = load_be<u16bit>(in, 3); + + for(u32bit j = 0; j != 8; ++j) + { + X1 = mul(X1, DK[6*j+0]); + X2 += DK[6*j+1]; + X3 += DK[6*j+2]; + X4 = mul(X4, DK[6*j+3]); + + u16bit T0 = X3; + X3 = mul(X3 ^ X1, DK[6*j+4]); + + u16bit T1 = X2; + X2 = mul((X2 ^ X4) + X3, DK[6*j+5]); + X3 += X2; + + X1 ^= X2; + X4 ^= X3; + X2 ^= T0; + X3 ^= T1; + } + + X1 = mul(X1, DK[48]); + X2 += DK[50]; + X3 += DK[49]; + X4 = mul(X4, DK[51]); + + store_be(out, X1, X3, X2, X4); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - X1 = mul(X1, DK[48]); - X2 += DK[50]; - X3 += DK[49]; - X4 = mul(X4, DK[51]); - - store_be(out, X1, X3, X2, X4); } /* diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h index 2c53cd0e4..59484531b 100644 --- a/src/block/idea/idea.h +++ b/src/block/idea/idea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL IDEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); DK.clear(); } std::string name() const { return "IDEA"; } BlockCipher* clone() const { return new IDEA; } + IDEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 52> EK, DK; }; diff --git a/src/block/kasumi/kasumi.cpp b/src/block/kasumi/kasumi.cpp index e051ddefb..dff6db13c 100644 --- a/src/block/kasumi/kasumi.cpp +++ b/src/block/kasumi/kasumi.cpp @@ -109,79 +109,91 @@ u16bit FI(u16bit I, u16bit K) /* * KASUMI Encryption */ -void KASUMI::enc(const byte in[], byte out[]) const +void KASUMI::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* K = EK + 8*j; + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); - u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); + for(u32bit j = 0; j != 8; j += 2) + { + const u16bit* K = EK + 8*j; - L = FI(L ^ K[ 2], K[ 3]) ^ R; - R = FI(R ^ K[ 4], K[ 5]) ^ L; - L = FI(L ^ K[ 6], K[ 7]) ^ R; + u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); + u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); - R = B2 ^= R; - L = B3 ^= L; + L = FI(L ^ K[ 2], K[ 3]) ^ R; + R = FI(R ^ K[ 4], K[ 5]) ^ L; + L = FI(L ^ K[ 6], K[ 7]) ^ R; - R = FI(R ^ K[10], K[11]) ^ L; - L = FI(L ^ K[12], K[13]) ^ R; - R = FI(R ^ K[14], K[15]) ^ L; + R = B2 ^= R; + L = B3 ^= L; - R ^= (rotate_left(L, 1) & K[8]); - L ^= (rotate_left(R, 1) | K[9]); + R = FI(R ^ K[10], K[11]) ^ L; + L = FI(L ^ K[12], K[13]) ^ R; + R = FI(R ^ K[14], K[15]) ^ L; - B0 ^= L; - B1 ^= R; - } + R ^= (rotate_left(L, 1) & K[8]); + L ^= (rotate_left(R, 1) | K[9]); + + B0 ^= L; + B1 ^= R; + } - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * KASUMI Decryption */ -void KASUMI::dec(const byte in[], byte out[]) const +void KASUMI::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* K = EK + 8*(6-j); + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - u16bit L = B2, R = B3; + for(u32bit j = 0; j != 8; j += 2) + { + const u16bit* K = EK + 8*(6-j); - L = FI(L ^ K[10], K[11]) ^ R; - R = FI(R ^ K[12], K[13]) ^ L; - L = FI(L ^ K[14], K[15]) ^ R; + u16bit L = B2, R = B3; - L ^= (rotate_left(R, 1) & K[8]); - R ^= (rotate_left(L, 1) | K[9]); + L = FI(L ^ K[10], K[11]) ^ R; + R = FI(R ^ K[12], K[13]) ^ L; + L = FI(L ^ K[14], K[15]) ^ R; - R = B0 ^= R; - L = B1 ^= L; + L ^= (rotate_left(R, 1) & K[8]); + R ^= (rotate_left(L, 1) | K[9]); - L ^= (rotate_left(R, 1) & K[0]); - R ^= (rotate_left(L, 1) | K[1]); + R = B0 ^= R; + L = B1 ^= L; - R = FI(R ^ K[2], K[3]) ^ L; - L = FI(L ^ K[4], K[5]) ^ R; - R = FI(R ^ K[6], K[7]) ^ L; + L ^= (rotate_left(R, 1) & K[0]); + R ^= (rotate_left(L, 1) | K[1]); - B2 ^= L; - B3 ^= R; - } + R = FI(R ^ K[2], K[3]) ^ L; + L = FI(L ^ K[4], K[5]) ^ R; + R = FI(R ^ K[6], K[7]) ^ L; + + B2 ^= L; + B3 ^= R; + } - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/kasumi/kasumi.h b/src/block/kasumi/kasumi.h index df49fa9eb..0f5a5d182 100644 --- a/src/block/kasumi/kasumi.h +++ b/src/block/kasumi/kasumi.h @@ -18,14 +18,15 @@ namespace Botan { class BOTAN_DLL KASUMI : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "KASUMI"; } BlockCipher* clone() const { return new KASUMI; } KASUMI() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 64> EK; diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp index c7cdf6d13..83c1e3aa3 100644 --- a/src/block/lion/lion.cpp +++ b/src/block/lion/lion.cpp @@ -14,41 +14,53 @@ namespace Botan { /* * Lion Encryption */ -void Lion::enc(const byte in[], byte out[]) const +void Lion::encrypt_n(const byte in[], byte out[], u32bit blocks) const { SecureVector<byte> buffer(LEFT_SIZE); - xor_buf(buffer, in, key1, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(buffer, in, key1, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); - hash->update(out + LEFT_SIZE, RIGHT_SIZE); - hash->final(buffer); - xor_buf(out, in, buffer, LEFT_SIZE); + hash->update(out + LEFT_SIZE, RIGHT_SIZE); + hash->final(buffer); + xor_buf(out, in, buffer, LEFT_SIZE); - xor_buf(buffer, out, key2, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + xor_buf(buffer, out, key2, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Lion Decryption */ -void Lion::dec(const byte in[], byte out[]) const +void Lion::decrypt_n(const byte in[], byte out[], u32bit blocks) const { SecureVector<byte> buffer(LEFT_SIZE); - xor_buf(buffer, in, key2, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(buffer, in, key2, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + + hash->update(out + LEFT_SIZE, RIGHT_SIZE); + hash->final(buffer); + xor_buf(out, in, buffer, LEFT_SIZE); - hash->update(out + LEFT_SIZE, RIGHT_SIZE); - hash->final(buffer); - xor_buf(out, in, buffer, LEFT_SIZE); + xor_buf(buffer, out, key1, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); - xor_buf(buffer, out, key1, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/lion/lion.h b/src/block/lion/lion.h index 5bc4e72c0..d421771d6 100644 --- a/src/block/lion/lion.h +++ b/src/block/lion/lion.h @@ -20,6 +20,9 @@ namespace Botan { class BOTAN_DLL Lion : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const; BlockCipher* clone() const; @@ -27,8 +30,6 @@ class BOTAN_DLL Lion : public BlockCipher Lion(HashFunction*, StreamCipher*, u32bit); ~Lion() { delete hash; delete cipher; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); const u32bit LEFT_SIZE, RIGHT_SIZE; diff --git a/src/block/lubyrack/lubyrack.cpp b/src/block/lubyrack/lubyrack.cpp index a9d2b1db2..6ad64f2b0 100644 --- a/src/block/lubyrack/lubyrack.cpp +++ b/src/block/lubyrack/lubyrack.cpp @@ -13,59 +13,71 @@ namespace Botan { /* * Luby-Rackoff Encryption */ -void LubyRackoff::enc(const byte in[], byte out[]) const +void LubyRackoff::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - const u32bit len = hash->OUTPUT_LENGTH; - - SecureVector<byte> buffer(len); - hash->update(K1); - hash->update(in, len); - hash->final(buffer); - xor_buf(out + len, in + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, in, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, buffer, len); + for(u32bit i = 0; i != blocks; ++i) + { + const u32bit len = hash->OUTPUT_LENGTH; + + SecureVector<byte> buffer(len); + hash->update(K1); + hash->update(in, len); + hash->final(buffer); + xor_buf(out + len, in + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, in, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, buffer, len); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Luby-Rackoff Decryption */ -void LubyRackoff::dec(const byte in[], byte out[]) const +void LubyRackoff::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - const u32bit len = hash->OUTPUT_LENGTH; - - SecureVector<byte> buffer(len); - hash->update(K2); - hash->update(in + len, len); - hash->final(buffer); - xor_buf(out, in, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, in + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, buffer, len); + for(u32bit i = 0; i != blocks; ++i) + { + const u32bit len = hash->OUTPUT_LENGTH; + + SecureVector<byte> buffer(len); + hash->update(K2); + hash->update(in + len, len); + hash->final(buffer); + xor_buf(out, in, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, in + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, buffer, len); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/lubyrack/lubyrack.h b/src/block/lubyrack/lubyrack.h index ebde31304..940b34603 100644 --- a/src/block/lubyrack/lubyrack.h +++ b/src/block/lubyrack/lubyrack.h @@ -19,6 +19,9 @@ namespace Botan { class BOTAN_DLL LubyRackoff : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const; BlockCipher* clone() const; @@ -26,9 +29,8 @@ class BOTAN_DLL LubyRackoff : public BlockCipher LubyRackoff(HashFunction* hash); ~LubyRackoff() { delete hash; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); + HashFunction* hash; SecureVector<byte> K1, K2; }; diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp index 08c8409c5..69556acb3 100644 --- a/src/block/mars/mars.cpp +++ b/src/block/mars/mars.cpp @@ -1,6 +1,6 @@ /* * MARS -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -50,75 +50,87 @@ u32bit gen_mask(u32bit input) /* * MARS Encryption */ -void MARS::enc(const byte in[], byte out[]) const +void MARS::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) + EK[0]; - u32bit B = load_le<u32bit>(in, 1) + EK[1]; - u32bit C = load_le<u32bit>(in, 2) + EK[2]; - u32bit D = load_le<u32bit>(in, 3) + EK[3]; - - forward_mix(A, B, C, D); - - encrypt_round(A, B, C, D, 0); - encrypt_round(B, C, D, A, 1); - encrypt_round(C, D, A, B, 2); - encrypt_round(D, A, B, C, 3); - encrypt_round(A, B, C, D, 4); - encrypt_round(B, C, D, A, 5); - encrypt_round(C, D, A, B, 6); - encrypt_round(D, A, B, C, 7); - - encrypt_round(A, D, C, B, 8); - encrypt_round(B, A, D, C, 9); - encrypt_round(C, B, A, D, 10); - encrypt_round(D, C, B, A, 11); - encrypt_round(A, D, C, B, 12); - encrypt_round(B, A, D, C, 13); - encrypt_round(C, B, A, D, 14); - encrypt_round(D, C, B, A, 15); - - reverse_mix(A, B, C, D); - - A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39]; - - store_le(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0) + EK[0]; + u32bit B = load_le<u32bit>(in, 1) + EK[1]; + u32bit C = load_le<u32bit>(in, 2) + EK[2]; + u32bit D = load_le<u32bit>(in, 3) + EK[3]; + + forward_mix(A, B, C, D); + + encrypt_round(A, B, C, D, 0); + encrypt_round(B, C, D, A, 1); + encrypt_round(C, D, A, B, 2); + encrypt_round(D, A, B, C, 3); + encrypt_round(A, B, C, D, 4); + encrypt_round(B, C, D, A, 5); + encrypt_round(C, D, A, B, 6); + encrypt_round(D, A, B, C, 7); + + encrypt_round(A, D, C, B, 8); + encrypt_round(B, A, D, C, 9); + encrypt_round(C, B, A, D, 10); + encrypt_round(D, C, B, A, 11); + encrypt_round(A, D, C, B, 12); + encrypt_round(B, A, D, C, 13); + encrypt_round(C, B, A, D, 14); + encrypt_round(D, C, B, A, 15); + + reverse_mix(A, B, C, D); + + A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * MARS Decryption */ -void MARS::dec(const byte in[], byte out[]) const +void MARS::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 3) + EK[39]; - u32bit B = load_le<u32bit>(in, 2) + EK[38]; - u32bit C = load_le<u32bit>(in, 1) + EK[37]; - u32bit D = load_le<u32bit>(in, 0) + EK[36]; - - forward_mix(A, B, C, D); - - decrypt_round(A, B, C, D, 15); - decrypt_round(B, C, D, A, 14); - decrypt_round(C, D, A, B, 13); - decrypt_round(D, A, B, C, 12); - decrypt_round(A, B, C, D, 11); - decrypt_round(B, C, D, A, 10); - decrypt_round(C, D, A, B, 9); - decrypt_round(D, A, B, C, 8); - - decrypt_round(A, D, C, B, 7); - decrypt_round(B, A, D, C, 6); - decrypt_round(C, B, A, D, 5); - decrypt_round(D, C, B, A, 4); - decrypt_round(A, D, C, B, 3); - decrypt_round(B, A, D, C, 2); - decrypt_round(C, B, A, D, 1); - decrypt_round(D, C, B, A, 0); - - reverse_mix(A, B, C, D); - - A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0]; - - store_le(out, D, C, B, A); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 3) + EK[39]; + u32bit B = load_le<u32bit>(in, 2) + EK[38]; + u32bit C = load_le<u32bit>(in, 1) + EK[37]; + u32bit D = load_le<u32bit>(in, 0) + EK[36]; + + forward_mix(A, B, C, D); + + decrypt_round(A, B, C, D, 15); + decrypt_round(B, C, D, A, 14); + decrypt_round(C, D, A, B, 13); + decrypt_round(D, A, B, C, 12); + decrypt_round(A, B, C, D, 11); + decrypt_round(B, C, D, A, 10); + decrypt_round(C, D, A, B, 9); + decrypt_round(D, A, B, C, 8); + + decrypt_round(A, D, C, B, 7); + decrypt_round(B, A, D, C, 6); + decrypt_round(C, B, A, D, 5); + decrypt_round(D, C, B, A, 4); + decrypt_round(A, D, C, B, 3); + decrypt_round(B, A, D, C, 2); + decrypt_round(C, B, A, D, 1); + decrypt_round(D, C, B, A, 0); + + reverse_mix(A, B, C, D); + + A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0]; + + store_le(out, D, C, B, A); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/mars/mars.h b/src/block/mars/mars.h index ca49695af..7d0bfe4fa 100644 --- a/src/block/mars/mars.h +++ b/src/block/mars/mars.h @@ -15,13 +15,15 @@ namespace Botan { class BOTAN_DLL MARS : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "MARS"; } BlockCipher* clone() const { return new MARS; } + MARS() : BlockCipher(16, 16, 32, 4) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void encrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const; diff --git a/src/block/misty1/misty1.cpp b/src/block/misty1/misty1.cpp index a35ff584d..8a92824cc 100644 --- a/src/block/misty1/misty1.cpp +++ b/src/block/misty1/misty1.cpp @@ -1,6 +1,6 @@ /* * MISTY1 -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -102,89 +102,101 @@ u16bit FI(u16bit input, u16bit key7, u16bit key9) /* * MISTY1 Encryption */ -void MISTY1::enc(const byte in[], byte out[]) const +void MISTY1::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 12; j += 3) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* RK = EK + 8 * j; + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - B1 ^= B0 & RK[0]; - B0 ^= B1 | RK[1]; - B3 ^= B2 & RK[2]; - B2 ^= B3 | RK[3]; + for(u32bit j = 0; j != 12; j += 3) + { + const u16bit* RK = EK + 8 * j; - u32bit T0, T1; + B1 ^= B0 & RK[0]; + B0 ^= B1 | RK[1]; + B3 ^= B2 & RK[2]; + B2 ^= B3 | RK[3]; - T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; - T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; - T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; + u32bit T0, T1; - B2 ^= T1 ^ RK[13]; - B3 ^= T0; + T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; + T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; + T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; - T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; - T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; - T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + B2 ^= T1 ^ RK[13]; + B3 ^= T0; - B0 ^= T1 ^ RK[23]; - B1 ^= T0; - } + T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; + T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; + T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + + B0 ^= T1 ^ RK[23]; + B1 ^= T0; + } - B1 ^= B0 & EK[96]; - B0 ^= B1 | EK[97]; - B3 ^= B2 & EK[98]; - B2 ^= B3 | EK[99]; + B1 ^= B0 & EK[96]; + B0 ^= B1 | EK[97]; + B3 ^= B2 & EK[98]; + B2 ^= B3 | EK[99]; - store_be(out, B2, B3, B0, B1); + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * MISTY1 Decryption */ -void MISTY1::dec(const byte in[], byte out[]) const +void MISTY1::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 2); - u16bit B1 = load_be<u16bit>(in, 3); - u16bit B2 = load_be<u16bit>(in, 0); - u16bit B3 = load_be<u16bit>(in, 1); - - for(u32bit j = 0; j != 12; j += 3) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* RK = DK + 8 * j; + u16bit B0 = load_be<u16bit>(in, 2); + u16bit B1 = load_be<u16bit>(in, 3); + u16bit B2 = load_be<u16bit>(in, 0); + u16bit B3 = load_be<u16bit>(in, 1); - B2 ^= B3 | RK[0]; - B3 ^= B2 & RK[1]; - B0 ^= B1 | RK[2]; - B1 ^= B0 & RK[3]; + for(u32bit j = 0; j != 12; j += 3) + { + const u16bit* RK = DK + 8 * j; - u32bit T0, T1; + B2 ^= B3 | RK[0]; + B3 ^= B2 & RK[1]; + B0 ^= B1 | RK[2]; + B1 ^= B0 & RK[3]; - T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; - T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; - T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; + u32bit T0, T1; - B0 ^= T1 ^ RK[13]; - B1 ^= T0; + T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; + T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; + T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; - T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; - T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; - T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + B0 ^= T1 ^ RK[13]; + B1 ^= T0; - B2 ^= T1 ^ RK[23]; - B3 ^= T0; - } + T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; + T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; + T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + + B2 ^= T1 ^ RK[23]; + B3 ^= T0; + } - B2 ^= B3 | DK[96]; - B3 ^= B2 & DK[97]; - B0 ^= B1 | DK[98]; - B1 ^= B0 & DK[99]; + B2 ^= B3 | DK[96]; + B3 ^= B2 & DK[97]; + B0 ^= B1 | DK[98]; + B1 ^= B0 & DK[99]; - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/misty1/misty1.h b/src/block/misty1/misty1.h index 62d4f856f..8db6881de 100644 --- a/src/block/misty1/misty1.h +++ b/src/block/misty1/misty1.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL MISTY1 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); DK.clear(); } std::string name() const { return "MISTY1"; } BlockCipher* clone() const { return new MISTY1; } + MISTY1(u32bit = 8); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 100> EK, DK; diff --git a/src/block/noekeon/noekeon.cpp b/src/block/noekeon/noekeon.cpp index 90eb9ad2b..1b327aa47 100644 --- a/src/block/noekeon/noekeon.cpp +++ b/src/block/noekeon/noekeon.cpp @@ -84,65 +84,77 @@ const byte Noekeon::RC[] = { /* * Noekeon Encryption */ -void Noekeon::enc(const byte in[], byte out[]) const +void Noekeon::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A0 = load_be<u32bit>(in, 0); - u32bit A1 = load_be<u32bit>(in, 1); - u32bit A2 = load_be<u32bit>(in, 2); - u32bit A3 = load_be<u32bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - A0 ^= RC[j]; - theta(A0, A1, A2, A3, EK); + u32bit A0 = load_be<u32bit>(in, 0); + u32bit A1 = load_be<u32bit>(in, 1); + u32bit A2 = load_be<u32bit>(in, 2); + u32bit A3 = load_be<u32bit>(in, 3); - A1 = rotate_left(A1, 1); - A2 = rotate_left(A2, 5); - A3 = rotate_left(A3, 2); + for(u32bit j = 0; j != 16; ++j) + { + A0 ^= RC[j]; + theta(A0, A1, A2, A3, EK); - gamma(A0, A1, A2, A3); + A1 = rotate_left(A1, 1); + A2 = rotate_left(A2, 5); + A3 = rotate_left(A3, 2); - A1 = rotate_right(A1, 1); - A2 = rotate_right(A2, 5); - A3 = rotate_right(A3, 2); - } + gamma(A0, A1, A2, A3); - A0 ^= RC[16]; - theta(A0, A1, A2, A3, EK); + A1 = rotate_right(A1, 1); + A2 = rotate_right(A2, 5); + A3 = rotate_right(A3, 2); + } + + A0 ^= RC[16]; + theta(A0, A1, A2, A3, EK); + + store_be(out, A0, A1, A2, A3); - store_be(out, A0, A1, A2, A3); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Noekeon Encryption */ -void Noekeon::dec(const byte in[], byte out[]) const +void Noekeon::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A0 = load_be<u32bit>(in, 0); - u32bit A1 = load_be<u32bit>(in, 1); - u32bit A2 = load_be<u32bit>(in, 2); - u32bit A3 = load_be<u32bit>(in, 3); - - for(u32bit j = 16; j != 0; --j) + for(u32bit i = 0; i != blocks; ++i) { - theta(A0, A1, A2, A3, DK); - A0 ^= RC[j]; + u32bit A0 = load_be<u32bit>(in, 0); + u32bit A1 = load_be<u32bit>(in, 1); + u32bit A2 = load_be<u32bit>(in, 2); + u32bit A3 = load_be<u32bit>(in, 3); - A1 = rotate_left(A1, 1); - A2 = rotate_left(A2, 5); - A3 = rotate_left(A3, 2); + for(u32bit j = 16; j != 0; --j) + { + theta(A0, A1, A2, A3, DK); + A0 ^= RC[j]; - gamma(A0, A1, A2, A3); + A1 = rotate_left(A1, 1); + A2 = rotate_left(A2, 5); + A3 = rotate_left(A3, 2); - A1 = rotate_right(A1, 1); - A2 = rotate_right(A2, 5); - A3 = rotate_right(A3, 2); - } + gamma(A0, A1, A2, A3); - theta(A0, A1, A2, A3, DK); - A0 ^= RC[0]; + A1 = rotate_right(A1, 1); + A2 = rotate_right(A2, 5); + A3 = rotate_right(A3, 2); + } - store_be(out, A0, A1, A2, A3); + theta(A0, A1, A2, A3, DK); + A0 ^= RC[0]; + + store_be(out, A0, A1, A2, A3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h index 893892446..37b24fb7d 100644 --- a/src/block/noekeon/noekeon.h +++ b/src/block/noekeon/noekeon.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Noekeon : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Noekeon"; } BlockCipher* clone() const { return new Noekeon; } + Noekeon() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const byte RC[17]; diff --git a/src/block/rc2/rc2.cpp b/src/block/rc2/rc2.cpp index 5827bdb68..b5e4a7d50 100644 --- a/src/block/rc2/rc2.cpp +++ b/src/block/rc2/rc2.cpp @@ -14,73 +14,85 @@ namespace Botan { /* * RC2 Encryption */ -void RC2::enc(const byte in[], byte out[]) const +void RC2::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; - R0 = rotate_left(R0, 1); + u16bit R0 = load_le<u16bit>(in, 0); + u16bit R1 = load_le<u16bit>(in, 1); + u16bit R2 = load_le<u16bit>(in, 2); + u16bit R3 = load_le<u16bit>(in, 3); + + for(u32bit j = 0; j != 16; ++j) + { + R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; + R0 = rotate_left(R0, 1); - R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; - R1 = rotate_left(R1, 2); + R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; + R1 = rotate_left(R1, 2); - R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; - R2 = rotate_left(R2, 3); + R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; + R2 = rotate_left(R2, 3); - R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; - R3 = rotate_left(R3, 5); + R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; + R3 = rotate_left(R3, 5); - if(j == 4 || j == 10) - { - R0 += K[R3 % 64]; - R1 += K[R0 % 64]; - R2 += K[R1 % 64]; - R3 += K[R2 % 64]; + if(j == 4 || j == 10) + { + R0 += K[R3 % 64]; + R1 += K[R0 % 64]; + R2 += K[R1 % 64]; + R3 += K[R2 % 64]; + } } - } - store_le(out, R0, R1, R2, R3); + store_le(out, R0, R1, R2, R3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC2 Decryption */ -void RC2::dec(const byte in[], byte out[]) const +void RC2::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R3 = rotate_right(R3, 5); - R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; + u16bit R0 = load_le<u16bit>(in, 0); + u16bit R1 = load_le<u16bit>(in, 1); + u16bit R2 = load_le<u16bit>(in, 2); + u16bit R3 = load_le<u16bit>(in, 3); + + for(u32bit j = 0; j != 16; ++j) + { + R3 = rotate_right(R3, 5); + R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; - R2 = rotate_right(R2, 3); - R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; + R2 = rotate_right(R2, 3); + R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; - R1 = rotate_right(R1, 2); - R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; + R1 = rotate_right(R1, 2); + R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; - R0 = rotate_right(R0, 1); - R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; + R0 = rotate_right(R0, 1); + R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; - if(j == 4 || j == 10) - { - R3 -= K[R2 % 64]; - R2 -= K[R1 % 64]; - R1 -= K[R0 % 64]; - R0 -= K[R3 % 64]; + if(j == 4 || j == 10) + { + R3 -= K[R2 % 64]; + R2 -= K[R1 % 64]; + R1 -= K[R0 % 64]; + R0 -= K[R3 % 64]; + } } - } - store_le(out, R0, R1, R2, R3); + store_le(out, R0, R1, R2, R3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc2/rc2.h b/src/block/rc2/rc2.h index cb6f58f04..db623b385 100644 --- a/src/block/rc2/rc2.h +++ b/src/block/rc2/rc2.h @@ -18,15 +18,17 @@ namespace Botan { class BOTAN_DLL RC2 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + static byte EKB_code(u32bit); void clear() throw() { K.clear(); } std::string name() const { return "RC2"; } BlockCipher* clone() const { return new RC2; } + RC2() : BlockCipher(8, 1, 32) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 64> K; diff --git a/src/block/rc5/rc5.cpp b/src/block/rc5/rc5.cpp index 5d83d5a4e..4bfa27ea0 100644 --- a/src/block/rc5/rc5.cpp +++ b/src/block/rc5/rc5.cpp @@ -16,47 +16,59 @@ namespace Botan { /* * RC5 Encryption */ -void RC5::enc(const byte in[], byte out[]) const +void RC5::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); - - A += S[0]; B += S[1]; - for(u32bit j = 0; j != ROUNDS; j += 4) + for(u32bit i = 0; i != blocks; ++i) { - A = rotate_left(A ^ B, B % 32) + S[2*j+2]; - B = rotate_left(B ^ A, A % 32) + S[2*j+3]; - A = rotate_left(A ^ B, B % 32) + S[2*j+4]; - B = rotate_left(B ^ A, A % 32) + S[2*j+5]; - A = rotate_left(A ^ B, B % 32) + S[2*j+6]; - B = rotate_left(B ^ A, A % 32) + S[2*j+7]; - A = rotate_left(A ^ B, B % 32) + S[2*j+8]; - B = rotate_left(B ^ A, A % 32) + S[2*j+9]; - } + u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); + + A += S[0]; B += S[1]; + for(u32bit j = 0; j != ROUNDS; j += 4) + { + A = rotate_left(A ^ B, B % 32) + S[2*j+2]; + B = rotate_left(B ^ A, A % 32) + S[2*j+3]; + A = rotate_left(A ^ B, B % 32) + S[2*j+4]; + B = rotate_left(B ^ A, A % 32) + S[2*j+5]; + A = rotate_left(A ^ B, B % 32) + S[2*j+6]; + B = rotate_left(B ^ A, A % 32) + S[2*j+7]; + A = rotate_left(A ^ B, B % 32) + S[2*j+8]; + B = rotate_left(B ^ A, A % 32) + S[2*j+9]; + } - store_le(out, A, B); + store_le(out, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC5 Decryption */ -void RC5::dec(const byte in[], byte out[]) const +void RC5::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); - - for(u32bit j = ROUNDS; j != 0; j -= 4) + for(u32bit i = 0; i != blocks; ++i) { - B = rotate_right(B - S[2*j+1], A % 32) ^ A; - A = rotate_right(A - S[2*j ], B % 32) ^ B; - B = rotate_right(B - S[2*j-1], A % 32) ^ A; - A = rotate_right(A - S[2*j-2], B % 32) ^ B; - B = rotate_right(B - S[2*j-3], A % 32) ^ A; - A = rotate_right(A - S[2*j-4], B % 32) ^ B; - B = rotate_right(B - S[2*j-5], A % 32) ^ A; - A = rotate_right(A - S[2*j-6], B % 32) ^ B; - } - B -= S[1]; A -= S[0]; + u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); + + for(u32bit j = ROUNDS; j != 0; j -= 4) + { + B = rotate_right(B - S[2*j+1], A % 32) ^ A; + A = rotate_right(A - S[2*j ], B % 32) ^ B; + B = rotate_right(B - S[2*j-1], A % 32) ^ A; + A = rotate_right(A - S[2*j-2], B % 32) ^ B; + B = rotate_right(B - S[2*j-3], A % 32) ^ A; + A = rotate_right(A - S[2*j-4], B % 32) ^ B; + B = rotate_right(B - S[2*j-5], A % 32) ^ A; + A = rotate_right(A - S[2*j-6], B % 32) ^ B; + } + B -= S[1]; A -= S[0]; - store_le(out, A, B); + store_le(out, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc5/rc5.h b/src/block/rc5/rc5.h index 083224720..ff9204710 100644 --- a/src/block/rc5/rc5.h +++ b/src/block/rc5/rc5.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL RC5 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { S.clear(); } std::string name() const; BlockCipher* clone() const { return new RC5(ROUNDS); } + RC5(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureVector<u32bit> S; const u32bit ROUNDS; diff --git a/src/block/rc6/rc6.cpp b/src/block/rc6/rc6.cpp index 3b30ea93a..8bda62259 100644 --- a/src/block/rc6/rc6.cpp +++ b/src/block/rc6/rc6.cpp @@ -15,85 +15,97 @@ namespace Botan { /* * RC6 Encryption */ -void RC6::enc(const byte in[], byte out[]) const +void RC6::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0); + u32bit B = load_le<u32bit>(in, 1); + u32bit C = load_le<u32bit>(in, 2); + u32bit D = load_le<u32bit>(in, 3); - B += S[0]; D += S[1]; + B += S[0]; D += S[1]; - for(u32bit j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; - C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; - D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; - A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; - B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; - } + for(u32bit j = 0; j != 20; j += 4) + { + u32bit T1, T2; + + T1 = rotate_left(B*(2*B+1), 5); + T2 = rotate_left(D*(2*D+1), 5); + A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; + C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; + + T1 = rotate_left(C*(2*C+1), 5); + T2 = rotate_left(A*(2*A+1), 5); + B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; + D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; - A += S[42]; C += S[43]; + T1 = rotate_left(D*(2*D+1), 5); + T2 = rotate_left(B*(2*B+1), 5); + C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; + A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; - store_le(out, A, B, C, D); + T1 = rotate_left(A*(2*A+1), 5); + T2 = rotate_left(C*(2*C+1), 5); + D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; + B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; + } + + A += S[42]; C += S[43]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC6 Decryption */ -void RC6::dec(const byte in[], byte out[]) const +void RC6::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0); + u32bit B = load_le<u32bit>(in, 1); + u32bit C = load_le<u32bit>(in, 2); + u32bit D = load_le<u32bit>(in, 3); - C -= S[43]; A -= S[42]; + C -= S[43]; A -= S[42]; - for(u32bit j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; - D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; - C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; - B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; - A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; - } + for(u32bit j = 0; j != 20; j += 4) + { + u32bit T1, T2; + + T1 = rotate_left(A*(2*A+1), 5); + T2 = rotate_left(C*(2*C+1), 5); + B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; + D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; + + T1 = rotate_left(D*(2*D+1), 5); + T2 = rotate_left(B*(2*B+1), 5); + A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; + C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; - D -= S[1]; B -= S[0]; + T1 = rotate_left(C*(2*C+1), 5); + T2 = rotate_left(A*(2*A+1), 5); + D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; + B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; - store_le(out, A, B, C, D); + T1 = rotate_left(B*(2*B+1), 5); + T2 = rotate_left(D*(2*D+1), 5); + C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; + A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; + } + + D -= S[1]; B -= S[0]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc6/rc6.h b/src/block/rc6/rc6.h index cb2800be7..5171006f5 100644 --- a/src/block/rc6/rc6.h +++ b/src/block/rc6/rc6.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL RC6 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { S.clear(); } std::string name() const { return "RC6"; } BlockCipher* clone() const { return new RC6; } + RC6() : BlockCipher(16, 1, 32) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 44> S; diff --git a/src/block/safer/safer_sk.cpp b/src/block/safer/safer_sk.cpp index f72c4773b..eb5c22fc9 100644 --- a/src/block/safer/safer_sk.cpp +++ b/src/block/safer/safer_sk.cpp @@ -1,6 +1,6 @@ /* * SAFER-SK -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -15,54 +15,75 @@ namespace Botan { /* * SAFER-SK Encryption */ -void SAFER_SK::enc(const byte in[], byte out[]) const +void SAFER_SK::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7], X, Y; - for(u32bit j = 0; j != 16*ROUNDS; j += 16) + for(u32bit i = 0; i != blocks; ++i) { - A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]]; - C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]]; - E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]]; - G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]]; - A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11]; - E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15]; - B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; - C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; - H += D; Y = D + H; D = B + F; X = B + D; B = A + E; - A += B; F = C + G; E = C + F; C = X; G = Y; + byte A = in[0], B = in[1], C = in[2], D = in[3], + E = in[4], F = in[5], G = in[6], H = in[7], X, Y; + + for(u32bit j = 0; j != 16*ROUNDS; j += 16) + { + A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]]; + C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]]; + E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]]; + G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]]; + + A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11]; + E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15]; + + B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; + C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; + H += D; Y = D + H; D = B + F; X = B + D; B = A + E; + A += B; F = C + G; E = C + F; C = X; G = Y; + } + + out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1]; + out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3]; + out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5]; + out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1]; - out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3]; - out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5]; - out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7]; } /* * SAFER-SK Decryption */ -void SAFER_SK::dec(const byte in[], byte out[]) const +void SAFER_SK::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7]; - A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2]; - D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5]; - G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7]; - for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16) + for(u32bit i = 0; i != blocks; ++i) { - byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; - A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; - A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; - A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; - A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]]; - C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256]; - E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]]; - G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256]; - A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3]; - E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7]; + byte A = in[0], B = in[1], C = in[2], D = in[3], + E = in[4], F = in[5], G = in[6], H = in[7]; + + A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2]; + D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5]; + G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7]; + + for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16) + { + byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; + A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; + A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; + A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; + + A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]]; + C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256]; + E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]]; + G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256]; + + A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3]; + E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7]; + } + + out[0] = A; out[1] = B; out[2] = C; out[3] = D; + out[4] = E; out[5] = F; out[6] = G; out[7] = H; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[0] = A; out[1] = B; out[2] = C; out[3] = D; - out[4] = E; out[5] = F; out[6] = G; out[7] = H; } /* diff --git a/src/block/safer/safer_sk.h b/src/block/safer/safer_sk.h index e52c5837c..4d17bba51 100644 --- a/src/block/safer/safer_sk.h +++ b/src/block/safer/safer_sk.h @@ -18,19 +18,22 @@ namespace Botan { class BOTAN_DLL SAFER_SK : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const; BlockCipher* clone() const; + SAFER_SK(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const byte EXP[256]; static const byte LOG[512]; static const byte BIAS[208]; static const byte KEY_INDEX[208]; + SecureVector<byte> EK; const u32bit ROUNDS; }; diff --git a/src/block/seed/seed.cpp b/src/block/seed/seed.cpp index b06a7cd77..378be16e4 100644 --- a/src/block/seed/seed.cpp +++ b/src/block/seed/seed.cpp @@ -22,69 +22,81 @@ u32bit SEED::G_FUNC::operator()(u32bit X) const /* * SEED Encryption */ -void SEED::enc(const byte in[], byte out[]) const +void SEED::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_be<u32bit>(in, 0); - u32bit B1 = load_be<u32bit>(in, 1); - u32bit B2 = load_be<u32bit>(in, 2); - u32bit B3 = load_be<u32bit>(in, 3); - - G_FUNC G; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit T0, T1; - - T0 = B2 ^ K[2*j]; - T1 = G(B2 ^ B3 ^ K[2*j+1]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B1 ^= T1; - B0 ^= T0 + T1; - - T0 = B0 ^ K[2*j+2]; - T1 = G(B0 ^ B1 ^ K[2*j+3]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B3 ^= T1; - B2 ^= T0 + T1; + u32bit B0 = load_be<u32bit>(in, 0); + u32bit B1 = load_be<u32bit>(in, 1); + u32bit B2 = load_be<u32bit>(in, 2); + u32bit B3 = load_be<u32bit>(in, 3); + + G_FUNC G; + + for(u32bit j = 0; j != 16; j += 2) + { + u32bit T0, T1; + + T0 = B2 ^ K[2*j]; + T1 = G(B2 ^ B3 ^ K[2*j+1]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B1 ^= T1; + B0 ^= T0 + T1; + + T0 = B0 ^ K[2*j+2]; + T1 = G(B0 ^ B1 ^ K[2*j+3]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B3 ^= T1; + B2 ^= T0 + T1; + } + + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - store_be(out, B2, B3, B0, B1); } /* * SEED Decryption */ -void SEED::dec(const byte in[], byte out[]) const +void SEED::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_be<u32bit>(in, 0); - u32bit B1 = load_be<u32bit>(in, 1); - u32bit B2 = load_be<u32bit>(in, 2); - u32bit B3 = load_be<u32bit>(in, 3); - - G_FUNC G; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit T0, T1; - - T0 = B2 ^ K[30-2*j]; - T1 = G(B2 ^ B3 ^ K[31-2*j]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B1 ^= T1; - B0 ^= T0 + T1; - - T0 = B0 ^ K[28-2*j]; - T1 = G(B0 ^ B1 ^ K[29-2*j]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B3 ^= T1; - B2 ^= T0 + T1; + u32bit B0 = load_be<u32bit>(in, 0); + u32bit B1 = load_be<u32bit>(in, 1); + u32bit B2 = load_be<u32bit>(in, 2); + u32bit B3 = load_be<u32bit>(in, 3); + + G_FUNC G; + + for(u32bit j = 0; j != 16; j += 2) + { + u32bit T0, T1; + + T0 = B2 ^ K[30-2*j]; + T1 = G(B2 ^ B3 ^ K[31-2*j]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B1 ^= T1; + B0 ^= T0 + T1; + + T0 = B0 ^ K[28-2*j]; + T1 = G(B0 ^ B1 ^ K[29-2*j]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B3 ^= T1; + B2 ^= T0 + T1; + } + + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - store_be(out, B2, B3, B0, B1); } /* diff --git a/src/block/seed/seed.h b/src/block/seed/seed.h index 54c25d580..5a5a512e7 100644 --- a/src/block/seed/seed.h +++ b/src/block/seed/seed.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL SEED : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { K.clear(); } std::string name() const { return "SEED"; } BlockCipher* clone() const { return new SEED; } + SEED() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); class G_FUNC diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp index df7592fea..2fa27308f 100644 --- a/src/block/serpent/serpent.cpp +++ b/src/block/serpent/serpent.cpp @@ -243,93 +243,105 @@ inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) /* * Serpent Encryption */ -void Serpent::enc(const byte in[], byte out[]) const +void Serpent::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_le<u32bit>(in, 0); - u32bit B1 = load_le<u32bit>(in, 1); - u32bit B2 = load_le<u32bit>(in, 2); - u32bit B3 = load_le<u32bit>(in, 3); - - key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); - - store_le(out, B0, B1, B2, B3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit B0 = load_le<u32bit>(in, 0); + u32bit B1 = load_le<u32bit>(in, 1); + u32bit B2 = load_le<u32bit>(in, 2); + u32bit B3 = load_le<u32bit>(in, 3); + + key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); + + store_le(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Serpent Decryption */ -void Serpent::dec(const byte in[], byte out[]) const +void Serpent::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_le<u32bit>(in, 0); - u32bit B1 = load_le<u32bit>(in, 1); - u32bit B2 = load_le<u32bit>(in, 2); - u32bit B3 = load_le<u32bit>(in, 3); - - key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); - - store_le(out, B0, B1, B2, B3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit B0 = load_le<u32bit>(in, 0); + u32bit B1 = load_le<u32bit>(in, 1); + u32bit B2 = load_le<u32bit>(in, 2); + u32bit B3 = load_le<u32bit>(in, 3); + + key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); + + store_le(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/serpent/serpent.h b/src/block/serpent/serpent.h index 5b9be257f..d919c3008 100644 --- a/src/block/serpent/serpent.h +++ b/src/block/serpent/serpent.h @@ -18,13 +18,14 @@ namespace Botan { class BOTAN_DLL Serpent : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "Serpent"; } BlockCipher* clone() const { return new Serpent; } Serpent() : BlockCipher(16, 16, 32, 8) {} protected: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 132> round_key; diff --git a/src/block/serpent_ia32/serp_ia32.cpp b/src/block/serpent_ia32/serp_ia32.cpp index 37dd4e637..997bec2fc 100644 --- a/src/block/serpent_ia32/serp_ia32.cpp +++ b/src/block/serpent_ia32/serp_ia32.cpp @@ -21,17 +21,27 @@ void botan_serpent_ia32_key_schedule(u32bit[140]); /* * Serpent Encryption */ -void Serpent_IA32::enc(const byte in[], byte out[]) const +void Serpent_IA32::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - botan_serpent_ia32_encrypt(in, out, round_key); + for(u32bit i = 0; i != blocks; ++i) + { + botan_serpent_ia32_encrypt(in, out, round_key); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Serpent Decryption */ -void Serpent_IA32::dec(const byte in[], byte out[]) const +void Serpent_IA32::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - botan_serpent_ia32_decrypt(in, out, round_key); + for(u32bit i = 0; i != blocks; ++i) + { + botan_serpent_ia32_decrypt(in, out, round_key); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/serpent_ia32/serp_ia32.h b/src/block/serpent_ia32/serp_ia32.h index 565e9889d..dc6beaf13 100644 --- a/src/block/serpent_ia32/serp_ia32.h +++ b/src/block/serpent_ia32/serp_ia32.h @@ -18,10 +18,11 @@ namespace Botan { class BOTAN_DLL Serpent_IA32 : public Serpent { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + BlockCipher* clone() const { return new Serpent_IA32; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); }; diff --git a/src/block/serpent_sse2/info.txt b/src/block/serpent_sse2/info.txt new file mode 100644 index 000000000..b00ab6e88 --- /dev/null +++ b/src/block/serpent_sse2/info.txt @@ -0,0 +1,16 @@ +realname "Serpent (SSE2)" + +define SERPENT_SSE2 + +load_on auto + +<add> +serp_sse2.cpp +serp_sse2.h +serp_sse2_sbox.h +</add> + +<requires> +serpent +sse2_eng +</requires> diff --git a/src/block/serpent_sse2/serp_sse2.cpp b/src/block/serpent_sse2/serp_sse2.cpp new file mode 100644 index 000000000..c51bb69ab --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2.cpp @@ -0,0 +1,240 @@ +/* +* Serpent (SSE2) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/serp_sse2.h> +#include <botan/serp_sse2_sbox.h> +#include <botan/loadstor.h> +#include <emmintrin.h> + +namespace Botan { + +namespace { + +#define key_xor(round, B0, B1, B2, B3) \ + do { \ + __m128i key = _mm_loadu_si128(keys + round); \ + B0 = _mm_xor_si128(B0, _mm_shuffle_epi32(key, _MM_SHUFFLE(0,0,0,0))); \ + B1 = _mm_xor_si128(B1, _mm_shuffle_epi32(key, _MM_SHUFFLE(1,1,1,1))); \ + B2 = _mm_xor_si128(B2, _mm_shuffle_epi32(key, _MM_SHUFFLE(2,2,2,2))); \ + B3 = _mm_xor_si128(B3, _mm_shuffle_epi32(key, _MM_SHUFFLE(3,3,3,3))); \ + } while(0); + +/* +* Serpent's linear transformations +*/ +#define rotate_left_m128(vec, rot) \ + _mm_or_si128(_mm_slli_epi32(vec, rot), _mm_srli_epi32(vec, 32-rot)) + +#define rotate_right_m128(vec, rot) \ + _mm_or_si128(_mm_srli_epi32(vec, rot), _mm_slli_epi32(vec, 32-rot)) + +#define transform(B0, B1, B2, B3) \ + do { \ + B0 = rotate_left_m128(B0, 13); \ + B2 = rotate_left_m128(B2, 3); \ + B1 = _mm_xor_si128(B1, _mm_xor_si128(B0, B2)); \ + B3 = _mm_xor_si128(B3, _mm_xor_si128(B2, _mm_slli_epi32(B0, 3))); \ + B1 = rotate_left_m128(B1, 1); \ + B3 = rotate_left_m128(B3, 7); \ + B0 = _mm_xor_si128(B0, _mm_xor_si128(B1, B3)); \ + B2 = _mm_xor_si128(B2, _mm_xor_si128(B3, _mm_slli_epi32(B1, 7))); \ + B0 = rotate_left_m128(B0, 5); \ + B2 = rotate_left_m128(B2, 22); \ + } while(0); + +#define i_transform(B0, B1, B2, B3) \ + do { \ + B2 = rotate_right_m128(B2, 22); \ + B0 = rotate_right_m128(B0, 5); \ + B2 = _mm_xor_si128(B2, _mm_xor_si128(B3, _mm_slli_epi32(B1, 7))); \ + B0 = _mm_xor_si128(B0, _mm_xor_si128(B1, B3)); \ + B3 = rotate_right_m128(B3, 7); \ + B1 = rotate_right_m128(B1, 1); \ + B3 = _mm_xor_si128(B3, _mm_xor_si128(B2, _mm_slli_epi32(B0, 3))); \ + B1 = _mm_xor_si128(B1, _mm_xor_si128(B0, B2)); \ + B2 = rotate_right_m128(B2, 3); \ + B0 = rotate_right_m128(B0, 13); \ + } while(0); + +/* +* 4x4 SSE2 integer matrix transpose +*/ +#define transpose(B0, B1, B2, B3) \ + do { \ + __m128i T0 = _mm_unpacklo_epi32(B0, B1); \ + __m128i T1 = _mm_unpacklo_epi32(B2, B3); \ + __m128i T2 = _mm_unpackhi_epi32(B0, B1); \ + __m128i T3 = _mm_unpackhi_epi32(B2, B3); \ + B0 = _mm_unpacklo_epi64(T0, T1); \ + B1 = _mm_unpackhi_epi64(T0, T1); \ + B2 = _mm_unpacklo_epi64(T2, T3); \ + B3 = _mm_unpackhi_epi64(T2, T3); \ + } while(0); + +/* +* SSE2 Serpent Encryption of 4 blocks in parallel +*/ +void serpent_encrypt_4(const byte in[64], + byte out[64], + const u32bit keys_32[132]) + { + const __m128i all_ones = _mm_set1_epi8(0xFF); + + const __m128i* keys = (const __m128i*)(keys_32); + __m128i* out_mm = (__m128i*)(out); + __m128i* in_mm = (__m128i*)(in); + + __m128i B0 = _mm_loadu_si128(in_mm); + __m128i B1 = _mm_loadu_si128(in_mm + 1); + __m128i B2 = _mm_loadu_si128(in_mm + 2); + __m128i B3 = _mm_loadu_si128(in_mm + 3); + + transpose(B0, B1, B2, B3); + + key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); + + transpose(B0, B1, B2, B3); + + _mm_storeu_si128(out_mm , B0); + _mm_storeu_si128(out_mm + 1, B1); + _mm_storeu_si128(out_mm + 2, B2); + _mm_storeu_si128(out_mm + 3, B3); + } + +/* +* SSE2 Serpent Decryption of 4 blocks in parallel +*/ +void serpent_decrypt_4(const byte in[64], + byte out[64], + const u32bit keys_32[132]) + { + const __m128i all_ones = _mm_set1_epi8(0xFF); + + const __m128i* keys = (const __m128i*)(keys_32); + __m128i* out_mm = (__m128i*)(out); + __m128i* in_mm = (__m128i*)(in); + + __m128i B0 = _mm_loadu_si128(in_mm); + __m128i B1 = _mm_loadu_si128(in_mm + 1); + __m128i B2 = _mm_loadu_si128(in_mm + 2); + __m128i B3 = _mm_loadu_si128(in_mm + 3); + + transpose(B0, B1, B2, B3); + + key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); + + transpose(B0, B1, B2, B3); + + _mm_storeu_si128(out_mm , B0); + _mm_storeu_si128(out_mm + 1, B1); + _mm_storeu_si128(out_mm + 2, B2); + _mm_storeu_si128(out_mm + 3, B3); + } + +} + +/* +* Serpent Encryption +*/ +void Serpent_SSE2::encrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 4) + { + serpent_encrypt_4(in, out, this->round_key); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + + Serpent::encrypt_n(in, out, blocks); + } + +/* +* Serpent Decryption +*/ +void Serpent_SSE2::decrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 4) + { + serpent_decrypt_4(in, out, this->round_key); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + + Serpent::decrypt_n(in, out, blocks); + } + +} diff --git a/src/block/serpent_sse2/serp_sse2.h b/src/block/serpent_sse2/serp_sse2.h new file mode 100644 index 000000000..f1e5c2028 --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2.h @@ -0,0 +1,29 @@ +/* +* Serpent (SSE2) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_SERPENT_SSE2_H__ +#define BOTAN_SERPENT_SSE2_H__ + +#include <botan/serpent.h> + +namespace Botan { + +/* +* Serpent +*/ +class BOTAN_DLL Serpent_SSE2 : public Serpent + { + public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + BlockCipher* clone() const { return new Serpent_SSE2; } + }; + +} + +#endif diff --git a/src/block/serpent_sse2/serp_sse2_sbox.h b/src/block/serpent_sse2/serp_sse2_sbox.h new file mode 100644 index 000000000..40c552e87 --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2_sbox.h @@ -0,0 +1,434 @@ +/* +* Serpent Sboxes in SSE2 form +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef SERPENT_SSE2_SBOXES_H__ +#define SERPENT_SSE2_SBOXES_H__ + +#define SBoxE1(B0, B1, B2, B3) \ + do { \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B1); \ + B2 = _mm_xor_si128(B2, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B4 = _mm_or_si128(B4, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B3 = _mm_or_si128(B3, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = B0; \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE2(B0, B1, B2, B3) \ + do { \ + B0 = _mm_xor_si128(B0, all_ones); \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B0; \ + B0 = _mm_and_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_or_si128(B4, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B2 = _mm_or_si128(B2, B0); \ + B2 = _mm_and_si128(B2, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_and_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = B2; \ + B2 = B3; \ + B3 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE3(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B0; \ + B0 = _mm_and_si128(B0, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B2 = _mm_xor_si128(B2, B1); \ + B2 = _mm_xor_si128(B2, B0); \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = B3; \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B0 = B2; \ + B2 = B1; \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE4(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B0; \ + B0 = _mm_or_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_and_si128(B1, B4); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_and_si128(B3, B0); \ + B4 = _mm_or_si128(B4, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B4 = _mm_and_si128(B4, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = _mm_or_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B2 = B1; \ + B1 = _mm_or_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE5(B0, B1, B2, B3) \ + do { \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B2); \ + B4 = _mm_xor_si128(B4, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B2 = _mm_and_si128(B2, B4); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B4 = _mm_or_si128(B4, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B2); \ + B2 = _mm_and_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, all_ones); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B0; \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE6(B0, B1, B2, B3) \ + do { \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_xor_si128(B3, all_ones); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B0); \ + B2 = _mm_xor_si128(B2, B3); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = _mm_and_si128(B3, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B4 = _mm_xor_si128(B4, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_or_si128(B4, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B0; \ + B0 = B1; \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE7(B0, B1, B2, B3) \ + do { \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B3; \ + B3 = _mm_and_si128(B3, B0); \ + B0 = _mm_xor_si128(B0, B4); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B3); \ + B4 = _mm_xor_si128(B4, B0); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_and_si128(B2, B4); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = B4; \ + } while(0); + +#define SBoxE8(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B1; \ + B1 = _mm_or_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_and_si128(B3, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B4); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_or_si128(B0, B4); \ + B0 = _mm_xor_si128(B0, B2); \ + B1 = _mm_xor_si128(B1, B4); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = _mm_and_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B4); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B2 = _mm_or_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B3; \ + B3 = B0; \ + B0 = B4; \ + } while(0); + +#define SBoxD1(B0, B1, B2, B3) \ + do \ + { \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B1; \ + B1 = _mm_or_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B0 = _mm_xor_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B4); \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B1); \ + B2 = _mm_and_si128(B2, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxD2(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B1; \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_and_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B0 = _mm_or_si128(B0, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_or_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_or_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B0); \ + B1 = _mm_or_si128(B1, B4); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = B0; \ + B0 = B4; \ + B4 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD3(B0, B1, B2, B3) \ + do \ + { \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B3; \ + B3 = _mm_and_si128(B3, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B4); \ + B4 = _mm_and_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, B3); \ + B4 = _mm_and_si128(B4, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_and_si128(B2, B1); \ + B2 = _mm_or_si128(B2, B0); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B3); \ + B0 = _mm_and_si128(B0, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxD4(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_xor_si128(B2, B1); \ + B0 = _mm_xor_si128(B0, B2); \ + B4 = _mm_and_si128(B4, B2); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_or_si128(B3, B4); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B3 = _mm_and_si128(B3, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_xor_si128(B1, B0); \ + B1 = _mm_or_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B4 = B0; \ + B0 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD5(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_and_si128(B2, B3); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = _mm_or_si128(B1, B3); \ + B1 = _mm_and_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, all_ones); \ + B3 = _mm_xor_si128(B3, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_and_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B0 = _mm_xor_si128(B0, B1); \ + B2 = _mm_and_si128(B2, B0); \ + B3 = _mm_xor_si128(B3, B0); \ + B2 = _mm_xor_si128(B2, B4); \ + B2 = _mm_or_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD6(B0, B1, B2, B3) \ + do \ + { \ + B1 = _mm_xor_si128(B1, all_ones); \ + __m128i B4 = B3; \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_or_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B1); \ + B2 = _mm_and_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, B4); \ + B4 = _mm_or_si128(B4, B0); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_and_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = B1; \ + B1 = B4; \ + B4 = B3; \ + B3 = B2; \ + B2 = B4; \ + } while(0); + +#define SBoxD7(B0, B1, B2, B3) \ + do \ + { \ + B0 = _mm_xor_si128(B0, B2); \ + __m128i B4 = B2; \ + B2 = _mm_and_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B3 = _mm_xor_si128(B3, B1); \ + B2 = _mm_xor_si128(B2, B3); \ + B4 = _mm_or_si128(B4, B0); \ + B0 = _mm_xor_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B3); \ + B0 = _mm_or_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = B1; \ + B1 = B2; \ + B2 = B4; \ + } while(0); + +#define SBoxD8(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B4 = _mm_or_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B2); \ + B2 = _mm_and_si128(B2, B4); \ + B3 = _mm_and_si128(B3, B4); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B1); \ + B0 = _mm_xor_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_or_si128(B4, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B0; \ + B0 = B3; \ + B3 = B4; \ + } while(0); + +#endif diff --git a/src/block/skipjack/skipjack.cpp b/src/block/skipjack/skipjack.cpp index f5ffc861e..6c308c0f8 100644 --- a/src/block/skipjack/skipjack.cpp +++ b/src/block/skipjack/skipjack.cpp @@ -13,51 +13,63 @@ namespace Botan { /* * Skipjack Encryption */ -void Skipjack::enc(const byte in[], byte out[]) const +void Skipjack::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit W1 = load_le<u16bit>(in, 3); - u16bit W2 = load_le<u16bit>(in, 2); - u16bit W3 = load_le<u16bit>(in, 1); - u16bit W4 = load_le<u16bit>(in, 0); + for(u32bit i = 0; i != blocks; ++i) + { + u16bit W1 = load_le<u16bit>(in, 3); + u16bit W2 = load_le<u16bit>(in, 2); + u16bit W3 = load_le<u16bit>(in, 1); + u16bit W4 = load_le<u16bit>(in, 0); - step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4); - step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8); + step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4); + step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8); - step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12); - step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16); + step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12); + step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16); - step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20); - step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24); + step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20); + step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24); - step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28); - step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32); + step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28); + step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32); - store_le(out, W4, W3, W2, W1); + store_le(out, W4, W3, W2, W1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Skipjack Decryption */ -void Skipjack::dec(const byte in[], byte out[]) const +void Skipjack::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit W1 = load_le<u16bit>(in, 3); - u16bit W2 = load_le<u16bit>(in, 2); - u16bit W3 = load_le<u16bit>(in, 1); - u16bit W4 = load_le<u16bit>(in, 0); + for(u32bit i = 0; i != blocks; ++i) + { + u16bit W1 = load_le<u16bit>(in, 3); + u16bit W2 = load_le<u16bit>(in, 2); + u16bit W3 = load_le<u16bit>(in, 1); + u16bit W4 = load_le<u16bit>(in, 0); + + step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29); + step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25); - step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29); - step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25); + step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21); + step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17); - step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21); - step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17); + step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13); + step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9); - step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13); - step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9); + step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5); + step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1); - step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5); - step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1); + store_le(out, W4, W3, W2, W1); - store_le(out, W4, W3, W2, W1); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h index 231cd9c87..f12032f36 100644 --- a/src/block/skipjack/skipjack.h +++ b/src/block/skipjack/skipjack.h @@ -18,18 +18,21 @@ namespace Botan { class BOTAN_DLL Skipjack : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Skipjack"; } BlockCipher* clone() const { return new Skipjack; } + Skipjack() : BlockCipher(8, 10) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void step_A(u16bit&, u16bit&, u32bit) const; void step_B(u16bit&, u16bit&, u32bit) const; void step_Ai(u16bit&, u16bit&, u32bit) const; void step_Bi(u16bit&, u16bit&, u32bit) const; + SecureBuffer<byte, 256> FTABLE[10]; }; diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp index cb226542d..fdd47d3b2 100644 --- a/src/block/square/square.cpp +++ b/src/block/square/square.cpp @@ -14,103 +14,123 @@ namespace Botan { /* * Square Encryption */ -void Square::enc(const byte in[], byte out[]) const +void Square::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit T0, T1, T2, T3, B0, B1, B2, B3; - B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^ - TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0]; - B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^ - TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1]; - B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^ - TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2]; - B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^ - TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3]; - for(u32bit j = 1; j != 7; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^ - TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0]; - T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^ - TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1]; - T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^ - TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2]; - T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^ - TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3]; - B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^ - TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4]; - B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5]; - B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6]; - B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^ - TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7]; + u32bit T0, T1, T2, T3, B0, B1, B2, B3; + + B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^ + TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0]; + B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^ + TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1]; + B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^ + TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2]; + B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^ + TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3]; + + for(u32bit j = 1; j != 7; j += 2) + { + T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^ + TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0]; + T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^ + TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1]; + T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^ + TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2]; + T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^ + TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3]; + + B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^ + TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4]; + B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^ + TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5]; + B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^ + TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6]; + B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^ + TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7]; + } + + out[ 0] = SE[get_byte(0, B0)] ^ ME[16]; + out[ 1] = SE[get_byte(0, B1)] ^ ME[17]; + out[ 2] = SE[get_byte(0, B2)] ^ ME[18]; + out[ 3] = SE[get_byte(0, B3)] ^ ME[19]; + out[ 4] = SE[get_byte(1, B0)] ^ ME[20]; + out[ 5] = SE[get_byte(1, B1)] ^ ME[21]; + out[ 6] = SE[get_byte(1, B2)] ^ ME[22]; + out[ 7] = SE[get_byte(1, B3)] ^ ME[23]; + out[ 8] = SE[get_byte(2, B0)] ^ ME[24]; + out[ 9] = SE[get_byte(2, B1)] ^ ME[25]; + out[10] = SE[get_byte(2, B2)] ^ ME[26]; + out[11] = SE[get_byte(2, B3)] ^ ME[27]; + out[12] = SE[get_byte(3, B0)] ^ ME[28]; + out[13] = SE[get_byte(3, B1)] ^ ME[29]; + out[14] = SE[get_byte(3, B2)] ^ ME[30]; + out[15] = SE[get_byte(3, B3)] ^ ME[31]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[ 0] = SE[get_byte(0, B0)] ^ ME[16]; - out[ 1] = SE[get_byte(0, B1)] ^ ME[17]; - out[ 2] = SE[get_byte(0, B2)] ^ ME[18]; - out[ 3] = SE[get_byte(0, B3)] ^ ME[19]; - out[ 4] = SE[get_byte(1, B0)] ^ ME[20]; - out[ 5] = SE[get_byte(1, B1)] ^ ME[21]; - out[ 6] = SE[get_byte(1, B2)] ^ ME[22]; - out[ 7] = SE[get_byte(1, B3)] ^ ME[23]; - out[ 8] = SE[get_byte(2, B0)] ^ ME[24]; - out[ 9] = SE[get_byte(2, B1)] ^ ME[25]; - out[10] = SE[get_byte(2, B2)] ^ ME[26]; - out[11] = SE[get_byte(2, B3)] ^ ME[27]; - out[12] = SE[get_byte(3, B0)] ^ ME[28]; - out[13] = SE[get_byte(3, B1)] ^ ME[29]; - out[14] = SE[get_byte(3, B2)] ^ ME[30]; - out[15] = SE[get_byte(3, B3)] ^ ME[31]; } /* * Square Decryption */ -void Square::dec(const byte in[], byte out[]) const +void Square::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit T0, T1, T2, T3, B0, B1, B2, B3; - B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^ - TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0]; - B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^ - TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1]; - B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^ - TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2]; - B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^ - TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3]; - for(u32bit j = 1; j != 7; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^ - TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0]; - T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^ - TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1]; - T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^ - TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2]; - T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^ - TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3]; - B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^ - TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4]; - B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5]; - B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6]; - B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^ - TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7]; + u32bit T0, T1, T2, T3, B0, B1, B2, B3; + + B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^ + TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0]; + B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^ + TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1]; + B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^ + TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2]; + B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^ + TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3]; + + for(u32bit j = 1; j != 7; j += 2) + { + T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^ + TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0]; + T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^ + TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1]; + T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^ + TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2]; + T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^ + TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3]; + + B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^ + TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4]; + B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^ + TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5]; + B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^ + TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6]; + B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^ + TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7]; + } + + out[ 0] = SD[get_byte(0, B0)] ^ MD[16]; + out[ 1] = SD[get_byte(0, B1)] ^ MD[17]; + out[ 2] = SD[get_byte(0, B2)] ^ MD[18]; + out[ 3] = SD[get_byte(0, B3)] ^ MD[19]; + out[ 4] = SD[get_byte(1, B0)] ^ MD[20]; + out[ 5] = SD[get_byte(1, B1)] ^ MD[21]; + out[ 6] = SD[get_byte(1, B2)] ^ MD[22]; + out[ 7] = SD[get_byte(1, B3)] ^ MD[23]; + out[ 8] = SD[get_byte(2, B0)] ^ MD[24]; + out[ 9] = SD[get_byte(2, B1)] ^ MD[25]; + out[10] = SD[get_byte(2, B2)] ^ MD[26]; + out[11] = SD[get_byte(2, B3)] ^ MD[27]; + out[12] = SD[get_byte(3, B0)] ^ MD[28]; + out[13] = SD[get_byte(3, B1)] ^ MD[29]; + out[14] = SD[get_byte(3, B2)] ^ MD[30]; + out[15] = SD[get_byte(3, B3)] ^ MD[31]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[ 0] = SD[get_byte(0, B0)] ^ MD[16]; - out[ 1] = SD[get_byte(0, B1)] ^ MD[17]; - out[ 2] = SD[get_byte(0, B2)] ^ MD[18]; - out[ 3] = SD[get_byte(0, B3)] ^ MD[19]; - out[ 4] = SD[get_byte(1, B0)] ^ MD[20]; - out[ 5] = SD[get_byte(1, B1)] ^ MD[21]; - out[ 6] = SD[get_byte(1, B2)] ^ MD[22]; - out[ 7] = SD[get_byte(1, B3)] ^ MD[23]; - out[ 8] = SD[get_byte(2, B0)] ^ MD[24]; - out[ 9] = SD[get_byte(2, B1)] ^ MD[25]; - out[10] = SD[get_byte(2, B2)] ^ MD[26]; - out[11] = SD[get_byte(2, B3)] ^ MD[27]; - out[12] = SD[get_byte(3, B0)] ^ MD[28]; - out[13] = SD[get_byte(3, B1)] ^ MD[29]; - out[14] = SD[get_byte(3, B2)] ^ MD[30]; - out[15] = SD[get_byte(3, B3)] ^ MD[31]; } /* diff --git a/src/block/square/square.h b/src/block/square/square.h index 94a1fc370..5d9cfc78c 100644 --- a/src/block/square/square.h +++ b/src/block/square/square.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Square : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Square"; } BlockCipher* clone() const { return new Square; } + Square() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void transform(u32bit[4]); diff --git a/src/block/tea/tea.cpp b/src/block/tea/tea.cpp index 2b4212d9c..de30858da 100644 --- a/src/block/tea/tea.cpp +++ b/src/block/tea/tea.cpp @@ -13,37 +13,49 @@ namespace Botan { /* * TEA Encryption */ -void TEA::enc(const byte in[], byte out[]) const +void TEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - u32bit S = 0; - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - S += 0x9E3779B9; - L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); - R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + u32bit S = 0; + for(u32bit j = 0; j != 32; ++j) + { + S += 0x9E3779B9; + L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); + R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * TEA Decryption */ -void TEA::dec(const byte in[], byte out[]) const +void TEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - u32bit S = 0xC6EF3720; - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); - L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); - S -= 0x9E3779B9; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + u32bit S = 0xC6EF3720; + for(u32bit j = 0; j != 32; ++j) + { + R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); + L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); + S -= 0x9E3779B9; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/tea/tea.h b/src/block/tea/tea.h index 8ddf3e330..825a051aa 100644 --- a/src/block/tea/tea.h +++ b/src/block/tea/tea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL TEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { K.clear(); } std::string name() const { return "TEA"; } BlockCipher* clone() const { return new TEA; } + TEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 4> K; }; diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp index 9784b00a2..6a482a8f3 100644 --- a/src/block/twofish/twofish.cpp +++ b/src/block/twofish/twofish.cpp @@ -14,91 +14,103 @@ namespace Botan { /* * Twofish Encryption */ -void Twofish::enc(const byte in[], byte out[]) const +void Twofish::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) ^ round_key[0]; - u32bit B = load_le<u32bit>(in, 1) ^ round_key[1]; - u32bit C = load_le<u32bit>(in, 2) ^ round_key[2]; - u32bit D = load_le<u32bit>(in, 3) ^ round_key[3]; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit X, Y; - - X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ - SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; - Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ - SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; - X += Y; - Y += X + round_key[2*j + 9]; - X += round_key[2*j + 8]; - - C = rotate_right(C ^ X, 1); - D = rotate_left(D, 1) ^ Y; - - X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ - SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; - Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ - SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; - X += Y; - Y += X + round_key[2*j + 11]; - X += round_key[2*j + 10]; - - A = rotate_right(A ^ X, 1); - B = rotate_left(B, 1) ^ Y; - } + u32bit A = load_le<u32bit>(in, 0) ^ round_key[0]; + u32bit B = load_le<u32bit>(in, 1) ^ round_key[1]; + u32bit C = load_le<u32bit>(in, 2) ^ round_key[2]; + u32bit D = load_le<u32bit>(in, 3) ^ round_key[3]; - C ^= round_key[4]; - D ^= round_key[5]; - A ^= round_key[6]; - B ^= round_key[7]; + for(u32bit j = 0; j != 16; j += 2) + { + u32bit X, Y; + + X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ + SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; + Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ + SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; + X += Y; + Y += X + round_key[2*j + 9]; + X += round_key[2*j + 8]; + + C = rotate_right(C ^ X, 1); + D = rotate_left(D, 1) ^ Y; + + X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ + SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; + Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ + SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; + X += Y; + Y += X + round_key[2*j + 11]; + X += round_key[2*j + 10]; + + A = rotate_right(A ^ X, 1); + B = rotate_left(B, 1) ^ Y; + } - store_le(out, C, D, A, B); + C ^= round_key[4]; + D ^= round_key[5]; + A ^= round_key[6]; + B ^= round_key[7]; + + store_le(out, C, D, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Twofish Decryption */ -void Twofish::dec(const byte in[], byte out[]) const +void Twofish::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) ^ round_key[4]; - u32bit B = load_le<u32bit>(in, 1) ^ round_key[5]; - u32bit C = load_le<u32bit>(in, 2) ^ round_key[6]; - u32bit D = load_le<u32bit>(in, 3) ^ round_key[7]; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit X, Y; - - X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ - SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; - Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ - SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; - X += Y; - Y += X + round_key[39 - 2*j]; - X += round_key[38 - 2*j]; - - C = rotate_left(C, 1) ^ X; - D = rotate_right(D ^ Y, 1); - - X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ - SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; - Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ - SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; - X += Y; - Y += X + round_key[37 - 2*j]; - X += round_key[36 - 2*j]; - - A = rotate_left(A, 1) ^ X; - B = rotate_right(B ^ Y, 1); - } + u32bit A = load_le<u32bit>(in, 0) ^ round_key[4]; + u32bit B = load_le<u32bit>(in, 1) ^ round_key[5]; + u32bit C = load_le<u32bit>(in, 2) ^ round_key[6]; + u32bit D = load_le<u32bit>(in, 3) ^ round_key[7]; - C ^= round_key[0]; - D ^= round_key[1]; - A ^= round_key[2]; - B ^= round_key[3]; + for(u32bit j = 0; j != 16; j += 2) + { + u32bit X, Y; + + X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ + SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; + Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ + SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; + X += Y; + Y += X + round_key[39 - 2*j]; + X += round_key[38 - 2*j]; + + C = rotate_left(C, 1) ^ X; + D = rotate_right(D ^ Y, 1); + + X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ + SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; + Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ + SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; + X += Y; + Y += X + round_key[37 - 2*j]; + X += round_key[36 - 2*j]; + + A = rotate_left(A, 1) ^ X; + B = rotate_right(B ^ Y, 1); + } - store_le(out, C, D, A, B); + C ^= round_key[0]; + D ^= round_key[1]; + A ^= round_key[2]; + B ^= round_key[3]; + + store_le(out, C, D, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h index 0640e32f8..87b9aa626 100644 --- a/src/block/twofish/twofish.h +++ b/src/block/twofish/twofish.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Twofish : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Twofish"; } BlockCipher* clone() const { return new Twofish; } + Twofish() : BlockCipher(16, 16, 32, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void rs_mul(byte[4], byte, u32bit); diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp index 5047f6594..77543e1e8 100644 --- a/src/block/xtea/xtea.cpp +++ b/src/block/xtea/xtea.cpp @@ -7,40 +7,51 @@ #include <botan/xtea.h> #include <botan/loadstor.h> -#include <botan/parsing.h> namespace Botan { /* * XTEA Encryption */ -void XTEA::enc(const byte in[], byte out[]) const +void XTEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; - R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + for(u32bit j = 0; j != 32; ++j) + { + L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; + R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * XTEA Decryption */ -void XTEA::dec(const byte in[], byte out[]) const +void XTEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; - L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + for(u32bit j = 0; j != 32; ++j) + { + R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; + L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h index d9c6066cb..de265818d 100644 --- a/src/block/xtea/xtea.h +++ b/src/block/xtea/xtea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL XTEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "XTEA"; } BlockCipher* clone() const { return new XTEA; } + XTEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 64> EK; }; |