aboutsummaryrefslogtreecommitdiffstats
path: root/src/block
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-09-15 12:39:44 +0000
committerlloyd <[email protected]>2009-09-15 12:39:44 +0000
commit467cfb8b8a31eecfaf63c30cfa13b69bef4cd566 (patch)
treeaa6314c8afa6d2c5e0759a57fc52c91a36f43af1 /src/block
parent63fb872cb36a44a852ec33133de7c242bd44427e (diff)
parent18d1a6d4d11d40afb2d5a9d96b0437933bcaa472 (diff)
propagate from branch 'net.randombit.botan.1_8' (head ef51dd2869ed38dae3aeb1c3b931ca9d595580e1)
to branch 'net.randombit.botan' (head fc1942640045423f411fd865cbd584090b28d7eb)
Diffstat (limited to 'src/block')
-rw-r--r--src/block/aes/aes.cpp266
-rw-r--r--src/block/aes/aes.h8
-rw-r--r--src/block/block_cipher.h20
-rw-r--r--src/block/blowfish/blowfish.cpp70
-rw-r--r--src/block/blowfish/blowfish.h8
-rw-r--r--src/block/cast/cast128.cpp100
-rw-r--r--src/block/cast/cast128.h6
-rw-r--r--src/block/cast/cast256.cpp140
-rw-r--r--src/block/cast/cast256.h6
-rw-r--r--src/block/des/des.cpp144
-rw-r--r--src/block/des/des.h12
-rw-r--r--src/block/des/desx.cpp28
-rw-r--r--src/block/des/desx.h6
-rw-r--r--src/block/gost_28147/gost_28147.cpp67
-rw-r--r--src/block/gost_28147/gost_28147.h5
-rw-r--r--src/block/idea/idea.cpp132
-rw-r--r--src/block/idea/idea.h6
-rw-r--r--src/block/kasumi/kasumi.cpp110
-rw-r--r--src/block/kasumi/kasumi.h5
-rw-r--r--src/block/lion/lion.cpp52
-rw-r--r--src/block/lion/lion.h5
-rw-r--r--src/block/lubyrack/lubyrack.cpp104
-rw-r--r--src/block/lubyrack/lubyrack.h6
-rw-r--r--src/block/mars/mars.cpp138
-rw-r--r--src/block/mars/mars.h6
-rw-r--r--src/block/misty1/misty1.cpp130
-rw-r--r--src/block/misty1/misty1.h6
-rw-r--r--src/block/noekeon/noekeon.cpp92
-rw-r--r--src/block/noekeon/noekeon.h6
-rw-r--r--src/block/rc2/rc2.cpp104
-rw-r--r--src/block/rc2/rc2.h6
-rw-r--r--src/block/rc5/rc5.cpp72
-rw-r--r--src/block/rc5/rc5.h6
-rw-r--r--src/block/rc6/rc6.cpp140
-rw-r--r--src/block/rc6/rc6.h6
-rw-r--r--src/block/safer/safer_sk.cpp97
-rw-r--r--src/block/safer/safer_sk.h7
-rw-r--r--src/block/seed/seed.cpp116
-rw-r--r--src/block/seed/seed.h6
-rw-r--r--src/block/serpent/serpent.cpp172
-rw-r--r--src/block/serpent/serpent.h5
-rw-r--r--src/block/serpent_ia32/serp_ia32.cpp18
-rw-r--r--src/block/serpent_ia32/serp_ia32.h5
-rw-r--r--src/block/serpent_sse2/info.txt16
-rw-r--r--src/block/serpent_sse2/serp_sse2.cpp240
-rw-r--r--src/block/serpent_sse2/serp_sse2.h29
-rw-r--r--src/block/serpent_sse2/serp_sse2_sbox.h434
-rw-r--r--src/block/skipjack/skipjack.cpp68
-rw-r--r--src/block/skipjack/skipjack.h7
-rw-r--r--src/block/square/square.cpp192
-rw-r--r--src/block/square/square.h6
-rw-r--r--src/block/tea/tea.cpp52
-rw-r--r--src/block/tea/tea.h6
-rw-r--r--src/block/twofish/twofish.cpp156
-rw-r--r--src/block/twofish/twofish.h6
-rw-r--r--src/block/xtea/xtea.cpp45
-rw-r--r--src/block/xtea/xtea.h6
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;
};