aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--checks/algos.cpp2
-rw-r--r--checks/bench.cpp56
-rw-r--r--checks/bench.h4
-rw-r--r--checks/check.cpp25
-rw-r--r--checks/pk_bench.cpp2
-rw-r--r--checks/validate.dat822
-rwxr-xr-xconfigure.py27
-rw-r--r--doc/examples/package.cpp61
-rw-r--r--doc/log.txt13
-rwxr-xr-xdoc/scripts/configure.pl (renamed from configure.pl)0
-rw-r--r--readme.txt2
-rw-r--r--src/algo_factory/algo_factory.cpp4
-rw-r--r--src/aont/info.txt17
-rw-r--r--src/aont/package.cpp128
-rw-r--r--src/aont/package.h45
-rw-r--r--src/benchmark/benchmark.cpp3
-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
-rw-r--r--src/build-data/arch/m68k5
-rw-r--r--src/build-data/arch/ppc1
-rw-r--r--src/build-data/arch/s3903
-rw-r--r--src/build-data/arch/s390x3
-rw-r--r--src/build-data/buildh.in12
-rw-r--r--src/codec/openpgp/openpgp.cpp1
-rw-r--r--src/engine/sse2_eng/eng_sse2.cpp23
-rw-r--r--src/engine/sse2_eng/eng_sse2.h5
-rw-r--r--src/engine/sse2_eng/info.txt10
-rw-r--r--src/filters/algo_filt.cpp10
-rw-r--r--src/filters/basefilt.cpp21
-rw-r--r--src/filters/basefilt.h33
-rw-r--r--src/filters/filters.h42
-rw-r--r--src/filters/info.txt1
-rw-r--r--src/filters/key_filt.h45
-rw-r--r--src/hash/sha1_sse2/info.txt12
-rw-r--r--src/hash/sha1_sse2/sha1_sse2_imp.cpp108
-rw-r--r--src/libstate/libstate.cpp2
-rw-r--r--src/libstate/libstate.h2
-rw-r--r--src/libstate/scan_name.cpp4
-rw-r--r--src/libstate/scan_name.h4
-rw-r--r--src/mac/mac.cpp4
-rw-r--r--src/modes/ctr/ctr.cpp111
-rw-r--r--src/modes/ctr/ctr.h21
-rw-r--r--src/modes/eax/eax.h2
-rw-r--r--src/modes/ecb/ecb.cpp191
-rw-r--r--src/modes/ecb/ecb.h68
-rw-r--r--src/modes/modebase.cpp2
-rw-r--r--src/modes/modebase.h9
-rw-r--r--src/modes/xts/xts.h8
-rw-r--r--src/rng/auto_rng/auto_rng.cpp2
-rw-r--r--src/stream/turing/turing.cpp48
-rw-r--r--src/stream/turing/turing.h2
106 files changed, 4092 insertions, 1641 deletions
diff --git a/checks/algos.cpp b/checks/algos.cpp
index 2edaaf14c..dff903e21 100644
--- a/checks/algos.cpp
+++ b/checks/algos.cpp
@@ -62,6 +62,8 @@ std::vector<algorithm> get_algos()
"AES-128/CTR-BE", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/EAX", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/XTS", 32, 16));
+ algos.push_back(algorithm("Cipher Mode", "Serpent/CTR",
+ "Serpent/CTR-BE", 32, 16));
algos.push_back(algorithm("Stream Cipher", "ARC4", 16));
algos.push_back(algorithm("Stream Cipher", "Salsa20", 32));
diff --git a/checks/bench.cpp b/checks/bench.cpp
index 6df7319c0..1610bed1e 100644
--- a/checks/bench.cpp
+++ b/checks/bench.cpp
@@ -27,7 +27,7 @@ namespace {
double bench_filter(std::string name, Botan::Filter* filter,
Botan::RandomNumberGenerator& rng,
- bool html, double seconds)
+ double seconds)
{
Botan::Pipe pipe(filter, new BitBucket);
@@ -52,27 +52,13 @@ double bench_filter(std::string name, Botan::Filter* filter,
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout.precision(2);
- if(html)
- {
- if(name.find("<") != std::string::npos)
- name.replace(name.find("<"), 1, "&lt;");
- if(name.find(">") != std::string::npos)
- name.replace(name.find(">"), 1, "&gt;");
- std::cout << " <TR><TH>" << name
- << std::string(25 - name.length(), ' ') << " <TH>";
- std::cout.width(6);
- std::cout << mbytes_per_sec << std::endl;
- }
- else
- {
- std::cout << name << ": " << std::string(25 - name.length(), ' ');
- std::cout.width(6);
- std::cout << mbytes_per_sec << " MiB/sec" << std::endl;
- }
+ std::cout << name << " " << std::string(25 - name.length(), ' ');
+ std::cout.width(6);
+ std::cout << mbytes_per_sec << " MiB/sec" << std::endl;
return (mbytes_per_sec);
}
-double bench(const std::string& name, const std::string& filtername, bool html,
+double bench(const std::string& name, const std::string& filtername,
double seconds, u32bit keylen, u32bit ivlen,
Botan::RandomNumberGenerator& rng)
{
@@ -88,7 +74,7 @@ double bench(const std::string& name, const std::string& filtername, bool html,
Botan::Filter* filter = lookup(filtername, params);
if(filter)
- return bench_filter(name, filter, rng, html, seconds);
+ return bench_filter(name, filter, rng, seconds);
return 0;
}
@@ -96,23 +82,9 @@ double bench(const std::string& name, const std::string& filtername, bool html,
void benchmark(const std::string& what,
Botan::RandomNumberGenerator& rng,
- bool html, double seconds)
+ double seconds)
{
try {
- if(html)
- {
- std::cout << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD "
- << "HTML 4.0 Transitional//EN\">\n"
- << "<HTML>\n\n"
- << "<TITLE>Botan Benchmarks</TITLE>\n\n"
- << "<BODY>\n\n"
- << "<P><TABLE BORDER CELLSPACING=1>\n"
- << "<THEAD>\n"
- << "<TR><TH>Algorithm "
- << "<TH>Mib / second\n"
- << "<TBODY>\n";
- }
-
double sum = 0;
u32bit how_many = 0;
@@ -122,26 +94,18 @@ void benchmark(const std::string& what,
if(what == "All" || what == algos[j].type)
{
double speed = bench(algos[j].name, algos[j].filtername,
- html, seconds, algos[j].keylen,
+ seconds, algos[j].keylen,
algos[j].ivlen, rng);
if(speed > .00001) /* log(0) == -inf -> messed up average */
sum += std::log(speed);
how_many++;
}
- if(html)
- std::cout << "</TABLE>\n\n";
-
double average = std::exp(sum / static_cast<double>(how_many));
- if(what == "All" && html)
- std::cout << "\n<P>Overall speed average: " << average
- << "\n\n";
- else if(what == "All")
+ if(what == "All")
std::cout << "\nOverall speed average: " << average
<< std::endl;
-
- if(html) std::cout << "</BODY></HTML>\n";
}
catch(Botan::Exception& e)
{
@@ -172,7 +136,7 @@ u32bit bench_algo(const std::string& name,
{
if(algos[j].name == name)
{
- bench(algos[j].name, algos[j].filtername, false, seconds,
+ bench(algos[j].name, algos[j].filtername, seconds,
algos[j].keylen, algos[j].ivlen, rng);
return 1;
}
diff --git a/checks/bench.h b/checks/bench.h
index 07d67e0d1..0cc3f46d1 100644
--- a/checks/bench.h
+++ b/checks/bench.h
@@ -25,10 +25,10 @@ class Benchmark_Report
void benchmark(const std::string&, Botan::RandomNumberGenerator&,
- bool html, double seconds);
+ double seconds);
void bench_pk(Botan::RandomNumberGenerator&,
- const std::string&, bool html, double seconds);
+ const std::string&, double seconds);
u32bit bench_algo(const std::string&,
Botan::RandomNumberGenerator&,
diff --git a/checks/check.cpp b/checks/check.cpp
index 678cf4b09..30ee90d98 100644
--- a/checks/check.cpp
+++ b/checks/check.cpp
@@ -94,7 +94,7 @@ int main(int argc, char* argv[])
{
try
{
- OptionParser opts("help|html|test|validate|"
+ OptionParser opts("help|test|validate|"
"benchmark|bench-type=|bench-algo=|seconds=");
opts.parse(argv);
@@ -113,7 +113,6 @@ int main(int argc, char* argv[])
<< " --benchmark: Benchmark everything\n"
<< " --bench-type={block,mode,stream,hash,mac,rng,pk}:\n"
<< " Benchmark only algorithms of a particular type\n"
- << " --html: Produce HTML output for benchmarks\n"
<< " --seconds=n: Benchmark for n seconds\n"
<< " --init=<str>: Pass <str> to the library\n"
<< " --help: Print this message\n";
@@ -140,11 +139,9 @@ int main(int argc, char* argv[])
}
}
- const bool html = opts.is_set("html");
-
if(opts.is_set("benchmark"))
{
- benchmark("All", rng, html, seconds);
+ benchmark("All", rng, seconds);
}
else if(opts.is_set("bench-algo"))
{
@@ -156,7 +153,7 @@ int main(int argc, char* argv[])
const std::string alg = algs[j];
u32bit found = bench_algo(alg, rng, seconds);
if(!found) // maybe it's a PK algorithm
- bench_pk(rng, alg, html, seconds);
+ bench_pk(rng, alg, seconds);
}
}
else if(opts.is_set("bench-type"))
@@ -164,21 +161,21 @@ int main(int argc, char* argv[])
const std::string type = opts.value("bench-type");
if(type == "all")
- benchmark("All", rng, html, seconds);
+ benchmark("All", rng, seconds);
else if(type == "block")
- benchmark("Block Cipher", rng, html, seconds);
+ benchmark("Block Cipher", rng, seconds);
else if(type == "stream")
- benchmark("Stream Cipher", rng, html, seconds);
+ benchmark("Stream Cipher", rng, seconds);
else if(type == "hash")
- benchmark("Hash", rng, html, seconds);
+ benchmark("Hash", rng, seconds);
else if(type == "mode")
- benchmark("Cipher Mode", rng, html, seconds);
+ benchmark("Cipher Mode", rng, seconds);
else if(type == "mac")
- benchmark("MAC", rng, html, seconds);
+ benchmark("MAC", rng, seconds);
else if(type == "rng")
- benchmark("RNG", rng, html, seconds);
+ benchmark("RNG", rng, seconds);
else if(type == "pk")
- bench_pk(rng, "All", html, seconds);
+ bench_pk(rng, "All", seconds);
else
std::cerr << "Unknown --bench-type " << type << "\n";
}
diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp
index 88a72afde..fcc0a0f13 100644
--- a/checks/pk_bench.cpp
+++ b/checks/pk_bench.cpp
@@ -603,7 +603,7 @@ void benchmark_elg(RandomNumberGenerator& rng,
}
void bench_pk(RandomNumberGenerator& rng,
- const std::string& algo, bool, double seconds)
+ const std::string& algo, double seconds)
{
/*
There is some strangeness going on here. It looks like algorithms
diff --git a/checks/validate.dat b/checks/validate.dat
index 675e1afb0..524cc4b2f 100644
--- a/checks/validate.dat
+++ b/checks/validate.dat
@@ -19472,7 +19472,20 @@ D261D6041824D259290EABD3E9132DB8:7E3B14847526572FF2AA5D7BD626B560:\
01000000000000000000000000000000:07E5E5AD7097B849BADC2D5D803B7F6A:\
0000000000000000000000000000000000000000000000000000000000000000
+1032547698BADCFEEFCDAB8967452301:D5BAA00A4BB9D8A7C981C8DC90D89D92:\
+FFEEDDCCBBAA99887766554433221100
+145F0B8B663176B95DCAB7E9DCD5CC24:1032547698BADCFEEFCDAB8967452301:\
+FFEEDDCCBBAA99887766554433221100
+
+1032547698BADCFEEFCDAB8967452301:DA860842B720802BF404A4C71034879A:\
+8899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100
+
+B2696BD0D98C17953E4239225D27202C:1032547698BADCFEEFCDAB8967452301:\
+8899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100
+
+1032547698BADCFEEFCDAB8967452301:93DF9A3CAFE387BD999EEBE393A17FCA:\
+00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100
# Corrected test vectors, based on NIST's clarification of May 9, 2002
[Skipjack]
@@ -22938,6 +22951,51 @@ B4ECC305C3DBD8E5:FBBEC8F5DBF4CEFD:1B5E23EBD915C1FEE59F57DD91AF7347
# The block cipher tests above are distinct from these ECB mode tests
# for testing reasons. They could otherwise easily be CIPHER/ECB/NoPadding
+
+[AES/ECB/NoPadding]
+D8F532538289EF7D06B506A4FD5BE9C9FD7A929E0FD917686D9520ED236A276D\
+69E63C821F9DE0BF23CF1D19C7374FD1C3139DE2E1BA4693C3E9D29D774C2FF4\
+69E63C821F9DE0BF23CF1D19C7374FD1C3139DE2E1BA4693C3E9D29D774C2FF4\
+D8F532538289EF7D06B506A4FD5BE9C9FD7A929E0FD917686D9520ED236A276D\
+D8F532538289EF7D06B506A4FD5BE9C9C3139DE2E1BA4693C3E9D29D774C2FF4:\
+FD7A929E0FD917686D9520ED236A276D69E63C821F9DE0BF23CF1D19C7374FD1\
+C3139DE2E1BA4693C3E9D29D774C2FF46BA2DCF84C0E7E4D75CB53AD11BA76D6\
+C3139DE2E1BA4693C3E9D29D774C2FF46BA2DCF84C0E7E4D75CB53AD11BA76D6\
+FD7A929E0FD917686D9520ED236A276D69E63C821F9DE0BF23CF1D19C7374FD1\
+FD7A929E0FD917686D9520ED236A276D6BA2DCF84C0E7E4D75CB53AD11BA76D6:\
+00010203050607080A0B0C0D0F101112
+
+[Serpent/ECB/NoPadding]
+D29D576FCEA3A3A7ED9099F29273D78E2D62A890CEA3A3A7ED9099F29273D78E\
+D29D576F315C5C58ED9099F29273D78E2D62A890315C5C58ED9099F29273D78E\
+D29D576FCEA3A3A7126F660D9273D78E2D62A890CEA3A3A7126F660D9273D78E\
+D29D576F315C5C58126F660D9273D78E2D62A890315C5C58126F660D9273D78E\
+D29D576FCEA3A3A7ED9099F26D8C28712D62A890CEA3A3A7ED9099F26D8C2871\
+D29D576F315C5C58ED9099F26D8C28712D62A890315C5C58ED9099F26D8C2871\
+D29D576FCEA3A3A7126F660D6D8C28712D62A890CEA3A3A7126F660D6D8C2871\
+D29D576F315C5C58126F660D6D8C28712D62A890315C5C58126F660D6D8C2871\
+AA26D561F567520E8AE47528C24C18D731A2193D9A97FED6922B17AAA6372B74\
+BE5DEBD559E303C9C92B174A5107BBFEB626D8F65EDCCDF3AEE475C8A1837722\
+41DDE7C1F1631F5FDED4F42746471BD651D238BA86176EFE39E4695AAEB73B52\
+EA5926CADAD8018962E469BA920CB8BF1EA9062E4D9CEDD5FAD4F4C7990367A4\
+B966E5C5D2277288C61B96A559CC84AFB6A6583C5AACFCD6212B0BD8AEF3C6A9\
+A11DDBD175639341052B0B384678D8D9352299B71DD880E29D1B96452DB86540:\
+B2288B968AE8B08648D1CE9606FD992D717EB02EB81A2E939D54ACA91087112D\
+0D809C5EE82F477EBA7B956DBB23463B0F0190D616F5294112FFB7884E8B37F9\
+41BA1B505386B7428B88338188F7E718A3348230BF5CFA552F88D22463D9703A\
+115351622E016BCA26918D17E13225F67EE4E3F2C46FE52ECBDA044C585717DC\
+563A8403FF5309D62370B1DCF5A11EDD2F7D73602B70CD2553E44C1D3F170126\
+155BBD9BE3A965B345E834718F651CEF6CC65E8C5C566E894817350F497816F1\
+EEFA51FC91FEBB6E9F8CB141CC0EB6AF3C6F8380CBD3C996167F2F0E90E71B75\
+6C87EB62A4975356B28DCBF6A64A0BD107206D48FE6DBE19D50314B90AC87B83\
+35706F9B26007071AD8105CFAA1C1E2FF7FEAE5CEC4D11477F24E6B200906870\
+3C0E29E2950F2AC2DACD63DEEB5C7EFA9FDB9F3B740563D5518287DC981FC9CB\
+46D4B5A5A86FEC08FE70D18297DCF51072DDBE038DA040EBB12C509F5940A212\
+DDEB59F02132BE4581FC23EABAA960D6341D9352E36DFD6E4EAF0F6F439BC8CE\
+73A9AB3164FF30350F2DC08E939A104D6DF0C2C28F8E2D44468A61278BB6B429\
+4DAE45AE0CAA032FC97CD4D8C57FB83BBA8AFCAE22070BC882D3A42B38A09E65:\
+00000000000000000000000000000000
+
[DES/ECB/NoPadding]
059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE
4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF
@@ -24214,6 +24272,142 @@ D05BC090A8E04F1B3D3ECDD5BAEC0FD4EDBF9DACE45D6F6A7306E64BE5DD82:\
FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
9A785634120000000000000000000000
+[Serpent/XTS]
+
+53514C69746520666F726D6174203300040001010040202091E4F9BE00000000\
+0000000000000000000000020000000100000000000000000000000100000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+000000000D00000002033B00039F033B00000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000006202071717\
+170181237461626C657465737432746573743203435245415445205441424C45\
+20277465737432272028696420494E5445474552205052494D415259204B4559\
+2C206E616D6520544558542C206372656174696F6E74696D652054455854295F\
+01071715150181217461626C6574657374746573740243524541544520544142\
+4C45202774657374272028696420494E5445474552205052494D415259204B45\
+592C206E616D6520544558542C206372656174696F6E74696D65205445585429:\
+EF1F13233DE8092DDE062280F8CA8F480EC61DD555396F41FB8ED9444844F837\
+89933DCF9AEEC1933D3DBB4D54A26C329D7461ECDD009CAF263EDE40007F2673\
+6782D95B629205E87D4747FADA1434EE74DB09505C43230A0E700EFD012A5F80\
+8FC713FB22624AF804FA318BDAC382773E2653B4D576D0BC1A42F9652F56280D\
+A21CF82595137F9C472938F7519B6CC24708FD5409B75C5309E2C85294A2D182\
+2A218D9891D56696ABBF569906CA0452478628A719E3F11AB097D62D3FFB4549\
+576159282232655AB69CE1A4103DA8428F74D73E540A95ACBCF347D4EDD299FE\
+8ED90AB8F09D5D16B35BC5925E0B191DD753E2617B9085F108CE6B445F604CAF\
+2B266D5A10B460DE08A307D7CDE626D84412B8938B24EDBAFD98205978207014\
+4413A7C354F99D89CA475ECB626E7D93687A505B0F3E7D48823E4133E1C59465\
+56D55266A90F8C213ADFB020CA2D55462FA400B26B159306A5D3A4C91815C3E4\
+ECB8545E394099B330659E9B9C188AB09A53838AA8D0119ED9E55837BBDA655C\
+FD4096C4E2227287195602F32A8239D69DF555145F4EFF077F69366416F800DC\
+30C03C50DE4AFA12CFB4A8CD2E86B36D54CB44C3848FAD7917642551A85C76A3\
+A3C616D32B471B5775A1662B997D392D0B091570710B1CCDE49DCEE634EE3BC3\
+BC85ACEBB7F8551DAF5D15EF19A9DCD3CC9C82B46A4B9EFF8AAD0F8971A0F26D\
+C37E2DDBBD7603298654AD6CE0829EB76F0892E81C569A71343BA8EF767B70B8\
+A24ECF342B832483B7C9375D07BDDE2F1D6D4E6D28E997B1CEE1254F70D17F7C\
+24EFB08A3634802B37C8C0081F501EBE9346B9DFF3705A449B5517984DDBC2BC\
+91F626045EE89276C137233D8560B15C11592082D11935FF68A2ED6087527030\
+E4FC31F37680132CC53DAC81DC3636DB5068FBFA3B6923A2DC7CA617707944FC\
+D0CF81D092916AA54D5D26151C259FAA9AFCF9CD77A5E22FEBC019694205A1D3\
+F999E59F00D42F26FB5B9BE68B45F37DD664A2E9BA3336CA8A37BBC7EB452585\
+8FCCD69B746C7B8EFD534AF44028F915743FC858B45DD12D7F637FFFCCB431B3\
+DB609578811A67BB80D954A16B456792084E0E828CAB146A11A84DDBE4C79859\
+C9302FC55EBF8BFE8CD2B6214098549EA67FA52C8E0DF383F3532D87816C7452\
+A7AD571C213307961F786C45FA3AA89A0B66766EF0775904A66BC17DF3EB5646\
+0444EA22EB838A555D58EAE5DD0628581B9709738A1D9B2A3F66D4CA254FDE4D\
+EF8DE858574672F34BAEC851C58E58209C9019A32E0C728A866D04C1A5524689\
+C11C97302E3BE145486887E7E6F11581F6751DEBD01C28CBEE855CB58F69D794\
+5831AE82AF364ADD56CFA0C160CAB270D963CBF82E324409690597D80F152025\
+0B8254B29B09BA74E3700F9E614D37728C373C15C1E92D2674686D811507C34E:\
+9F7DC5DB8ECF4302325E0A993D761186BD59BD247615E560B704F8C9B6126A85:\
+2B1B7B6EAF72CA6F7F6CD1C0ED88DAD0
+
+0D0000000503920003EA03D403BE03A803920000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000140504001B1F7769646765743235\
+74682074696D6532140404001B1F776964676574323474682074696D65321403\
+04001B1F776964676574323372642074696D6532140204001B1F776964676574\
+32326E642074696D6532140104001B1F776964676574323173742074696D6532:\
+3A88A5D687632C9EB390B37C721A2010006D31FC9D4E3D169D242E1E44A317C0\
+675566A5414EC5C5FB19FB10D329C9F8A0250AD8F07880459B98E079FBB1CA58\
+725EABB2CCD6427E14BA01580B402B9EE34C6B23CEE38F5AC5B50A8198C5441E\
+C3955B3290E2F7211C8B2970E3082EBFA1DA9233E0D94923D5F658A6BA1E0E5C\
+7FC01889E3486551180032304FE118BBF7484A487B20B356C89C2DC5C1C8DE94\
+882676B19FF952B3316B9C8C0187B5BF781D894AB1DE6E8537B57CAF45CF23E6\
+9B62B143E1AD9C47483525EB0D89AEAD9CAA731E6FB2A3ADFAB8C05E1F967460\
+B05ECD759B6485AEB2A87F8E9030AD6C01C1E3E7FB468C624C50B2A20A9564FF\
+5E1C164C0ADE0839099FF7AEA385AF3CD07D743B7C0812477AED4EE7EAF09AE2\
+45CB1A646F63A5B4A7741C1B223C73235A973FC08A7DA0B60D5B8BD8DA07C236\
+7DC32CDE9A468DE47570D8FE52BAA8088D75572671F227D8BF5031165581C7D0\
+24535729112182B38ABF9DBA5F15B3EC590A6BE6C4AEB987E851C9A850D8AA8D\
+E7CF93A60E8159130E94BCA5FB252A0089EABEFAB3E2FF77C7CB3193D3123CD2\
+929E336C2E183272F83AE13574A0595591619BCE9FBBBB5D9EAC69B5D8C8BBD1\
+27EA886544BF770DCD8FF9C96F0EBF63F9D9C20FC8F1962CAB0E5FA7D61CF41F\
+4F38A43E402FD91119ACD6F7EBB1BEE6D56C7BA2C014BF64018464E8D3938FC5\
+4F7A8B58A1B86C16859A9CDAFD5604954AC1BA17CC1057481FA8704FD3DA9B3E\
+EC91B850B9DB54B38F59438494A316A0D271D813C8B95FA21FE7776F112327F3\
+21D6DA9E1C2909CEE630856A53140D9905DA751F42BE351FCCEFBC44EB80F086\
+5A3EB6CB14A91471D9B0ACDFF0D65DA1CBB8E17E2234B20BA8D3555627A4356B\
+8C0D0851AB981DBFE79A293C242BF862D8487895D7B86DE8D77810D0AEDEC249\
+6063C9ECDC57B1D3B1B6BC54F9280984D532CF30CECFCF954B5D06DF949E405C\
+A68C12C2BC8584BAE50EAC0F98BD2D1E8B53237F10F414D61E90BF3FE927D950\
+8670D614EB1CFECF00C92AA3F50E2737F7BD3FB91C46D3677FC3F1EE03FE81EA\
+6E7ADCE6FCCF06719BF1385C6608D2F833CB926ADC03339D03CB45996B199BD9\
+C3B18AA60BD9841FBE5331CFF7544BCECFA79E44BAD1F8757DFCCE491267772F\
+0BFB4AE236E19DFE16BD166856851999614F38997EAB29EBA438D10FB7278FF3\
+1334B8AFA0D6CBDCA39DD2ABAF46560805BBD9F7B32A3C551A4BBEFEBABB8906\
+9640C7E310C0DD8BDA60641D2468E2C59933DF671C22B57190F973E8EF85F5C6\
+E05D89E412243366DC2947F3418198FF5A0A38A383354ACDB3B2D79E99E7F734\
+57A9EA05506307CFE13E8BB571B032DE8DD22F3DC33AE338185FC099E9A5693C\
+10B78D140F6B3BCD8F2ACBBADED84941AC3CFC8F2795BD94499B89E92E45B9C1:\
+9F7DC5DB8ECF4302325E0A993D761186BD59BD247615E560B704F8C9B6126A85:\
+92E8641C3A25F1A79D188D7DA317F4F1
+
[Serpent/CTR-BE]
F3:3A:\
740614949B42870F0851A0D639A37AC8288898B0F9CC3B326B983ADA69BDBB76:\
@@ -24755,6 +24949,466 @@ DBCFC865520E4DEFAD4000CE0EC528916A415C4661E1ED7095E5777BF375DC31CED5F966\
11C63D070095FCD408DC7E7596C177C0A09961B2BDCB6E7C0F300C918E7E830B:\
41EF5DF5CF14D6D2C14CC4CBC4EADAB7
+BFDA49CDF67A114D29A7949CEE9BBDE5D26FF8E35407A266E12F98FE1247D74A1005366F\
+526F7460FF5B5C45D6791069BDF075C8BD396BA71AED8B7F812F0A31403046F30418A11D\
+B134127434B14CAF1E696DE716B41AFAC8FAC96687ABB8A81E1EB37C0C518806673A7395\
+AFED27408AF1B83B3EDB1D1AAF54B3C754E8361F:\
+D645EE5B89B1FDDE1056BFE827B8F7C2DBEB72E89E8ABA4AD0915193916EA8E6AD540288\
+69D0B1E71E396881006482C013B25915563C492B55F6CFF5DEA950590228899EDCA68C81\
+9B9AC2A485CF40023CBD4465170232F429D06DBB42E4E2C9B5E201EC41E4DF5C9674A1D3\
+2DD33A341E2E0D13351CAA4267BD869BB5AF2804:\
+BF4DBB8609E7AB12773DEB38FA1FB31DEF23A89137E4B292EB569028B6A5F836:\
+FE53D28C28A8CD12C0D66B79CE6EE6C1
+
+967DC68154B9B3957216DA8538588B899005DA3D2CB9500B1AB2FC4EE815232C01970F19\
+BF4068081EC07B041A6AC7A2FD97ABBB447C7AF73C0286EDCD99DBB6FDA189BA76212EC3\
+7B23A72FA8213D5C54AE716845E00262266400DC041D89AA69F1DE8B600F66B16485FFDB\
+5BFF89EA33625DADFB00DC35827C4CE73EB098B3A6639B26:\
+DAAC288ADD605085CBBC9867F0FBDD007472B15F34F8A7A91F16208CE15F0BD2DEF3FEF4\
+32DF84F66B1463777D3B2F0E3D2A41982BD845217383412BDDF2EB628EC8DF59240A32F9\
+FE442E334CA6670C6F3AFE7835C5D12E064F272C610F1084CE39380E029D050E5DC5676E\
+D7DD090FEF19A547EF90258670B3A49349728733E69CEC34:\
+B6E12C2EE1A50C4860591BC5AD7677BE5C77120BE31814A03B1B308198853950:\
+2E78B846599FB10E51D8AB906D7AC754
+
+6A3C46C05E280864DA7660DD5600F4050AF7EDE52B786F246C2BCAD03C8A88B6BBEDAC3D\
+5FE79AD40697BD88EEE4CEB3F0C8DF2F0F5381321D8C6E89049728B0A0DA9A71AF00DF1B\
+9BA71565C73F042CE22FFAD7B9DE33084BEE400C11E6A6F8398AC35E816E63B42AC23098\
+E7C5CA9B4D78395019B6123EA198EFB6A2E92793BBE243B46B1DC872:\
+2178CB3861AC4ECCA38D4C31EF1EAB6575AE0012BB4AEE9615069F62013B920F13797DB8\
+E432A8DC486F62A9F219FEFA356B8AEE7B1BFCAECE0DFA4F94E22A2219F6468C2D15A69D\
+11CF93B67AFBBB98F185807D32B794C6FA8F22794EE880084F6BCCD8CB5A7D0C59D0B737\
+781A60B29F17290D39422BE10A6AE430AD37C717D5C461EABDF8862C:\
+91E98D4A6EE9D7FD83D643C3BA829746FF2EFF77FCBFA41D44CE95C4CD76CAF6:\
+7B659AC1248FECCA3EE765ABB8D93D1F
+
+B0B0645AFA0E15A28D3EB6ABCAF31C6996CEE3C93B76F957424FA82B174BB3E9945F3969\
+094C0E6E5544D64606B54575CB6CD6E40964B84E94DE2193E7B9A00D4C5D140976DEDEE0\
+40585741F7ABB55CF8EE815F7848C4CD48D30C16783E76ECC14D384F480CE896532CF6F3\
+67E23633642794E6A913B871BDD702934E8968EBE1B2859CC62C01BE12091CFB:\
+406EB5C237784660784E9A1F477E4B8655B07FC54D1C69515C1B046005C05B82D8065886\
+39EB44323FCAA1F797D210FC51C91E3A51AE8236C0C2D6C521F2FAB29E89361BDA2275C5\
+43B54110AF60C7829D6C5CBC42BAEE86FDB0FF22C08EE59E81E63F0A98A6781926770B5A\
+C7792CCEA9847055813F065225B49F387E474A333D8B50926E3D7864035D75C6:\
+DBD7D9C318FECB268FF109238110F96FCBF2400BE054071478C7A2AFF75B384E:\
+BCDEBB1E6BC37F18D49C0A4A1C7665A5
+
+C47325105EFC7B78FF868A0E1CABEBB41B6A184780A52AA1D1E78A284C073089762B8029\
+9A628B3B22124250CC683CDB54DCE31E4072708C232129D437B89C0CB8BEC7A8F658291F\
+50AE9C66A0D62E26528032FBECD9B3112CCD022B7648BF995ABC46C57E821B3F3CE0EDA9\
+7358F31024F532C5D560D016CFD316A04FDD29588E6D50E681068EFDFB8361F93AA979F5:\
+D1043171968DF2B850257D7D14FBB7DE4E34FE62217E9972BDE0283E6EB2054874C6CB8F\
+B66A18A6F6885522D719EA965A0BE5F079370EB76587B8BBF5672FFD6B4390956C5B81E4\
+0AB21A15C8EF17D1189B6EF8E931A07B192ADDB3CEF0C66B28CF545774762CEC9968EC1C\
+06FCBA860BAEC78EE635495137D4E7B659100C59BD4496A850BC0FCF464531181F47EDAA:\
+B58E1583AFD26D09ECC1B81270BDA381ADCE90DA1A6096D27A61C8DAEDDD9F4E:\
+7BBB7496BA015237C080354FD061CBDA
+
+73DBE3EF41EA394F52138D24103977D8010166084F8FECFEA4C5327765735D5002FC7808\
+955D2DA9E786AC33F41A41E47D06E18B84344B4A5ADA2F925E536799ABE3367E0CB181EA\
+720EF44D286DF2223A34030E66FE161404724DB33DDB026FD5C88072D47AAE1BA89738DB\
+BE681D79E330856E4DDFCBD2E998E5065BBE6B3AB93DFFCC0EE04BBBB13E47080C511F74\
+61ECB802:\
+BCAA1E8F81FF49528EA23C4A62C40953CD98F16F91AE3EB6878C7DB5C3A6CAC4F8551A34\
+A5A624CC587A5A22E81CF9405E38913B77344DA59A53FA0BACFA1A4BBF64D234D1963AE5\
+E89159A24EB1237B93F25D652ECBB9EFD26E2881368287357D6783A8F3C1ACAB50FE60BE\
+7ABF7225F8AA0A06F54A63577634B9E930618A1CC8892D290ACD04F7933CF654A8A60AB9\
+00D8E0A1:\
+3A945A5C8FD52A46037A426C32946D59AA9B081C4993C634D9EAC2B7E144C040:\
+4C6D4D342E2582177F3641F777D337FC
+
+451FC9DCFBC3C8F106FC9C17A81D1C562E45341B4F05B5319C912CEBBE01743AE34D0693\
+0A5AAB36166780F9E75C154FBB1110375B271C297FC46D4B97BC70C1E8B378CB1E29F61B\
+5B0BCFBC8238E6D460054FEFB4A649430AAFDB7F01CF78A5406A3087E9C39FC2D60C4CAB\
+6CEE3DF6A3A8D2F0CD4134209C323D9CACF15308524519C40A81AFEC9736FF858D78927A\
+F66EFC5FCE806ECE:\
+C111527D486F8581AAB32257A7577B062AE1D781CF5B44333D12C3208BAF3C8E1276ACAB\
+0F4C325BC0D3FBF3913B13D2F06E8E64E2CF8017634AC9162EF32324A3465156613AFC57\
+779B9340CCCCBDEFC6476D2A4673DF123E435C6A98FBB8E59221C7667CB831EF2E7B5D49\
+26C9A022204F0B3564C66A9C8A7F494EBB337D148A8681982F70524C467D868BAABC86FD\
+50D5A2BC4C858342:\
+94EB2F6DAFC83A9FEEDF7081D40104F661916D4D68611AE3620A7E52D7C8F79A:\
+FCB50453BF443A452F735A2A7BFBC5D8
+
+5C1DB0ADA94F46127F18B21406B6FA32EFD090B0FDEB549474CFC19EBF68D4BFCB3137F5\
+47C48174E79DC87CBF308E0E9306E68B5FA1F9F67E005A2E033DF9034BE4F1E8C53C5D47\
+73846E8EA3782C70E8B1026965C40CDC7D5884F763BE3E2B64AA7458F48B6BC76818B52A\
+FB743300BED3971A416C587BDDC713A8C5782E91AD001E8D3DDD0EBDB978427173AFA9AC\
+A2180F7DEE47FA5A76F7989A:\
+C8E1CCDE12CBE92D8E61F23DAEBC35123564A94BAF6F2511B4BAF697D04EAE69C9B1C8D7\
+8E6383F9EB053C6B09F9A2A91EC0EC1CEE7801B3B01AF1E9BA4A481A4C7B73B0DC086285\
+C43CE33919DA440C1EF892D9A254FEB9179BAA1183EF319702EDB67FA2EE08F43A719D5A\
+EE5D3D7E10F0599278C70F25104885DA2F3CE797D3064FE6400366950661B6F703C8FB9E\
+1F773D893DCAC13DA94162CB:\
+E667049150AA0CC53BAB66F3EDFD5C32FBCBA264A6EB12D4563EB5E1E73F2D86:\
+EB8D65B2A91A7003E9CB84241B1DC009
+
+734BDE1B88BF91B571B7EF20524347DEA07BDFAEA8D194E00367A905DAB483F76F923087\
+B1E307EC990148E1C3B2E9DCDEF1694D9CEAE1A86A2D092D84B1247B5DD627B68E6CBEA1\
+7A539A5C650E8A6713ADDC2517B8FEEC7656264C795B1B0034B30B302DFBBEAAA12AA6C4\
+2BB3857A3C641A7A760C275F9C01521432A697984E12C2C7727A538834E90750D4FDF44D\
+F7083842090196A95D2E8143AAFF1D5E:\
+8289B871A4AE2E14F7398E510C5B522883893F59C8ABE42567FB879334A761E5332100EF\
+A7C6F6D4CEB8B6778D0C4B543BEA8B3EA58D198DC3FF02A8FB5CF063CB40E607087B5F08\
+DF86C906F14336ACB78832F20303533F8A7AE39A95C0AEBFA2985F97DB96E84EBB996F76\
+491D186ADC6D0C681F33F0FD3B42632E87E10DCEA36F222E4E7E8B4F2A5CF58D341BDA67\
+9516C829370C251824000BF463A75322:\
+F26DE261DCFE004B4F0B322D1CB4752F2D38279600B0A9421E1577C863A7978C:\
+2A4169C8E13B81AD96DC1CEC8723152A
+
+CCF6EDC92B1D17CC548C9973270FA54865DBEE4DD450683C7D542293BB2C59D2163027C2\
+29055943F7872D8CC2C9889B12E9B409D9EC55C346FE69998F013256A250FD23EC8C23E3\
+6B5412101FB35E7A0C78124BF23AD040327C608849E720EF644A552E35A2E98CB8ECC28F\
+FA8521BC4CD947E4BD24E4A70AE1A29572C746CDB98DE74477FF79101C9E75F45B55D6BC\
+2BD0FBC9CE24B569DBDC2DAB7FA88A07CF9BE2A0:\
+80FCDC8D13CDA4FD4653BE225654BD597279CE58C66A3CF67B95A8348DC976944477ADC2\
+0E9CD0E24C7913C928B2E0C531D43DD7F708FD4247D87954A7AFABE300085D169D280FCF\
+E16E580A0FF5AB435A7B64FAFE9928A11BDA14FD827D3B6DA14373879B4FF12F151BBEA4\
+17DB039CB8226AC91C8567B38DAE42015456FCBECE1C1CA8F0D2CAC3ED75F3D6F01D8F32\
+2F2822D2D4B0929D2831D9C0A801D49F77EEDA99:\
+32EA9D65FF14E80EB4AF36A9C6E8F663CB37CB6BFD131F14B49AB528614A613F:\
+3F1BFB148CB229C2E07719F6F99AAE22
+
+428D69DB8D1BADDB36EA5950FB2F99124A78BCBB0A7A9B1398F84A7E121637B48D12BBF8\
+5F045718C3F0409633E263F62F4992F4C6D497AD7093BC8BB1BE5663B40789DA824AC2EC\
+929C5FBB5107969688A9DB02BACFDB400ED395091A98DA4F806CBD7A9229AB96FB12BF50\
+2243D810B6A9B905C48B7612F94AA37E671F543FAD6BCD9C6B181506F447E90F88F050B2\
+C7B7199B88AE55AB922FB1BF4A5EAD00F71E83EEA2FC4F25:\
+5050237A09192DB1FABDE4EC7E865E3969AECB8900CAFD72B223A8E08A34AF993B1F3018\
+32DB0620BFC6757BEE80D215DA0D6B23666371158876E0422D540B2DF889C9F8EA92D181\
+A79AA8BDE50ED123C0301527C0987C4EC1FC105E6B8C0EC12750AC13FEE9CFF30E5A6DFE\
+47A6E63992A803F94D6E79F5693292C4D12D963BAAF42727FB9F6B144F6AFBD819C54D37\
+B3558EDEB4A049C7947E83E68C6ACE0203C882D9A038727D:\
+4A1EA133F919B366E3084F80E89E091C87F5F703FC9185F5C8E34E14973DCB2C:\
+CC96182632AD38AF5273863621B25E55
+
+C6092B37D8B6C14650D8AB31815C321B7923E9CAB069598003744F33EBEF1A693CC3E03E\
+B801BEE76182BBCE6CCAAFAA061250F5FC6BE6E07A3C39ED3F4344982E2DEC0A5075E5D2\
+A3218AD1C27F12C55D9BBC1B43BFBB79BAB35F74E1899517A839A54AD5274B8718F2AC2E\
+8F89A6CE94972A0AE020BE5256F8B5365B8AEBFEB63B886BAC9D263107A13B95E29A521D\
+3FBC7CCCD620E134D2D45082328AF1BAC6EB8B917B3F70A47B9D5CE5:\
+3F8FCC0A28C43035C055519FDBB13E8E5A4B35DDC04B62BD2AC7064BF7E4F7CA6C5194B4\
+0344F4C0D0C40AC3696C47A6CC2F800139EED2677E580BFF68399D8AA68DF7A28B95FA79\
+A1CD776739C1E2FB9C302EFB924013ED0FB2B06EB6B031FEC8AF7BB47E212859E1D13EA0\
+96E029EC051784317F63F5DFC2EB9C7E8E249BD88684537CC36785C54D8DA6F512450831\
+559BE2E67B024171A52F0481102C211DE9138120669D1C2A1F8BFB10:\
+C383B62616C48E3FCC6BB32DE3AFE5DC184E83ECB739AAEB94D82E942F0CFFCE:\
+52C109E1FAD94E490BD93584126E30A5
+
+0D85590B10C077184BA269C135DD1558CAD1A3D792BEDFEF45BCCE14E9099CC4B64D9864\
+97223B4D3CC9193E37E31FDE74E31023C9D265ED49E8D7B1032F1FA13F50E486F68FBFA3\
+B449F671878BCACA4009CF4607556E85878A2769472D481D30CE43787E1065BAC0506045\
+A26456644E7D5149C54C5C8387F5E23DBCC762E4369D4E7E24C4EB7AA5F3FAC3D76EEA37\
+DB6DE27601FBD37EB44D4C3F30E5688B549A029C22EE2282E408F9EBB259A86F:\
+B317F91E9BABF4361F26F96D001E3D63F3A82F2C8DADC4E4080611711CB4A7D77FC58D71\
+9B6ED93D118C7ED676A5B65CD259B9E1AA77AC2813B62FB869C42DBB0A710D1C986C0F97\
+8517DB2EA942D0F76C06AAD414ADE04BBC908DC428A18729B4D55CA600874EAF530B38FD\
+4318F1B2D97513BD3FF17949BAF9FFF3BB84C3F0065A521B4595E9801B5233DB2023D17F\
+5204D87AE7ABE1ED73F091A63CEB338FE9BDB2B82463E6B6B05883FFBC0AABCE:\
+357D3ED5C533FBDB195DD88811F3D6D50EC133A5E0A36DD256BC0E561ED28CF4:\
+38670C0DFF42CB73FDC3295694CFA934
+
+F8891DD530B83DD5EE3EF9050C7AA6A9C8A6EAAA4C8669FE126EC1C78A6F6583E57BEA88\
+84A368302C2D9C00D6F2D8DBBB98DC35152E43B1A9D744BF0FE1455A36B6164F09F55D4B\
+12290418E14A88F3F80A5EF558FF4EE01CA1ACE680FA028E81C12BF8A18A18792AE98513\
+636AB075C12320038C5BD733DCC8305551514D45E098E8E07EF0A293A489DA24BAB16973\
+D270E5D92AF34E6ADF9EBF945648192640BEE963281303D6DE6097E48D0AC4868E87A58D:\
+A54CF0CC7FF8A5B041A15C78F26EE7542BAC19254BD4D421E9A1843C66E9D8B136A80E28\
+31E6C52278CA54C79750CE64F6DAC5078BE3CAB44AE9F4D9019CBB310900282A6BD48313\
+7870CF8B0CDD002C61BBE679C2A87C7B1B1F1632DC57CC277FA4767D77BC2F0273879153\
+69012D0124BA8B2B85D8454499843C5F2FD9DBD584F9E2588BFDBA062C9F0761609BCE8E\
+0CF2B487F0F2C78A1C0B6D5C37D483F6B6EC52B7451B057C2D5FF2CD5F2BA443AFBA9215:\
+C2B6E94866DE53E7B7BF5827D5C0179A530094FE6AC5F44C9B3330D6C855E918:\
+A4EEEA6808FD5626B56AEB9206F86EF0
+
+1712A86BFE8C268C84902ED230BACA2B7B1610B5E6837ECB817D5D945E009BF627039587\
+D42EFB7C3966B9E84FA3A8A5363E1077F287150387C3A9AF1719D91CD175A97156049340\
+13A8A39A90EF97974A419796DB11DF04F3AC7AD348F37969FCB4F560B02108674026C17D\
+59D191A92DA7C7E32292D3DBCCB6D3B29C09F794851BBABDF7F455A9F050A069578B6A30\
+315BFA63448CF7A6AE2EC87C507E0A762A18ADD0BE18DF7BBD4F622B1BDCB693B53AB440\
+6E88AA7E:\
+3C43430F459A8E942D7360E97A89B2AD6454DAC2E72F64A1B06233810334C549D63D0BE1\
+C90A419203632CFB5C52E205756B751630DD08008BFFD348CD67C96774AF48C50AF4057B\
+4A3CCEB8DCC2223481AFC79FE717CEA8EFA2759C4B64339B2987175D14B4C195CB8E1363\
+D4F4249BB6F8A769454237FCCA5F848BFC05158F1D27BF39E1777A3A1648B555A72DA4CF\
+5B297DE904DCD84E36EE569B3F0E1F943873576F97D65B8669ADCA2BDB322E4A864DA4A9\
+E09BFE3C:\
+CD9057AF000AAF8EEF7F304A770DA1394F8707E59917A82671449D336167E456:\
+4DF89B713AC1141D62E2C824896B80CF
+
+EC9A99CC500450A9EDC1E707A9480144E242DF106E840B9E8D3DEA995A0C9F63FCC02117\
+02E8807EC1ABA88F5E33645B754B2E28EDA71F1B88E25B4B03B0909BD075F3855B4F6E18\
+AB07406AD94E9C32730C09CEF69F7A4FEB3F09C83D46338926ED795ED4EFBD2917E47873\
+FB6F516F6E4AEDA8D0310A914DAA25A08CE4528D67C3E1DECA8754552619027FA6FE7CD7\
+A1D9638EDB529445113C09FCA8BD4AA540EABB931B6BE201BA372D213162E14141E3AD51\
+AF9E684896D3566C:\
+A7A266F5E6CADE688097C04788CFD45BD87FC636201D0F484927B42FADEE8F789EF93F31\
+19D0DDE8E3716C3176360B928D3006A9F42BDC12D0591817DBD82D75FBA44C784FDF2D86\
+5E11215AF461C7DD1F9E3B82A146942CEFC56DFA4F8F80C4F0CAEFDD323607F43B33FBDA\
+7B6BEDF9DDB2A8C908E6D172900D2B4CC633C610812B62CDF225CBA62E09A8A1A1D7CBDE\
+1BF1C14CBF4C24080678677AE59166314703A11607C983C5AB3C7F755B220F10DB049983\
+C1EC0ACCB1368305:\
+B86E45AB9929C8382C8B068D619CD8450FAC18D39F31D38310BE8DFB8BABC18D:\
+3B10255473C571368D678D36964404C6
+
+02AD0113F276A03AE7A6C336B4DF4092F27AECFE4FE0DE526F6C548BBCA129FA24AAE385\
+0D0889FBB6F99324F7C01C749E5C7EA3F550594B98F4488F546C509CC256926174875DCB\
+99470F2D79EE7532E36A88BEAA0AB336197954B13171897727242BFE37DD15EE0F9BDEB5\
+E512A202AC3BC467C91191E83FAC86A80EEAFE0A8585E293558F7071C375A91824844347\
+5B57044ACA87243CDF11AA0838D9509A712626461E9DAFD0058A16DC7C4E8D69F53C165C\
+3CFD4AFAEC80E4F764DB4BE9:\
+7F3B26E6C98FACA940DE8DD01BF79AC15EBA4223AD8FF243909C321226B7497CCE5169E5\
+3A3A342FB1854C1802A38F87F393224EA8F518F633B04BB8EFB4ADDCD47CD2599249A40D\
+85A91CAC62ECE87834C028DD2F4FA50FAC1E6B591AEA8A454FE3BF3B41EF7C7FF533AD2A\
+5D4D690F899F5CCF8D4DF6D4FFF94E7F7567070B0309A905DC671515AA617018F7C37C13\
+763A445D48A5A4569D77815C1349A7E0BCB01D667EC0613A1EB0F12044DC748BFD1FFBF4\
+B173FE804CD0C91744302030:\
+CC207471BE9C6952378E60D263D69618DED46A78A21D8B7CA94E6BCBC4E3DEF1:\
+44F3D7AE3D2BA40BFBAA37A0709BEACB
+
+459C134A5BE569AFEBB4C7109D43FA4A5691B113D13CCBF47C06E90787A23C3F9C296B94\
+D47E2606B655C60C26E9DE647F4CC5BA5A49F5BCF458F40938E06BD259C20254F46F6932\
+C63C29EF311B63BE600E5BB7179FEA67EE10F7DA52C1A30E9EF1944D6321C3CE169123E2\
+E7D4B4074254D7C4998ED6C153BE0F79895CBE9B3462122BEA0FAE7B3FCCA09E5F980CB4\
+39A2F748D0E704C0184B56332921E85AAD4214EC7DA6EA8C6E852F7E1773A9602DF512C3\
+4895861E1C61D8EA0408F103E88702AD:\
+95042E5A21E494CF178601CE390B4F9AB388C698AB66ED4F2E7578A10984E30F63BED24E\
+BC839EA91BF852AB63AB170D8EAAF93FF2188D416DAFCF8C30B29455F70022284A6F934E\
+417F582B774B034ACC257C38C173556CC2909F5AF94C0E7E7CA69286CD7FC2C729DF2F6C\
+2543F4B12506DAA449CA990BFBAF39D386F36D490DE0932DFACA60644D7852007EA5532B\
+6EC98789F49E77239C236284FC94B77488FCB5EE37F0A3CF575541EE2F8FC0F2BFB67044\
+7A7E54C63AF122536C4B61B7A9C143F5:\
+DF3DE7C6FB886CE9DC51AEAC38374C29AC993630BEF81F21F725DFD4D6B799E2:\
+825A5B8F13472C46443D47145A1C136F
+
+158C45549636EE574B32800377F970320B9F861641425ED07021C9C4E44B5F1664046328\
+CCC1064397FCDB67015873B5EB433F52DF4936AB289A8CA161EC6A43E7459DC36332479C\
+704D956E18C86E11A8C1AABADD88E1EAA313A3D133004A34ADCF5E0F2301C3E0317834A6\
+A08CFEFD219DFB5F825CFA794DBA5971E6360DF22E3E0C15881021377DFD3EE69E53841E\
+F08B3F95D9D04CAA005ED15870B94557BB73CCE60B73495655C9C164098E2AFA19FA7420\
+6685D8103BFD9476808E38F8401FC582496A8EE5:\
+DF6250DDF592B446ED6D976462EEE2CB2D7830E67AB9567BC275CBA74CCCBBCF008441B7\
+B1593756DDAFAB05B1B728557F6D027A2A5EF2ABB072F456761AEECAA143795D93D6EC56\
+7D17F259013858513D20CB461BB51C3CD3D4204CBA768A5A3CD4B5D19563FADB62C4054C\
+9F7D8BCAF30F450F14AF29429E3E27C130FBC7B53840A00BACA0281A90293C6D60376B4C\
+6C455C771D1008A542E19B13AE1D4D14E3B8C69FB44550F74384C02861AF985BC210CF9C\
+4625012CEDA24B08842986E2DA30F9009113F0A8:\
+2DBCBA50DDC8EF3BFF1511BF0172A073CE37F42C83BA223D7573A82B13CFB813:\
+68A59DA89E8D3AEC1D4434F7A2EDD2AD
+
+F3087E4CCF4C82AA5B3CACFBFE367B2F501D1992D6455F10EA6C047A26ED06BF4393D53E\
+B0FD5B8B587B19ABE106269A74297B517D57D89D7CD26009B5DA7BD1B5CD40CB5B4DDA96\
+E495A02BF58108337A4F74E2A33C8EE14E730740F023560B70582EF4D1CE87C3AE5F5FE1\
+546F5C16683A0630342C319E2A5C43BBE7EE522BE44F955B4912A765B1AC476828C0C5E9\
+8948ABFC096ABCFC4FF2DD5077926C9A3F21F85D6B3EA941560A307BFB4714A11525C60E\
+4D70DCCA56ACF6FD3B95560CB6C3DE1342D8FF18828783C5:\
+996FC92E3A276EDF16CA8850CF8C9530364D170EFA51D1C5DFC2843A968E3CD1EFC50402\
+7C2E056AEB2E7AA5DC3EBED6CD25728812CEB545ED9FA552B1D0B1FCEFC4CDA5BC2646BC\
+5FAAA4C20B821A417980572112F737A7DDC93C39B533E9808D86A495547078087A678570\
+1D27D4632EA57D398F217BC191A30807999BDC509AC74AF3DEF4B1105FB8B904DD9F2CB4\
+158ED207614A07FC8F3803DC5BF81CAF15B709B099AC4F1F0968B7577A81819858D20967\
+77346AFC426792B9581202DDB4F1EB17EFFD81CDA476AF26:\
+B09FB55A95EDF75A610A03183D05A8D03D6CD9CCA7276530A72F6948CC074848:\
+0866EC523C35B5D03269F4F2FB004AE9
+
+710647FB3C699E7E83D1601D49513706C54CADC3034E47F8C20E1523225BED6FAF93308A\
+653921AB1043732F142196A32329AB98094C580657617967787D738A4EEF541ADCAADE48\
+84113C020026F6AF952FAEB1F9745B6D450FC86A04A9C4D81F4AB15089DC0BF7B1548D4F\
+850CFD97C6732FEE47B2320A31BEFDA8398C4AB0D7FC123C43F642CE07AB8DFE87B114B2\
+28455479AF224BF82B04BC3341D257F4EC166D9CBDB1793946FC2BC08B72F7099128CB41\
+0140DF4FA38A2EA4A2569DDE2E3AFB3164DD2F9D830A831A323A09D1:\
+EE6EFF319198C6C10DDF6F10546A5F38490A9D9858E021F5DFDFAA8ACBBEF0A446358928\
+5E8F1EFA697D08ED42F9160C4E6EEAE1F15D78207FB207565B9DE9DFFCDD96E88766B2BD\
+A996CBD439E45578596D91E88F7706A94C9428CBCC3108E1F61CBAEB184C30E5BA0370E5\
+DEB1A9B8A42191BAA3D722CEB9DF9ADB69764820FA95BE1B48493BDA88030469CFD41F5F\
+13731A983FDC9B2CFE562881BC479253A126D57A8BD02BCEF2FC6DD8BF1AB265C924EA40\
+F5CF75F4E36EE10133923E2427E19BADB34F221CDF4673D871ACAD8B:\
+F6286D8D4FD9D8B373C7ACAACC517DD041E6E8A69578CD444B22579B4D3C3EBE:\
+621D087684EF405E7E49478F145FBD45
+
+707ED22B1DE93A11A851C0B14B1CC4B09E6431FAF7F11E97730D1E9F5C729D9DF12E4DFA\
+53E88A5F8507FAD0AB721510E02EEBDB84EF9B34120FFA1FD80C5C0C3503AD02AF96E4F4\
+66C462C3B4F3D26C78DF8C08A551DC39AAAF7EE05B13D2E1B80DA5A1A532B13EF0D1B065\
+9D2A0B43246E52CF8B6CF4EC5918769C21C51C6D1DA8DCCD2F3B0360248480C36D4F5CB8\
+317973D42FF7DE23D34329FD57B204EDD045BB87DFA5913819F15C6D5049DF1DBCC696D2\
+4C34160249CD84AE0E94C9D50A5EC764C48B26C7C8E28BBBF418525F9FEB0DE1:\
+4F9221B68E45395D5C923C4A6F96826018E207CEECC5DF1560A7587D15427B75FF3188E2\
+19D5EA5F92F909B129D6CDA2AAFD9D52B8B0C05B9E9363E8117E9996923ED6C59287108D\
+A2F5FF3451823362B2CEAB17E862E622437A990F7B23A9FDB6791A9FBFC1C06214673C92\
+41164044EFCC6439AE42079D3B1130320A878581D2EBD264D4FB53ADF5A60091695636F3\
+EB58B73A3342D3CDF833F7E82D6EE1FAF65E327DBE4350307CBD631042517C448F91603F\
+2BD6038FBB847B53F98A8DF30205022C613365C8C69CC55C6B911CF3D5567004:\
+6886D97D7FB73175DA93375F14FBA49AAA7ABE901751EB42CD243B568AD6DC18:\
+9F9E1F292C86CFB45E0334700755C190
+
+0612DA958E54589E58F7C2E70F374D0CC47109B326598E46FCFD23553E3D84C703475618\
+68DD38847E0096E2FDD36CE8997820679ECD5219FA16CC9FF0F2DF8AACF9116E6FC9F926\
+1674EAAC3142DE0B9941DE77172FCA477759531B77348D914017B5E1896DD87B3DC0CB84\
+4CF642C1919D25E21E2A94977065621A4433265F590DE23612FA6B16B031F6DB3648A42F\
+57DB126211F6FE7231849B5B54694DD736E512D1EEF0001BDD94DA84AF47C71FF61F4951\
+019CBFFAB709278DBCB60F17EBAFA7DDFC071ADB89EDD569CF4A8C7D566FF1B7E20CB0CE:\
+67943CFCC4B795A311DCDACCFDBE44FA84FAFD87889892F0410166017B032B78CE7B96D0\
+3D00222424E0D363DD321634F4D151E1E03C357BEE8AFC7C561E8629EC55EB52567EFC8D\
+906C2AF0E4C385A0011CCB9E254834E55F7870F10BB563BF0A732CD6AC6F8DDF19C0D3E9\
+AF3A7F54C38E66BBDF3CF7A00361FEC2F5A7EBEA03C4C42AAA0A74F11EC51D3F5E1F78B9\
+0B09CB524F7A5DC8CD561E15EB866449F4893FD49346290A63A8D478A0C5ACED66550BF6\
+4D2A0CC5AE29886DA6DF798D8EDA7258B74BECD3094D6E83A61A9288EA1A8D0FA91E6F19:\
+F1F03359760DEFBA1ED11309F0C1D27A311FA4DEC398107B2D0AB2E0EAA895D2:\
+2FF7028F78B7F5623CBE7D592EE5603A
+
+4202E5DAF05E4E2DA055A9B76CA4C678A5D7F1B5F130E68389A57A52AD82B1A08FD35CD6\
+1832A0964A5C66F91E9F7826DEA9C78F5257206DD3A78C099768524D1E3B01306A9AF70F\
+2FA7DFB02F9717C2C9D7CF037603B96AFB5B9A5C832FFD86793C0228F9F38593338D92FB\
+70CFE3EB0B4B0E149E52ECD784E0756C1934B3DE03B439292052C21B40CB5D39FDD7BF3D\
+81C314F927C6EF03FB4270BD1DFB796EF59F887AB566D2AC112C1EBBE1C98679D7F0B724\
+94BAA6735FBA58D3CD125ED42272E34A9D51407D5550FD3DBE0E06004D31CA3B5CC1874E\
+10A60668:\
+DB896F08DC3DD1224CAA35F8D841E6174E03595794F8C623987CD275AAFD213A0622D2CA\
+B9DA6C8FB847FAD852352CE37806529A4F06A1620AB065D157E8992981BC74DAAE1AAD30\
+0447E720146174D75C8C09F1A47D307C6492D93E7035A081D4B47EAA116BA2F2643CDF4B\
+26EE8B82BC90FAAE8BEDC463B93F2ABE99BB7A1FECFF8FBAADF907FDDC34AFE59484DFEA\
+97937C02EDECBD1F3827518F3183FAEE67798726A220624A7C5AFBCDCABA3ACCA8862B31\
+9DE90F4C59C13EF1B8FF43DDACBC0A18548F148676034A3D71E928B1D25609C539C3203B\
+7055498D:\
+8739533FF38CD3C2A5969CDF010BE33299B5772DA0F4A56FEFBCFB4C187A398B:\
+C28792697951BA0551162D5FAC70775D
+
+2A797C4F230EBA8E8D560B141D6F7498036F7C54D326F67E8A0894E7C7DEBB49A717E2FF\
+12E5020B8F4F3D00236075334BC1C1BE18609339FFE59A60DBCCA006446B05FF8C296E57\
+FCABA4121656638EB88214BB0252941598EAEE42966CC162D78D0DA6D54C037876AE0931\
+F94BA160CD17DE6FAFFACAA68C5F765CE64BC85B4B132366618C723B04ACBE5392991A1D\
+1570BB5D3FF257256473297D9DE7FA8901F69B8603C9BBC267E3629A33A6A79697CE70B9\
+37E6B15BC6DEE6C0298CEB375B40DB4E0FCEAF71D5302680DE2875F14750E45771D5538A\
+CA54A19EE9E438CB:\
+B0C2C84FA758C6144BC07E436E7C4A7FD9279C35256524329930F5934B6D7CF4BCE3C7ED\
+4D6603794393D85C28E4DB61D4FCD17A90EE2AA4E6C29E99FD6C4BE9E245329D4F33127F\
+05C903EE1360DC713132281D67D23BA2B738A0F8C66A071DD9C31A19E13489EB8681CA99\
+84B3020F497CC66E5CBB3979F09B0A7C5A043150D846EFE148E7871A45FA8DAC26416BE6\
+936E5D3289A5B7AB77762726F7E4EA82D00D3123183BAF7CC146C761A7FC483055C0D687\
+944BCF9072377A7F797EF2163FE07B7656A56083E351EF3F2026B19FF76C3162CAB2CC86\
+293C537407F0F569:\
+C7B7849FE8962C5670F745C8E26B979CCA21F1628305A75E9372A684EB8FAB87:\
+CE0C1E9870A5D615C9F6D8826D7B61A5
+
+43328C5C5E30B0396CBCFC0E6BE81C49B9164FBCB9A9081CC22E223CA5CC5FD28922013E\
+4A9A95DEB0025DD15087D516FF4771182A67E2E69E55C19809A8B9BF4F77E02748DB3CD1\
+CC0718E37C0A9555E703C579F5761EE6DDC484BF619243A95BA97E8B0A5CE152F3C1D72F\
+D69519E9479F4B1C46C23194DD06050224A7C2F467BE08C7EFCB0AF1DF523E294FD7382F\
+4B60690CF7EE8B8AEC379363FF636111AD4CFEA81EF2953BF76C2C8E76DE5B29334FCD09\
+F01FD4902C1021C93BA381CEEE9ADC7CA08D18B00FB5E652839848999FABD577870DAD51\
+0E8115B01AFABDD683FB3CA1:\
+1775067911F026BEE6DAC1CB54B8FCD1AFEAAA98D610FE00C63524F9AB0EFFE7CB7861E1\
+C7B1243990514BFD92C1402305958731E5E730D2AC179916220291A604B479471A249874\
+D1B067558F0D61F29790DC82765A0C4B00DBC0AE2A3B1E608E9D1F429E64CEB08D2AC7E6\
+1DC0A3B8174D8F79CA27260991CBD7D739128012B6DF93DAD582B96603E61398BA8BEEDE\
+F70AF98CE871CB49F2557C239CD61BADE4F38E0CBE1EBDC4580B56CB1830B5A14179C55B\
+A1C3EBD60F60388B164CA51F1369900E9C3FFFDB39D0E9A594A329723CE60A21E7C87F8D\
+756EE5C92CBD45D7E5A57395:\
+BCCCB7F12DE82B841EF1C0171472BE0188C2468C8D660F268F2332530A2930DA:\
+570030C34B809C5D361636F477FA84CA
+
+033362424F88682DB69F71DFFB5C08A010BA4394CE1305A467B4BC7E6DFF93DFBBBD7FAB\
+DBE62567612AC8AC5581A7A506D13CB8FED0C856A89D84B4D14D98005C74616704E46CFF\
+43A878B66D1D6B3636949C19404EC55B61A1F5DBBC829AA720FB4A5D3FDB8919885E6CCC\
+35943AC13E655E4149A587C4A60DC54BEE8C64A0DF49656CD4F67FD5ABFE1A8090E48212\
+646D730B50E8255774A3A1756F63DDFBB33DC0D2EF5786B6BB6E303006A2FA3217143CD9\
+237D15F24FF27DF41A9099E53432EBCFBEAA0ECD5FD419D736857E57F8917DAB5C20274B\
+F0F61075BE07EC5383BDF320C8F04FE4:\
+11C73FFB2F85FE26E087184A4E7D0E74CA4769A072EC036EAAA0162984CBF53979926FC7\
+09BB59158685C6F131BB3E79886D13F0A644A420D14DE9DD497FBBF5C8CAF27E6C2CFD83\
+CFE6A5219EEB8B29DB9D2722FD7E1004BD1152F6698C4DADEC589BBBFA3EF96BCF4E90CB\
+1395EABA2F1D90D5B2F81F312F2AF94583B4F3A8DEF1EAB26FC8EC9C4C2663F4CBF856B1\
+BA593A3E3F54B3D3831E24B44C7A5217695F3FD36D834DF32488DF461A118A93264B2E66\
+57DDC66D246720E94EACD77ECF23642A036229143868ABD20F3B1FAE1B852C9669CCB0B3\
+334FBA0D8FEAFDD56D03E52F5D136E87:\
+2CFCC0880B1BCB48651602B2F653034A6B8406B143AED550F85F122DA3BC6E28:\
+68A553188B539B46214ADE17802A5ADB
+
+9481ACE7C47FEC3A22B41B81E1A72363D4F4EED3CB0C93200769415B4779755982EA26E0\
+F6363C973A7C59A43FD6CC4B2D1857EB38B5AE5BEA22DA4781AC36F5559A2A2A8EC111AC\
+33275AEB3863B2A7CAEF572A16523A1231FACDF0FEBAF9305B658A4E7B0CCB9A424D5838\
+4B385132389D5545ED6D2BDC3D615D229ACFBCE60205CE1119322C642F4D81ADAEA50995\
+E4DEEB23D9976A1FF4A9C8CE7F0CC7DE657690F9651E53DE4E58561E9570CC4526FE03DD\
+686BA1AF9557718D38641B080592C9BFB2FEAEE56AFACB4F811439FE29AD6BA8D6F0ACC3\
+FE3836369CE06AEAC64898DB676EA7640D7A7BE6:\
+8217EAB21AA0D8A541AB0CE258E96EDD82866A5460455B82C339F5157C2B159FD8CA8AF0\
+413BDB5995EBEE6AB6E1F8FBB03C67B086DD2E6AE05E0B37ECB43EC2C77E9510F24BA1D6\
+E5D4906A10BEDEC2D3ABC09019274E8D09CD3921B3DF7F9EA607011655C684C3FD435747\
+6F97C1FE8314A80AE372EC4C4B19B5D34469E66A94DDF0E0C5546A290FE42A3D00F071B5\
+846DDF4D88E320E4AFF2CE3D650DDCE965C16C3943F1EA5A63D9696F8DCA6D7D65C3FAA6\
+157549B214FC3B44E6C62D124EA327E97A91126256CC475A5C533CAF2EB3F6B08769436E\
+CCD52D2AB31A87E1E09D00D2F835BF9A7356EF71:\
+30A6450164DA25B43CA6DB430F827299AB79CA4A52C636C690F7BBDF82BA9B0E:\
+4A87D1FFB56ADFC374C09B2F8D021CE8
+
+3F5E7DEA03EC52DD0CDB0030F676EDF2EC5B91C788D1AC9F8E88391FED510CC64123E47A\
+C2B685E5387365DC98DA305A832BE09C50F2E3E5B97E02C92F92EFCE59DD0A18E1227661\
+719B54397B0367359A1EE476E8106D2CAF3988E95BCA0947E2411574E3E61D79BC8C6FF5\
+F7D806BDA98E0C69E4F44F70E9B2F1178DA75DB504D3F8096AE002E2C7C36E95EA3D37CA\
+3807E760424D022697FD763B1B85E4D4D15D95153BFA3F74BADF46EC1906B1904D250E98\
+4D7CB5314EADD248A801373FBE2D9EF1B9D82AB3FB0C2CA0F3F9EC0F83268EB2464E40E0\
+C40EEEFC1B9C4859A357CC62C5537783D7437E6509689C6A:\
+E4E2000ACFA0762A90E16CE545060CB60961F69586A8845D37709DA643894EB7BB29B2A0\
+69E0533EABEA770AAEF101CEC381983F59278E7EF2A55B190F7B758DD97050315B3EF563\
+CF92CF9D2CF955F266C77AC4AC8BD7BBE39CD4F5EE6E57854C8F2DDC6462889E1F02DF8A\
+7C1AC02B65423A17299973745C7C4F17E4579F514F199932D98062E3F0E141A8133CD974\
+A4B1C8A066C4800CDDE54424F4BE19C4E0099A9AAF11692C27E182AA55DEF8A439A746E9\
+DDB83F674F76F297BBE8C1DD7F4A4582260DB38C14E6FC40FB1DD429FAD55769A89BCCF0\
+0677FBE04B07C5BF6380AC4DCF47FFE08AB15370ACF4082A:\
+9361EA127351940052051851106E32E21B5B74CAC5EE2C65A478DC07962653D1:\
+F6159606256712C7DCBB2F3E8ECEE258
+
+378FB5CB6B0FAD01796C73A850C8EF78AF71CB2AAC0CF7FE9EDB58D64EFA6D138FB8FF48\
+4500C5E15F8013ED56BADC846334DB7AA6DD1B0C55BCD1A32B93A86B54B74D06F3224369\
+D5E2ABF310A13D76CD3C0E037E161047CCDB49C1F117097AB42E0CEEFB4B09EA86305C72\
+D1627D53C5D8DB79070F20BADF51DAC0F6D019C7520DF841978F0249E24F995D4C0823A5\
+CA663B67B25EEBB8A38A95D27F44E425DE53CF55E5E3811CADDB9C0AD3C415587DB968FB\
+1F2D93D3B02D5628BE64E09AAA0A79E9EB6B72D0088554E77574315F1152F489ECCC4B8B\
+9705B10C96CDF2368DD61D8A345570B4751DB4533643C8F10CA2E5E9:\
+6EC13D2297C89EBE84380FD858E68FEC5E09BA9F4974C03B0C1A098C42644170358B7926\
+01D88B40CDF56ABD6A2D8B7CA430AF87EC349C2B11D44731A0C219F0DF310832ECA798BE\
+E87C293C8834CD74724E96A6D7A1DFCEFA893DA180CC2CA8465274D176BB0D25B1FCD04A\
+3142EDE3B74A6D3E1ED86F3289DED1E37D32B9925C8BB51913B2850E5DA43159D4F70F64\
+06F5BCF600B1AFB2244BFEED3B40303C58892BA8A59151F8E2649964E767D918771E2681\
+26CE88156C4FA319F65CB1E2909F5A196399B45EF0B040C3DCA7E79232E4782041C7E6B6\
+5C9C82D8B4517B469493A46831B9E9094AEC31639E353F40D3AF1488:\
+2377222F39987D62CE8CB5F64E88437543E20EBB58F2DCB159E0AECAF439217D:\
+2DAD0FE823C71638F1910AB8D8924C87
+
+41E99B44C7C94FD5B8978507A99DFCF6EC7A49304EC6099AD1C38DBF8BE918860AB5C37B\
+D13253B763406AA6DA1CE6779CED6F7F7B222CD51967BD3B61FA48F6B65B96891E34FB58\
+3E0935454ADCB3CF6419216B798A7C0CE5402A3232510940839D4DCA082247505CD68D73\
+B1AE4E352B9A95F6CD68CACF68F28A525CC3DAA1504DE85B51CFDC3B693DFAD28D4ED86B\
+70B93B02FAAA0BFE452544C81ADEEF99A59378CE0625234EA69E9F69ED52D5FBB6687F9E\
+E248479E1B29ACF0CC3BE7BA5B77537C29CAB662B2DD7D8937B9DEE577E7C8DE85D3CEF3\
+0912FF62687756C6F978FBB147E6B27E923C62F9A38BD7F50D8801E676FA07DA:\
+BC7838EBF0287786D89BAAEBA8ECA378E898BB36A6D3D6CC125938D71768BA704E30F9FB\
+7B09A43D85786790FCEEBB46A2A341C4EA50AEEFF3DC57005DFD7BE9C4052AB3CAB38B11\
+221EA39EA778AC6F4111CD1978E5D467301BC7ADDC54D084F36652A9AD3EDB8D70AE6380\
+3B077A39CF064017DC2A8CED0E4B1A7D6FAB58B0FC92684778B7B3F5D76477CAB7C6C1C6\
+AE6BCA1F661CF26DFEFCD1DB5DF58F1358D38406E3D880F30E43E1837132B5DEE65EC09B\
+7622CDA1F52A78F8EDF870D2AF375C7526C70E43FF650B8EDCF6A35D02CA479DD560A672\
+45C7087D0376C9915777FCCB390109115AAE52C4512ADAC046C8C1E9092F3018:\
+19F394E4AF235F4BDD3F0798E904A2E114041B351F0D71C5BB269845BB53D4B9:\
+093E57768A6107B8D6F31A083B23B3FE
+
+20143BDD828F687A93266C2E489909BFD6D85884A40018082FDE227841647D162DAFC241\
+40580495B6E0C393CFE2BBE80615C87CBF5E057D74A4CD7589DE69E136870A24AE67F9F0\
+FC7B92369903718B9268500155ABBD6C8D0E81FB1104403A02A56FC82F1DE4137EBA1433\
+AAD9CE7B34198ABE7D9845DC462DBB4FC6DA4F937EBEAC139339B405ABA51BFC9B06B38C\
+BF17352F47C6EF3968F06305123888130738B887911567A28DEFBCE943D18C73ACBE920C\
+386143E0B6B2C9EA30C84A7E4196481F93395C8BECE5F9B341725DA7883DD74792AD0140\
+7A05BE7A2121AFB2E9EAEBBA7574F9582D0455571A077603A511ABBEF9EABEF4553A48EF:\
+FC293D577FE018127C31A901490F19DD72D0A3212C828EA530B256E563874E03C7003668\
+84568B2F58B0478B8953F5A667E070BDC386404C47A45A862626D7F621C5E87C3F48A15B\
+8F7DFA5EC168ACBEE32E08551DC7AB5826F42A75CE8A0A61BB9E1F4AD5BE53AC87687961\
+388BB809ECEFDDD93782A956F9976242B20B1C2B5EAE31D28B48A44337AC677C6B865D89\
+954E1159353FCFA1741C287FEE15473CB4004E400FAF336995004964A79E2EB0FDF48C2E\
+A09120126443E8771F9700718BC94E5070DA8DAC17BB3F73555F3942AAC1C2830371D641\
+7EE51EBCB1ACB8B4C74BAAE38E6CED7F7622388FBE2B2153DB6945B77AADCF7DC99502D6:\
+BA516D7A4B7638995562CE54FEFC84B6DFB4B8A81A03F24BB065B060E4FA2966:\
+23C93FBB6EF742A576769819A5BC6AC3
+
# MARKER: Cipher Modes (Decryption)
# Cipher mode format is plaintext:ciphertext:key:iv
@@ -24901,6 +25555,37 @@ E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF277:\
4E6F77206973207468652074696D6520666F7220616C6C20:\
0123456789ABCDEF:1234567890ABCDEF
+[Serpent/ECB/NoPadding]
+B2288B968AE8B08648D1CE9606FD992D717EB02EB81A2E939D54ACA91087112D\
+0D809C5EE82F477EBA7B956DBB23463B0F0190D616F5294112FFB7884E8B37F9\
+41BA1B505386B7428B88338188F7E718A3348230BF5CFA552F88D22463D9703A\
+115351622E016BCA26918D17E13225F67EE4E3F2C46FE52ECBDA044C585717DC\
+563A8403FF5309D62370B1DCF5A11EDD2F7D73602B70CD2553E44C1D3F170126\
+155BBD9BE3A965B345E834718F651CEF6CC65E8C5C566E894817350F497816F1\
+EEFA51FC91FEBB6E9F8CB141CC0EB6AF3C6F8380CBD3C996167F2F0E90E71B75\
+6C87EB62A4975356B28DCBF6A64A0BD107206D48FE6DBE19D50314B90AC87B83\
+35706F9B26007071AD8105CFAA1C1E2FF7FEAE5CEC4D11477F24E6B200906870\
+3C0E29E2950F2AC2DACD63DEEB5C7EFA9FDB9F3B740563D5518287DC981FC9CB\
+46D4B5A5A86FEC08FE70D18297DCF51072DDBE038DA040EBB12C509F5940A212\
+DDEB59F02132BE4581FC23EABAA960D6341D9352E36DFD6E4EAF0F6F439BC8CE\
+73A9AB3164FF30350F2DC08E939A104D6DF0C2C28F8E2D44468A61278BB6B429\
+4DAE45AE0CAA032FC97CD4D8C57FB83BBA8AFCAE22070BC882D3A42B38A09E65:\
+D29D576FCEA3A3A7ED9099F29273D78E2D62A890CEA3A3A7ED9099F29273D78E\
+D29D576F315C5C58ED9099F29273D78E2D62A890315C5C58ED9099F29273D78E\
+D29D576FCEA3A3A7126F660D9273D78E2D62A890CEA3A3A7126F660D9273D78E\
+D29D576F315C5C58126F660D9273D78E2D62A890315C5C58126F660D9273D78E\
+D29D576FCEA3A3A7ED9099F26D8C28712D62A890CEA3A3A7ED9099F26D8C2871\
+D29D576F315C5C58ED9099F26D8C28712D62A890315C5C58ED9099F26D8C2871\
+D29D576FCEA3A3A7126F660D6D8C28712D62A890CEA3A3A7126F660D6D8C2871\
+D29D576F315C5C58126F660D6D8C28712D62A890315C5C58126F660D6D8C2871\
+AA26D561F567520E8AE47528C24C18D731A2193D9A97FED6922B17AAA6372B74\
+BE5DEBD559E303C9C92B174A5107BBFEB626D8F65EDCCDF3AEE475C8A1837722\
+41DDE7C1F1631F5FDED4F42746471BD651D238BA86176EFE39E4695AAEB73B52\
+EA5926CADAD8018962E469BA920CB8BF1EA9062E4D9CEDD5FAD4F4C7990367A4\
+B966E5C5D2277288C61B96A559CC84AFB6A6583C5AACFCD6212B0BD8AEF3C6A9\
+A11DDBD175639341052B0B384678D8D9352299B71DD880E29D1B96452DB86540:\
+00000000000000000000000000000000
+
[RC5(8)/CBC/PKCS7]
7875DBF6738C64788F34C3C681C99695:FFFFFFFFFFFFFFFF:0102030405:0000000000000000
7875DBF6738C64787CB3F1DF34F948117FD1A023A5BBA217:\
@@ -25799,6 +26484,143 @@ D05BC090A8E04F1B3D3ECDD5BAEC0FD4EDBF9DACE45D6F6A7306E64BE5DD82:\
FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
9A785634120000000000000000000000
+[Serpent/XTS]
+
+EF1F13233DE8092DDE062280F8CA8F480EC61DD555396F41FB8ED9444844F837\
+89933DCF9AEEC1933D3DBB4D54A26C329D7461ECDD009CAF263EDE40007F2673\
+6782D95B629205E87D4747FADA1434EE74DB09505C43230A0E700EFD012A5F80\
+8FC713FB22624AF804FA318BDAC382773E2653B4D576D0BC1A42F9652F56280D\
+A21CF82595137F9C472938F7519B6CC24708FD5409B75C5309E2C85294A2D182\
+2A218D9891D56696ABBF569906CA0452478628A719E3F11AB097D62D3FFB4549\
+576159282232655AB69CE1A4103DA8428F74D73E540A95ACBCF347D4EDD299FE\
+8ED90AB8F09D5D16B35BC5925E0B191DD753E2617B9085F108CE6B445F604CAF\
+2B266D5A10B460DE08A307D7CDE626D84412B8938B24EDBAFD98205978207014\
+4413A7C354F99D89CA475ECB626E7D93687A505B0F3E7D48823E4133E1C59465\
+56D55266A90F8C213ADFB020CA2D55462FA400B26B159306A5D3A4C91815C3E4\
+ECB8545E394099B330659E9B9C188AB09A53838AA8D0119ED9E55837BBDA655C\
+FD4096C4E2227287195602F32A8239D69DF555145F4EFF077F69366416F800DC\
+30C03C50DE4AFA12CFB4A8CD2E86B36D54CB44C3848FAD7917642551A85C76A3\
+A3C616D32B471B5775A1662B997D392D0B091570710B1CCDE49DCEE634EE3BC3\
+BC85ACEBB7F8551DAF5D15EF19A9DCD3CC9C82B46A4B9EFF8AAD0F8971A0F26D\
+C37E2DDBBD7603298654AD6CE0829EB76F0892E81C569A71343BA8EF767B70B8\
+A24ECF342B832483B7C9375D07BDDE2F1D6D4E6D28E997B1CEE1254F70D17F7C\
+24EFB08A3634802B37C8C0081F501EBE9346B9DFF3705A449B5517984DDBC2BC\
+91F626045EE89276C137233D8560B15C11592082D11935FF68A2ED6087527030\
+E4FC31F37680132CC53DAC81DC3636DB5068FBFA3B6923A2DC7CA617707944FC\
+D0CF81D092916AA54D5D26151C259FAA9AFCF9CD77A5E22FEBC019694205A1D3\
+F999E59F00D42F26FB5B9BE68B45F37DD664A2E9BA3336CA8A37BBC7EB452585\
+8FCCD69B746C7B8EFD534AF44028F915743FC858B45DD12D7F637FFFCCB431B3\
+DB609578811A67BB80D954A16B456792084E0E828CAB146A11A84DDBE4C79859\
+C9302FC55EBF8BFE8CD2B6214098549EA67FA52C8E0DF383F3532D87816C7452\
+A7AD571C213307961F786C45FA3AA89A0B66766EF0775904A66BC17DF3EB5646\
+0444EA22EB838A555D58EAE5DD0628581B9709738A1D9B2A3F66D4CA254FDE4D\
+EF8DE858574672F34BAEC851C58E58209C9019A32E0C728A866D04C1A5524689\
+C11C97302E3BE145486887E7E6F11581F6751DEBD01C28CBEE855CB58F69D794\
+5831AE82AF364ADD56CFA0C160CAB270D963CBF82E324409690597D80F152025\
+0B8254B29B09BA74E3700F9E614D37728C373C15C1E92D2674686D811507C34E:\
+53514C69746520666F726D6174203300040001010040202091E4F9BE00000000\
+0000000000000000000000020000000100000000000000000000000100000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+000000000D00000002033B00039F033B00000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000006202071717\
+170181237461626C657465737432746573743203435245415445205441424C45\
+20277465737432272028696420494E5445474552205052494D415259204B4559\
+2C206E616D6520544558542C206372656174696F6E74696D652054455854295F\
+01071715150181217461626C6574657374746573740243524541544520544142\
+4C45202774657374272028696420494E5445474552205052494D415259204B45\
+592C206E616D6520544558542C206372656174696F6E74696D65205445585429:\
+9F7DC5DB8ECF4302325E0A993D761186BD59BD247615E560B704F8C9B6126A85:\
+2B1B7B6EAF72CA6F7F6CD1C0ED88DAD0
+
+3A88A5D687632C9EB390B37C721A2010006D31FC9D4E3D169D242E1E44A317C0\
+675566A5414EC5C5FB19FB10D329C9F8A0250AD8F07880459B98E079FBB1CA58\
+725EABB2CCD6427E14BA01580B402B9EE34C6B23CEE38F5AC5B50A8198C5441E\
+C3955B3290E2F7211C8B2970E3082EBFA1DA9233E0D94923D5F658A6BA1E0E5C\
+7FC01889E3486551180032304FE118BBF7484A487B20B356C89C2DC5C1C8DE94\
+882676B19FF952B3316B9C8C0187B5BF781D894AB1DE6E8537B57CAF45CF23E6\
+9B62B143E1AD9C47483525EB0D89AEAD9CAA731E6FB2A3ADFAB8C05E1F967460\
+B05ECD759B6485AEB2A87F8E9030AD6C01C1E3E7FB468C624C50B2A20A9564FF\
+5E1C164C0ADE0839099FF7AEA385AF3CD07D743B7C0812477AED4EE7EAF09AE2\
+45CB1A646F63A5B4A7741C1B223C73235A973FC08A7DA0B60D5B8BD8DA07C236\
+7DC32CDE9A468DE47570D8FE52BAA8088D75572671F227D8BF5031165581C7D0\
+24535729112182B38ABF9DBA5F15B3EC590A6BE6C4AEB987E851C9A850D8AA8D\
+E7CF93A60E8159130E94BCA5FB252A0089EABEFAB3E2FF77C7CB3193D3123CD2\
+929E336C2E183272F83AE13574A0595591619BCE9FBBBB5D9EAC69B5D8C8BBD1\
+27EA886544BF770DCD8FF9C96F0EBF63F9D9C20FC8F1962CAB0E5FA7D61CF41F\
+4F38A43E402FD91119ACD6F7EBB1BEE6D56C7BA2C014BF64018464E8D3938FC5\
+4F7A8B58A1B86C16859A9CDAFD5604954AC1BA17CC1057481FA8704FD3DA9B3E\
+EC91B850B9DB54B38F59438494A316A0D271D813C8B95FA21FE7776F112327F3\
+21D6DA9E1C2909CEE630856A53140D9905DA751F42BE351FCCEFBC44EB80F086\
+5A3EB6CB14A91471D9B0ACDFF0D65DA1CBB8E17E2234B20BA8D3555627A4356B\
+8C0D0851AB981DBFE79A293C242BF862D8487895D7B86DE8D77810D0AEDEC249\
+6063C9ECDC57B1D3B1B6BC54F9280984D532CF30CECFCF954B5D06DF949E405C\
+A68C12C2BC8584BAE50EAC0F98BD2D1E8B53237F10F414D61E90BF3FE927D950\
+8670D614EB1CFECF00C92AA3F50E2737F7BD3FB91C46D3677FC3F1EE03FE81EA\
+6E7ADCE6FCCF06719BF1385C6608D2F833CB926ADC03339D03CB45996B199BD9\
+C3B18AA60BD9841FBE5331CFF7544BCECFA79E44BAD1F8757DFCCE491267772F\
+0BFB4AE236E19DFE16BD166856851999614F38997EAB29EBA438D10FB7278FF3\
+1334B8AFA0D6CBDCA39DD2ABAF46560805BBD9F7B32A3C551A4BBEFEBABB8906\
+9640C7E310C0DD8BDA60641D2468E2C59933DF671C22B57190F973E8EF85F5C6\
+E05D89E412243366DC2947F3418198FF5A0A38A383354ACDB3B2D79E99E7F734\
+57A9EA05506307CFE13E8BB571B032DE8DD22F3DC33AE338185FC099E9A5693C\
+10B78D140F6B3BCD8F2ACBBADED84941AC3CFC8F2795BD94499B89E92E45B9C1:\
+0D0000000503920003EA03D403BE03A803920000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000140504001B1F7769646765743235\
+74682074696D6532140404001B1F776964676574323474682074696D65321403\
+04001B1F776964676574323372642074696D6532140204001B1F776964676574\
+32326E642074696D6532140104001B1F776964676574323173742074696D6532:\
+9F7DC5DB8ECF4302325E0A993D761186BD59BD247615E560B704F8C9B6126A85:\
+92E8641C3A25F1A79D188D7DA317F4F1
+
+
# MARKER: Stream Ciphers
# Stream cipher format is plaintext:ciphertext:key
diff --git a/configure.py b/configure.py
index 6d7647812..8e37dc4e3 100755
--- a/configure.py
+++ b/configure.py
@@ -36,9 +36,9 @@ class BuildConfigurationInformation(object):
Version information
"""
version_major = 1
- version_minor = 8
- version_patch = 8
- version_so_patch = 8
+ version_minor = 9
+ version_patch = 1
+ version_so_patch = 1
version_suffix = '-dev'
version_string = '%d.%d.%d%s' % (
@@ -115,6 +115,15 @@ def process_command_line(args):
target_group.add_option('--with-endian', metavar='ORDER', default=None,
help='override guess of CPU byte order')
+ target_group.add_option('--with-unaligned-mem',
+ dest='unaligned_mem', action='store_true',
+ default=None,
+ help='enable unaligned memory accesses')
+
+ target_group.add_option('--without-unaligned-mem',
+ dest='unaligned_mem', action='store_false',
+ help=SUPPRESS_HELP)
+
build_group = OptionGroup(parser, 'Build options')
build_group.add_option('--enable-shared', dest='build_shared_lib',
@@ -404,7 +413,7 @@ class ArchInfo(object):
self.submodel_aliases.items(),
key = lambda k: len(k[0]), reverse = True)
- def defines(self, target_submodel, with_endian):
+ def defines(self, target_submodel, with_endian, unaligned_ok):
macros = ['TARGET_ARCH_IS_%s' % (self.basename.upper())]
def form_cpu_macro(cpu_name):
@@ -419,7 +428,12 @@ class ArchInfo(object):
elif self.endian != None:
macros.append('TARGET_CPU_IS_%s_ENDIAN' % (self.endian.upper()))
- macros.append('TARGET_UNALIGNED_LOADSTORE_OK %d' % (self.unaligned_ok))
+ if unaligned_ok is None:
+ unaligned_ok = self.unaligned_ok
+
+ if unaligned_ok:
+ logging.info('Assuming unaligned memory access works on this CPU')
+ macros.append('TARGET_UNALIGNED_LOADSTORE_OK %d' % (unaligned_ok))
return macros
@@ -725,7 +739,8 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
cc.defines(options.with_tr1)),
'target_cpu_defines': make_cpp_macros(
- arch.defines(options.cpu, options.with_endian)),
+ arch.defines(options.cpu, options.with_endian,
+ options.unaligned_mem)),
'include_files': makefile_list(build_config.headers),
diff --git a/doc/examples/package.cpp b/doc/examples/package.cpp
new file mode 100644
index 000000000..981abaa31
--- /dev/null
+++ b/doc/examples/package.cpp
@@ -0,0 +1,61 @@
+
+#include <botan/botan.h>
+#include <botan/serpent.h>
+#include <botan/package.h>
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+using namespace Botan;
+
+std::vector<byte> slurp_file(const std::string& filename)
+ {
+ std::ifstream in(filename.c_str());
+
+ std::vector<byte> out;
+ byte buf[4096] = { 0 };
+
+ while(in.good())
+ {
+ in.read((char*)buf, sizeof(buf));
+ ssize_t got = in.gcount();
+
+ out.insert(out.end(), buf, buf+got);
+ }
+
+ return out;
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " filename\n";
+ return 1;
+ }
+
+ LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ BlockCipher* cipher = new Serpent;
+
+ std::vector<byte> input = slurp_file(argv[1]);
+ std::vector<byte> output(input.size() + cipher->BLOCK_SIZE);
+
+ AllOrNothingTransform::package(rng, new Serpent,
+ &input[0], input.size(),
+ &output[0]);
+
+ std::vector<byte> unpackage_output(output.size() - cipher->BLOCK_SIZE);
+
+ AllOrNothingTransform::unpackage(new Serpent,
+ &output[0], output.size(),
+ &unpackage_output[0]);
+
+ if(unpackage_output == input)
+ std::cout << Package/unpackage worked\n";
+ else
+ std::cout << "Something went wrong :(\n";
+ }
diff --git a/doc/log.txt b/doc/log.txt
index 7183bd8b6..4fa9da368 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -1,4 +1,17 @@
+* 1.9.1-pre, 2009-??-??
+ - Enable SSE2 optimizations under Visual C++
+ - Alter Skein-512 to match the tweaked 1.2 specification
+
+* 1.9.0, 2009-09-09
+ - Add support for parallel invocation of block ciphers where possible
+ - Add SSE2 implementation of Serpent
+ - Add Rivest's package transform (an all or nothing transform)
+ - Minor speedups to the Turing key schedule
+ - Fix processing multiple messages in XTS mode
+ - Add --no-autoload option to configure.py, for minimized builds
+ - The previously used configure.pl script is no longer supported
+
* 1.8.8-dev, 2009-??-??
- Alter Skein-512 to match the tweaked 1.2 specification
diff --git a/configure.pl b/doc/scripts/configure.pl
index bd7e41a3e..bd7e41a3e 100755
--- a/configure.pl
+++ b/doc/scripts/configure.pl
diff --git a/readme.txt b/readme.txt
index 36f2d2043..307344cea 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
-Botan 1.8.8-dev 2009-??-??
+Botan 1.9.1-pre 2009-??-??
Botan is a C++ class library for performing a wide variety of
cryptographic operations.
diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp
index 269c58c3b..3523b19d4 100644
--- a/src/algo_factory/algo_factory.cpp
+++ b/src/algo_factory/algo_factory.cpp
@@ -1,6 +1,6 @@
/*
-Algorithm Factory
-(C) 2008 Jack Lloyd
+* Algorithm Factory
+* (C) 2008 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
diff --git a/src/aont/info.txt b/src/aont/info.txt
new file mode 100644
index 000000000..a0387f358
--- /dev/null
+++ b/src/aont/info.txt
@@ -0,0 +1,17 @@
+realname "All or Nothing Transforms"
+
+define PACKAGE_TRANSFORM
+
+load_on auto
+
+<add>
+package.cpp
+package.h
+</add>
+
+<requires>
+block
+ctr
+rng
+filters
+</requires>
diff --git a/src/aont/package.cpp b/src/aont/package.cpp
new file mode 100644
index 000000000..6c6b56865
--- /dev/null
+++ b/src/aont/package.cpp
@@ -0,0 +1,128 @@
+/*
+* Rivest's Package Tranform
+*
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/package.h>
+#include <botan/pipe.h>
+#include <botan/ctr.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+namespace AllOrNothingTransform {
+
+void package(RandomNumberGenerator& rng,
+ BlockCipher* cipher,
+ const byte input[], u32bit input_len,
+ byte output[])
+ {
+ if(!cipher->valid_keylength(cipher->BLOCK_SIZE))
+ throw Invalid_Argument("AONT::package: Invalid cipher");
+
+ // The all-zero string which is used both as the CTR IV and as K0
+ const std::string all_zeros(cipher->BLOCK_SIZE*2, '0');
+
+ SymmetricKey package_key(rng, cipher->BLOCK_SIZE);
+
+ // takes ownership of cipher object
+ Keyed_Filter* ctr_mode = new CTR_BE(cipher,
+ package_key,
+ InitializationVector(all_zeros));
+
+ Pipe pipe(ctr_mode);
+
+ pipe.process_msg(input, input_len);
+ pipe.read(output, pipe.remaining());
+
+ // Set K0 (the all zero key)
+ cipher->set_key(SymmetricKey(all_zeros));
+
+ SecureVector<byte> buf(cipher->BLOCK_SIZE);
+
+ const u32bit blocks =
+ (input_len + cipher->BLOCK_SIZE - 1) / cipher->BLOCK_SIZE;
+
+ byte* final_block = output + input_len;
+ clear_mem(final_block, cipher->BLOCK_SIZE);
+
+ // XOR the hash blocks into the final block
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ u32bit left = std::min<u32bit>(cipher->BLOCK_SIZE,
+ input_len - cipher->BLOCK_SIZE * i);
+
+ buf.clear();
+ copy_mem(&buf[0], output + cipher->BLOCK_SIZE * i, left);
+
+ for(u32bit j = 0; j != 4; ++j)
+ buf[cipher->BLOCK_SIZE - 1 - j] ^= get_byte(3-j, i);
+
+ cipher->encrypt(buf);
+
+ xor_buf(final_block, buf, cipher->BLOCK_SIZE);
+ }
+
+ // XOR the random package key into the final block
+ xor_buf(final_block, package_key.begin(), cipher->BLOCK_SIZE);
+ }
+
+void unpackage(BlockCipher* cipher,
+ const byte input[], u32bit input_len,
+ byte output[])
+ {
+ if(!cipher->valid_keylength(cipher->BLOCK_SIZE))
+ throw Invalid_Argument("AONT::unpackage: Invalid cipher");
+
+ if(input_len < cipher->BLOCK_SIZE)
+ throw Invalid_Argument("AONT::unpackage: Input too short");
+
+ // The all-zero string which is used both as the CTR IV and as K0
+ const std::string all_zeros(cipher->BLOCK_SIZE*2, '0');
+
+ cipher->set_key(SymmetricKey(all_zeros));
+
+ SecureVector<byte> package_key(cipher->BLOCK_SIZE);
+ SecureVector<byte> buf(cipher->BLOCK_SIZE);
+
+ // Copy the package key (masked with the block hashes)
+ copy_mem(&package_key[0],
+ input + (input_len - cipher->BLOCK_SIZE),
+ cipher->BLOCK_SIZE);
+
+ const u32bit blocks = ((input_len - 1) / cipher->BLOCK_SIZE);
+
+ // XOR the blocks into the package key bits
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ u32bit left = std::min<u32bit>(cipher->BLOCK_SIZE,
+ input_len - cipher->BLOCK_SIZE * (i+1));
+
+ buf.clear();
+ copy_mem(&buf[0], input + cipher->BLOCK_SIZE * i, left);
+
+ for(u32bit j = 0; j != 4; ++j)
+ buf[cipher->BLOCK_SIZE - 1 - j] ^= get_byte(3-j, i);
+
+ cipher->encrypt(buf);
+
+ xor_buf(&package_key[0], buf, cipher->BLOCK_SIZE);
+ }
+
+ // takes ownership of cipher object
+ Pipe pipe(new CTR_BE(cipher,
+ SymmetricKey(package_key),
+ InitializationVector(all_zeros)));
+
+ pipe.process_msg(input, input_len - cipher->BLOCK_SIZE);
+
+ pipe.read(output, pipe.remaining());
+ }
+
+}
+
+}
diff --git a/src/aont/package.h b/src/aont/package.h
new file mode 100644
index 000000000..35d2a23fc
--- /dev/null
+++ b/src/aont/package.h
@@ -0,0 +1,45 @@
+/*
+* Rivest's Package Tranform
+*
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/block_cipher.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+namespace AllOrNothingTransform {
+
+/**
+* Rivest's Package Tranform
+* @arg rng the random number generator to use
+* @arg cipher the block cipher to use
+* @arg input the input data buffer
+* @arg input_len the length of the input data in bytes
+* @arg output the output data buffer (must be at least
+* input_len + cipher->BLOCK_SIZE bytes long)
+*/
+void package(RandomNumberGenerator& rng,
+ BlockCipher* cipher,
+ const byte input[], u32bit input_len,
+ byte output[]);
+
+/**
+* Rivest's Package Tranform (Inversion)
+* @arg rng the random number generator to use
+* @arg cipher the block cipher to use
+* @arg input the input data buffer
+* @arg input_len the length of the input data in bytes
+* @arg output the output data buffer (must be at least
+* input_len - cipher->BLOCK_SIZE bytes long)
+*/
+void unpackage(BlockCipher* cipher,
+ const byte input[], u32bit input_len,
+ byte output[]);
+
+}
+
+}
diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp
index 01e3b94f3..3bbc1f883 100644
--- a/src/benchmark/benchmark.cpp
+++ b/src/benchmark/benchmark.cpp
@@ -57,8 +57,7 @@ bench_block_cipher(BlockCipher* block_cipher,
while(nanoseconds_used < nanoseconds_max)
{
- for(u32bit i = 0; i != in_blocks; ++i)
- block_cipher->encrypt(buf + block_cipher->BLOCK_SIZE * i);
+ block_cipher->encrypt_n(buf, buf, in_blocks);
++reps;
nanoseconds_used = timer.clock() - start;
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;
};
diff --git a/src/build-data/arch/m68k b/src/build-data/arch/m68k
index 27f246abc..759a3dac1 100644
--- a/src/build-data/arch/m68k
+++ b/src/build-data/arch/m68k
@@ -2,6 +2,11 @@ realname "Motorola 680x0"
default_submodel 68020
+endian big
+
+# Except for Coldfire
+#unaligned ok
+
<aliases>
680x0
68k
diff --git a/src/build-data/arch/ppc b/src/build-data/arch/ppc
index 16112f389..e2dfa6ea2 100644
--- a/src/build-data/arch/ppc
+++ b/src/build-data/arch/ppc
@@ -1,6 +1,7 @@
realname "PowerPC"
endian big
+unaligned ok
default_submodel ppc604
diff --git a/src/build-data/arch/s390 b/src/build-data/arch/s390
index 392f51397..312b262c4 100644
--- a/src/build-data/arch/s390
+++ b/src/build-data/arch/s390
@@ -2,6 +2,9 @@ realname "S/390 31-bit"
default_submodel s390
+endian big
+unaligned ok
+
<submodels>
s390
</submodels>
diff --git a/src/build-data/arch/s390x b/src/build-data/arch/s390x
index 49fb0bda7..9fe6bd615 100644
--- a/src/build-data/arch/s390x
+++ b/src/build-data/arch/s390x
@@ -2,6 +2,9 @@ realname "S/390 64-bit"
default_submodel s390x
+endian big
+unaligned ok
+
<submodels>
s390x
</submodels>
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index e4ab0f44b..e0d8368ed 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -22,6 +22,18 @@
#define BOTAN_KARAT_SQR_THRESHOLD 32
#define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64
+/*
+* Toggles for parallel block cipher mode processing
+*
+* CBC and CFB can only use parallel processing in decryption mode
+*/
+#define BOTAN_PARALLEL_BLOCKS_ECB 8
+#define BOTAN_PARALLEL_BLOCKS_CBC 8
+#define BOTAN_PARALLEL_BLOCKS_CFB 8
+#define BOTAN_PARALLEL_BLOCKS_CTR 8
+#define BOTAN_PARALLEL_BLOCKS_EAX 8
+#define BOTAN_PARALLEL_BLOCKS_XTS 8
+
/* PK key consistency checking toggles */
#define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1
#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD 1
diff --git a/src/codec/openpgp/openpgp.cpp b/src/codec/openpgp/openpgp.cpp
index 7f9cf5f9c..bfba828af 100644
--- a/src/codec/openpgp/openpgp.cpp
+++ b/src/codec/openpgp/openpgp.cpp
@@ -7,6 +7,7 @@
#include <botan/openpgp.h>
#include <botan/filters.h>
+#include <botan/basefilt.h>
#include <botan/charset.h>
#include <botan/crc24.h>
diff --git a/src/engine/sse2_eng/eng_sse2.cpp b/src/engine/sse2_eng/eng_sse2.cpp
index c738b3d96..9f68a070e 100644
--- a/src/engine/sse2_eng/eng_sse2.cpp
+++ b/src/engine/sse2_eng/eng_sse2.cpp
@@ -1,6 +1,6 @@
/**
* SSE2 Assembly Engine
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,10 +11,27 @@
#include <botan/sha1_sse2.h>
#endif
+#if defined(BOTAN_HAS_SERPENT_SSE2)
+ #include <botan/serp_sse2.h>
+#endif
+
namespace Botan {
-HashFunction* SSE2_Assembler_Engine::find_hash(const SCAN_Name& request,
- Algorithm_Factory&) const
+BlockCipher*
+SSE2_Assembler_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_SERPENT_SSE2)
+ if(request.algo_name() == "Serpent")
+ return new Serpent_SSE2;
+#endif
+
+ return 0;
+ }
+
+HashFunction*
+SSE2_Assembler_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
{
#if defined(BOTAN_HAS_SHA1_SSE2)
if(request.algo_name() == "SHA-160")
diff --git a/src/engine/sse2_eng/eng_sse2.h b/src/engine/sse2_eng/eng_sse2.h
index 129697e8f..c6b0ce889 100644
--- a/src/engine/sse2_eng/eng_sse2.h
+++ b/src/engine/sse2_eng/eng_sse2.h
@@ -1,6 +1,6 @@
/**
* SSE2 Assembly Engine
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -17,6 +17,9 @@ class BOTAN_DLL SSE2_Assembler_Engine : public Engine
public:
std::string provider_name() const { return "sse2"; }
private:
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
HashFunction* find_hash(const SCAN_Name& reqeust,
Algorithm_Factory&) const;
};
diff --git a/src/engine/sse2_eng/info.txt b/src/engine/sse2_eng/info.txt
index 6242c7fee..7508b9874 100644
--- a/src/engine/sse2_eng/info.txt
+++ b/src/engine/sse2_eng/info.txt
@@ -10,6 +10,14 @@ eng_sse2.h
</add>
<arch>
-ia32
+pentium-m
+pentium4
+prescott
amd64
</arch>
+
+<cc>
+gcc
+icc
+msvc
+</cc>
diff --git a/src/filters/algo_filt.cpp b/src/filters/algo_filt.cpp
index 23f7a20cf..3268276a6 100644
--- a/src/filters/algo_filt.cpp
+++ b/src/filters/algo_filt.cpp
@@ -18,7 +18,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) :
buffer(DEFAULT_BUFFERSIZE)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- base_ptr = cipher = af.make_stream_cipher(sc_name);
+ cipher = af.make_stream_cipher(sc_name);
}
/*
@@ -27,7 +27,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) :
StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) :
buffer(DEFAULT_BUFFERSIZE)
{
- base_ptr = cipher = stream_cipher;
+ cipher = stream_cipher;
}
/*
@@ -38,7 +38,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name,
buffer(DEFAULT_BUFFERSIZE)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- base_ptr = cipher = af.make_stream_cipher(sc_name);
+ cipher = af.make_stream_cipher(sc_name);
cipher->set_key(key);
}
@@ -95,7 +95,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, u32bit len) :
OUTPUT_LENGTH(len)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- base_ptr = mac = af.make_mac(mac_name);
+ mac = af.make_mac(mac_name);
}
/*
@@ -105,7 +105,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key,
u32bit len) : OUTPUT_LENGTH(len)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- base_ptr = mac = af.make_mac(mac_name);
+ mac = af.make_mac(mac_name);
mac->set_key(key);
}
diff --git a/src/filters/basefilt.cpp b/src/filters/basefilt.cpp
index 02dbd8a73..c91a5aa62 100644
--- a/src/filters/basefilt.cpp
+++ b/src/filters/basefilt.cpp
@@ -50,25 +50,4 @@ Fork::Fork(Filter* filters[], u32bit count)
set_next(filters, count);
}
-/*
-* Set the algorithm key
-*/
-void Keyed_Filter::set_key(const SymmetricKey& key)
- {
- if(base_ptr)
- base_ptr->set_key(key);
- else
- throw Invalid_State("Keyed_Filter::set_key: No base algorithm set");
- }
-
-/*
-* Check if a keylength is valid
-*/
-bool Keyed_Filter::valid_keylength(u32bit n) const
- {
- if(base_ptr)
- return base_ptr->valid_keylength(n);
- throw Invalid_State("Keyed_Filter::valid_keylength: No base algorithm set");
- }
-
}
diff --git a/src/filters/basefilt.h b/src/filters/basefilt.h
index 75625abb0..348ad6fd3 100644
--- a/src/filters/basefilt.h
+++ b/src/filters/basefilt.h
@@ -9,7 +9,6 @@
#define BOTAN_BASEFILT_H__
#include <botan/filter.h>
-#include <botan/sym_algo.h>
namespace Botan {
@@ -62,38 +61,6 @@ class BOTAN_DLL Fork : public Fanout_Filter
Fork(Filter* filter_arr[], u32bit length);
};
-/**
-* This class represents keyed filters, i.e. filters that have to be
-* fed with a key in order to function.
-*/
-class BOTAN_DLL Keyed_Filter : public Filter
- {
- public:
-
- /**
- * Set the key of this filter.
- * @param key the key to set
- */
- virtual void set_key(const SymmetricKey& key);
-
- /**
- * Set the initialization vector of this filter.
- * @param iv the initialization vector to set
- */
- virtual void set_iv(const InitializationVector&) {}
-
- /**
- * Check whether a key length is valid for this filter.
- * @param length the key length to be checked for validity
- * @return true if the key length is valid, false otherwise
- */
- virtual bool valid_keylength(u32bit length) const;
-
- Keyed_Filter() { base_ptr = 0; }
- protected:
- SymmetricAlgorithm* base_ptr;
- };
-
}
#endif
diff --git a/src/filters/filters.h b/src/filters/filters.h
index 725651f7d..964be0bd8 100644
--- a/src/filters/filters.h
+++ b/src/filters/filters.h
@@ -15,7 +15,9 @@
#include <botan/pipe.h>
#include <botan/basefilt.h>
+#include <botan/key_filt.h>
#include <botan/data_snk.h>
+
#include <botan/scan_name.h>
#if defined(BOTAN_HAS_BASE64_CODEC)
@@ -36,6 +38,13 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
public:
/**
+ * Write input data
+ * @param input data
+ * @param input_len length of input in bytes
+ */
+ void write(const byte input[], u32bit input_len);
+
+ /**
* Seek in the stream.
* @param position the position to seek ahead
*/
@@ -53,7 +62,20 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
* @param iv the initialization vector to set
*/
void set_iv(const InitializationVector& iv);
- void write(const byte[], u32bit);
+
+ /**
+ * Set the key of this filter.
+ * @param key the key to set
+ */
+ void set_key(const SymmetricKey& key) { cipher->set_key(key); }
+
+ /**
+ * Check whether a key length is valid for this filter.
+ * @param length the key length to be checked for validity
+ * @return true if the key length is valid, false otherwise
+ */
+ bool valid_keylength(u32bit length) const
+ { return cipher->valid_keylength(length); }
/**
* Construct a stream cipher filter.
@@ -126,6 +148,20 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter
void end_msg();
/**
+ * Set the key of this filter.
+ * @param key the key to set
+ */
+ void set_key(const SymmetricKey& key) { mac->set_key(key); }
+
+ /**
+ * Check whether a key length is valid for this filter.
+ * @param length the key length to be checked for validity
+ * @return true if the key length is valid, false otherwise
+ */
+ bool valid_keylength(u32bit length) const
+ { return mac->valid_keylength(length); }
+
+ /**
* Construct a MAC filter. The MAC key will be left empty.
* @param mac the MAC to use
* @param len the output length of this filter. Leave the default
@@ -136,7 +172,7 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter
MAC_Filter(MessageAuthenticationCode* mac_obj,
u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
{
- base_ptr = mac = mac_obj;
+ mac = mac_obj;
}
/**
@@ -152,7 +188,7 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter
const SymmetricKey& key,
u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
{
- base_ptr = mac = mac_obj;
+ mac = mac_obj;
mac->set_key(key);
}
diff --git a/src/filters/info.txt b/src/filters/info.txt
index 79a92a9c5..fb8108659 100644
--- a/src/filters/info.txt
+++ b/src/filters/info.txt
@@ -17,6 +17,7 @@ data_src.h
filter.cpp
filter.h
filters.h
+key_filt.h
out_buf.cpp
out_buf.h
pbe.h
diff --git a/src/filters/key_filt.h b/src/filters/key_filt.h
new file mode 100644
index 000000000..36af91f88
--- /dev/null
+++ b/src/filters/key_filt.h
@@ -0,0 +1,45 @@
+/*
+* Keyed_Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KEYED_FILTER_H__
+#define BOTAN_KEYED_FILTER_H__
+
+#include <botan/filter.h>
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents keyed filters, i.e. filters that have to be
+* fed with a key in order to function.
+*/
+class BOTAN_DLL Keyed_Filter : public Filter
+ {
+ public:
+ /**
+ * Set the key of this filter.
+ * @param key the key to set
+ */
+ virtual void set_key(const SymmetricKey& key) = 0;
+
+ /**
+ * Set the initialization vector of this filter.
+ * @param iv the initialization vector to set
+ */
+ virtual void set_iv(const InitializationVector&) {}
+
+ /**
+ * Check whether a key length is valid for this filter.
+ * @param length the key length to be checked for validity
+ * @return true if the key length is valid, false otherwise
+ */
+ virtual bool valid_keylength(u32bit length) const = 0;
+ };
+
+}
+
+#endif
diff --git a/src/hash/sha1_sse2/info.txt b/src/hash/sha1_sse2/info.txt
index b8d693b70..995c2513e 100644
--- a/src/hash/sha1_sse2/info.txt
+++ b/src/hash/sha1_sse2/info.txt
@@ -10,18 +10,6 @@ sha1_sse2.cpp
sha1_sse2.h
</add>
-<arch>
-pentium-m
-pentium4
-prescott
-amd64
-</arch>
-
-<cc>
-gcc
-icc
-</cc>
-
<requires>
sha1
sse2_eng
diff --git a/src/hash/sha1_sse2/sha1_sse2_imp.cpp b/src/hash/sha1_sse2/sha1_sse2_imp.cpp
index 90a8dccd5..57b287bdb 100644
--- a/src/hash/sha1_sse2/sha1_sse2_imp.cpp
+++ b/src/hash/sha1_sse2/sha1_sse2_imp.cpp
@@ -20,8 +20,10 @@
* on a Linux/Core2 system.
*/
+
#include <botan/sha1_sse2.h>
-#include <xmmintrin.h>
+#include <botan/rotate.h>
+#include <emmintrin.h>
namespace Botan {
@@ -30,21 +32,13 @@ namespace {
typedef union {
u32bit u32[4];
__m128i u128;
- } v4si __attribute__((aligned(16)));
+ } v4si;
static const v4si K00_19 = { { 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999 } };
static const v4si K20_39 = { { 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1 } };
static const v4si K40_59 = { { 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc } };
static const v4si K60_79 = { { 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 } };
-#define UNALIGNED 1
-#if UNALIGNED
-#define load(p) _mm_loadu_si128(p)
-#else
-#define load(p) (*p)
-#endif
-
-
/*
the first 16 bytes only need byte swapping
@@ -57,19 +51,15 @@ and is overwritten with the swapped bytes
__m128i r1, r2; \
\
r1 = (W); \
- if (1) { \
r1 = _mm_shufflehi_epi16(r1, _MM_SHUFFLE(2, 3, 0, 1)); \
r1 = _mm_shufflelo_epi16(r1, _MM_SHUFFLE(2, 3, 0, 1)); \
r2 = _mm_slli_epi16(r1, 8); \
r1 = _mm_srli_epi16(r1, 8); \
r1 = _mm_or_si128(r1, r2); \
(W) = r1; \
- } \
(prep).u128 = _mm_add_epi32(K00_19.u128, r1); \
} while(0)
-
-
/*
for each multiple of 4, t, we want to calculate this:
@@ -115,45 +105,38 @@ W0 = W[t]..W[t+3]
* efficeon, pentium-m, and opteron but shifts are available in
* only one unit.
*/
-#define prep(prep, XW0, XW1, XW2, XW3, K) do { \
- __m128i r0, r1, r2, r3; \
- \
- /* load W[t-4] 16-byte aligned, and shift */ \
- r3 = _mm_srli_si128((XW3), 4); \
- r0 = (XW0); \
- /* get high 64-bits of XW0 into low 64-bits */ \
- r1 = _mm_shuffle_epi32((XW0), _MM_SHUFFLE(1,0,3,2)); \
- /* load high 64-bits of r1 */ \
- r1 = _mm_unpacklo_epi64(r1, (XW1)); \
- r2 = (XW2); \
- \
- r0 = _mm_xor_si128(r1, r0); \
- r2 = _mm_xor_si128(r3, r2); \
- r0 = _mm_xor_si128(r2, r0); \
- /* unrotated W[t]..W[t+2] in r0 ... still need W[t+3] */ \
- \
- r2 = _mm_slli_si128(r0, 12); \
- r1 = _mm_cmplt_epi32(r0, _mm_setzero_si128()); \
- r0 = _mm_add_epi32(r0, r0); /* shift left by 1 */ \
- r0 = _mm_sub_epi32(r0, r1); /* r0 has W[t]..W[t+2] */ \
- \
- r3 = _mm_srli_epi32(r2, 30); \
- r2 = _mm_slli_epi32(r2, 2); \
- \
- r0 = _mm_xor_si128(r0, r3); \
- r0 = _mm_xor_si128(r0, r2); /* r0 now has W[t+3] */ \
- \
- (XW0) = r0; \
- (prep).u128 = _mm_add_epi32(r0, (K).u128); \
- } while(0)
-
-
-static inline u32bit rol(u32bit src, u32bit amt)
- {
- /* gcc and icc appear to turn this into a rotate */
- return (src << amt) | (src >> (32 - amt));
- }
-
+#define prep(prep, XW0, XW1, XW2, XW3, K) \
+ do { \
+ __m128i r0, r1, r2, r3; \
+ \
+ /* load W[t-4] 16-byte aligned, and shift */ \
+ r3 = _mm_srli_si128((XW3), 4); \
+ r0 = (XW0); \
+ /* get high 64-bits of XW0 into low 64-bits */ \
+ r1 = _mm_shuffle_epi32((XW0), _MM_SHUFFLE(1,0,3,2)); \
+ /* load high 64-bits of r1 */ \
+ r1 = _mm_unpacklo_epi64(r1, (XW1)); \
+ r2 = (XW2); \
+ \
+ r0 = _mm_xor_si128(r1, r0); \
+ r2 = _mm_xor_si128(r3, r2); \
+ r0 = _mm_xor_si128(r2, r0); \
+ /* unrotated W[t]..W[t+2] in r0 ... still need W[t+3] */ \
+ \
+ r2 = _mm_slli_si128(r0, 12); \
+ r1 = _mm_cmplt_epi32(r0, _mm_setzero_si128()); \
+ r0 = _mm_add_epi32(r0, r0); /* shift left by 1 */ \
+ r0 = _mm_sub_epi32(r0, r1); /* r0 has W[t]..W[t+2] */ \
+ \
+ r3 = _mm_srli_epi32(r2, 30); \
+ r2 = _mm_slli_epi32(r2, 2); \
+ \
+ r0 = _mm_xor_si128(r0, r3); \
+ r0 = _mm_xor_si128(r0, r2); /* r0 now has W[t+3] */ \
+ \
+ (XW0) = r0; \
+ (prep).u128 = _mm_add_epi32(r0, (K).u128); \
+ } while(0)
static inline u32bit f00_19(u32bit x, u32bit y, u32bit z)
{
@@ -184,11 +167,12 @@ static inline u32bit f60_79(u32bit x, u32bit y, u32bit z)
return f20_39(x, y, z);
}
-#define step(nn_mm, xa, xb, xc, xd, xe, xt, input) do { \
- (xt) = (input) + f##nn_mm((xb), (xc), (xd)); \
- (xb) = rol((xb), 30); \
- (xt) += ((xe) + rol((xa), 5)); \
- } while(0)
+#define step(nn_mm, xa, xb, xc, xd, xe, xt, input) \
+ do { \
+ (xt) = (input) + f##nn_mm((xb), (xc), (xd)); \
+ (xb) = rotate_left((xb), 30); \
+ (xt) += ((xe) + rotate_left((xa), 5)); \
+ } while(0)
}
@@ -210,14 +194,14 @@ extern "C" void botan_sha1_sse2_compress(u32bit H[5],
* steps ahead of the integer code. 12 steps ahead seems
* to produce the best performance. -dean
*/
- W0 = load(&input[0]);
+ W0 = _mm_loadu_si128(&input[0]);
prep00_15(prep0, W0); /* prepare for 00 through 03 */
- W1 = load(&input[1]);
+ W1 = _mm_loadu_si128(&input[1]);
prep00_15(prep1, W1); /* prepare for 04 through 07 */
- W2 = load(&input[2]);
+ W2 = _mm_loadu_si128(&input[2]);
prep00_15(prep2, W2); /* prepare for 08 through 11 */
- W3 = load(&input[3]);
+ W3 = _mm_loadu_si128(&input[3]);
step(00_19, a, b, c, d, e, t, prep0.u32[0]); /* 00 */
step(00_19, t, a, b, c, d, e, prep0.u32[1]); /* 01 */
step(00_19, e, t, a, b, c, d, prep0.u32[2]); /* 02 */
diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp
index 3275c6493..20e736868 100644
--- a/src/libstate/libstate.cpp
+++ b/src/libstate/libstate.cpp
@@ -212,7 +212,7 @@ std::string Library_State::deref_alias(const std::string& key) const
/*
* Set/Add an option
*/
-void Library_State::set_option(const std::string key,
+void Library_State::set_option(const std::string& key,
const std::string& value)
{
set("conf", key, value);
diff --git a/src/libstate/libstate.h b/src/libstate/libstate.h
index 2493863a9..a0421953e 100644
--- a/src/libstate/libstate.h
+++ b/src/libstate/libstate.h
@@ -77,7 +77,7 @@ class BOTAN_DLL Library_State
* @param key the key of the option to set
* @param value the value to set
*/
- void set_option(const std::string key, const std::string& value);
+ void set_option(const std::string& key, const std::string& value);
/**
* Add a parameter value to the "alias" section.
diff --git a/src/libstate/scan_name.cpp b/src/libstate/scan_name.cpp
index ef771871d..88992d66e 100644
--- a/src/libstate/scan_name.cpp
+++ b/src/libstate/scan_name.cpp
@@ -1,6 +1,6 @@
/**
-SCAN Name Abstraction
-(C) 2008 Jack Lloyd
+* SCAN Name Abstraction
+* (C) 2008 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h
index 9e7af40d6..b3f2004e2 100644
--- a/src/libstate/scan_name.h
+++ b/src/libstate/scan_name.h
@@ -1,6 +1,6 @@
/**
-SCAN Name Abstraction
-(C) 2008 Jack Lloyd
+* SCAN Name Abstraction
+* (C) 2008 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
diff --git a/src/mac/mac.cpp b/src/mac/mac.cpp
index 96df25503..04b259647 100644
--- a/src/mac/mac.cpp
+++ b/src/mac/mac.cpp
@@ -1,6 +1,6 @@
/**
-Message Authentication Code base class
-(C) 1999-2008 Jack Lloyd
+* Message Authentication Code base class
+* (C) 1999-2008 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
diff --git a/src/modes/ctr/ctr.cpp b/src/modes/ctr/ctr.cpp
index 9eb42ec5a..d458d7848 100644
--- a/src/modes/ctr/ctr.cpp
+++ b/src/modes/ctr/ctr.cpp
@@ -1,6 +1,6 @@
/*
* CTR Mode
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,12 +11,21 @@
namespace Botan {
+namespace {
+
+const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_CTR;
+
+}
+
/*
* CTR-BE Constructor
*/
-CTR_BE::CTR_BE(BlockCipher* ciph) :
- BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1)
+CTR_BE::CTR_BE(BlockCipher* ciph) : cipher(ciph)
{
+ position = 0;
+
+ counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS);
+ enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS);
}
/*
@@ -24,39 +33,88 @@ CTR_BE::CTR_BE(BlockCipher* ciph) :
*/
CTR_BE::CTR_BE(BlockCipher* ciph, const SymmetricKey& key,
const InitializationVector& iv) :
- BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1)
+ cipher(ciph)
{
- set_key(key);
+ position = 0;
+
+ counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS);
+ enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS);
+
+ cipher->set_key(key);
set_iv(iv);
}
/*
+* CTR_BE Destructor
+*/
+CTR_BE::~CTR_BE()
+ {
+ delete cipher;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CTR_BE::name() const
+ {
+ return ("CTR-BE/" + cipher->name());
+ }
+
+/*
+* Set CTR-BE IV
+*/
+void CTR_BE::set_iv(const InitializationVector& iv)
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ if(iv.length() != BLOCK_SIZE)
+ throw Invalid_IV_Length(name(), iv.length());
+
+ enc_buffer.clear();
+ position = 0;
+
+ counter.copy(0, iv.begin(), iv.length());
+
+ for(u32bit i = 1; i != PARALLEL_BLOCKS; ++i)
+ {
+ counter.copy(i*BLOCK_SIZE,
+ counter.begin() + (i-1)*BLOCK_SIZE, BLOCK_SIZE);
+
+ for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j)
+ if(++counter[i*BLOCK_SIZE+j])
+ break;
+ }
+
+ cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS);
+ }
+
+/*
* CTR-BE Encryption/Decryption
*/
void CTR_BE::write(const byte input[], u32bit length)
{
- u32bit copied = std::min(BLOCK_SIZE - position, length);
- xor_buf(buffer + position, input, copied);
- send(buffer + position, copied);
+ u32bit copied = std::min(enc_buffer.size() - position, length);
+ xor_buf(enc_buffer + position, input, copied);
+ send(enc_buffer + position, copied);
input += copied;
length -= copied;
position += copied;
- if(position == BLOCK_SIZE)
+ if(position == enc_buffer.size())
increment_counter();
- while(length >= BLOCK_SIZE)
+ while(length >= enc_buffer.size())
{
- xor_buf(buffer, input, BLOCK_SIZE);
- send(buffer, BLOCK_SIZE);
+ xor_buf(enc_buffer, input, enc_buffer.size());
+ send(enc_buffer, enc_buffer.size());
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
+ input += enc_buffer.size();
+ length -= enc_buffer.size();
increment_counter();
}
- xor_buf(buffer + position, input, length);
- send(buffer + position, length);
+ xor_buf(enc_buffer + position, input, length);
+ send(enc_buffer + position, length);
position += length;
}
@@ -65,10 +123,23 @@ void CTR_BE::write(const byte input[], u32bit length)
*/
void CTR_BE::increment_counter()
{
- for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j)
- if(++state[j])
- break;
- cipher->encrypt(state, buffer);
+ for(u32bit i = 0; i != PARALLEL_BLOCKS; ++i)
+ {
+ byte* this_ctr = counter + i*cipher->BLOCK_SIZE;
+
+ byte last_byte = this_ctr[cipher->BLOCK_SIZE-1];
+ last_byte += PARALLEL_BLOCKS;
+
+ if(this_ctr[cipher->BLOCK_SIZE-1] > last_byte)
+ for(s32bit j = cipher->BLOCK_SIZE - 2; j >= 0; --j)
+ if(++this_ctr[j])
+ break;
+
+ this_ctr[cipher->BLOCK_SIZE-1] = last_byte;
+ }
+
+ cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS);
+
position = 0;
}
diff --git a/src/modes/ctr/ctr.h b/src/modes/ctr/ctr.h
index aa0db5761..1948ffe48 100644
--- a/src/modes/ctr/ctr.h
+++ b/src/modes/ctr/ctr.h
@@ -8,22 +8,37 @@
#ifndef BOTAN_COUNTER_MODE_H__
#define BOTAN_COUNTER_MODE_H__
-#include <botan/modebase.h>
-#include <botan/modebase.h>
+#include <botan/key_filt.h>
+#include <botan/block_cipher.h>
namespace Botan {
/*
* CTR-BE Mode
*/
-class BOTAN_DLL CTR_BE : public BlockCipherMode
+class BOTAN_DLL CTR_BE : public Keyed_Filter
{
public:
+ std::string name() const;
+
+ void set_iv(const InitializationVector&);
+
+ void set_key(const SymmetricKey& key) { cipher->set_key(key); }
+
+ bool valid_keylength(u32bit key_len) const
+ { return cipher->valid_keylength(key_len); }
+
CTR_BE(BlockCipher*);
CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&);
+
+ ~CTR_BE();
private:
void write(const byte[], u32bit);
void increment_counter();
+
+ BlockCipher* cipher;
+ SecureVector<byte> counter, enc_buffer;
+ u32bit position;
};
}
diff --git a/src/modes/eax/eax.h b/src/modes/eax/eax.h
index 1bb2e510d..f569f2ede 100644
--- a/src/modes/eax/eax.h
+++ b/src/modes/eax/eax.h
@@ -8,7 +8,7 @@
#ifndef BOTAN_EAX_H__
#define BOTAN_EAX_H__
-#include <botan/basefilt.h>
+#include <botan/key_filt.h>
#include <botan/block_cipher.h>
#include <botan/mac.h>
diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp
index 8da0a4802..988a8b3f2 100644
--- a/src/modes/ecb/ecb.cpp
+++ b/src/modes/ecb/ecb.cpp
@@ -9,22 +9,60 @@
namespace Botan {
+namespace {
+
+const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_ECB;
+
+}
+
/*
-* Verify the IV is not set
+* ECB_Encryption Constructor
*/
-bool ECB::valid_iv_size(u32bit iv_size) const
+ECB_Encryption::ECB_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad)
{
- if(iv_size == 0)
- return true;
- return false;
+ cipher = ciph;
+ padder = pad;
+
+ plaintext.create(cipher->BLOCK_SIZE);
+ ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
+
+ position = 0;
+ }
+
+/*
+* ECB_Encryption Constructor
+*/
+ECB_Encryption::ECB_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key)
+ {
+ cipher = ciph;
+ padder = pad;
+
+ plaintext.create(cipher->BLOCK_SIZE);
+ ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
+
+ position = 0;
+
+ cipher->set_key(key);
+ }
+
+/*
+* ECB_Encryption Destructor
+*/
+ECB_Encryption::~ECB_Encryption()
+ {
+ delete cipher;
+ delete padder;
}
/*
* Return an ECB mode name
*/
-std::string ECB::name() const
+std::string ECB_Encryption::name() const
{
- return (cipher->name() + "/" + mode_name + "/" + padder->name());
+ return (cipher->name() + "/ECB/" + padder->name());
}
/*
@@ -32,23 +70,34 @@ std::string ECB::name() const
*/
void ECB_Encryption::write(const byte input[], u32bit length)
{
- buffer.copy(position, input, length);
- if(position + length >= BLOCK_SIZE)
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ if(position)
{
- cipher->encrypt(buffer);
- send(buffer, BLOCK_SIZE);
- input += (BLOCK_SIZE - position);
- length -= (BLOCK_SIZE - position);
- while(length >= BLOCK_SIZE)
+ plaintext.copy(position, input, length);
+
+ if(position + length >= BLOCK_SIZE)
{
- cipher->encrypt(input, buffer);
- send(buffer, BLOCK_SIZE);
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
+ cipher->encrypt(plaintext, ciphertext);
+ send(ciphertext, BLOCK_SIZE);
+ input += (BLOCK_SIZE - position);
+ length -= (BLOCK_SIZE - position);
+ position = 0;
}
- buffer.copy(input, length);
- position = 0;
}
+
+ while(length >= BLOCK_SIZE)
+ {
+ const u32bit to_proc =
+ std::min<u32bit>(length, ciphertext.size()) / BLOCK_SIZE;
+
+ cipher->encrypt_n(input, ciphertext, to_proc);
+ send(ciphertext, to_proc * BLOCK_SIZE);
+ input += to_proc * BLOCK_SIZE;
+ length -= to_proc * BLOCK_SIZE;
+ }
+
+ plaintext.copy(position, input, length);
position += length;
}
@@ -57,6 +106,8 @@ void ECB_Encryption::write(const byte input[], u32bit length)
*/
void ECB_Encryption::end_msg()
{
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
SecureVector<byte> padding(BLOCK_SIZE);
padder->pad(padding, padding.size(), position);
write(padding, padder->pad_bytes(BLOCK_SIZE, position));
@@ -65,27 +116,93 @@ void ECB_Encryption::end_msg()
}
/*
+* ECB_Decryption Constructor
+*/
+ECB_Decryption::ECB_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad)
+ {
+ cipher = ciph;
+ padder = pad;
+
+ ciphertext.create(cipher->BLOCK_SIZE);
+ plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
+
+ position = 0;
+ }
+
+/*
+* ECB_Decryption Constructor
+*/
+ECB_Decryption::ECB_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key)
+ {
+ cipher = ciph;
+ padder = pad;
+
+ ciphertext.create(cipher->BLOCK_SIZE);
+ plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
+
+ position = 0;
+
+ cipher->set_key(key);
+ }
+
+/*
+* ECB_Decryption Destructor
+*/
+ECB_Decryption::~ECB_Decryption()
+ {
+ delete cipher;
+ delete padder;
+ }
+
+/*
+* Return an ECB mode name
+*/
+std::string ECB_Decryption::name() const
+ {
+ return (cipher->name() + "/ECB/" + padder->name());
+ }
+
+/*
* Decrypt in ECB mode
*/
void ECB_Decryption::write(const byte input[], u32bit length)
{
- buffer.copy(position, input, length);
- if(position + length > BLOCK_SIZE)
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ if(position)
{
- cipher->decrypt(buffer);
- send(buffer, BLOCK_SIZE);
- input += (BLOCK_SIZE - position);
- length -= (BLOCK_SIZE - position);
- while(length > BLOCK_SIZE)
+ ciphertext.copy(position, input, length);
+
+ if(position + length > BLOCK_SIZE)
{
- cipher->decrypt(input, buffer);
- send(buffer, BLOCK_SIZE);
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
+ cipher->decrypt(ciphertext, plaintext);
+ send(plaintext, BLOCK_SIZE);
+ input += (BLOCK_SIZE - position);
+ length -= (BLOCK_SIZE - position);
+ position = 0;
}
- buffer.copy(input, length);
- position = 0;
}
+
+ while(length > BLOCK_SIZE)
+ {
+ /* Always leave at least 1 byte left over, to ensure that (as long
+ as the input message actually is a multiple of the block size)
+ we will have the full final block left over in end_msg so as
+ to remove the padding
+ */
+ const u32bit to_proc =
+ std::min<u32bit>(length - 1, plaintext.size()) / BLOCK_SIZE;
+
+ cipher->decrypt_n(input, plaintext, to_proc);
+ send(plaintext, to_proc * BLOCK_SIZE);
+ input += to_proc * BLOCK_SIZE;
+ length -= to_proc * BLOCK_SIZE;
+ }
+
+ ciphertext.copy(position, input, length);
position += length;
}
@@ -94,11 +211,11 @@ void ECB_Decryption::write(const byte input[], u32bit length)
*/
void ECB_Decryption::end_msg()
{
- if(position != BLOCK_SIZE)
+ if(position != cipher->BLOCK_SIZE)
throw Decoding_Error(name());
- cipher->decrypt(buffer);
- send(buffer, padder->unpad(buffer, BLOCK_SIZE));
- state = buffer;
+
+ cipher->decrypt(ciphertext);
+ send(ciphertext, padder->unpad(ciphertext, cipher->BLOCK_SIZE));
position = 0;
}
diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h
index 5230f9b14..ff9ea9635 100644
--- a/src/modes/ecb/ecb.h
+++ b/src/modes/ecb/ecb.h
@@ -1,6 +1,6 @@
/*
* ECB Mode
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -8,64 +8,74 @@
#ifndef BOTAN_ECB_H__
#define BOTAN_ECB_H__
-#include <botan/modebase.h>
-#include <botan/mode_pad.h>
+#include <botan/basefilt.h>
#include <botan/block_cipher.h>
+#include <botan/mode_pad.h>
-namespace Botan {
-
-/*
-* ECB
-*/
-class BOTAN_DLL ECB : public BlockCipherMode
- {
- protected:
- ECB(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) :
- BlockCipherMode(ciph, "ECB", 0), padder(pad) {}
- ~ECB() { delete padder; }
+#include <botan/modebase.h>
- std::string name() const;
- BlockCipherModePaddingMethod* padder;
- private:
- bool valid_iv_size(u32bit) const;
- };
+namespace Botan {
/*
* ECB Encryption
*/
-class BOTAN_DLL ECB_Encryption : public ECB
+class BOTAN_DLL ECB_Encryption : public Keyed_Filter
{
public:
+ std::string name() const;
+
+ void set_key(const SymmetricKey& key) { cipher->set_key(key); }
+
+ bool valid_keylength(u32bit key_len) const
+ { return cipher->valid_keylength(key_len); }
+
ECB_Encryption(BlockCipher* ciph,
- BlockCipherModePaddingMethod* pad) :
- ECB(ciph, pad) {}
+ BlockCipherModePaddingMethod* pad);
ECB_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
- const SymmetricKey& key) :
- ECB(ciph, pad) { set_key(key); }
+ const SymmetricKey& key);
+
+ ~ECB_Encryption();
private:
void write(const byte[], u32bit);
void end_msg();
+
+ BlockCipher* cipher;
+ BlockCipherModePaddingMethod* padder;
+ SecureVector<byte> plaintext, ciphertext;
+ u32bit position;
};
/*
* ECB Decryption
*/
-class BOTAN_DLL ECB_Decryption : public ECB
+class BOTAN_DLL ECB_Decryption : public Keyed_Filter
{
public:
+ std::string name() const;
+
+ void set_key(const SymmetricKey& key) { cipher->set_key(key); }
+
+ bool valid_keylength(u32bit key_len) const
+ { return cipher->valid_keylength(key_len); }
+
ECB_Decryption(BlockCipher* ciph,
- BlockCipherModePaddingMethod* pad) :
- ECB(ciph, pad) {}
+ BlockCipherModePaddingMethod* pad);
ECB_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
- const SymmetricKey& key) :
- ECB(ciph, pad) { set_key(key); }
+ const SymmetricKey& key);
+
+ ~ECB_Decryption();
private:
void write(const byte[], u32bit);
void end_msg();
+
+ BlockCipher* cipher;
+ BlockCipherModePaddingMethod* padder;
+ SecureVector<byte> plaintext, ciphertext;
+ u32bit position;
};
}
diff --git a/src/modes/modebase.cpp b/src/modes/modebase.cpp
index 8293acc54..b048862a4 100644
--- a/src/modes/modebase.cpp
+++ b/src/modes/modebase.cpp
@@ -19,7 +19,7 @@ BlockCipherMode::BlockCipherMode(BlockCipher* cipher_ptr,
BLOCK_SIZE(cipher_ptr->BLOCK_SIZE), BUFFER_SIZE(buf_mult * BLOCK_SIZE),
IV_METHOD(iv_meth), mode_name(cipher_mode_name)
{
- base_ptr = cipher = cipher_ptr;
+ cipher = cipher_ptr;
buffer.create(BUFFER_SIZE);
state.create(iv_size);
position = 0;
diff --git a/src/modes/modebase.h b/src/modes/modebase.h
index 173fde58c..4a15524b6 100644
--- a/src/modes/modebase.h
+++ b/src/modes/modebase.h
@@ -8,7 +8,7 @@
#ifndef BOTAN_MODEBASE_H__
#define BOTAN_MODEBASE_H__
-#include <botan/basefilt.h>
+#include <botan/key_filt.h>
#include <botan/block_cipher.h>
namespace Botan {
@@ -21,12 +21,17 @@ class BOTAN_DLL BlockCipherMode : public Keyed_Filter
public:
std::string name() const;
+ void set_iv(const InitializationVector&);
+ void set_key(const SymmetricKey& key) { cipher->set_key(key); }
+
+ bool valid_keylength(u32bit key_len) const
+ { return cipher->valid_keylength(key_len); }
+
BlockCipherMode(BlockCipher*, const std::string&,
u32bit, u32bit = 0, u32bit = 1);
virtual ~BlockCipherMode() { delete cipher; }
protected:
- void set_iv(const InitializationVector&);
const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD;
const std::string mode_name;
BlockCipher* cipher;
diff --git a/src/modes/xts/xts.h b/src/modes/xts/xts.h
index 01558175b..9badd3666 100644
--- a/src/modes/xts/xts.h
+++ b/src/modes/xts/xts.h
@@ -8,7 +8,7 @@
#ifndef BOTAN_XTS_H__
#define BOTAN_XTS_H__
-#include <botan/basefilt.h>
+#include <botan/key_filt.h>
#include <botan/block_cipher.h>
namespace Botan {
@@ -22,6 +22,9 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter
void set_key(const SymmetricKey& key);
void set_iv(const InitializationVector& iv);
+ bool valid_keylength(u32bit key_len) const
+ { return cipher->valid_keylength(key_len); }
+
std::string name() const;
XTS_Encryption(BlockCipher* ciph);
@@ -52,6 +55,9 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter
void set_key(const SymmetricKey& key);
void set_iv(const InitializationVector& iv);
+ bool valid_keylength(u32bit key_len) const
+ { return cipher->valid_keylength(key_len); }
+
std::string name() const;
XTS_Decryption(BlockCipher* ciph);
diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp
index 171c83cca..07b2ddec2 100644
--- a/src/rng/auto_rng/auto_rng.cpp
+++ b/src/rng/auto_rng/auto_rng.cpp
@@ -140,7 +140,7 @@ AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits)
#endif
if(!rng)
- throw Algorithm_Not_Found("No usable RNG found enabled in build");
+ throw Internal_Error("No usable RNG found enabled in build");
/* If X9.31 is available, use it to wrap the other RNG as a failsafe */
#if defined(BOTAN_HAS_X931_RNG)
diff --git a/src/stream/turing/turing.cpp b/src/stream/turing/turing.cpp
index b988568c3..1e2203480 100644
--- a/src/stream/turing/turing.cpp
+++ b/src/stream/turing/turing.cpp
@@ -218,25 +218,6 @@ u32bit Turing::fixedS(u32bit W)
}
/*
-* Generate the expanded Turing Sbox tables
-*/
-void Turing::gen_sbox(MemoryRegion<u32bit>& S, u32bit which,
- const MemoryRegion<u32bit>& K)
- {
- for(u32bit j = 0; j != 256; ++j)
- {
- u32bit W = 0, C = j;
-
- for(u32bit k = 0; k < K.size(); ++k)
- {
- C = SBOX[get_byte(which, K[k]) ^ C];
- W ^= rotate_left(Q_BOX[C], k + 8*which);
- }
- S[j] = (W & rotate_right(0x00FFFFFF, 8*which)) | (C << (24 - 8*which));
- }
- }
-
-/*
* Turing Key Schedule
*/
void Turing::key_schedule(const byte key[], u32bit length)
@@ -250,10 +231,31 @@ void Turing::key_schedule(const byte key[], u32bit length)
PHT(K);
- gen_sbox(S0, 0, K);
- gen_sbox(S1, 1, K);
- gen_sbox(S2, 2, K);
- gen_sbox(S3, 3, K);
+ for(u32bit i = 0; i != 256; ++i)
+ {
+ u32bit W0 = 0, C0 = i;
+ u32bit W1 = 0, C1 = i;
+ u32bit W2 = 0, C2 = i;
+ u32bit W3 = 0, C3 = i;
+
+ for(u32bit j = 0; j < K.size(); ++j)
+ {
+ C0 = SBOX[get_byte(0, K[j]) ^ C0];
+ C1 = SBOX[get_byte(1, K[j]) ^ C1];
+ C2 = SBOX[get_byte(2, K[j]) ^ C2];
+ C3 = SBOX[get_byte(3, K[j]) ^ C3];
+
+ W0 ^= rotate_left(Q_BOX[C0], j);
+ W1 ^= rotate_left(Q_BOX[C1], j + 8);
+ W2 ^= rotate_left(Q_BOX[C2], j + 16);
+ W3 ^= rotate_left(Q_BOX[C3], j + 24);
+ }
+
+ S0[i] = (W0 & 0x00FFFFFF) | (C0 << 24);
+ S1[i] = (W1 & 0xFF00FFFF) | (C1 << 16);
+ S2[i] = (W2 & 0xFFFF00FF) | (C2 << 8);
+ S3[i] = (W3 & 0xFFFFFF00) | C3;
+ }
resync(0, 0);
}
diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h
index d48c1d8a8..455d3c612 100644
--- a/src/stream/turing/turing.h
+++ b/src/stream/turing/turing.h
@@ -29,8 +29,6 @@ class BOTAN_DLL Turing : public StreamCipher
void generate();
static u32bit fixedS(u32bit);
- static void gen_sbox(MemoryRegion<u32bit>&, u32bit,
- const MemoryRegion<u32bit>&);
static const u32bit Q_BOX[256];
static const byte SBOX[256];